Free SSL for Rails and Nginx using Let's Encrypt
Let's Encrypt is a wonderful new Certificate Authority that provides free, automated SSL Certificates. It's supported by some of the best companies in the world and promotes the idea that all websites should be protected by SSL.
They're doing that by offering free SSL certificates that you can use on any site. They're short lived so they last 3 months, and you setup a cron job in order to attempt to renew them periodically. Let's get started!
Install the Let's Encrypt client
First off, we're going to SSH into our server:
Next, we're going to grab a copy of the Let's Encrypt client from Github:
cd ~ git clone https://github.com/letsencrypt/letsencrypt cd letsencrypt/
Then we need to run the script to install it:
Creating a Let's Encrypt SSL Cert
We can create a cert using the following command. Note that you'll need to change a few things:
example.comshould be replaced with your domain
email@example.com be replaced with your email address on the domain
/home/deploy/myapp/current/publicshould be replaced with the path to your Rails app
sudo /home/deploy/.local/share/letsencrypt/bin/letsencrypt certonly --webroot --webroot-path /home/deploy/myapp/current/public --renew-by-default --email firstname.lastname@example.org --text --agree-tos -d example.com -d www.example.com
Another thing we need to do to get an A+ rating on our SSL security is to create our own Diffie-Hellman group. The reason for this is that it protects us from the Logjam Attack. It's pretty simple. We just need to use OpenSSL to generate a Diffie-Hellman group which we will later add to our Nginx SSL config.
cd ~ openssl dhparam -out dhparams.pem 2048
Now that we've registered our SSL cert and created our Diffie-Hellman group, we can modify your Nginx config to add SSL.
Add the following lines to your server block for your app and be sure to change
example.com to your domain.
listen 443 ssl; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; ssl_session_timeout 5m; 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: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; ssl_session_cache shared:SSL:10m; ssl_dhparam /home/deploy/dhparams.pem;
Once you've updated your Nginx config you can run the following command to reload Nginx.
sudo nginx -s reload
Now open up your site in your browser to verify that you can access it over SSL!
Setup Renewal Cron Job
Since Let's Encrypt is designed for short-lived SSL certificates, we need to setup the renewal script to run periodically to try to renew the SSL cert. We'll add this to the root user's cron job so that it can attempt to update the cert every Monday at 2:30am.
Run this command to open up the crontab:
sudo crontab -e
Add this line to the bottom which will denotes when to run and which script to run.
30 2 * * 1 /home/deploy/.local/share/letsencrypt/bin/letsencrypt renew
Save and close the file.
That's really it! Nothing more to it. It's incredibly easy and simple to setup an SSL cert using Let's Encrypt. You can find out more information at the Let's Encrypt website.