How to configure TLS Let's Encrypt Certificates with Nginx

Let’s encrypt beta is public since yesterday. I already use their certificates for several domains. The main problem I actually face is certificates renewal. I want to be able to renew automatically my certificates without turning off Nginx.

Let’s encrypt official client can be used in a automatic way. Unfortunately, this feature is poorly documented… In order to automate this process, we need to configure Nginx to deliver acme’s challenge specific files, then we need to create a zsh script that we will launch using a Cron routine.

Nginx Setup

If you are already using https on your webserver, you probably have a configuration like this one:

    server {
        listen         80;
        server_name    ...;
        return         301 https://$server_name$request_uri;
      }
    server {
        listen 443 ssl;
        ssl_certificate fullchain.pem;
        ssl_certificate_key privkey.pem;
        server_name ...
        root ...
        location / {
          index index.html index.htm index.php;
        }

You are basically redirecting all the http requests to the https endpoint and serving this endpoint with whatever CGI service you want.

What we need to do is simply add the /.well-known/acme-challenge endpoint for each domain. This endpoint is used by the ACME protocol in order to make sure that we truly own the domain.

Just alter the http server like this:

    server {
        listen         80;
        server_name    ...;
        return         301 https://$server_name$request_uri;

        #Let's encrypt endpoint
        location '/.well-known/acme-challenge' {
          default_type "text/plain";
          root        /tmp/letsencrypt-auto/blog/;
        }
      }

Repeat that setup for all your vhosts. Once you done that, you are finally ready to create your let’s encrypt.

Let’s Encrypt

First, download the project’s client:

    git clone https://github.com/letsencrypt/letsencrypt

Now, we need to generate a certificate for each of your sub-domains. We also want to automatize this step in order to facilitate the certificate renewal. I created a zsh script as follow:

#!/bin/zsh
root="/tmp/letsencrypt-auto/"
domain="yourwebsite.net"
email="youremail@domain.net"

mkdir -p ${root}

/root/letsencrypt/letsencrypt-auto --renew --debug\
  --email ${{email}} --agree-tos certonly\
  --webroot -w ${root} -d ${domain}

You need to specify:

  • acme’s webroot specified in your nginx configuration.
  • the domain name you want to register.

Do not forget to set the exec rights to that file for the root user.

As you can see, I personally placed letsencrypt bin in my /root folder since you need to run it as root. It can be a big deal for some people, for me it’s not.

Now that we have our certificates, we want to automatize the renewal process. In order to do that, we need to call our script using a cron entry.

You just need to add this line to you root’s croontab:

0 0 1 * * /root/letsencrypt/run.zsh >/dev/null 2>&1

This line will renew your certificate each 1st day of the month at midnight.