Let's Encrypt with a Rails app on Heroku
Padlock by Moyan Brenn is licensed under CC BY 2.0
I needed to renew an SSL certificate today, so I used it as an excuse to try Let’s Encrypt for a free certificate.
First, grab the Let’s Encrypt client,
On a mac, simply run:
brew install certbot
On other platforms install and run the
certbot-auto command everywhere I use
Let’s Encrypt’s ideal workflow involves running it on your server. Since we’re not “on” the Heroku server, we have to do it locally and in a few steps.
sudo certbot certonly --manual
You’ll be prompted to enter the domain you want a certificate for, and another prompt or two.
Then you’ll see a message about the next steps. Don’t continue on yet! Read the message that begins like this:
Make sure your web server displays the following content at http://inchworm.io/.well-known/acme-challenge/ya6k1ed-SOME-LONG-URL before continuing: ya6k1edW38z-your-value-here
We need the server to serve this code at that particular URL to verify that it is indeed ours.
In Rails, we first add a route to
get '/.well-known/acme-challenge/:id' => 'pages#letsencrypt'
PagesController since I already had one for our static pages, but you can use any controller (or a new one).
Then we’ll add the actual controller code. Remember to substitute your long code here:
class PagesController < ApplicationController def letsencrypt # use your code here, not mine render text: "ya6k1edW38z-your-value-here" end end
Once this is in your app, deploy it to Heroku.
Then, and only then, do you continue the Let’s Encrypt process.
If you did it right, you’ll see a message like this:
IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/inchworm.io/fullchain.pem. Your cert will expire on 2016-04-11. To obtain a new version of the certificate in the future, simply run Let's Encrypt again.
That means it worked and you have your certificate!
The final step is to upload the certificate to Heroku.
If you are replacing an existing certificate:
sudo heroku certs:update /etc/letsencrypt/live/inchworm.io/fullchain.pem /etc/letsencrypt/live/inchworm.io/privkey.pem
If this is your first time adding a certificate to your Heroku app, you need to enable the SSL Endpoint ($20/month) and add the cert:
heroku addons:create ssl:endpoint
sudo heroku certs:add /etc/letsencrypt/live/inchworm.io/fullchain.pem /etc/letsencrypt/live/inchworm.io/privkey.pem
Adding the SSL Endpoint changes the CNAME you need to point your custom domain to. You’ll need to edit your DNS using the new value listed in your Heroku dashboard for it to work correctly.
Ready to upgrade your certificate? Run this command to renew:
sudo certbot certonly --manual -d inchworm.io
Then go back up to set the new challenge key and upload the certificate when complete.
There are a few things I’d like to see improved, and I expect they will be soon.
A homebrew package for
certbot. I expect we'll see this after the bugs are worked out.
- Don’t require
sudo. I expect this will come, but most use cases today will need
sudo, so I understand why they require it.
- Heroku should provide this as an automated service. I hope they do before my 90-day certificate expires, but otherwise I’ll do this process again.
 A static file would work too and skip the route.
 You can also use an ENV variable for this, but I’m hoping this is automated by Heroku soon.