TOPICS
Tutorials

Use Let's Encrypt for SSL

In this guide, we'll go over integrating Let's Encrypt with your existing webserver, and setting up automatic certificate renewal. We'll also monitor for SSL expiration; with the automatic renewal, the certificate shouldn't expire, but it's safer to have monitoring in case something goes wrong.

Note that some webservers support integration with Let's Encrypt, so you don't need to set up anything on top of them. Let's Encrypt also comes with a plugin that automatically manages certificates for Apache. We'll cover these two easier alternatives at the bottom of the guide, but we'll start off assuming you already have a webserver with SSL.

Adding Let's Encrypt to your Existing Webserver

We will set up a cron job to regularly update the certificates using the Let's Encrypt client. We will run the client in stand-alone mode, where it creates its own webserver to perform the domain validation process.

First, install Let's Encrypt; on Debian/Ubuntu, run as root user:

apt-get install git
git clone https://github.com/letsencrypt/letsencrypt /root/letsencrypt
cd /root/letsencrypt
./letsencrypt-auto --help

Turn your webserver off so that we can run the stand-alone Let's Encrypt client:

service nginx stop

Try to get certificates for your domain:

./letsencrypt-auto certonly --standalone --standalone-supported-challenges http-01 -d www.YOUR_DOMAIN.com,YOUR_DOMAIN.com --renew-by-default

Above, replace "www.YOUR_DOMAIN.com,YOUR_DOMAIN.com" with a comma-separated list of domain names you want the certificate for. You'll need to enter an e-mail address and agree to the Let's Encrypt terms of service (this only needs to be entered once; it'll be saved in /etc/letsencrypt/accounts/).

If this suceeds, your SSL certificates will be installed in /etc/letsencrypt/archive, with symlinks to the latest version in /etc/letsencrypt/live. With nginx, your configuration will look like this:

server {
	listen 443 ssl;
	listen [::]:443 ssl;
	server_name YOUR_DOMAIN.com;

	ssl_certificate /etc/letsencrypt/live/YOUR_DOMAIN.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/YOUR_DOMAIN.com/privkey.pem;
	ssl_session_timeout 5m;
	ssl_session_cache shared:SSL:5m;

	ssl_dhparam /etc/nginx/dhparam.pem;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
	ssl_prefer_server_ciphers on;
	# ...

Note: see Mozilla's server-side TLS page for instructions on robustly configuring SSL in your webserver. Also, the certificates will by default only be accessible to the root user; depending on your webserver setup, you may need to modify the permissions (for example, chown root:www-data /etc/letsencrypt/live /etc/letsencrypt/archive/; chmod 750 /etc/letsencrypt/live/ /etc/letsencrypt/archive/).

Once updated, restart your webserver (e.g. service nginx start).

Let's automate this process so that we don't have to worry about renewing the certificates. Create a script that basically executes the commands we performed above, and save it in /usr/local/sbin/renew-letsencrypt:

#!/bin/bash
cd /root/letsencrypt
sudo service nginx stop
./letsencrypt-auto certonly --standalone --standalone-supported-challenges http-01 -d www.YOUR_DOMAIN.com,YOUR_DOMAIN.com --renew-by-default
sudo service nginx start

Then, make this a cron job to run every month:

chmod +x /usr/local/sbin/renew-letsencrypt
echo "$((RANDOM%60)) $((RANDOM%24)) $((RANDOM%26+1)) * * root /usr/local/sbin/renew-letsencrypt" >> /etc/crontab

Above, we use RANDOM to space out the renewal time, and write it to /etc/crontab to associate the cron job.

We also recommend setting up monitoring so that if something goes wrong with the automatic renewal, you get a notification that your certificate is expiring. Let's Encrypt should send out warning notifications, but just in case we can add our own.

  • From Luna Node Dynamic, select Monitoring.
  • Create a new SSL expiration check.
  • Enter YOUR_DOMAIN.com:443 for the target, and set the check interval to 3600. Set other options as desired.
  • Make sure to associate the check with a contact, such as your e-mail address.

Caddy

Caddy is a webserver written in Golang that natively supports HTTPS with Let's Encrypt.

Mathias Beke has a good tutorial on setting up Caddy to run as an upstart service as a normal user on Ubuntu: http://denbeke.be/blog/servers/running-caddy-server-as-a-service/.

The Caddyfile can be as simple as this (Caddy will handle the Let's Encrypt communication):

http://YOUR_DOMAIN.com, http://www.YOUR_DOMAIN.com, https://YOUR_DOMAIN.com {
	redir https://www.YOUR_DOMAIN.com
}

https://www.YOUR_DOMAIN.com {
	root /var/www
	log access.log
}

Apache Plugin

Let's Encrypt offers a plugin that interacts directly with Apache to perform domain validation and update the certificates. The plugin will attempt to automatically make configuration changes for the certificates. Essentially, you would run the command below instead of running the Let's Encrypt client in stand-alone mode:

./letsencrypt-auto certonly --apache -d YOUR_DOMAIN.com,www.YOUR_DOMAIN.com --renew-by-default

Note: when first setting this up, you should run without the certonly argument so that configuration changes are made. Also, you do not need to stop and restart the webserver when using the Let's Encrypt Apache plugin.