trhall chop image Thomas R. Hall Thoughts...

Using Let's Encrypt for Automated SSL Certificates

As soon as I heard about Let’s Encrypt, I knew that I had to try it out. Being able to generate and renew SSL certificates for free using automation is a noble cause. Having the Internet encrypted by default is important. As of 2015-12-03, Let’s Encrypt is in public beta, which means anyone can now create SSL certificates for free. Currently, it’s still quite technical to use, but companies will doubtless provide more automated integration to generate and use these certificates.

Installing and Updating letsencrypt-auto

I won’t go into too much detail on how to install the official letsencrypt-auto client, as it is still in beta and is subject to change. The How It Works page gives some basic information. I’ll assume that you’re installing this on a Linux server and using Nginx web server, running under the user ID myuserid. If you’d prefer to use Apache web server, it has integrated functionality to install the generated SSL certificates. Full details are in the official documentation site.

cd $HOME/bin/
git clone https://github.com/letsencrypt/letsencrypt

As the letsencrypt-auto tool is being actively modified during the public beta, you’ll want to keep updated with the latest version. To update, simply run the following command to update:

cd $HOME/bin/letsencrypt
git pull

Configuring Nginx for Let’s Encrypt Challenge

The following is an example of a configuration file for Nginx. Simply add the listen 443 ssl; and include includes/letsencrypt-ssl; lines:

server {
	listen 80;
	listen 443 ssl;

	root /var/www/www.example.com;
	index index.html index.xml;

	server_name www.example.com;

	# Include SSL configuration
	include includes/letsencrypt-ssl;
}

Details that can be reused for each site’s SSL certificate are stored in a common file, includes/letsencrypt-ssl. Contents of this file are:

ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_dhparam /etc/ssl/certs/dhparam.pem;

# Let's Encrypt webroot authentication
location '/.well-known/acme-challenge' {
	default_type "text/plain";
	root /tmp/letsencrypt-auto;
}

Generating a certificate

In this example, I’ll add two domain names (www.example.com and wiki.example.com) to a single certificate using Let’s Encrypt’s SNI support. We’ll use this certificate with Nginx. This is based on the instructions in forum post. The latest version of these instructions from renchap are available in this GitHub Gist.

$HOME/bin/letsencrypt/letsencrypt-auto certonly --server https://acme-v01.api.letsencrypt.org/directory -a webroot --webroot-path=/tmp/letsencrypt-auto -d www.example.com -d wiki.example.com

This installs the certificate and account information for Let’s Encrypt in the /etc/letsencrypt/ directory. Restart nginx using something like sudo service nginx reload to allow the settings to take effect.

Automating Certificate Renewal

We can run a command similar to the original one used to generate the certificate. We can run this every month to keep the certificate upated. The following shell script ($HOME/bin/letsencrypt_renew.sh) will be what we run monthly via cron:

#!/bin/sh

/home/myuserid/bin/letsencrypt/letsencrypt-auto --renew certonly --server https://acme-v01.api.letsencrypt.org/directory -a webroot --webroot-path=/tmp/letsencrypt-auto -d www.example.com -d wiki.example.com

sudo service nginx reload

Now, let’s add this to our crontab (using crontab -e to modify the crontab):

0 0 1 * * /home/myuserid/bin/letsencrypt_renew.sh

Now, part of the letsencrypt-auto command requires running via sudo. Since we want this to run automatically via cron, we don’t want to be prompted for a password. Update the sudoers file to allow these commands to run without a password. Edit the sudoers file using the visudo command and add the folowing lines:

# Run without password
myuserid  ALL = NOPASSWD: /home/myuserid/.local/share/letsencrypt/bin/letsencrypt, /usr/sbin/service

This will allow the letsencrypt binary and the service command (used to restart nginx) to run automatically.

Now, your SSL certificates should be renewed every month, automatically!