Renewing a let’s encrypt certificate made even simpler: automatically

I have written about renewing certificates from Let’s Encrypt in the past, and to the project developers’ credit, they keep making the process of getting, installing and renewing certificates easier. There’s a new client called certbot (and certbot-auto) that can be used to almost completely automate the certificate process. As an added bonus, the certbot client’s --webroot method allows you to renew without having to stop your web server and restart, and you no longer need to pause services like Cloudflare.

After following the certbot installation instructions – here are the steps for Nginx under Ubuntu 14.04 – you’ll have a Let’s Encrypt client that will process and install certificates at the same time. If you want to automate the process, and skip having to stop and restart your web server, you’ll need to make a few changes first.

These instructions are for Nginx, because Let’s Encrypt’s automation support for Nginx is still quite limited.

Certbot has a method called webroot which will create a temporary file on your server to allow Let’s Encrypt to verify that you own the domain and server for the certificate. This temporary file will be created in a directory called .well-known in your site’s root directory. You will probably need to modify your Nginx config to allow it to serve requests from this directory. To do so, add the following lines to your Nginx configuration file, in the main server {} block:

  # Allow serving from letsencrypt cert verification folder
  location ~ /.well-known {
    allow all;

Then restart your Nginx server with sudo service nginx restart.

At this point, you should be able to automatically renew your certificates. To test, use the following:

sudo ./certbot-auto renew --dry-run --webroot --webroot-path /path/to/your/webroot

If all goes well, you should see the following:

Congratulations, all renewals succeeded. The following certs have been renewed:
  /path/to/certs/site1/sitecert1.pem (success)
  /path/to/certs/site2/ (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)

Note: I experienced errors when trying to renew several certificates, and certbot doesn’t allow for partial renewals. If you get errors such as Failed authorization procedure for some of your domains, it is because certbot is trying to validate domain ownership for each domain using a separate .well-known directory for each domain, when in fact the verification file is only written to the /path/to/your/webroot/.well-known directory that was specified in the certbot-auto command.

To get around this, remove the .well-known directory from all other domain webroots, and instead create a symlink to the /path/to/your/webroot/.well-known directory that was specified in the certbot-auto command, like this:

/path/to/domain2/webroot $ ln -s /path/to/your/webroot/.well-known ./

Note: I assumed that the --dry-run switch would be a perfect simulation of a real renewal. However, when I ran certbot-auto renew in production mode, I encountered new errors. I had to make minor changes to the individual configuration files in /etc/letsencrypt/renewal/ One of the domain renewal files was set to use Apache as its installer method. Changing that configuration line to installer = None seems to have resolved the issue.

certbot-auto also allows for pre- and post-renewal hooks to run commands as needed before and after the renewal. These commands will only run if a certificate renewal took place. For example, to restart the Nginx service after a certificate renewal, add --post-hook "service nginx restart" to your certbot-auto command. You can test a renewal by adding --force-renew to the command. But don’t add this switch to your crontab: “This form is not appropriate to run daily because each certificate will be renewed every day, which will quickly run into the certificate authority rate limit.”

Once you have verified that your renewal command will successfully complete, you can add the renewal command to your crontab so that renewals get processed automatically. Let’s Encrypt says that “Note: if you’re setting up a cron or systemd job, we recommend running it twice per day. […] Please select a random minute within the hour for your renewal tasks.” I set my renewal check to run once a day. To randomize the time when the task is run, I used a solution I found on StackExchange:

30 1    * * *   root    perl -le 'sleep rand 9000' && /path/to/certbot-auto renew --webroot --webroot-path /path/to/your/webroot --post-hook "service nginx restart"

Leave a Reply

Your email address will not be published. Required fields are marked *