Monday, July 6, 2020

Use Certbot to renew Let's Encrypt TLS certificates

You created a new website or perhaps even configured a SMTP mail server. You patted yourself on the back because you had not forgotten about securing the web and mail services. Specifically, you set up a free TLS certificate from Let's Encrypt. So, it is time to put your feet up and admire the good work you had done, right?

Not yet. The TLS certificate from Let's Encrypt would expire every 90 days, and is renewable only after 60 days. Doesn't this scream for automation?

Assuming that you have shell access to the host server, this blog post explains how to use Certbot to automate the renewal of Let's Encrypt certificates, and points out some gotchas to avoid.

Certbot

The recommended way to deploy Let's Encrypt certificates on a Linux system is to use the certbot tool. This tutorial assumes that you have successfully used certbot to obtain and install a Let's Encrypt certificate.

The Let's Encrypt ecosystem with certbot is designed with automation in mind. When you install certbot on various Linux distributions such as Debian, Ubuntu, Fedora, CentOS, etc, the mechanism for certificate renewal is already put in place. What you need to do is make sure that the timer for certbot is enabled.

$ systemctl status certbot.timer
● certbot.timer - Run certbot twice daily
   Loaded: loaded (/lib/systemd/system/certbot.timer; enabled; vendor preset: enabled)
   Active: active (waiting) since Sat 2020-06-27 10:20:51 PDT; 3 days ago
  Trigger: Wed 2020-07-01 12:14:52 PDT; 2h 1min left

To enable the timer,

$ sudo systemctl enable certbot.timer 

Certbot is scheduled to automatically run twice daily to check if certificate renewal is needed. A certificate is only renewed, however, if expiry is impending—within 30 days before expiration.

For your peace of mind, you can verify the current status of your TLS certificates using the web tools SSL Test and crt.sh.

Gotcha # 1: Refreshing certificates

Renewing a certificate before it expires is only half the battle. The other half is to get the web server (and email server if applicable) to use the new certificate. The obsolete version is still in use until the webserver (and email server) is reloaded.

Certbot provides a hook interface to run scripts before or after a certificate is renewed. I used the Deploy hooks and the Pre-hooks to automate the reloading of web and email server programs.

Deploy hooks

A Deploy hook is run after the successful renewal of a certificate. Deploy hooks are placed in the /etc/letsencrypt/renewal-hooks/deploy directory.

If there is more than 1 script in the directory, the scripts are executed in alphabetical order based on their filenames.

I created 2 Deploy scripts, 01-reload-nginx.sh and 02-reload-postfix.sh to reload NGINX and postfix respectively. Both scripts should be executable(file permissions set to 770).

A typical script to reload NGINX is as follows.

$ sudo cat /etc/letsencrypt/renewal-hooks/deploy/01-reload-nginx.sh
#! /bin/sh
set -e
/etc/init.d/nginx configtest
/etc/init.d/nginx reload 

To switch to the new certificate for postfix, both postfix and dovecot need to be reloaded.

$ sudo cat /etc/letsencrypt/renewal-hooks/deploy/02-reload-postfix.sh
#! /bin/sh
set -e
/etc/init.d/postfix reload
/etc/init.d/dovecot reload

Pre-hooks

Pre-hooks are scripts to be run when a certificate is due for renewal, i.e., within 30 days prior to expiration, and before the renewal is actually performed. Those scripts are placed in the /etc/letsencrypt/renewal-hooks/pre/ directory.

I created a Pre-hook script named 01-notify-renewal.sh to email me when a certificate is due for renewal.

$ sudo cat /etc/letsencrypt/renewal-hooks/pre/01-notify-renewal.sh 
#! /bin/sh
set -e
echo 'Message' | /usr/bin/mail yourEmail@example.com -s 'Subject' 

Manual execution

After auto-renewal is set up, there is little need to manually renew a certificate. But, you have the option to do so. To manually renew:

$ sudo certbot -q renew

The -q option suppresses all output except errors.

Recall that a certificate will only be renewed if it is within 30 days to expiry. You can override this restriction by specifying the --force-renewal option. Use it with caution however(see gotcha # 2).

$ sudo certbot -q --force-renewal renew

Gotcha # 2: Rate limit

Renewal is subject to a Duplicate Certificate limit of 5 per week. Please read the rate limits documentation to be acquainted with what counts toward this limit.

If the rate limit for a certificate is exceeded, renewal is temporarily suspended until the rate limit resets—on a sliding basis—after a week. For instance, if you renew a certificate 3 times on Monday and twice more on Friday, renewal is suspended until the following Monday.

No comments: