run Documentation

Official TypeScript developer resources and documentation for cockpit-project/run. Verified technical context for AI.

0 stars TypeScript TypeScript 1 file ยท ~12,685 tokens
RAW Doc

1. Project Overview & Quickstart (cockpit-project/run)

run

Open-source repository cockpit-project/run

Repository Details

Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.

2. Official Technical Reference & Guides (cockpit-project/cockpit-project.github.io)

File: external/wiki/Cockpit-Coding-Guidelines.md


title: Cockpit Coding Guidelines source: https://github.com/cockpit-project/cockpit/wiki/Cockpit-Coding-Guidelines

General

  • No trailing whitespace, no tab characters, except in Makefile.am files
  • Generally line length should be limited to 120 chars
  • Indentation: 4 spaces per level, no tabs

Languages

C style

  • Gtk+ coding standards

  • GNU C with C11 features is allowed and the default.

  • When in doubt, check the surrounding code and try to imitate it.

  • Exception: We don't require tabular alignment of function arguments like GTK and Glib do. Function definitions look like this:

c
static JsonArray *
interframe_compress_samples (int count,
                             JsonArray *samples)
{
  /* code */
}

Sample code

c
/* Store the code/data payload */
if (len >= 2)
  {
    pv->peer_close_code = (guint16)data[0] << 8 | data[1];
  }
if (len > 2)
  {
    data += 2;
    len -= 2;
    if (g_utf8_validate ((gchar *)data, len, NULL))
      pv->peer_close_data = g_strndup ((gchar *)data, len);
    else
      g_message ("received non-UTF8 close data: %d '%.*s' %d", (int)len, (int)len, (gchar *)data, (int)data[0]);
  }

JavaScript style

Don't indent top level code, even if using a top level private scope (see above).

javascript
(function() {
"use strict";

console.log("not indented");

}());

Variables should be declared outside of loops or condition braces.

javascript
{
  var demo = 1; /* here */
  while(false) {
     /* not here */
  }
}

Function declarations and invocations should have no space after function name. Function starting brace goes on same line as function keyword.

javascript
function name(arg) {
   /* body */
}

Anonymous functions do not need a space between the function keyword and arguments.

javascript
div.onclick = function(e) {
   /* body */
}

Control flow keywords such as if for and while should have a space after them. If there is only one statement in a conditional or loop, you may leave out the braces.

javascript
while (false)
   console.log("never reached");

