menu

Let’s Encrypt: How to Automatically Restart Nginx With Certbot

Updated Posted by Arnon Erba in How-To Guides on .

Let’s Encrypt has steadily improved since its public debut in late 2015. Certbot, the most popular Let’s Encrypt client, is available for a wide variety of Linux distributions, making it easy to integrate Let’s Encrypt with many common web server configurations. However, because of this broad support, and because Certbot offers many internal options, there are several different ways to integrate Certbot with Nginx.

If you run Certbot with the --nginx flag, it will automatically make whatever changes are necessary to your Nginx configuration to enable SSL/TLS for your website. On the other hand, if you’d prefer to handle the Nginx configuration separately, you can run Certbot with the --webroot flag. In this mode, Certbot will still fetch a certificate, but it’s up to you to integrate it with Nginx.

Once you’ve obtained certificates from Let’s Encrypt, you’ll need to set up a method to automatically renew them, since they expire after just 90 days. On Ubuntu 18.04, the “certbot” package from the Ubuntu repositories includes an automatic renewal framework right out of the box. However, you’ll also need to reload your web server so it can actually serve the renewed certificates. The packaged renewal scripts on Ubuntu won’t restart Nginx unless you used the --nginx flag to request certificates in the first place. If you’re using --webroot or some other method, there’s an additional important step to take.

Automatically Restarting Nginx

On Ubuntu 18.04, Certbot comes with two automated methods for renewing certificates: a cron job, located at /etc/cron.d/certbot, and a systemd timer. The cron job is set to run every 12 hours but only takes effect if systemd is not active. Instead, the systemd timer (visible in the output of systemctl list-timers) works in tandem with the certbot systemd service to handle certificate renewals.

Instead of modifying the cron job or the systemd service, we can change Certbot’s renewal behavior by editing a config file. Add the following line to /etc/letsencrypt/cli.ini:

deploy-hook = systemctl reload nginx

This will cause Certbot to reload Nginx after it renews a certificate. With the deploy-hook option, Certbot will only reload Nginx when a certificate is actually renewed, not every time the Certbot renewal check runs. Ed: A previous version of this post recommended using renew-hook instead. This option has been superseded by deploy-hook.

You can verify that your changes are working by running certbot renew --dry-run. This will not renew any certificates but will tell you if your deploy-hook command is being picked up by Certbot.

A Little Background Information

If you’re new to Let’s Encrypt, and you’re wondering why you need to automatically renew your certificates and restart your web server when you get new ones, it’s a good thing you’re here. While “traditional” SSL/TLS certificates are manually requested and can be valid for up to two years, certificates from Let’s Encrypt are only valid for 90 days. In their blog post, the Let’s Encrypt team explains their reasoning behind such short certificate lifetimes: they limit the time period for damage to be caused by stolen keys or mis-issued certificates, and they heavily encourage automation, which is key to the success of the Let’s Encrypt model.

This means that you’re going to need to automatically renew your certificates in order to take full advantage of Let’s Encrypt. Fortunately, since this is how Let’s Encrypt is designed to work, auto-renewal functionality is built directly into Certbot, the recommended ACME client for Let’s Encrypt.

A slightly less obvious question is why you’d want to automatically restart your web server as well. The answer is simple: web servers, such as Apache or Nginx, don’t read your SSL/TLS certificates directly from disk every time they need them. Instead, they load them into memory along with the rest of the web server configuration. This is great, and perfectly normal, since reading the certificates from disk would be horribly inefficient. However, it means that updating (or renewing) a certificate with Let’s Encrypt won’t directly change the certificate that Apache/Nginx serves when a page is requested. Instead, the web server must be restarted in order to load the new certificate into memory.

Sources

