DEV Community

Cover image for SSL for Rails with Heroku and Let’s encrypt
Capripot
Capripot

Posted on

SSL for Rails with Heroku and Let’s encrypt

SSL certificates have been finally made common thanks to Let’s encrypt.

Since I originally wrote this article, Heroku released Automated Certificate Management (ACM) which should be the preferred way to do this task. But for the sake of brain exercising, here is the original article.

Let’s see how we can configure a Rails app hosted on Heroku with a Let’s encrypt generated certificate. The second part can be applied to any certificate.

Replace example.com with your actual domain 😉

Create the page to verify your domain

At this step, I assume you already have an up and running Rails application on Heroku.

You need to add the page to serve the private key given by Let’s encrypt to validate the ownership of your domain.

Create a controller or use one you have already with the following public method:

def letsencrypt
  render text: "#{params[:id]}.#{ENV['LETS_ENCRYPT_KEY']}"
end
Enter fullscreen mode Exit fullscreen mode

In your config/routes.rb file, add a route to the page you just created.

get '/.well-known/acme-challenge/:id', to: "pages#letsencrypt", constraints: { id: /[a-z0-9_-]+/i }
Enter fullscreen mode Exit fullscreen mode

Get Let’s encrypt certificate

We need to get Let’s encrypt binaries first. In a working directory:

git clone https://github.com/letsencrypt/letsencrypt
Enter fullscreen mode Exit fullscreen mode

Then just go in the folder and use letsencrypt-auto binary. It’s in development, so you still need to use the --debug flag. Also, to protect your certificate, you need to run the binary as root user, with sudo for instance.

sudo ./letsencrypt-auto certonly -d your.domain  --debug
Enter fullscreen mode Exit fullscreen mode

Set the environment variable LETS_ENCRYPT_KEY to match the private key given by Let’s encrypt binary, that the part given after the .. Here for instance, when you get prompted

Make sure your web server displays the following content at
http://your.domain/.well-known/acme-challenge/pA0ucRCnGPnG6S-0fVF93A_-0CQb_rSfeDOYvAXh8Ck before continuing:

pA0ucRCnGPnG6S-0fVF93A_-0CQb_rSfeDOYvAXh8Ck.Yq3zvhj7vmfBveGvR85p4nwlOBtf7gip40sSrif__Rr
Enter fullscreen mode Exit fullscreen mode

the private key is Yq3zvhj7vmfBveGvR85p4nwlOBtf7gip40sSrif__Rr. In a second terminal, in your Rails app folder, do the following:

heroku config:set LETS_ENCRYPT_KEY=Yq3zvhj7vmfBveGvR85p4nwlOBtf7gip40sSrif__Rr
Enter fullscreen mode Exit fullscreen mode

You can then continue with the Let’s encrypt process by pressing ENTER.

Now the binary is requesting a certificate via letsencrypt.com and the Authority is checking that your domain is yours by accessing via http protocol, the page http://your.domain/.well-known/acme-challenge/pA0ucRCnGPnG6S-0fVF93A_-0CQb_rSfeDOYvAXh8Ck.

You should get a Congratulations message.

Configure Heroku

Assuming you already installed the Heroku CLI, add the ssl endpoint add-on:

heroku addons:create ssl:endpoint

Add your new fresh certificate to Heroku:

sudo heroku certs:add /etc/letsencrypt/live/your.domain/fullchain.pem /etc/letsencrypt/live/your.domain/privkey.pem

Learn more about SSL endpoints in Heroku doc.

Reconfigure your DNS

Ask Heroku what is the ssl endpoint your application got

heroku certs
Enter fullscreen mode Exit fullscreen mode

You get a list like that:

Endpoint                  Common Name(s)  Expires               Trusted
------------------------  --------------  --------------------  -------
endpoint-0.herokussl.com  example.com     2016-01-01 00:00 UTC  True
Enter fullscreen mode Exit fullscreen mode

Change now your DNS entry to

IN CNAME endpoint-0.herokussl.com.
Enter fullscreen mode Exit fullscreen mode

Learn more about configuring your DNS in Heroku doc.

Test your configuration

After your new DNS entry got propagated, you should be able to access https://example.com with a valid secured connection.

If you want to test it before, you can access directly https://endpoint-0.herokussl.com and check the certificate being properly served.

🍻 Peace!

Originally published on February 24, 2016

Photo by Jason Blackeye on Unsplash

Top comments (0)