All binary operators except . (period) and ( (left parenthesis) and [ (left bracket) should be separated from their operands by a space.

More Sample code

javascript
/* if an image is older than two days, don't show the time */
var threshold_date = new Date(image.Created * 1000);
threshold_date.setDate(threshold_date.getDate() + 2);

if (threshold_date > (new Date())) {
    $(row[1]).text(new Date(image.Created * 1000).toLocaleString());
} else {
    var creation_date = new Date(image.Created * 1000);

    /* we hide the time, so put full timestamp in the hover text */
    $(row[1])
        .text(creation_date.toLocaleDateString())
        .attr("title", creation_date.toLocaleString());
}

New javascript files should be in the Asynchronous Module Definition form. For example:

javascript
define([
    "jquery",
    "base1/cockpit"
], function($, cockpit) {
    /* ... */

    var module = {
        api1: function api1() { /* ... */ },
        api2: function api2() { /* ... */ }
    };

    return module;
});

As a general rule: Modules that return API (as above) should avoid global side-effects. And modules that have global side-effects should not return or define API.

React/JSX conventions:

  • Wrap multiline jsx in parentheses
  • Inside JSX code, simple variables or expressions don't require spaces in curly braces, complex ones do, {key.val} and {key} but { this.props.fun_stuff.map(myMapFunction) }
jsx
var panel = (
    <tr className="listing-panel">
        <td colSpan={ header_entries.length + (expand_toggle?1:0) }>
            <div className="listing-head">
                <div className="listing-actions">
                    {this.props.listingActions}
                </div>
                <ul className="nav nav-tabs nav-tabs-pf">
                    {links}
                </ul>
            </div>
            {tabs}
        </td>
    </tr>
);

CSS/HTML style

  • Use dashes instead of underscores in ids
  • Use namespaces for ids if writing code that is consumed as part of a larger whole.

Sample code

css
/* Panels don't draw borders between them */
.panel > .table > tbody:first-child td {
    border-top: 1px solid rgb(221, 221, 221);
}

/* Table headers should not generate a double border */
.panel .table thead tr th {
    border-bottom: none;
}

Python style

Sample code

python
def run(self, proc, output=""):
    # Complete retrieval of the list of tests
    output += proc.stdout.read()
    proc.wait()
    if proc.returncode:
        sys.stderr.write("tap-gtester: listing GTest tests failed: %d\n" % proc.returncode)
        return proc.returncode
    self.test_remaining = []
    for line in output.split("\n"):
        if line.startswith("/"):
            self.test_remaining.append(line.strip())
    if not self.test_remaining:
        print "Bail out! No tests found in GTest: %s" % self.command[0]
        return 0

    print "1..%d" % len(self.test_remaining)

Emacs setup

emacs
(setq indent-tabs-mode nil)
(add-hook 'before-save-hook 'delete-trailing-whitespace)
(setq whitespace-style '(face trailing lines-tail empty))
(setq whitespace-line-column 120)
(global-whitespace-mode)

File: external/wiki/Demos-and-Talks.md


title: Demos and Talks source: https://github.com/cockpit-project/cockpit/wiki/Demos-and-Talks

2025

2024

2023

2022

2021

2020

2019

2018

2016


File: external/wiki/Proxying-Cockpit-over-Apache-with-LetsEncrypt.md


title: Proxying Cockpit over Apache with LetsEncrypt source: https://github.com/cockpit-project/cockpit/wiki/Proxying-Cockpit-over-Apache-with-LetsEncrypt

Cockpit works on a web socket combined with http/https interface, Web Socket is used to deliver active content back and forth between client and server. But when a proxy sits in between, it needs to be configured likely.

We will need to create a virtual host, give the virtual host a domain name, install TLS/SSL certificate and set up a reverse proxy. (instructions adapted from here and here)

Set up Apache X-Frame-Options

Edit Apache X-Frame-Options policy by running:

sudo nano /etc/apache2/conf-available/ssl-params.conf

Find a line that says Header always set X-Frame-Options DENY
and change it to Header always set X-Frame-Options SAMEORIGIN

Set up Apache Virtual Host

Install Apache web server with the following command:

sudo apt install apache2

Run the following command to create an Apache virtual host file. Replace the domain name with your actual domain name for Cockpit. Donโ€™t forget to create an A record for this domain name.

sudo nano /etc/apache2/sites-available/cockpit.your-domain.com.conf

Put the following text into the file.

apacheconf
<VirtualHost *:80>
 ServerName cockpit.your-domain.com
</VirtualHost>

Save and close the file. Enable this virtual host with the following command:

sudo a2ensite cockpit.your-domain.com.conf

Then restart Apache.

sudo systemctl restart apache2

TLS/SSL certificate with Let's Encrypt

HTTPS helps us prevent man-in-the-middle attack and password sniffing. We can obtain a free TLS/SSL certificate from Letโ€™s Encrypt CA. First Letโ€™s install the certbot client. The client is still named letsnecrypt in Ubuntu repository. The following command will install the client and apache plugin.

sudo apt install letsencrypt python-letsencrypt-apache

Now issue the following command to obtain a free TLS/SSL certificate. Replace the text with your actual data.

sudo letsencrypt --apache --agree-tos --email YOUR-EMAIL-ADDRESS -d COCKPIT.YOUR-DOMAIN.COM

You will be asked to choose easy or secure. Itโ€™s recommended to choose secure so that all http requests will be redirected to https.

Once you hit the OK button, a free TLS/SSL certificate is obtained and installed on the Apache virtual host.

Now copy the certificates information into the cockpit certificate folder using the following commands

cat /etc/letsencrypt/live/cockpit.your-domain.com/fullchain.pem >> /etc/cockpit/ws-certs.d/1-my-cert.cert

cat /etc/letsencrypt/live/cockpit.your-domain.com/privkey.pem >> /etc/cockpit/ws-certs.d/1-my-cert.cert

You will need to do this every time the certificate gets renewed (every 3 months).

Set up Apache Reverse Proxy in a Subdomain

To be able to proxy traffic using Apache, run the following commands to enable each of these Apache modules.

sudo a2enmod proxy proxy_wstunnel proxy_http ssl rewrite

Then run the following command to edit the new virtual host file created by Letโ€™s Encrypt (certbot) client.

sudo nano /etc/apache2/sites-enabled/cockpit.your-domain.com-le-ssl.conf

Change this file so it looks like the following.

apacheconf
<IfModule mod_ssl.c>
<VirtualHost *:443>
  ServerName cockpit.your-domain.com
  SSLCertificateFile /etc/letsencrypt/live/cockpit.your-domain.com/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/cockpit.your-domain.com/privkey.pem
  Include /etc/letsencrypt/options-ssl-apache.conf

  ProxyPreserveHost On
  ProxyRequests Off

  # allow for upgrading to websockets
  RewriteEngine On
  RewriteCond %{HTTP:Upgrade} =websocket [NC]
  RewriteRule /(.*)           ws://127.0.0.1:9090/$1 [P,L]
  RewriteCond %{HTTP:Upgrade} !=websocket [NC]
  RewriteRule /(.*)           http://127.0.0.1:9090/$1 [P,L]

  # Proxy to your local cockpit instance
  ProxyPass / http://127.0.0.1:9090/
  ProxyPassReverse / http://127.0.0.1:9090/
</VirtualHost>
</IfModule>

With Apache 2.4.47 or later, this could also be written as:

apacheconf
<IfModule mod_ssl.c>
<VirtualHost *:443>
  ServerName cockpit.your-domain.com
  SSLCertificateFile /etc/letsencrypt/live/cockpit.your-domain.com/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/cockpit.your-domain.com/privkey.pem
  Include /etc/letsencrypt/options-ssl-apache.conf

  ProxyPreserveHost On
  ProxyRequests Off

  # Proxy to your local cockpit instance
  ProxyPass / http://127.0.0.1:9090/ upgrade=websocket
  ProxyPassReverse / http://127.0.0.1:9090/
</VirtualHost>
</IfModule>

Save and close the file. Then restart Apache web server.

sudo systemctl restart apache2

Make sure you changed /etc/cockpit/cockpit.conf to include the following:

ini
[WebService]
Origins = https://cockpit.your-domain.com http://127.0.0.1:9090
ProtocolHeader = X-Forwarded-Proto
AllowUnencrypted = true

Restart cockpit

sudo systemctl restart cockpit.service

You can now login to cockpit at the specified subdomain.

Set up Apache Reverse Proxy in a Subdirectory

The following steps allow proxying traffic from a subdirectory of an existing Apache virtual host.
Important: /cockpit/ and /cockpit+/ are reserved. Do not use any reserved names [listed here]({{ site.baseurl }}/guide/latest/cockpit.conf.5). This example will use /UrlRoot/.

Run the following command to enable all the required Apache modules.

sudo a2enmod proxy proxy_wstunnel proxy_http ssl rewrite

Then run the following command to edit the new virtual host file created by Letโ€™s Encrypt (certbot) client.

sudo nano /etc/apache2/sites-enabled/cockpit.your-domain.com-le-ssl.conf

If you are not using certbot, an example file normally exists at the following:

sudo nano /etc/apache2/sites-available/default-ssl.conf

Otherwise, consult your man pages/packager for the correct filepath, or follow the prior certbot tutorial, or create a site manually.

Assuming you followed the prior LetsEncrypt strategy, are using the common default file, or have an existing virtual host such that the file starts with <VirtualHost *:443> and has the appropriate directives for TLS/SSL, append the following to your virtual host, replacing UrlRoot with your desired subdirectory name.

apacheconf
SSLProxyEngine          On
                # required module
                RewriteEngine           On
                # required module
                ProxyPreserveHost       On
                # required
                ProxyRequests           Off
                # RECOMMENDED, disables forwarding, see https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxyrequests
                ProxyErrorOverride      Off
                # if possible, present cockpit's error pages instead of apache's
                SSLProxyVerify optional_no_ca
                # cockpit has a self-signed cert by default, therefore no CA
                SSLProxyCheckPeerCN Off
                # SSL error without this
                SSLProxyCheckPeerName Off
                # SSL error without this
                SSLProxyCheckPeerExpire Off
                # recommended since potential SSL error without this
                RequestHeader set "X-Forwarded-Proto" "https"
                # required by cockpit.conf
                # following is adapted from https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html
                RewriteCond %{HTTP:Upgrade} websocket [NC]
                RewriteCond %{HTTP:Connection} upgrade [NC]
                RewriteRule "^/UrlRoot/(.*)" "wss://127.0.0.1:9090/UrlRoot/$1" [P,L]
                # when websocket in upgrade AND
                # within UrlRoot, rewrite proxy with wss://
                RewriteCond ${HTTP:Upgrade} !=websocket [NC]
                RewriteRule "^/UrlRoot/(.*)" "https://127.0.0.1:9090/UrlRoot/$1" [P,L]
                # when no websocket upgrade AND
                # within UrlRoot, rewrite proxy with https://
        </VirtualHost>
</IfModule>

Save and close the file. Then restart Apache web server.

sudo systemctl restart apache2

Lastly, change the /etc/cockpit/cockpit.conf to include the following:

ini
[WebService]
Origins = https://your-domain.com http://127.0.0.1:9090
ProtocolHeader = X-Forwarded-Proto
UrlRoot = /UrlRoot/

Replace /UrlRoot/ with your choice of subdirectory, though keep the enclosing /.
This method does not require you to disable encryption (AllowUnencrypted = true) since the self-signed certificate is allowed.

Restart cockpit

sudo systemctl restart cockpit.service

You can now login to cockpit at https://your-domain.com/UrlRoot/.


File: external/wiki/Proxying-Cockpit-over-NGINX.md


title: Proxying Cockpit over NGINX source: https://github.com/cockpit-project/cockpit/wiki/Proxying-Cockpit-over-NGINX

Preamble

Cockpit uses web sockets to deliver active content back and forth between the client and the server in real time. One of the challenges of placing Cockpit behind a proxy server such as nginx is that additional configuration is required to ensure that web socket connections are proxied as well.

For the purposes of this example we will assume:

  • Cockpit is listening on port 9090
  • Nginx is listening on port 80 (http) and port 443 (https)
  • You have a subdomain of cockpit.domain.tld pointed to your nginx instance
  • You can access your nginx instance by connecting to http://cockpit.domain.tld, even if you just get the default page

Make Cockpit proxy aware

For security Cockpit will be unable to serve requests from origins it is unfamiliar with due to cross domain limitations. In our example, Cockpit will see the origin as cockpit.domain.tld however it will believe it's running on 127.0.0.1 and therefore be unable to serve the request.

To make Cockpit proxy aware, you will need to modify the [Cockpit config file]({{ site.baseurl }}/guide/latest/cockpit.conf.5.html) located at /etc/cockpit/cockpit.conf. This file may not exist and if it doesn't you should create it.

text
[WebService]
Origins = https://cockpit.domain.tld wss://cockpit.domain.tld
ProtocolHeader = X-Forwarded-Proto

These changes will let Cockpit know that connections will come through for https (secure http) and wss (secure websockets) on the subdomain cockpit.domain.tld, and that it should look for the X-Forwarded-Proto header to determine if the connection is secure or not. This is important as Cockpit will [redirect any non-local connection from http to https automatically]({{ site.baseurl }}/guide/149/https.html) and sees cockpit.domain.tld is non-local.

Once these changes are made you will need to restart cockpit.

Virtual host file

To create a proxy you will first need to create a virtual server block so nginx is aware of what to do when it receives a request for your subdomain. If this block doesn't exist, nginx will just serve the default page.

This server block will allow you to access Cockpit via http://cockpit.domain.tld:

text
server {
    listen         80;
    listen         443 ssl;
    server_name    cockpit.domain.tld;

    location / {
        # Required to proxy the connection to Cockpit
        proxy_pass https://127.0.0.1:9090;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Required for web sockets to function
        proxy_http_version 1.1;
        proxy_buffering off;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # Pass ETag header from Cockpit to clients.
        # See: https://github.com/cockpit-project/cockpit/issues/5239
        gzip off;
    }
}

NOTE: Since Cockpit automatically handles the http to https redirect you can have one server block which covers both http and https connections.

Once you have added the new virtual host block you will need to restart nginx.

Security

It is recommended you generate a valid, signed certificate for your server, you can do this for free by using Certbot and Let's Encrypt.

NOTE: Once you have a certificate you will need to update the certificate and keys paths in the virtual server block.

Alternatively if you don't require a valid certificate you can generate your own certificate. This approach is only recommended for testing as you will get browser security warnings notifying you the connection is not secure.

If all else fails you can use cockpit's self signed certificates which are stored in /etc/cockpit/ws-certs.d/. To do this you will need to split the 0-self-signed.cert into two files, one containing the key and one containing the certificate.

502 Bad Gateway & SELinux

If SELinux is enabled, change boolean setting (solves 502 gateway error):

setsebool -P httpd_can_network_connect on

Other configurations

There are other common ways you can configure your proxy.

Serving via a subdirectory rather than subdomain

You may want to serve cockpit from a subdirectory rather than a subdomain.

For this example we will assume:

  • Cockpit is listening on port 9090
  • Nginx is listening on port 80 (http) and port 443 (https)
  • You have a domain of domain.tld pointed to your nginx instance
  • You can access your nginx instance by connecting to http://domain.tld, even if you just get the default page
  • You want to access Cockpit via http://domain.tld/secret/
  • You already have a virtual server block for this domain with existing content in it
text
server {
    ...

    location /secret/ {
        # Required to proxy the connection to Cockpit
        proxy_pass https://127.0.0.1:9090/secret/;

        ...
    }
}

The /secret/ location block here contains the exact same information as the location block in the original example, the /secret/ location block should be placed at the end of the virtual server block.

You will also need to let Cockpit know that you are serving the requests from a subdirectory by modifying the cockpit.conf file:

text
[WebService]
Origins = https://domain.tld wss://domain.tld
ProtocolHeader = X-Forwarded-Proto
UrlRoot=/secret

Using an external proxy

If you're not running nginx locally alongside Cockpit you will need to adjust the configuration so it works across a network IP address. This may be an instance where nginx is on another server or running in a docker container or otherwise doesn't have access to 127.0.0.1.

For this example we will assume:

  • Cockpit is listening on port 9090 on system 192.168.10.15
  • Nginx is listening on port 80 (http) and port 443 (https) on system 192.168.10.29
  • You have a domain of domain.tld pointed to your nginx instance
  • You can access your nginx instance by connecting to http://domain.tld, even if you just get the default page
text
server {
    ...

    location / {
        # Required to proxy the connection to Cockpit
        proxy_pass https://192.168.10.15:9090;

        ...
    }
}

For nginx to proxy the connection successfully you'll need to ensure the proxy pass is also using https. By default nginx doesn't check the validity of the SSL certificates for proxied connections, this means you can proxy directly to cockpit using https without needing to tell nginx it's using a self signed certificate.

Insecure connections

If you really want to disable the secure connection requirement in Cockpit and instead proxy to http this is possible by disabling the secure connection requirement in the cockpit.conf file:

text
[WebService]
AllowUnencrypted=true

Disabling the secure connection requirement doesn't provide any real advantage since nginx doesn't check the certificate for validity. Since you are transmitting sensitive information to Cockpit it is recommended to leave this setting intact unless you are troubleshooting or have no other option but to serve requests over http.


File: external/wiki/Workflow.md


title: Workflow source: https://github.com/cockpit-project/cockpit/wiki/Workflow

These are the rules we try to follow when working on Cockpit.

Review Criteria

  • Each commit should be easy to read.

    Commits are for people to read, so try to tell the story of a new feature clearly. For example, refactor the code in a preparatory commit to make the actual change in the next commit easier to understand. Try to separate changes to separate pieces of the code base.

    Historical accuracy of how you figured out the final form of a change is usually not very interesting, but it doesn't need to be totally hidden of course. If rewriting historical commits is tricky and has a high risk of introducing bugs, don't do it.

  • Each commit should adhere to the Cockpit Coding Guidelines

  • The tip of main must always pass the test suites

    A fleet of robots run the test suites for each pull request. This includes unit tests, integration tests, and browser-compatibility tests.

    The integration tests performed are slow and brittle, and not all failures are caused by bugs in the pull request, but don't just blame every failure on the crappy tests.

  • Whenever a pull request changes the API or makes other significant changes, the documentation needs to be updated. Documentation locations that require manual updating include:

    • the top-level README.md about the most important user-facing information about Cockpit
    • [HACKING.md]({{ site.baseurl }}/external/source/HACKING.html) for development information
    • test/README.md for how to set up and run the integration tests
    • the documentation tree, used for [the guide]({{ site.baseurl }}/guide/latest/)
  • Screenshots and/or videos should be included in every pull request that causes visual changes.

    Having visuals communicates changes, helps with design reviews, and provides a way to highlight features in the release notes on Cockpit-project.org.

    When a pull request changes, it's a good idea to include a new screenshot or video to reflect the current state.

  • No merge commits on main.

    See https://sandofsky.com/blog/git-workflow.html for the motivation. In brief, merge commits are confusing when rolling back history to find the commit that introduced a particular bug/feature.

    Thus, we normally use "Rebase and Merge" when merging pull requests.

  • Each commit on main must be reviewed.

    We trust that all information about the review process will be available from GitHub, thus we don't add Reviewed-By lines or similar markers to the commit messages. We also trust that GitHub can find the pull request for a given SHA1 by itself.

  • The subject of a commit should start with a short <topic>: prefix.

    This is usually the package name for frontend code, such as shell, base, or systemd, or some other suitable directory name. Check the existing commits for examples.

  • If a commit fixes an issue, it should have a Fixes #NNN line.

  • Force pushing to main or other release branches is not allowed.

    The only way to get commits onto main is to rebase/merge a pull request onto it. If you regret merging a pull request, revert its changes with a new pull request.

  • The main cockpit-project/cockpit repository should not have any work-in-progress branches.

    Otherwise, there will be a huge number of these branches over time. We could delete them, but that throws away information, and people would still have them in their local clones.

    Instead, each developer (including the core developers) should make his/her own clone and submit pull requests from there. This makes it slightly harder to take over a pull request from another developer, but it can be done.

  • A pull request in "Draft" state is not yet ready for serious review.

    You can make those pull requests to more visibly share some of your work with the rest of the team.

  • Github's 'Request changes' feature will be used to mark pull requests that have been reviewed and need action from the submitter.

    This includes changes to the code, or just replies to comments. Once you have done all that work, you should dismiss the review and comment to indicate that it is ready for review again.

  • A pull request is updated with copious rewrites and rebases until it has a small number of 'perfect' commits.

    These commits should be fit for main and the pull request is merged by rebasing these commits onto main.

  • A pull request that depends on other pull requests declares that in its description.

    When the commits of a pull request sit on top of the commits of another pull request, it's not easy to see from github where one pull request ends and the other begins. Thus, it is import to note dependencies explicitly so that the reviewer is less likely to get confused.

Merge Workflow

We merge requests from the GitHub Web UI with the "Rebase and Merge" button.

Screenshot

Screenshots should be in a PNG format.

In some cases, you'll want a full Cockpit page. In others, you may want to crop to the specific section, dialog, or feature you're working on. Some of the tools (like Firefox Screenshots) allow you to crop to the area before saving. Otherwise, you may consider using an additional tool like GIMP to crop the image afterward.

Firefox

Firefox has two built-in ways to take screenshots.

  1. Firefox Screenshots is integrated in the URL bar, in the โ€ฆ dropdown by default. (You can right click on the option and add it to always be in the URL bar if you take a lot of screenshots.)
    • When running the screenshot tool, it lets you screenshot a portion of the page (with an interactive, resizable area that lets you focus on a specific element), the visible area of a page, or the full page (if the page scrolls off the area โ€” which shouldn't be an issue in Cockpit itself).
    • Once you're happy with the screenshot, click the down arrow to save the screenshot to your computer (in the Downloads folder). It will be in a PNG format, perfect for uploading to GitHub in the comment form of an issue or pull request.
  2. Firefox Development Tools
    • If it's not on already, you might need to visit the DevTools configuration area and toggle the screenshot tool on.
    • Clicking on the camera icon will screenshot the whole page and save it to ~/Downloads/ with no UI. If you're already in development tools, it's a quick way to take a screenshot for uploading later. Depending on the context, might need to be cropped, or it might already be perfect for posting.
    • Firefox's responsive view includes this same screenshot tool in the mobile view switcher.

Chrome

Chrome does not have an easy-to-find screenshot tool built-in by default. It does, however, have hidden developer functionality to take a screenshot:

  1. Press "F12" (or hit Ctrl+Shift+I) to activate developer tools, if not active already.
  2. Hit Ctrl+Alt+P to bring up developer tool action palette.
  3. Start to type "screenshot"
  4. Select full size (full page), node (selected element), or screenshot (visible).
  5. Chrome saves the screenshot in ~/Downloads/

Also, Chrome has a tricky way to get a vector screenshot. This is super-useful for mockups and experimentation.

  1. Open developer tools (F12, just like any other browser).
  2. Click on the dev tools' โ ‡ menu next to the ร— button.
  3. Choose "More tools".
  4. Select "Rendering".
  5. Scroll down to "Emulate CSS media".
  6. Choose "screen" in the dropdown.
  7. Print the page. (Ctrl+P or select "Printโ€ฆ" from the browser's โ ‡ menu in the top-right.)
  8. Make the "Destination" set to "Save as PDF".
  9. Ensure layout is "Landscape" (in most cases).
  10. Click on "More settings".
  11. Experiment with paper size (usually A4 or A3).
  12. Set "Margins" to "None".
  13. Be sure to have "Background graphics" checked.
  14. Click the "Save" button.
  15. Choose a name and place for your PDF. (The name should default to the title of the page. The location is probably "Downloads" by default.)
  16. You can open the PDF in Inkscape to make an SVG, modify the graphics, export as a PNG, or anything else you'd like.

GNOME Screenshot

GNOME itself has two screenshot tools.

  1. Hit the PrtScn key (this is customizable, in case your keyboard doesn't have the key by default). A full screenshot is saved in your ~/Pictures/ folder as a PNG. This screenshot will most likely need to be cropped in the GIMP or a similar tool.
  2. Type "Screenshot" when in overview mode and the screenshot tool will show up. It lets you grab the whole screen, current window, or select an area to grab. You can add a delay, include the cursor, or apply an effect. When done, you can save the screenshot or copy it to the clipboard (to paste into a tool like GIMP or Inkscape).

GIMP

GIMP has the ability to take screenshots under the file menu. It has options similar to the GNOME Screenshot tool.

Video

Install video applications as Flatpaks from Flathub, to ensure the video output works on your system. (Distribution packages sometimes have issues with various codecs and other dependencies.)

Recording

Be sure to check your desktop to make sure there is no personal information onscreen or odd background tabs in your browser.

  • GNOME has a built-in screen recorder: Ctrl+Alt+Shift+R toggles the recording state. Your full video output is captured, regardless of the resolution or number of external monitors. Videos are saved in WebM format in the Videos folder in your home directory. Resulting videos probably need to be cropped & edited. This works on Wayland and X11.
  • Peek can record an arbitrary part of a screen, in both X11 and also on Wayland. Be sure to change the format from GIF to either MP4 or WebM (both can be edited in a video editor). In the preferences, change the framerate to 30.
  • SimpleScreenRecorder works great on X11, but does not work on Wayland.

Editing

Audio

In most cases, videos should have speech indicating what is happening. In everything but the quickest demos, you should have good quality audio.

Audio quality is important.

  • Think about what you're going to talk about in advance
  • Try to clearly enunciate words
  • Record in a quiet environment
  • Use a good microphone
  • Consider re-recording audio after the video, when you're not trying to multitask by showing the feature and speaking โ€” a good video editing tool lets you swap out the audio tracks

If you do not have an external microphone that works with your laptop, you might want to rely on your phone's built-in mic and swap out the audio track in the video editor.

Audio quality can be ranked (in order of best to worst):

  1. Dedicated studio condenser microphone. (A not-so-bad one can be purchased for โ‚ฌ35 โ€” be sure to use the USB adapter if you get it.)
  2. Phone's built-in microphone (as it's optimized for speech quality)
  3. Webcam microphone
  4. Headset/headphones/earbuds microphone (but the quality varies: sometimes it's great, sometimes it's awful)
  5. Laptop's built-in microphone

All of the above options will have a background hiss or background noise, unless you go with a higher-end dedicated microphone. Sometimes this comes from line noise; other times it may pick up noise from nearby electronics. Nearly every audio file benefits from processing in a tool like Audacity.

Cleaning up the audio track is a good idea. Audacity can process audio to remove background noise and normalize the levels. While this works with audio recorded on a laptop's built-in microphone too, the principle of GIGO (garbage-in, garbage-out) still applies, so try to use a higher quality recording device.


File: external/bots/README.md


title: Cockpit Bots source: https://github.com/cockpit-project/bots/blob/master/README.md

These are automated bots and tools that work on Cockpit. This includes updating
operating system images, updating translations or NPM modules, testing PRs, and
more.

Images

In order to test Cockpit-related projects, they are staged into an operating
system image. These images are tracked in the images/ directory. For example,
you might want to test a scenario where Cockpit on one machine talks to FreeIPA
on another, and you want those two machines to use different images.

This is handled by passing a specific image to image-create
and other scripts that work with test machine images. Available images include:

  • fedora-*, rhel-*, debian-*, etc: Various operating systems for testing Cockpit related projects
  • services: Auxiliary network services for tests which are independent from
    the OS where Cockpit runs: FreeIPA, Samba AD, candlepin, Grafana

These well known image names are expected to contain no .
characters and have no file name extension.

Individual projects are expected to locally build their code into packages, and
install them as overlay on top of these pristine images, with image-customize
or using the machine Python API.

For managing these images:

  • image-download: Download selected or all test images
  • image-create: Create test machine images from scratch (usually through
    downloading a cloud image), with common build and test dependencies for
    Cockpit projects preinstalled
  • image-upload: Upload a locally built test image to the official image servers

For running and debugging the images:

  • image-customize: Install packages, upload files, or run commands in a test
    machine image; this keeps the original image intact, and puts the changes
    into an image overlay into test/images/.
  • vm-run: Run a test machine image; by default this happens in an ephemeral
    overlay. You can use the --maintain option to write into the persistent
    overlay in test/images/ instead.
  • vm-reset: Remove all overlays from test/images/

Image location

Downloaded images are stored into ~/.cache/cockpit-images/ by default. If you
want to change that, you can set $COCKPIT_IMAGES_DATA_DIR or the
cockpit.bots.images-data-dir variable with git config to a directory where
to store the pristine virtual machine images. For example:

text
git config cockpit.bots.images-data-dir /srv/cockpit/images

Tests

The bots automatically run the tests as needed on pull requests
and branches. To check when and where tests will be run, use the
tests-scan tool:

text
./tests-scan -vd

Note on eslintrc interaction

As eslint looks for additional configurations, eslintrc.(json|yaml) files, in
parent directories, it is recommended to have "root": true in the eslint
configuration of any project which is using eslint and is tested through
cockpit-bots.

Integration with GitHub

A number of machines are watching our GitHub repositories and are
executing tests for pull requests as well as making new images.

Most of this happens automatically, but you can influence their
actions with the tests-trigger utility in this directory.

Setup

You need a GitHub token in ~/.config/cockpit-dev/github-token or from
the GitHub CLI configuration in
~/.config/gh/config.yml. You can create one for your account at
Developer Settings โ†’ Personal access tokens.

When generating a new personal access token, the scopes should contain
repo:status and read:org. Note in particular, that repo and
public_repo scopes each grant full push access, and should not be used.

You need at least "Write" access to the project for triggering statuses, either
individually per repo (e.g. cockpit
or for all cockpit-project repos.

If you'd like to download Red Hat-only internal images from S3, you'll
need to be in the it-cloud-aws-727920394381-cockpit-ci-images-download group
in Rover (under your Red Hat internal SSO account). Please contact Allison
(lis@) or Jelle (jvanderw@) about being added to the group. If you're in
this group and logged in to Kerberos (via kinit or GNOME Online Accounts) you
should be able to download RHEL images. As an alternative you can run the
./saml-login script to perform a web-based SSO authentication which will
cache a credential good for the next 12 hours. If anything isn't working,
please reach out.

Test contexts

For describing tests which we want to run we use contexts. A context has the form:

text
image[/scenario][@bots#bots_pr][@owner/project/ref]

where items have the following meaning:

  • image: Name of the image on which tests should run (e.g. 'fedora-coreos').
  • scenario: Name of a specific test. This is specific for each separate project and
    is passed verbatim to 'test/run' in $TEST_SCENARIO.
  • bots_pr: Number of pull request that exists in bots repository. When specified,
    bots from this PR would be used instead of main.
  • owner/project: Name of github project (e.g. 'cockpit-project/cockpit'). This part can
    be omitted when testing in the same project and no 'ref' is needed.
  • ref: Reference in the project (usually branch) (e.g. 'rhel-8.2'). Default is
    the project's primary branch.

For example, context for scenario 'firefox' on 'fedora-coreos' is:

text
fedora-coreos/firefox

If we want to trigger it on 'cockpit-project/cockpit':

text
fedora-coreos/firefox@cockpit-project/cockpit

If we want to also not run it on the primary branch, but on 'rhel-8-0' branch:

text
fedora-coreos/firefox@cockpit-project/cockpit/rhel-8-0

If we want to run tests on 'fedora-coreos' but with bots from pull request '169':

text
fedora-coreos@bots#169

Retrying a failed test

If you want to run the "fedora-coreos" testsuite again for pull
request #1234 of cockpit-project/cockpit, run tests-trigger like so:

text
./tests-trigger --repo cockpit-project/cockpit 1234 fedora-coreos

You can also invoke bots/tests/trigger from any project checkout, in which case
you don't need the explicit --repo -- it will default to the GitHub origin of
the current directory's project.

Testing a pull request by a non-allowed user

If you want to run all tests on pull request #1234 that has been opened by
someone who does not have push access to the repository nor isn't in the
allowlist
run tests-trigger with --allow:

text
./tests-trigger --allow [...]

Of course, you should make sure that the pull request is proper and
doesn't execute evil code during tests.

tests-trigger with a different origin

If you need to specify --repo in tests-trigger as your remote is different from
cockpit-project/cockpit, you can set a git configuration option from which
tests-trigger reads the repo. This has to be set per cockpit project.

text
git config cockpit.bots.github-repo cockpit-project/cockpit

Refreshing a test image

Test images are refreshed automatically once per week, and even if the
last refresh has failed, the machines wait one week before trying again.

If you want the machines to refresh the fedora-coreos image immediately,
run image-trigger like so:

text
./image-trigger fedora-coreos

Creating new images for a pull request

If as part of some new feature you need to change the content of some
or all images, you can ask the machines to create those images.

If you want to have a new fedora-coreos image for pull request #1234,
post a comment on the pull request like so:

text
/image-refresh fedora-coreos

The machines will post comments to the pull request about their
progress and at the end there will be links to commits with the new
images. You can then include these commits into the pull request in
any way you like.

Creating a new image

Creating a new image from scratch requires some
images/scripts/ files. For a new image called tux we need:

  • tux.bootstrap: Download or create an initial qcow2 image which boots and has SSH
    acccess. If available, this should be the latest available cloud image,
    but it may also invoke some other VM build tool or build service.
    This script runs in the cockpit/tasks
    container, and thus can only use the tools installed there. If necessary, add
    them first.
  • tux.setup: The setup script runs inside the downloaded test image,
    install all required build and test dependencies, and sets up an admin
    user.

For a new image it is recommended to follow the existing setup/bootstrap scripts,
for example the fedora one.

Run ./image-create -v tux to build the image. If that succeeds, a new image
is saved in images as images/tux (a symlink to the real qcow2 file).
Test-boot it with ./vm-run tux, and ensure you can:

  • Log in with SSH as the admin and root user with our usual test SSH key
  • Become root with sudo as admin works (password "foobar")

To add that image to our CI, create a PR and follow the "Creating new
images for a pull request" section. External contributors will need to ask a
Cockpit team member to create a copy of the PR and follow this workflow.

For the initial PR it is recommended to add the new image to the _manual
testmap of starter-kit or other project to prove that the created image is
functional.

Updating CI to a new Fedora release

TEST_OS_DEFAULT is usually set to the latest (stable) Fedora released,
used as default OS for test VMs.

  1. If this is a new image, add _manual test contexts for the new image to lib/testmap.py, and land that into main.
  2. Create a PR that updates TEST_OS_DEFAULT in lib/constants.py, and trigger all tests for that image there.

Fedora CoreOS

The Fedora CoreOS image is updated to a new Fedora release out of our
control, when this occurs:

  1. Update the naughty symlink naughty/fedora-coreos to the release
    CoreOS uses.
  2. Update OSTREE_BUILD_IMAGE to point to the Fedora release CoreOS
    uses.

Debian Testing

Sometimes packages are dropped out of the Debian testing repositories, when
this happens apply a temporary hack to fetch the package from unstable using
this 954f12fae1d2854e14c543e333338482a012c50d as example.

Pixel tests

The pixel tests used in Cockpit projects use test/reference-image to
determine what image to run the pixel tests on.

  1. Create a PR which updates test/reference-image.
  2. Update the pixel tests if required.

File: guide/index.md


title: Cockpit guide archives class: cockpit-guide

The Cockpit Guide is for those deploying Cockpit or developing parts of Cockpit.

Latest Cockpit Guide

Guide for specific older versions of Cockpit

Specific, older versions of the guide: