After installing Cockpit you will likely end up with certificates that are self-signed and therefore untrusted by default.
There is a better way; Let’s Encrypt.
NOTE: Through out the article the fully-qualified domain name of the Cockpit server is treated as a variable
$FQDN). Make sure to either define a similar variable with an appropriate value or replace it when copying the
First thing is first, install
certbot1. On Fedora 33, the
certbot tool is provided via
the system package manager (e.g.,
python3-certbot). Most Linux distributions have a simple way to install
through the system package manager; check yours.
The other thing you will need is a way for the certificate authority (CA), in this case Let’s Encrypt, to verify ownership of the domain for the certificate. There are a few different challenge types that can be used. I prefer DNS and use Amazon Route 53 so I will assume that in the rest of this.
$ dnf install python3-certbot python3-certbot-dns-route53
Register ACME account⌗
In order, for the ACME server to issue certificates an account must be created. This is simple and only requires an e-mail address and agreeing to the terms of service. If you would like to continue further you must agree to the terms.
$ certbot register --email "email@example.com"
Now the final part is requesting and downloading the X.509 certificates. Again, I prefer the DNS challenge specifically
through Amazon Route 53 so I use the
--dns-route53 flag. You might prefer a different challenge. Please read the
manual for other options.
$ certbot certonly --dns-route53 --domains $FQDN
After this completes you should have certificates in
/etc/letsencrypt/live/$FQDN. Additionally, you can verify the
$ certbot certificates Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Found the following certs: Certificate Name: $FQDN Serial Number: 3dd2fe7e49a5686d55f9c7c8ef790465cdf Key Type: RSA Domains: $FQDN Expiry Date: 2021-06-09 01:25:21+00:00 (VALID: 89 days) Certificate Path: /etc/letsencrypt/live/$FQDN/fullchain.pem Private Key Path: /etc/letsencrypt/live/$FQDN/privkey.pem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Notice that the certs expire? Setting up systemd units and timers
certbot can be configured to
automatically renew these certs.
Certbot Systemd Unit and Timers⌗
The tool provides a
certbot renew function that handles renewal of certificates. The first thing to do is to create
the systemd service.
[Unit] Description=Let's Encrypt renewal via Certbot Documentation=https://letsencrypt.readthedocs.io/en/latest/ [Service] Type=oneshot ExecStart=/usr/bin/certbot renew --quiet --agree-tos
Then the timer.
[Unit] Description=Twice daily renewal of Let's Encrypt's certificates [Timer] OnCalendar=0/12:00:00 RandomizedDelaySec=1h Persistent=true [Install] WantedBy=timers.target
Then it should be as simple as reloading systemd (e.g.,
systemctl daemon-reload) and then starting the timer (e.g.,
systemctl enable --now certbot.timer).
To check the status you can use
$ systemctl list-timers NEXT LEFT LAST PASSED UNIT ACTIVATES Thu 2021-03-11 00:10:56 EST 1h 20min left n/a n/a certbot.timer certbot.service 1 timers listed. Pass --all to see loaded but inactive timers, too.
certbot plugin requires environment variables, like with Route 53 you must provide
AWS_SECRET_ACCESS_KEY, a great way to provide these is through providing an override. This can be done using
systemctl edit certbot.service.
[Service] Environment="AWS_ACCESS_KEY_ID=<key>" Environment="AWS_SECRET_ACCESS_KEY=<secret>"
Cockpit loads certificates from the
/etc/cockpit/ws-certs.d directory. It will use the last file in the directory with
.crt extension in alphabetical order. The private key can be contained in a separate file with the same
name as the certificate, but with a
.key suffix instead. The key must not be encrypted.
This can be achieved by copying the Let’s Encrypt key and certificate to the correct location for Cockpit.
$ cp /etc/letsencrypt/live/$FQDN/fullchain.pem /etc/cockpit/ws-certs.d/$FQDN.crt $ cp /etc/letsencrypt/live/$FQDN/privkey.pem /etc/cockpit/ws-certs.d/$FQDN.key # Note: The user and group may be different $ chown cockpit-ws:cockpit-ws /etc/cockpit/ws-certs.d/$FQDN.crt /etc/cockpit/ws-certs.d/$FQDN.key
To check that the certificates Cockpit will use is now correct run the following command:
$ remotectl certificate certificate: /etc/cockpit/ws-certs.d/$FQDN.crt
Restarting the Cockpit server (
systemctl restart cockpit) should get the updated certificate in place. To make sure
that Cockpit always renews after a certificate renewal make a renewal hook.
#!/usr/bin/env bash echo "SSL certificates renewed" cp /etc/letsencrypt/live/$FQDN/fullchain.pem /etc/cockpit/ws-certs.d/$FQDN.crt cp /etc/letsencrypt/live/$FQDN/privkey.pem /etc/cockpit/ws-certs.d/$FQDN.key chown cockpit-ws:cockpit-ws /etc/cockpit/ws-certs.d/$FQDN.crt /etc/cockpit/ws-certs.d/$FQDN.key echo "Restarting Cockpit" systemctl restart cockpit
- Welcome to certbot-dns-route53’s documentation!
- Cockpit Guide: SSL/TLS Usage
- How To Use Systemctl to Manage Systemd Services and Units
- How To Install Cockpit on Debian 10
certbotis a tool that speaks the Automated Certificate Management Environment (ACME) protocol that Let’s Encrypt uses to issue its certificates. It is worth noting that
certbotdoes not have to speak to Let’s Encrypt. Realistically any certificate authority (CA) that speaks the ACME protocol will do. For example, Fraser Tweedale got it working with Dogtag’s PKI ACME responder. ↩︎