Greetings :)

Hi, I'm Louis!
I like to code, but I don't do enough of it.

This blog is about trying my best to keep up with the ever evolving stream of technology.

Monday, August 13, 2012

Setting up ssl on heroku

I'm setting up SSL on heroku, and it took a while to work things out, so here's my guide (based on heroku's) on how to setup SSL.

Overview

I'm assuming you're already on heroku and you want https traffic for your own domain name.

You want to add SSL. When you add SSL heroku will give you a new app address e.g. soaringeagle223.herokuapp.com for your https traffic. What you will have to do is point a subdomain to this new app. If you configure your certificate for the naked domain i.e. mycoolapp.com then you will get a warning when you visit https://mycoolapp.com... SO make sure you point a subdomain to the secure app name, or you'll end up buying a new certificate! (more info on why this is a good idea is here).

The other thing to note is that you will have to upload YOUR certificate, and also an INTERMEDIATE authority certificate. Basically there are a few trusted certificate issuing authorities on the internet, and some intermediate issuing authorities. You need to link your certificate to a trusted Root Authority, and you do this via intermediate certificates.

Once you have your heroku app configured and certificate on the server, then you should be able to visit https://mysecuresubdomain.mycoolapp.com - to enforce that everyone ends up on https and not http however, you will need to redirect http traffic to https from within your app code!

Let's get started

Get Certified

  1. Go to www.namecheap.com, and buy an ssl cetificate - I choose RapidSSL single domain (e.g. mysubdomain.myapp.com), as I'm cheap and it works for me ;)
  2. Now in namecheap, click on "My Account" -> "Your Domains/Products" -> "SSL Certificates"
  3. You should have a certificate with a status of "Activate Now" - CLICK to activate and you should be taken to a page where you can enter your 'CSR' key
  4. Now you have to generate a 'Certificate Signing Request' (CSR). There are some instructions on how to do this on heroku. Choose Apache 2 as the server type.

    Assuming you have openssl installed, here's the basics on a linux box (more details at heroku):
    1. openssl genrsa -des3 -out server.orig.key 2048
      openssl rsa -in server.orig.key -out server.key
      
      openssl req -new -key server.key -out server.csr
      
  5. Copy and paste your CSR code into namecheap, leaving out the BEGIN and END bits.
  6. Fill in the rest of the details with namecheap - they will send a verfication email to your admin email address.
  7. Finally, copy the certificates that you receive in your email into a text file (one after the other with the begin/end certificate bits), and save it as 'server.crt'. Ensure you have a new line at the end of the file.

Configure Heroku

  1. heroku addons:add ssl:endpoint --app myapp (this costs money)
  2. heroku certs:add server.crt server.key --app myapp (server.crt, and server.key were created in the previous steps) Heroku will let you know if this was successful or not
  3. heroku certs --app myappname (This will show you your certificate and ssl endpoint info)

Configure DNS

The next step is to point your subdomain to your heroku ssl endpoint.
  1. heroku certs --app myappname (This will show you your certificate and ssl endpoint info)
  2. Now create a CNAME record that points from your subdomain to the ssl endpoint (i.e. set it up via GoDaddy or whoever you bought your domain name from) 

Finally

If you browse to https://mysubdomain.mydomainname.com then you should go there, and see https:// in the address bar. If you get a warning message, then something isn't setup quite right...
You will still be able to access the http version too though... If you want to force users to use https rather than http, then you'll need something in your code to do this redirection.

Here's an example for sinatra based apps:
require 'sinatra'

before '*' do
  if(!request.ssl? && request.host != 'localhost')
    request_url = request.env['REQUEST_URI']
    request_url['http'] ='https' 
    redirect request_url
  end
end

If you found this useful let me know :) also, please let me know if I missed something or if there's an error etc.