Adding SSL to an app hosted at Heroku

[POST UPDATED 9/7/2012 TO REFLECT NEW HEROKU SSL ENDPOINT SETUP]

A friend needed some help adding SSL to their custom-domain-name app hosted at Heroku, and it wasn’t entirely trivial. We found bits and pieces in several places, but never found clear and complete instructions.

I previously recommended rapidssl.com even though their docs are pretty abysmal. $49 for one year for a single-domain certificate, and it took them about 1 hour to generate and email the certificate. However, a year later we bought a rapidssl certificate from cheapssls.com for under $10

Suppose your app domain is myapp.mydomain.com, your

  1. Generate the command that generates the “CSR”

This wizard worked fine and has clear directions on what goes into each field.
https://www.digicert.com/easy-csr/openssl.htm

However, you’ll need to change their default country code from “us” to “USA” the lowercase ‘us’ isn’t correct. Click Generate. That creates the Unix command needed to generate the CSR.

  1. “cd” to whatever directory you want to save your keys in. We put them in the “allmyapps” parent directory of the Heroku app.

  2. Copy the command and paste it onto the command line of your unix shell (we used Mac terminal). It looks something like openssl req -new -newkey rsa:2048 -nodes -out myapp_mydomain_com.csr -keyout myapp_mydomain_com.key -subj "/C=US /ST=Washington /L=Spokane /O=myco inc /CN=myapp.mydomain.com"

  3. that generates a text file called myapp_mydomain_com.csr and one called myapp_mydomain_com.key Copy the .csr file to your clipboard. Type
    cat myapp_mydomain_com.csr
    then copy everything between and including the lines that start —–BEGIN and —–END

Note: Heroku won’t let you have a passphrase in your key file, so don’t add one. Using the command shown, we weren’t prompted for one, so it wasn’t a problem. I have seen blogs that refer to removing the passphrase.

  1. Go to cheapssls.com [ we discovered cheapssls.com resells rapidssl certs at a fraction of the price] and click the button to get a single-domain certificate and choose the rapidssl option for under $10. Select “one year” assuming that’s what you want. Click Continue.

  2. Paste the .csr file you created/copied to your clipboard in steps 3/4 into the big text box and click Continue.

  3. The website will parse the CSR file and display the information encoded in it… be sure you have the domain name right, etc., then click Continue.

  4. Fill out your admin/tech/billing contact info, which unless you’re doing this for a corporation will likely be you in all three cases.

  5. Complete the order process on rapidssl.com. It includes entering a phone number so their automated system can call you to confirm you draw breath. The onscreen instructions are simple. The order process takes maybe a minute or two.

They will give you a list of possible email addresses to send your certificate, receipt, etc. One of them should already work for you (the email contact for the domain name), if not, you have to create a new email address and get it working BEFORE you go any further. In our case, we had to go to Godaddy and create a postmaster@mydomain.com forwarding address since we could not get email at any of the choice listed.

  1. After 49 minutes (in our case) rapidssl.com emailed our certificate. Two actually… one is a ‘chain’ certificate which we deal with soon.

  2. You need to take the certificate text from the email and save it into a .CRT text file in the same directory you used earlier. I suggest using the same naming convention as the CRT generator used, so you’d
    (a) copy to your clipboard the FIRST certificate text (including those begin/end dashed lines) then
    (b) type into your unix shell: cat > myapp_mydomain_com.crt then Enter
    (c) paste the certificate text then
    (d) hit Enter then
    (e) press control-D to terminate the file.
    Verify it: At the command prompt type cat myapp_mydomain_com.crt (NO > this time) and verify the file got created correctly.

  3. Do the same thing for the intermediate ‘chain’ certificate (the second certificate in the email from rapidssl) using cat > myapp_mydomain_com_<b>chain</b>.crt

  4. There is NO step #13. It’s bad luck.

  5. Now create the .PEM file. Near as I can tell, it simply has your main .crt, then your chain .crt file appended to each other in that order. Here’s the sequence of commands we used:

openssl x509 -in myapp_mydomain_com.crt -out myapp_mydomain_com.pem

openssl x509 -in myapp_mydomain_com_chain.crt >> myapp_mydomain_com.pem

  1. You need to enable the SSL ENDPOINT addon with: heroku addons:add ssl

  2. Now, finally, you get to use the heroku gem to schlep the key etc over to your heroku app. That means (which I never saw documented) you need to cd into the directory with your heroku app. In our case that’s one directory “down” from where we’ve been working… which measn onc ein that directory when we refer to the .key or .pem file we need ot point ‘up’ 1 directory… In your case, adjust the path to the .key and .pem files according to where you store them.

heroku certs:add ../ssldir/myapp_mydomain_com.pem ../ssldir/myapp_mydomain_com_chain.key

  1. Heroku instantly displays a message telling you to add a CNAME to your DNS that points to some long name similar to appid-1234.herokussl.com

Since the CNAME already existed in his DNS, we edited it, changing it form proxy.heroku.com to the long domainname they specified.

  1. A few minutes later, it was all working… going to https://myapp.mydomain.com worked fine, no certificate warnings, etc. (DNS can take a while to propagate, but I’ve found it usually happens within 5 minutes.)

FINAL TIP: you may need to reboot your PC (or flush your dns cache) for your PC to “see” the new DNS settings because the old settings (proxy.heroku.com) are probably cached on your PC. On a Mac OSX 10.5 you’d typedscacheutil -flushcache then type host myapp.mydomain.com to see if the DNS changes have taken effect.