HOWTO setup SSL with Rails & Heroku

Setting up SSL is fiddly, confusing, and something a lot of developers struggle with. It’s also critical for creating apps that are secure and which protect the privacy of users. This guide will show you how to setup SSL for a Rails application on Heroku.


You’ll need to setup SSL if you have an app which deals with passwords, credit card details, or any other kind of sensitive/confidential data. Even if you’re using Stripe for your payments, you’ll need SSL.

The primary benefit for your users is that SSL encrypts the data they are sending to your servers. Without this encryption the data will be sent “in the clear”, freely available to be read by anyone on the same network.

One excuse for not setting up SSL is that the login system you built is only for a handful of users. This is professional negligence. Even if you only have a small number of users, you should be using SSL to protect their passwords over the network (as well as encrypting passwords at the database level). Otherwise you are putting your users and any organizations or businesses they are affiliated with at risk.


Step 1: Purchase an SSL certificate

First you need to acquire the SSL certificate itself. The exact steps vary depending on what tools you are using and who you are buying the certificate from, but you’ll typically need to generate a private key, then generate a Certificate Signing Request which you submit when buying the certificate.

Step 2: Upload your certificate bundle & private key

Next you’ll need to upload your SSL certificate bundle and your private key to Heroku. The certificate bundle combines your certificate with some other certificates to form a chain of trust between your certificate and a root certificate. Some certificate providers will give you an option for downloading the bundle, but not all. If you need to create the bundle yourself, use the unix cat command to join the certificate files together. Something like this (the naming of these files will vary):

$ cat example_com.crt Inter.crt AddTrustExternalCARoot.crt > bundle.crt

Upload your certificate bundle and private key using the heroku certs:add command:

$ heroku certs:add bundle.crt server.key

After uploading your bundle and key to Heroku, verify that everything is configured correctly. The output of the heroku certs command should show that the certificate is trusted, and the output of the heroku certs:info command should show that the certificate is verified by a root authority.

Step 3: Update your DNS

Once you have SSL configured correctly on Heroku you’ll need to update the DNS for your website subdomain to route traffic to the app. The exact details depend on your DNS provider, but you’ll need to add a CNAME record for your subdomain, pointing at the herokudns.com subdomain given to you by Heroku.

Step 4: Configure your Rails app

This is where it gets Rails specific. As well as setting up the endpoint and routing traffic to it, you also need to configure your app appropriately. As of Rails 3.1 you can enable site-wide SSL by adding a single line to your production config:

config.force_ssl = true

This will make sure all requests to your app are sent securely over SSL, as well as setting Strict-Transport-Security headers and marking cookies as secure. Deploy your app and you should be ready to test it out.

Step 5: Secure your assets

Now that your app is secure you’ll need to make sure all assets are requested securely to avoid browsers displaying mixed content warnings. If you are serving static assets from your app you might not need to change anything, but if you are serving your assets from an external host or CDN you need to make sure those assets are requested over SSL.

Using “protocol independent” URLs when manually coding references to assets in your HTML will make this easier. For example, if you are linking to the CDN hosted jQuery, you might have markup like this in your layouts:

<script src="http://code.jquery.com/jquery-2.1.0.js"></script>

When content like this is accessed over SSL you’ll see mixed content warnings in some browsers. The fix is simple, just drop the protocol from the beginning. For example:

<script src="//code.jquery.com/jquery-2.1.0.js"></script>

The external resource will then be requested with whichever protocol the page was requested with, i.e. either https or http. So it’ll work just fine with or without SSL.


Some additional tips

Familiarise yourself with the Heroku SSL dev center article which covers a lot of the details, including more detail on generating private keys and certificate signing requests.

When using SSL to protect a login system you should be using it site-wide, not just for a single page. So if you have a “public” website with some additional functionality protected by a login system (e.g. a blog with an admin interface), host the additional functionality separately on a different subdomain and protect that with SSL.

Don’t forget to renew and re-upload your SSL certificate before it expires!