Over a million developers have joined DZone.

Free SSL/TLS Certificates With Let's Encrypt and Nginx

Here's how to use Let's Encrypt with Nginx for free and automated SSL/TLS certificates!

See Gartner’s latest research on the application performance monitoring landscape and how APM suites are becoming more and more critical to the business, brought to you in partnership with AppDynamics.

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.

The Let’s Encrypt client does not yet officially support NGINX and NGINX Plus (support is in beta), but you can still 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, letsencrypt‑auto. 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/letsencrypt/letsencrypt /opt/letsencrypt

$ cd /opt/letsencrypt

$ sudo ./letsencrypt-auto

Note that all required dependencies are installed along with letsencrypt‑auto, including Augeas, gcc, Python, and full CA certificates. You need to verify that this complies with your security policy. The definitive list of co-installed dependencies is in the letsencrypt‑auto 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 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 chgroup 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, which Let’s Encrypt stores in /etc/letsencrypt/live/my-domain. The files of interest are fullchain.pem and privkey.pem.

$ cd /opt/letsencrypt

$ ./letsencrypt-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

 - 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.
    cd /opt/letsencrypt/
    ./letsencrypt-auto --config /etc/letsencrypt/configs/my-domain.conf certonly
    if [ $? -ne 0 ]
     ERRORLOG=`tail /var/log/letsencrypt/letsencrypt.log`
     echo -e "The Let's Encrypt cert has not been renewed! \n \n" \
     nginx -s reload
    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


There are several alternative ways to combine NGINX and NGINX Plus with Let’s Encrypt to automate 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.

Original article by Faisal Memon.

The Performance Zone is brought to you in partnership with AppDynamics.  See Gartner’s latest research on the application performance monitoring landscape and how APM suites are becoming more and more critical to the business.


Published at DZone with permission of Patrick Nommensen, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}