Certbot Certificate Renewal Automation Done Right - 夜莺博客

Certbot Certificate Renewal Automation Done Right

Certificate expiry is the most predictable outage in IT, and it still happens because automated renewal is set up once and never verified. Certbot installs a renewal timer on most distributions, but the timer only runs certbot renew; whether the web server then serves the new certificate depends on a deploy hook that may or may not exist. This article covers checking what is already configured, adding the pieces that are missing, and proving renewal works before the certificate is hours from expiry.

First, find out what you already have

systemctl list-timers | grep -i certbot
grep -r certbot /etc/crontab /etc/cron.*/ 2>/dev/null
certbot certificates

Certbot is engineered to tolerate both a package-installed timer and a manually added one, so duplication is not dangerous — but two renewal paths that behave differently is a maintenance hazard. Pick one and remove the other.

A systemd timer that does the right thing

# /etc/systemd/system/renew-letsencrypt.service
[Unit]
Description=Renew Let's Encrypt certificates

[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet
# /etc/systemd/system/renew-letsencrypt.timer
[Unit]
Description=Twice daily certificate renewal check

[Timer]
OnCalendar=*-*-* 06,18:17:00
RandomizedDelaySec=1800
Persistent=true

[Install]
WantedBy=timers.target
systemctl enable --now renew-letsencrypt.timer
systemctl list-timers renew-letsencrypt.timer

Twice daily is the recommended cadence: renewal takes no action until a certificate is near expiry, so frequency costs nothing and buys resilience against an unscheduled revocation. The random minute and delay spread load across the ACME service rather than having every server in the estate renew at exactly 06:00. Persistent=true catches up on a run missed while the host was down.

Deploy hooks: the part that is usually missing

# /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
#!/bin/sh
nginx -t && systemctl reload nginx
chmod 755 /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
ls -l /etc/letsencrypt/renewal-hooks/{pre,deploy,post}/

Hooks in pre and post run on every attempt; deploy runs only after a successful renewal. Use deploy for reloads. Use pre/post for services that must stop to free a port — the standalone plugin needs port 80, so HAProxy and similar need to step aside:

printf '#!/bin/sh\nservice haproxy stop\n'  > /etc/letsencrypt/renewal-hooks/pre/haproxy.sh
printf '#!/bin/sh\nservice haproxy start\n' > /etc/letsencrypt/renewal-hooks/post/haproxy.sh
chmod 755 /etc/letsencrypt/renewal-hooks/pre/haproxy.sh /etc/letsencrypt/renewal-hooks/post/haproxy.sh

Prove it works now

certbot renew --dry-run
openssl s_client -connect example.com:443 -servername example.com /dev/null | openssl x509 -noout -dates

--dry-run exercises the whole renewal path against the staging service without touching your live certificates. Run it immediately after setup, and again after any change to the web server configuration. If it fails, fix it now rather than in 89 days.

OCSP stapling

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 1.1.1.1 9.9.9.9 valid=300s;

Nginx's OCSP implementation does not always fetch and cache responses reliably. Supplying the chain as ssl_trusted_certificate lets nginx validate the response it receives, and where reliability remains poor, fetching the response as a deploy hook and pointing nginx at the file with ssl_stapling_file is the established workaround. Note that OCSP stapling is being deprecated across the industry; if you are designing a new deployment, prefer short-lived certificates and rely on the renewal pipeline rather than on stapling.

Operational checklist

  • Renewal timer active and visible in systemctl list-timers.
  • Deploy hook present and executable, reloading every service that terminates TLS.
  • certbot renew --dry-run passes from a clean state.
  • Certificate dates verified over the wire, not from the filesystem — the file can be new while the server still serves the old one from cache.
  • Monitoring alerts on days-remaining, not on expiry, so there is time to react.
  • DNS-01 configured where port 80 validation is impossible or wildcard certificates are required.

For the reverse proxy these certificates are consumed by, and the log pipeline that records renewals, see Nginx Proxy Manager reverse proxy with SSL and Graylog as a central syslog server.

原文链接:https://eff-certbot.readthedocs.io/en/stable/using.html