Use Let's Encrypt certificates with Cockpit on Ubuntu
Use Let’s Encrypt certificates with Cockpit on Ubuntu
Cockpit is great for managing a box, but it ships with a self-signed cert. Here’s a clean, repeatable way to put a real Let’s Encrypt cert on Cockpit and keep it renewing automatically.
We’ll use the DNS-01 challenge with Cloudflare (works behind firewalls and supports wildcards).
What you’ll end up with
https://cockpit.your-domain.tld:9090on a valid Let’s Encrypt certificate- Auto-renewals via the Certbot snap systemd timer
- A deploy hook that restarts Cockpit only when this cert renews
Requirements
- Ubuntu 22.04+ (works on 24.04 too)
- Cockpit installed and running on port 9090
- A Cloudflare API token scoped to just the zone you need (DNS:Edit is sufficient; add Zone:Read if required)
1) Install Certbot
sudo snap install --classic certbot
The snap sets up a systemd timer for renewals out of the box.
2) Get a certificate
# allow plugins to run with root and install the cloudflare dns plugin
sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-cloudflare
# token file (restrict perms!)
sudo mkdir -p /root/.secrets/certbot
sudo tee /root/.secrets/certbot/cloudflare.ini > /dev/null <<'EOT'
dns_cloudflare_api_token = AN_API_TOKEN_HERE
EOT
sudo chmod 600 /root/.secrets/certbot/cloudflare.ini
# issue the cert (add a wildcard if you want)
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/certbot/cloudflare.ini \
--domain cockpit.example.com \
--deploy-hook 'systemctl restart cockpit.socket'
Using the --deploy-hook 'systemctl restart cockpit.socket arg we can make sure Cockpit restarts when the certificate is renewed.
3) Point Cockpit at the Let’s Encrypt cert
Cockpit reads certs from /etc/cockpit/ws-certs.d/. It picks the alphabetically last .cert file and expects a matching .key (same basename). The key must be unencrypted.
sudo mkdir -p /etc/cockpit/ws-certs.d
# pick a basename that sorts late (e.g., 99-*)
sudo ln -sf /etc/letsencrypt/live/cockpit.example.com/fullchain.pem /etc/cockpit/ws-certs.d/99-letsencrypt.cert
sudo ln -sf /etc/letsencrypt/live/cockpit.example.com/privkey.pem /etc/cockpit/ws-certs.d/99-letsencrypt.key
# reload Cockpit
sudo systemctl restart cockpit.socket
# sanity check
sudo /usr/lib/cockpit/cockpit-certificate-ensure --check
4) Renewals (already handled)
sudo certbot renew --dry-run
systemctl list-timers | grep certbot
That’s it, Cockpit will have be using a real certificate from Let’s Encrypt.