Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Setting up Heroku Hostname SSL with GoDaddy SSL Cert
How to setup Heroku Hostname SSL with GoDaddy SSL Certificate and Zerigo DNS
Heroku recently added an exciting new 'Hostname SSL' option. This option offers the broad compatibility of IP-based SSL, but at 1/5 the price ($20 / month at the time of this writing).
The following tutorial explains how to use Heroku's new 'Hostname SSL' option on your Heroku project. Before we begin, let's list what we're using here:
* Heroku Hostname SSL
* GoDaddy Standard SSL Certificate
* Zerigo DNS
Note: I am not using the Heroku Zerigo DNS add-on, instead I have a separate Zerigo account for my DNS needs. I do this because Zerigo offers 30 hosts on free direct accounts, versus only 10 hosts on the free Heroku add-on.
I. Getting a GoDaddy SSL Certificate (Part I)
1. Purchase a GoDaddy Standard SSL Certificate
GoDaddy sells Standard SSL Certificates for anywhere from $12.99/year to $49.99/year. I highly recommend you do a search for 'cheap ssl' on Google and see if there are any advertisements for discounted GoDaddy Standard SSL Certificates. I was able to buy my certificate for $12.99/year this way.
2. After you complete your purchase, GoDaddy will give you a credit that you can trade for a certificate. Make the trade and click on 'Manage Certificate' next to your new certificate. This will bring you to a Credits control panel where we will click 'Request Certificate' next to your new certificate later on when we are ready to setup your certificate.
II. Creating a Certificate Signing Request (CSR)
Note: To create an SSL certificate, you must first generate and submit a Certificate Signing Request (CSR) to the Certification Authority (CA) (i.e. GoDaddy). The CSR contains your certificate-application information, including your public key. The CSR will also create your public/private key pair used for encrypting and decrypting secure transactions.
These instructions are based on my experience using a Mac OS X laptop. The following probably won't work if you are not working from a unix-based system (i.e. Mac OS X / Ubuntu Linux / etc.).
Steps to create a CSR:
1. Make a new directory to hold your project's SSL-related stuff. It doesn't really matter where you put this, but I recommend not putting it in your rails project (i.e. alongside app, config, db, etc.), as it will get included in your git repository if you do. Rather, I put it in a folder that is one level above my rails project.
mkdir ssl-cert
2. Move to your newly created folder
cd ssl-cert
3. Use OpenSSL to generate an RSA host key ('host.key') using the triple DES encryption, with a 2,048-bit key length (as required by GoDaddy). Triple DES is just DES times three, but is more secure against brute force attacks because of its longer length.
openssl genrsa -des3 -out host.key 2048
It will ask you for a pass phrase. This should be a secret password. Don't forget the pass phrase you set, as we will need it later.
4. Use OpenSSL to generate a new self-signed certificate ('host.csr') using the host key we just created. This is what you'll be sending to GoDaddy to model your new SSL after.
openssl req -new -key host.key -out host.csr
You will be prompted with a bunch of questions. Answer all of them, except the last two 'extra' attributes are optional. Here are example responses:
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:California
Locality Name (eg, city) []:San Francisco
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Your Company Name
Organizational Unit Name (eg, section) []:secure.yourdomain.com
Common Name (eg, YOUR name) []:secure.yourdomain.com
Email Address []:contact@yourdomain.com
Please enter the following ‘extra’ attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
It is very important you don't mistype anything here, as you can't change this information without buying a new SSL certificate. 'Organizational Unit Name' and 'Common Name' must be the hostname you are using on Heroku. I highly recommend using the 'secure.yourdomain.com' host, as you will need to set a separate CNAME DNS record to route your secure traffic.
III. Getting a GoDaddy's SSL Certificate (Part II)
1. Return to where we left off with GoDaddy. You should have clicked 'Request Certificate' and see a form where you need to answer the following questions:
Where is your certificate going to be hosted? Third Party
Enter your Certificate Signing Request (CSR) below: [copy contents of 'host.csr' here]
Select your certificate issuing organization: GoDaddy
Is this certificate for Intel vPro? No
2. Verify everything and then click through to finish. You should now be able to view and download your GoDaddy SSL certificate from GoDaddy from the 'Manage Certificates' section.
IV. Prepare SSL Certificate for Heroku
1. Download your new SSL certificate from GoDaddy's website into your 'ssl-cert' directory that we created in step I. You will get two files from GoDaddy: 'secure.yourdomain.com.crt' and 'gd_bundle.crt'. 'secure.yourdomain.com.crt' is your new SSL certificate. 'gd_bundle.crt' contains the SSL issuing certificate chain back to the root SSL certificate.
2. Combine 'secure.yourdomain.com.crt' and 'host.key':
cat secure.yourdomain.com.crt host.key > host.pem
3. Remove pass phrase from the public key certificate (required by Heroku)
openssl rsa -in host.pem -out nopassphrase.pem
openssl x509 -in host.pem >>nopassphrase.pem
You will be asked for the pass phrase you set in step I. I told you to remember it!
4. Open 'nopassphrase.pem' in a text editor and delete the 'private key' section:
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
5. Combine 'gd_bundle.crt' and 'nopassphrase.pem':
cat nopassphrase.pem gd_bundle.crt > public.pem
'gd_bundle.crt' is a chain file that links your certificate to a original trusted host certificate that GoDaddy owns.
6. Remove pass phrase from the private key certificate (required by Heroku)
openssl rsa -in host.key -out private.key
You will be asked for the pass phrase you set in step I. I told you to remember it!
You might be asking yourself: What do all of these file extensions mean? Well, here you go:
*.csr -- Certificate Signing Request used for submission to signing authorities that issue SSL certificates
*.crt -- Public key of a certificate (same as a *.pem file, but with different extension). May include a chain of certificates back to the host certificate. This is what you'll get from GoDaddy when you download a purchased certificate.
*.pem -- Public key of a certificate (same as a *.crt file, but with different extension). May include a chain of certificates back to the host certificate. This is what you'll get from GoDaddy when you download a purchased certificate.
*.key -- Private key of a certificate
V. Add SSL Certificate to Heroku
1. Go to the root of your Heroku project folder and add the nopassphrase pem and key to Heroku:
heroku ssl:add ../ssl-cert/public.pem ../ssl-cert/private.key
You may need to adjust the paths to point to your 'nopassphrase.pem' and 'nopassphrase.key' files.
2. If you haven't done so already, you must enable the Heroku custom domains add-on and add 'secure.yourdomain.com' to Heroku's list of domains:
heroku addons:add custom_domains:basic
heroku domains:add secure.yourdomain.com
3. Next, you need to add Heroku's 'Hostname SSL' solution:
heroku addons:add ssl:hostname
This will add a $20/month (as of the time of this writing) fee to your Heroku bill for SSL.
VI: Setting up your DNS to work with Heroku Hostname SSL
1. You should recieve an email from heroku within a few minutes of adding the ssl:hostname addon. You need to add a CNAME record to your DNS that points to the AWS host in the email you receive. This should be pretty self explanatory, but if you have any questions, search for 'adding a CNAME record' in Google and you'll see lots of good guides.
2. Test that 'host secure.yourdomain.com' outputs 'something.amazonaws.com'. If it does, you're all set.
You should now be able to go to 'https://secure.yourdomain.com' and not see any errors or security warnings.
What is going on behind the scenes
When a user visits your site using 'https://secure.yourdomain.com', they're hitting your GoDaddy CNAME record, which points to an 'something.amazonaws.com' address which effectively routes the request to Heroku's grid, and a secure connection gets established from there following the standard SSL handshake process.