19 responses to “Let’s Encrypt: How to Automatically Restart Nginx With Certbot”

  1. Roeniss says:

    You read all my mind. kudos.

  2. Anonymous says:

    Thanks for this article. Saved my butt.

  3. Neil says:

    The dry run gives me:

    Dry run: skipping deploy hook command: systemctl reload nginx

    Is that OK? Other sources mean, that this is intentionally skipped in dry run, so it will be executed on renewal

    1. Arnon Erba says:

      This is OK. Per the certbot man page, "–dry-run" does not call "–deploy-hook" commands. (It does call "–pre-hook" and "–post-hook" commands, however.)

  4. Kasper says:

    Thanks man this helped me out a lot!

    Peace

  5. A. Nonymus says:

    Deploy-hook runs after each separate certificate renewal, to reload nginx you need to use post-hook. My advice is to use the following line instead, in /etc/letsencrypt/cli.ini:
    post-hook = systemctl reload nginx

    1. Arnon Erba says:

      My logic for using "deploy-hook" rather than "post-hook" is that "deploy-hook" only runs the hook after a successful renewal. If the certificate renewal fails, I would rather not reload Nginx, as it could potentially pick up a broken certificate that way.

      Based on the Certbot docs, I believe the two options are otherwise identical.

  6. James Home says:

    Incredibly helpful. Thank you.

  7. Ian says:

    Perhaps a test of the nginx configuration could be added. Perhaps doing this way might work:

    deploy-hook = nginx -t && systemctl reload nginx

    1. A. Nonymus says:

      The "nginx -t && …" construct will make certbot assume there is an error, probably because it prints the lines that the configuration files are okay.

      Because the nginx configuration does not get changed by certbot, there is little use in validating the nginx configuration after each renewal.

  8. Robert Siemer says:

    I would advice to use

    /etc/letsencrypt/renewal/your.domain.conf

    and use a line like

    renew_hook = systemctl try-reload-or-restart servicename

    Why? Now each certificate restarts its specific service. Otherwise each renewal triggers the reload of all services (if you have configured more than one).

    Note that the keyword chosen by certbot itself is renew_hook, even though it behaves like deploy-hook.

    And try-reload-or-restart (instead of reload) is also more general: it restarts if no reload is available for the service and does not even do that if the service is disabled.

    So: the advice from the OP is not wrong, but my variation is perfect in this case, and in many more cases as well.
    services (in case you have

    1. Arnon Erba says:

      Thanks, Robert — this is good advice.

  9. Mazufa says:

    Hello!

    I made the changes according to the instructions and it seems to me that the changes I made are working! 🙂 Could you look at this picture so you also think I'm okay?

    Picture link: https://aijaa.com/RkPWUN

    Thanks!

    1. Arnon Erba says:

      Looks good to me.

  10. Marc says:

    is the reload working well ? I hit several time an issue having nginx NOT using the new certificate after a reload. a restart fix it.

    1. Arnon Erba says:

      That's interesting. I've updated the post to recommend using "deploy-hook" over "renew-hook", but that should not change whether or not "systemctl reload nginx" works. I'm using "systemctl reload nginx" in production and will update the post if I catch it failing to load updated certificates.

  11. Daniel says:

    This was super handy, thank you. Looking at the directory structure, I thought I might have to create a file in `/etc/letsencrypt/renewal-hooks/(post|deploy)/`, but I didn't know which directory was required and what that file might have to look like. I'm glad to know that I just needed to edit an entirely different file. Thank you!

  12. Mark says:

    Thank you!! Certbot keeps changing the install instructions and I keep trying to keep up, but inevitably my SSL certs keep crapping out every 3 months. I hope this does it once and for all. Very helpful explanation.

  13. Grateful webmaster says:

    This is exactly what I needed to know! I couldn't understand why my websites kept serving "expired" certificates.

    At first, I thought certbot was failing to renew the certificates. But then I ran `sudo certbot renew –dry-run` and it said "no certificates are due for renewal". That let me know that the certificates ARE being renewed, but not served.

    Then I saw a comment somewhere on certbot's github that the web server nginx must be restarted after renewal. Finally I found you page and got the explanation I needed. Thank you! I didn't know that nginx served the SSL cert from memory and didn't read from disk upon renewal. Your solution of adding it into the cli.ini file is brilliant.

    Thanks again!

Leave a Reply

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