Free TLS with LetsEncrypt and Heroku in 5 Minutes

Cory Forsyth
4 min readJan 12, 2017

--

Our team at 201 Created recently built a proof-of-concept web app that showcases the extraordinary capabilities of the modern web. It is quickly converging on (and in some cases, surpassing) the feature set of native apps. We will be releasing the web app soon, along with more blog posts about our process; to stay tuned, follow @bantic (me) or 201 Created.

Update July 27 2018: A few readers have pointed out that this approach no longer works for apps on the free tier at Heroku. The bad news is that there is no longer a zero-cost way to deploy a Heroku app with TLS. The good news is that it is even easier, provided you upgrade to a (paid) hobby dyno or greater, to use Heroku’s Automated Certificate Management system to turn on TLS for your app.

Our web app accepts payments via Apple Pay (pay with your fingerprint!) and Android Pay, and in order to do so we must serve the app securely with TLS (aka https and, erroneously, SSL). In the past this would entail buying an TLS Certificate from one of the providers online and jumping through a few hoops to get it assigned.

These days, however, there’s a new CA (Certificate Authority) on the block: LetsEncrypt. They are a non-profit that launched in April, 2016, and are dedicated to allowing everyone to secure their website with TLS. LetsEncrypt now supports more than 20 million active certificates and is rapidly growing.

If you host your website on Heroku with a custom domain and haven’t yet secured your site with TLS, now is the time. The process takes less than 5 minutes and is completely free if you have a Heroku account that uses paid dynos (Hobby and up). See more details about Heroku’s free SSL here.

Step 1: Install certbot

The first step is to install the command-line tool certbot. If you are on Mac and use homebrew, installation is simple:

brew install certbot

For other OSes, see the certbot installation docs.

(Note: this post was tested with certbot version 0.9.3. If your version is significantly different you may need to adjust some commands below.)

After certbot is installed, generate a cert manually:

sudo certbot certonly --manual
Enter the domain name of your site as prompted.

After you hit ok you may be notified that your IP is logged. If so, hit ok again. At this point certbot will display the ACME challenge information: A URL and its required text content. It looks like this:

Make sure your web server displays the following content at
http://www.my-site.com/.well-known/acme-challenge/<long-string>:
<long-string>.<other-long-string>

Step 2: Upload static file

Before you continue, you must configure your server at heroku such that it returns the given string for the given URL. If you are using rails you can put a file in the public directory and it will be served statically:

$ mkdir -p public/.well-known/acme-challenge/$ echo "<long-string>.<other-long-string>" > public/.well-known/acme-challenge/<long-string>

The same principle applies for other types of serving software. Put that file in your public or similar directory (or configure a route in your application to serve this file). After you’ve put the static file in place, commit the changes and push them to heroku.

This step also requires that you have your custom domain (in the example above we are using www.my-site.com) set up at heroku. If you haven’t done this yet, you’ll need to do so before you can continue. This involves telling Heroku about the custom domain and setting a DNS CNAME record. See Heroku’s docs on custom domains for more details.

At this point you should be able to visit the url that certbot displays (e.g.: http://www.my-site.com/.well-known/acme-challenge/<long-string>) in your browser and see the correct string of text. When that is the case, hit enter and let certbot verify that you control this domain.

If all goes well you will see:

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/www.my-site.com/fullchain.pem. Your
cert will expire on 2017-04-12.

Step 3: Upload cert to heroku

Now, upload the certificate and private key to heroku. The heroku command-line tool will do this for you. Copy and paste the following command, replacing the domain name for the one you are using.

The command requires two arguments: the path to your certificate and the path to your key:

heroku certs:add path/to/cert path/to/key

Certbot will have placed both files in /etc/letsencrypt/live, so copy and paste the command below, replacing the bold text for the domain name you are using (same name, including ending “.com” or other tld, that you entered in the first step of generating the cert):

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

After heroku accepts the uploaded cert, you are all set! Visit https://yourdomain.com and bask in the glory of the green lock icon.

Before you go, remember to take note of the certificate expiration date and add a reminder so that you don’t forget to renew it. The command to renew your cert is:

sudo certbot renew --manual

Links

Some other links worth reading:

Did these steps work for you? Are you now running your site over https? Please let me know in the comments. If you’d like to see our follow-up blog posts about the web app we are building, follow me or 201 Created.

--

--

Cory Forsyth

Lifelong learner and technologist, based in NYC. Engineer @ Addepar, formerly co-ran Ember consultancy 201 Created.