1. Project Overview & Quickstart (cockpit-project/run)
run
Open-source repository cockpit-project/run
Repository Details
- Repository: cockpit-project/run
- Primary Language: Code
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
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:
static JsonArray *
interframe_compress_samples (int count,
JsonArray *samples)
{
/* code */
}/* 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
- Private scopes are only necessary in code that is not bundled with webpack.
"use strict"should be set on code that is not bundled with webpack.- Crockford with lots of exceptions
- Chained calls may be placed on separate lines for readability (see example below)
Don't indent top level code, even if using a top level private scope (see above).
(function() {
"use strict";
console.log("not indented");
}());Variables should be declared outside of loops or condition braces.
{
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.
function name(arg) {
/* body */
}Anonymous functions do not need a space between the function keyword and arguments.
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.
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.
/* 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:
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) }
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.
/* 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
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
(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
- Browser automation/testing with BiDi and minimal dependencies (Martin Pitt), devconf.cz; intro and demo code, video
2024
- Upstream cross-project testing: Never break your API consumers (Martin Pitt), devconf.cz; video, slides and notes
- How we integrated Btrfs in Cockpit (Jelle van der Waa), devconf.cz; video, slides
2023
- Monty Python's Flying Cockpit (Allison Karlitskaya and Martin Pitt), devconf.cz; video, slides and notes
2022
- Tame your CI with Error Budgets (Stef Walter and Martin Pitt); DevConf.cz page with slides and notes links
- (Mostly) Self-testing infrastructure updates (Martin Pitt, Cyborg Infrastructure Seminar)
2021
- Cockpit CI infrastructure overview (Sanne Raymaekers and Martin Pitt, Cyborg Infrastructure Seminar)
- Using the new metrics page to debug performance issues (Matej Marusak)
2020
- Authenticate to Cockpit from anywhere (slides, notes) (Martin Pitt, DevConf.cz)
2019
- Your-turn key Cockpit UI in a CICD ecosystem (slides with notes, slide sources) (Martin Pitt, DevConf.cz)
- Set up Smart Card authentication with Cockpit 209 (Martin Pitt)
2018
- Cockpit - Moving towards more advanced use-cases (Lars Karlitski, Andreas Nilsson, DevConf.cz)
- Cockpit: A Linux Sysadmin Session in your Browser (Stef Walter, FOSDEM)
- Is Cockpit Secure? ([blog post]({{ site.baseurl }}/blog/is-cockpit-secure.html)) (Stef Walter, All Systems Go)
2016
- Cockpit: A Linux Session In Your Browser (Peter Volpe, FOSDEM)
- What's new and what's next (Peter Volpe, Dominik Perpeet, DevConf.cz)
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.
<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.
<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:
<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:
[WebService]
Origins = https://cockpit.your-domain.com http://127.0.0.1:9090
ProtocolHeader = X-Forwarded-Proto
AllowUnencrypted = trueRestart 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.
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:
[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.
[WebService]
Origins = https://cockpit.domain.tld wss://cockpit.domain.tld
ProtocolHeader = X-Forwarded-ProtoThese 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:
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
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:
[WebService]
Origins = https://domain.tld wss://domain.tld
ProtocolHeader = X-Forwarded-Proto
UrlRoot=/secretUsing 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
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:
[WebService]
AllowUnencrypted=trueDisabling 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.
Git-related / Merging Conventions
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, orsystemd, or some other suitable directory name. Check the existing commits for examples.If a commit fixes an issue, it should have a
Fixes #NNNline.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.
- 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.
- 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:
- Press "F12" (or hit
Ctrl+Shift+I) to activate developer tools, if not active already. - Hit
Ctrl+Alt+Pto bring up developer tool action palette. - Start to type "screenshot"
- Select full size (full page), node (selected element), or screenshot (visible).
- 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.
- Open developer tools (F12, just like any other browser).
- Click on the dev tools' โ menu next to the ร button.
- Choose "More tools".
- Select "Rendering".
- Scroll down to "Emulate CSS media".
- Choose "screen" in the dropdown.
- Print the page. (
Ctrl+Por select "Printโฆ" from the browser's โ menu in the top-right.) - Make the "Destination" set to "Save as PDF".
- Ensure layout is "Landscape" (in most cases).
- Click on "More settings".
- Experiment with paper size (usually A4 or A3).
- Set "Margins" to "None".
- Be sure to have "Background graphics" checked.
- Click the "Save" button.
- 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.)
- 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.
- Hit the
PrtScnkey (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. - 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+Rtoggles 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
- Kdenlive is a full-featured editor.
- Flathub also has several other video editors available. Most are adequate for simple 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):
- 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.)
- Phone's built-in microphone (as it's optimized for speech quality)
- Webcam microphone
- Headset/headphones/earbuds microphone (but the quality varies: sometimes it's great, sometimes it's awful)
- 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 projectsservices: 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 imagesimage-create: Create test machine images from scratch (usually through
downloading a cloud image), with common build and test dependencies for
Cockpit projects preinstalledimage-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--maintainoption 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 thecockpit.bots.images-data-dir variable with git config to a directory where
to store the pristine virtual machine images. For example:
git config cockpit.bots.images-data-dir /srv/cockpit/imagesTests
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:
./tests-scan -vdNote 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 containrepo:status and read:org. Note in particular, that repo andpublic_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:
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:
fedora-coreos/firefoxIf we want to trigger it on 'cockpit-project/cockpit':
fedora-coreos/firefox@cockpit-project/cockpitIf we want to also not run it on the primary branch, but on 'rhel-8-0' branch:
fedora-coreos/firefox@cockpit-project/cockpit/rhel-8-0If we want to run tests on 'fedora-coreos' but with bots from pull request '169':
fedora-coreos@bots#169Retrying 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:
./tests-trigger --repo cockpit-project/cockpit 1234 fedora-coreosYou 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:
./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.
git config cockpit.bots.github-repo cockpit-project/cockpitRefreshing 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:
./image-trigger fedora-coreosCreating 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:
/image-refresh fedora-coreosThe 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 anadmin
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
adminandrootuser with our usual test SSH key - Become root with
sudoas 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.
- If this is a new image, add
_manualtest contexts for the new image tolib/testmap.py, and land that intomain. - Create a PR that updates
TEST_OS_DEFAULTinlib/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:
- Update the naughty symlink
naughty/fedora-coreosto the release
CoreOS uses. - Update
OSTREE_BUILD_IMAGEto 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.
- Create a PR which updates
test/reference-image. - 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: