Recently I've been migrating some of my sites to a new hosting platform. During this process I found myself re-creating configuration for various things, and realizing that I don't quite remember all the steps I took to configure it in the first place. One of those things has been the Let's Encrypt auto-renewal. I decided to write this post for future me in case I ever need to do this again and need to remember the steps.

The VM I am configuring is running on Amazon Linux 2 running the Nginx webserver.

First up you need to enable the python3 extras from the Amazon Linux Extras repository:

$ sudo amazon-linux-extras install python3

This installs python3 along with pip3 which we will use to install certbot:

$ sudo pip3 install certbot

Next, get the certs for your domain:

certbot certonly --standalone -d <domain>

If successful, you should see output like this:

 - Congratulations! Your certificate and chain have been saved at:
   Your key file has been saved at:
   Your cert will expire on 2018-05-17. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:
   Donating to EFF:          

Now that we have our certs, we can set up the auto-renewal. There are two parts to this. The first is to create the systemd service file which when started will perform the renewal. Create this file at /etc/systemd/system/renew-letsencrypt.service and add the following content:

Description=Renew certificates

ExecStart=/usr/bin/certbot renew --standalone --pre-hook "/usr/bin/systemctl stop nginx" --post-hook "/usr/bin/systemctl start nginx" --quiet

When this service runs it:

  1. Stops nginx to allow the standalone authentication http server to run on port 80
  2. Renews the certs with certbot renew
  3. Restarts nginx

The second part of the auto-renewal is the systemd timer. Create the file at /etc/systemd/system/renew-letsencrypt.timer and add the following content:

Description=Twice daily check for cert renewal

OnCalendar=*-*-* 06,18:09:00


The OnCalendar section determines how frequently this will run. It takes the format:

DayOfWeek Year-Month-Day Hour:Minute:Second

So in our example above we have it running every day of the week, every month, every year at both 6:09am and 6:09pm. The EFF (the creators of the certbot tool) recommend running renewals twice a day:

if you're setting up a cron or systemd job, we recommend running it twice per
day (it won't do anything until your certificates are due for renewal or
revoked, but running it regularly would give your site a chance of staying
online in case a Let's Encrypt-initiated revocation happened for some reason).
Please select a random minute within the hour for your renewal tasks.

Next, we need to start and enable our timer:

$ systemctl enable renew-letsencrypt.timer
$ systemctl start renew-letsencrypt.timer

This starts our timer running and ensures it starts on startup too.

You can validate that your timer is running by running:

$ systemctl list-timers
NEXT                         LEFT          LAST                         PASSED    UNIT                         ACTIVATES
Fri 2018-02-16 18:00:00 UTC  2h 29min left Fri 2018-02-16 06:00:07 UTC  9h ago    renew-letsencrypt.timer      renew-letsencrypt.service

I've had this running for some time now, so your output will look slightly different. You can see though that it last ran at 6am, and will be running again in 2h 30min. You can also see that it has picked up the service we created earlier and lists that as the target of the timer.

That's all there is to it!

If you have any comments / feedback on this post
reach out on twitter.

Auto-renew Let's Encrypt certs with systemd timers