TLS and Certbot
Certbot / Let's Encrypt
Tested on Ubuntu 20.04. Not supported on Ubuntu 14.04.
Install
sudo snap install core && sudo snap refresh core
sudo apt remove certbot # remove any apt-packaged version first
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo ufw allow 443
The old ppa:certbot/certbot PPA is deprecated; the snap is the supported route.
Everyday commands
certbot --version
sudo certbot certificates # list installed certificates
sudo certbot renew # renew everything near expiry
sudo certbot renew --dry-run # test renewal without touching anything
sudo systemctl status certbot.timer # the automatic-renewal timer
sudo certbot delete --cert-name www.domain.net
Issue a certificate
Standalone (Certbot runs its own temporary web server on port 80/443):
sudo certbot certonly --standalone -d your_domain1 -d your_domain2
sudo ls /etc/letsencrypt/live/your_domain
Webroot (your web server keeps running; Certbot writes the challenge into its document root):
sudo mkdir -p /var/www/letsencrypt/.well-known/acme-challenge
# nginx:
# location ^~ /.well-known/acme-challenge/ {
# default_type "text/plain";
# root /var/www/letsencrypt;
# }
certbot certonly --webroot \
--webroot-path /var/www/letsencrypt \
--agree-tos --email [email protected] \
-d example.com -d sub1.example.com
Add names to an existing certificate — list all names, including the ones already covered:
sudo certbot certonly --agree-tos --email [email protected] \
--expand -d example.com -d www.example.com
Key options
| Option | Meaning |
|---|---|
--apache / --nginx | Use the web-server plugin for auth and install |
--standalone | Run a temporary standalone server for the challenge |
--webroot | Serve the challenge from an existing web root |
--manual | Interactive or hook-driven issuance (e.g. DNS) |
--agree-tos | Accept the ACME subscriber agreement |
--expand | Reissue an existing cert with additional names |
--force-renewal | Renew even if not near expiry |
If port 80 is not reachable from the internet, you must use DNS validation instead of HTTP validation.
Nginx snippet
Certbot writes these into the server block when the nginx plugin is used:
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
Automatic renewal
The Debian/Ubuntu packages install two renewal mechanisms — a cron job and a systemd timer:
/etc/cron.d/certbot
/lib/systemd/system/certbot.timer -> certbot.service
Modern Certbot prefers deploy hooks in a directory over the deprecated
renew_hook line. Reload the web server after a successful renewal:
# /etc/letsencrypt/renewal-hooks/deploy/01-reload-nginx
#!/bin/sh
set -e
systemctl reload nginx
chmod +x /etc/letsencrypt/renewal-hooks/deploy/01-reload-nginx
Hooks in renewal-hooks/pre, .../deploy and .../post run at those three
phases. If you renew in standalone mode while a web server occupies port 80/443,
stop it in a pre hook and restart it in a post hook — but note this
interrupts service during renewal:
# renewal-hooks/pre/01-stop-nginx -> systemctl stop nginx
# renewal-hooks/post/01-restart-nginx -> systemctl start nginx
Pin a certificate to standalone validation in
/etc/letsencrypt/renewal/DOMAIN.conf:
authenticator = standalone
# installer = nginx
Troubleshooting
too many failed authorizations recently — remove the stale account state and
retry (rate limits still apply):
rm -rf /etc/letsencrypt/accounts
Java keytool
Manage a Java truststore/keystore. Do not rename the .jks file after creating
it — the alias and store are referenced by path elsewhere.
keytool -import -trustcacerts -alias root -file root.crt -keystore server.keystore
keytool -import -trustcacerts -alias cross -file 1_cross_Intermediate.crt -keystore server.keystore
keytool -import -trustcacerts -alias intermediate -file 2_issuer_Intermediate.crt -keystore server.keystore
keytool -import -trustcacerts -alias tomcat -file 3_user_domain.crt -keystore server.keystore
keytool -list -v -keystore server.keystore
Import the chain in order — root first, then each intermediate, then the leaf — so each certificate can be validated against the one above it as it is added.