Free SSL/TLS Certificates with Let's Encrypt and NGINX

Original: https://www.nginx.com/blog/free-certificates-lets-encrypt-and-nginx/

Editor – This blog post has been replaced by an updated version that is based on official NGINX support in certbot. Please go to the new blog post for the latest information and instructions.

Let’s Encrypt is a new certificate authority (CA) offering free and automated SSL/TLS certificates. Certificates issued by Let’s Encrypt are trusted by most browsers in production today, including Internet Explorer on Windows Vista. Simply download and run the Let’s Encrypt client to generate a certificate (there are a few more steps than that, of course, though not many).

Before issuing a certificate, Let’s Encrypt validates ownership of your domain. First, the Let’s Encrypt client running on your host creates a temporary file (a token) with the required information in it. The Let’s Encrypt validation server makes an HTTP request to retrieve the file and validates the token, which serves to verify that the DNS record for your domain resolves to the server running the Let’s Encrypt client.

You can get started right away using Let’s Encrypt with NGINX and NGINX Plus. (This blog applies to both NGINX and NGINX Plus, but for ease of reading we’ll refer only to NGINX Plus from now on.) All you need is the webroot plug‑in from Let’s Encrypt, and a few small changes to your NGINX Plus configuration.

This blog details the steps for configuring NGINX Plus, obtaining certificates, and setting up automatic renewal of the certificates.

Downloading the Let’s Encrypt Client

The first thing you need to do is download and install the Let’s Encrypt client, certbot. You can access the complete documentation at Let’s Encrypt, but in summary the commands are:

$ sudo apt-get update
$ sudo apt-get install -y git
$ sudo git clone https://github.com/certbot/certbot /opt/letsencrypt

Note: All required dependencies are installed along with certbot, including Augeas, gcc, Python, and full CA certificates. Please verify that this complies with your security policy. The definitive list of installed dependencies is in the certbot source code.

Creating a Template for the Let’s Encrypt Temporary File

The Let’s Encrypt client creates a temporary file in webroot-path/.well-known/acme-challenge/ containing the token used by the Let’s Encrypt server to verify that you own the domain you are attempting to get a free ssl certificate for. The webroot‑path in our example is /var/www/letsencrypt.

We first create a template file with the values that Let’s Encrypt needs to issue a certificate, using this GitHub Gist. Without the template, we would have to specify the values on the Let’s Encrypt command line.

  1. Create the directory where Let’s Encrypt stores the temporary file, and set the required permissions:

    $ cd /var/www
    $ mkdir letsencrypt
    $ sudo chgrp www-data letsencrypt
  2. Create the file /etc/letsencrypt/configs/my-domain.conf, where my‑domain is your fully qualified domain name (for example, www.example.com). Copy in the Gist contents and set the appropriate values in the domains (again, the fully qualified domain name), rsa-key-size, server (full URL with scheme), and email fields.

    # the domain we want to get the cert for;
    # technically it's possible to have multiple of this lines, but it only worked 
    # with one domain for me, another one only got one cert, so I would recommend 
    # separate config files per domain.
    domains = my-domain
     
    # increase key size
    rsa-key-size = 2048 # Or 4096
     
    # the current closed beta (as of 2015-Nov-07) is using this server
    server = https://acme-v01.api.letsencrypt.org/directory
     
    # this address will receive renewal reminders
    email = my-email
     
    # turn off the ncurses UI, we want this to be run as a cronjob
    text = True
     
    # authenticate by placing a file in the webroot (under .well-known/acme-challenge/) 
    # and then letting LE fetch it
    authenticator = webroot
    webroot-path = /var/www/letsencrypt/

Allowing Let’s Encrypt to Access the Temporary File

Now we modify the NGINX Plus configuration to allow Let’s Encrypt to access the temporary file.

  1. Add this location block to the virtual server for HTTP traffic:

    server {
        listen 80 default_server;
        server_name my-domain;
     
        location /.well-known/acme-challenge {
            root /var/www/letsencrypt;
        }
        # ...
    }
  2. Verify the configuration file is syntactically valid and restart NGINX:

    $ sudo nginx -t && sudo nginx -s reload

Requesting the Certificate

Now that everything is set up we request the certificate. The highlighted message confirms that we successfully obtained a certificate and associated files for NGINX, which Let’s Encrypt stores in /etc/letsencrypt/live/my-domain. The files of interest are fullchain.pem and privkey.pem.

$ cd /opt/letsencrypt
$ ./certbot-auto --config /etc/letsencrypt/configs/my-domain.conf certonly
Updating letsencrypt and virtual environment dependencies......
Requesting root privileges to run with virtualenv: /root/.local/share/letsencrypt/bin/letsencrypt --config /etc/letsencrypt/configs/my-domain.conf certonly
 
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/my-domain/fullchain.pem. Your cert
   will expire on date. To obtain a new version of the
   certificate in the future, simply run Let's Encrypt again.
   ...

Pointing NGINX Plus to the Certificate

  1. Add the certificate and key to the server block for HTTP traffic:

    server {
        listen 443 ssl default_server;
        server_name my-domain;
        
        ssl_certificate /etc/letsencrypt/live/my-domain/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/my-domain/privkey.pem;
      
        # ...
    }
  2. Verify the configuration file is syntactically valid and restart NGINX Plus to load the new certificates:

    $ sudo nginx -t && sudo nginx -s reload

Automating Renewal of Let’s Encrypt Certificates

Let’s Encrypt certificates are only valid for 90 days, after which they need to be renewed. Luckily this process can be easily automated using a cron job.

  1. Create a simple script like the following (obtained from this thread) to renew the certificate and restart NGINX Plus if successful. Save it as renew‑letsencrypt.sh in a directory that cron has permissions for.

    #!/bin/sh
     
    cd /opt/letsencrypt/
    ./certbot-auto --config /etc/letsencrypt/configs/my-domain.conf certonly
     
    if [ $? -ne 0 ]
     then
            ERRORLOG=`tail /var/log/letsencrypt/letsencrypt.log`
            echo -e "The Let's Encrypt cert has not been renewed! \n \n" \
                     $ERRORLOG
     else
            nginx -s reload
    fi
     
    exit 0
  2. Create /var/log/letsencrypt/ if it doesn’t exist.

  3. Run crontab -e and enter this string to run the script every two months:

    0 0 1 JAN,MAR,MAY,JUL,SEP,NOV * /path/to/renew-letsencrypt.sh

Summary

There are several alternative ways to combine NGINX and NGINX Plus with Let’s Encrypt to automate free ssl certificate generation and renewal. The steps presented in this blog are just one way to go about it. We’re interested in your approach – tell us about it (or any other issues) in the comments section below.

NGINX is open source software that’s supported by NGINX Plus, our commercial‑grade application delivery platform. Learn about the advanced features in NGINX Plus and try it free for 30 days.

Retrieved by Nick Shadrin from nginx.com website.