Skip to Content

Technology Blog

Technology Blog

Free and Auto-Renewing SSL Certificates: Letsencrypt Quick Setup (2017 Edition)

Recently updated on

Update 2017.11: Since this article was released in 2016, Letsencrypt has simplified its install process. This article has been updated to address those changes.

You may have heard of Letsencrypt, which is a new SSL certificate authority that provides free SSL certificates that are supported in all modern browsers. This service is also designed to help automate the issuance of SSL certificates. 

The following describes how to use Letsencrypt to configure auto-renewing SSL certificates on an Ubuntu 14.04 or 16.04 server with Nginx.  This guide assumes that you already have a site hosted with Nginx with the domain already pointed at your web server.  There's some detailed information at certbot.eff.org and letsencrypt.org; however, this guide helps boil it down into a single use-case.

Install

First, we need to install Certbot. Certbot is the official Letsencrypt client that runs on a the server requesting the SSL certificate. Certbot can be installed via the official Certbot Apt repositories. Here are the install instructions as provided on the Certbot website.

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot 

Create a letsencrypt directory under the Nginx webroot.  We chose to put it under the following location, but it could go anywhere as long as Nginx can serve it.

cd /srv/sites/example/htdocs/
mkdir letsencrypt

Next, create a configuration file for Letsencrypt. The default location that Certbot checks for this config file is /etc/letsencrypt/cli.ini. This file helps us reduce the number of command line flags that need to be passed to the Certbot command when we execute it. 

vim /etc/letsencrypt/cli.ini
# increase key size
rsa-key-size = 2048 # Or 4096

# this address will receive renewal reminders
email = domains@example.com

# turn off the ncurses UI, so this can be run as a cron job
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 = /srv/sites/example/htdocs/letsencrypt

Certbot will need to create a random file inside of the webroot-path directory specified in the above config.  Nginx will serve up this file, and Letsencrypt will use it to validate that you own the domain. To allow Nginx to serve this file, you need to add the following location block to both the http and https server blocks in your Nginx config.  We typically define a single locations.conf file which is then included in both server blocks.  See the example below. 

vim /srv/sites/example/etc/nginx/locations.conf
# letsencrypt challenge directory
location /.well-known/acme-challenge {
    root /srv/sites/example/htdocs/letsencrypt;
}

Here is an example Nginx server config that you would add the location includes to. (This example config assumes that a symlink exists in /etc/nginx/sites-enabled/ that points the file below.)

vim /srv/sites/example/etc/nginx/server.conf
# Nginx Server Config File
server {
   listen 80;
   server_name www.example.com example.com;   
   
   # includes the above locations.conf file.   
   include /srv/sites/example/etc/nginx/locations.conf;
   ...
   
}
server {   
    listen 443;
    server_name www.example.com example.com;

    # includes the above locations.conf file.
    include /srv/sites/example/etc/nginx/locations.conf;
    ...
} 

Next, for the above to take effect, we need to test the Nginx config and restart Nginx. 

sudo nginx -tc /etc/nginx/nginx.conf && sudo service nginx restart

Now that Nginx is able to serve up the Certbot-generated challenge file, we need to actually run the Certbot command to generate the certificate. The first time you run this command with a particular email address (from the config above), Certbot will prompt you through some questions to register that email. This command does a lot: verifies that you own the domain and it actually generates the SSL certificate and private key. 

The -d option lets you specify what domains to associate with the cert, and you can associate multiple domains with a cert.  Note, however, that every domain given will be verified by Letsencrypt, so every given domain must be to serve up the challenge file.

sudo certbot certonly \
    --config /etc/letsencrypt/cli.ini \
    -d example.com -d www.example.com

(A)gree/(C)ancel: A
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for example.com
http-01 challenge for www.example.com
Using the webroot path /srv/sites/example/htdocs/letsencrypt for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Generating key (2048 bits): /etc/letsencrypt/keys/0000_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0000_csr-certbot.pem

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.com/fullchain.pem. Your cert will
   expire on 2017-02-05. To obtain a new or tweaked version of this
   certificate in the future, simply run certbot-auto again. To
   non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - If you lose your account credentials, you can recover through
   e-mails sent to domains@example.com.
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:
   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

If this runs successfully, you should have a new set of certificates and keys in the following locations (in this example). 

  • /etc/letsencrypt/live/example.com/ - the files within are symlinks to current keys and certs
    • privkey.pem - private key for the certificate
    • cert.pem - the certificate by itself
    • chain.pem - the root and intermediary certs chain needed by the browser excluding the server certificate.
    • fullchain.pem - all certificates in the chain including the server certificate
  • /etc/letsencrypt/archive/example.com/ - contains all of the current and old certs

Next, you need to update Nginx again to use the new SSL certificate and private key. 

server {
  listen 443;   server_name www.example.com example.com;
  ssl on;
  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
   ....

As before, test and restart Nginx.

sudo nginx -tc /etc/nginx/nginx.conf && sudo service nginx restart

At this point, you should have a fresh SSL certificate installed.  If you point a web browser at your domain, hard-refresh, and check the SSL certificate properties, you should see that the new SSL certificate is in place. 

Auto-Renewal

Letsencrypt issues certificates for 3-month periods. The process of renewing can be automated so that you never need to manually install a certificate again on this server. 

To do this, we just need to create a script in cron.weekly.  Cron will run this on the first day of the week; if the certificate is less than a month from expiring, the certificate will be renewed automatically. (We have cron run this weekly, instead of monthly, to account for the rare case where the cert expires just before the end of the month.)

vim /etc/cron.weekly/letsencrypt
#!/bin/bash
certbot renew  --text --no-self-upgrade > /var/log/letsencrypt_cron.log 2>&1
service nginx restart

Finally, we want to change the permissions on this script so that it's executable.

chmod 755 /etc/cron.weekly/letsencrypt

That's it! Cron will take care of the rest and auto-renew the cert if needed. A few months down the line, just before your new Letsencrypt certificate is about to expire, you should check the certificate expiration date to make sure auto-updating is happening properly.


Share , ,
If you're getting even a smidge of value from this post, would you please take a sec and share it? It really does help.