imderek commented Jul 12, 2012

Well, this certainly got me out of a jam :)

This has been invaluable to me. The only thing I'd add is that in Step VI 1, another way to get the host for the SSL server is to use

heroku certs --app your-app-name

We user my CEO's GoDaddy account, so I personally never received the email about the SSL certificate, and had to find that host myself. I'm not sure why it's not listed anywhere in the app info in the Heroku site itself.

Thanks!

Thanks a ton. This is very helpful.

One question though. The only issue I seem to be having is getting an untrusted certificate warning when using Firefox. It sounds like an intermediate certificate needs to be added for Firefox to recognize Godaddy's certificate.

Was just wondering if that should have happened in these steps (and I did something incorrectly) or are additional steps needed.

Thanks again!

I agree. Many thanks. This saved many hours of my life.

Great post, helped a lot with generating the CSR and pretty much all the encryption stuff. A few things were different for me however, and just wanted to note them here in case they are different for others as well =).

  1. I don't have my heroku set to have a "default app" I guess, so for example in the 'heroku addons:add custom_domains:basic' I had to append '--app your-app-name-here' after the 'addons:add' part.
  2. To set my cert I used 'certs:add' instead of 'ssl:add', passing the same values however. This is what is listed in the official Heroku SSL docs (https://devcenter.heroku.com/articles/ssl) not sure what the difference is.
  3. And the biggest problem I faced which you also did not encounter, was that not only did I not receive an email from Heroku about any AWS endpoint, I was also not aware that they just automatically changed the endpoint I needed to map to for my app! Wheras before it was accessed using my-app-name.herokuapps.com, after adding the SSL cert it was changed to whatever.herokussl.com. This caused a lot of confusion when I was attempting to set up the CNAME from my domain name to point to the correct spot. So make sure you point your domain at the *.herokussl.com address, and NOT the *.herokuapp.com address.

Thanks again, great post!

nthj commented Apr 3, 2013

heroku ssl:add should be heroku certs:add

https://gist.github.com/nthj/5297916

Thanks for this, it's awesome!

bjrbhre commented Apr 18, 2013

Thanks a lot. You saved me a lot of time.
I confirm that, now, add certificates is done with 'heroku certs:add' as explained on heroku:
https://devcenter.heroku.com/articles/ssl#acquire-ssl-certificate

Thanks a bunch! You got me out of a real jam.

iscott commented Jul 5, 2013

Thanks for posting this! I always DREAD the ssl process, but this made it way easier.
Note: Step V1 is deprecated and gives an error. Thanks @MrJaeger for the updated command.

although heroku has changed their certs process this was still really helpful on navigating the CSR step. thanks

Super helpful! Thank you

Thank you for this detailed guide. I've gone through it carefully several times, and I keep getting the following error:

Resolving trust chain... failed
 !    No certificate given is a domain name certificate.

The domain I'm attempting to use is a Full Qualified Domain Name: www.pointsonpaper.com. (note the period at the end). I entered this domain name because I am under the impression it is necessary. Could my use of a FQDN somehow affect Heroku's acceptance of the SSL certificate? I can't think of any other reason why I'd be getting this error. I've googled around to no avail. Big thanks to anyone who has an idea of how I can get past this!

Thanks a ton for this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment