Today I had an incident which caused my webserver to serve expired certificates. My blog relies on Let’s Encrypt for SSL/TLS certificates, which have to be renewed every 3 months. Usually, the cronjob which runs certbot --renew
takes care of it automatically. However, there is one step missing, the server must reload the renewed certificates. Most of the time, the server gets reloaded often enough so everything is okay, but today, its been a quite a while since the last time since the nginx server was restarted, so expired certificates were served and the blog became unavailable.
To workaround it, we can make sure nginx
reloads it configuration after each successful certificate renewal. The automatic renewal is defined in /etc/cron.d/certbot
. The default contents under Debian Jessie are as follows:
# /etc/cron.d/certbot: crontab entries for the certbot package
#
# Upstream recommends attempting renewal twice a day
#
# Eventually, this will be an opportunity to validate certificates
# haven't been revoked, etc. Renewal will only occur if expiration
# is within 30 days.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
0 */12 * * * root test -x /usr/bin/certbot && perl -e 'sleep int(rand(3600))' && certbot -q renew
The last line makes sure certificate renewal runs twice a day. Append --renew-hook "/etc/init.d/nginx reload"
to it, so it looks like this:
0 */12 * * * root test -x /usr/bin/certbot && perl -e 'sleep int(rand(3600))' && certbot -q renew --renew-hook "/etc/init.d/nginx reload"
The --renew-hook
runs the next argument after each successful certificate renewal. In our case we use it to reload the nginx
configuration, which also reloads the newly renewed certificates.
Update 2019-02-27:
renew-hook
has been deprecated in recent versions of certbot
. Plus, debian moved from using cronjobs for automatic renewals to systemd timer if they are available. On the other hand, now certbot
supports having hooks in configuration files. So, instead of what is described above, i would suggest creating a file /etc/letsencrypt/renewal-hooks/deploy/01-reload-nginx
with the following content:
#! /bin/sh
set -e
/etc/init.d/nginx configtest
/etc/init.d/nginx reload
don’t forget to make the file executable.