Configuring Let's Encrypt and Nginx on EC2

Let's Encrypt

Let’s Encrypt is a new Certificate Authority that offers free TLS/SSL certificates. Now that it’s entered its public beta stage, I decided to experiment with installing and manually configuring a Let’s Encrypt certificate on a EC2 instance running Ubuntu 14.04, Ruby on Rails, and Nginx.

To get started, download the Let’s Encrypt client and run the built-in installer.

$ git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt
$ /opt/letsencrypt/letsencrypt-auto --server https://acme-v01.api.letsencrypt.org/directory --help --debug

Update your Nginx configuration (probably /etc/nginx/sites-available/default) to allow web access to all files in the .well-known/ directory of your web root. This endpoint will be accessed by Let’s Encrypt to ensure that you actually have control over your domain.

location ~ /.well-known {
  allow all;
}

After updating your Nginx configuration, restart your server.

$ sudo service nginx restart

Add the following to /etc/letsencrypt/cli.ini. The webroot plugin will automatically generate the files necessary for the ACME protocol. Remember to use the correct web root directory (if you’re using Capistrano, this will probably be /home/deploy/yourapp/current/public) and domain names.

rsa-key-size = 4096
email = [email protected]
domains = yourapp.com www.yourapp.com
authenticator = webroot
webroot-path = /home/deploy/yourapp/current/public

We can now begin the certificate authorization process.

$ /opt/letsencrypt/letsencrypt-auto certonly --config /etc/letsencrypt/cli.ini --agree-tos

Update your Nginx configuration to take advantage of your newly-issued certificate.

listen 443;
server_name localhost;

ssl on;
ssl_certificate /etc/letsencrypt/live/yourapp.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourapp.com/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

After restarting your web server, your site should now be accessible via HTTPS.

Certificate Renewal

Let’s Encrypt certificates expire after 90 days to ensure security and to encourage automation. We can automate the certificate renewal process by creating a simple monthly cronjob in /etc/cron.monthly/letsencrypt.

#!/bin/sh
#
# Let's Encrypt renewal service

/opt/letsencrypt/letsencrypt-auto certonly --config /etc/letsencrypt/cli.ini --agree-tos --renew-by-default
service nginx restart

Test your renewal script. If you see a success message, you’re set!

$ sudo /etc/cron.monthly/letsencrypt