Enable SSL with Heroku for https access

For rstat.us, we’ve been meaning to enable ssl/https for a long time. I’m pleased to announce that we’ve finally gotten around to it, and everything seems to be working now!

What was the hold up? On heroku (where we started hosting rstat.us, then we weren’t, now we are again), it used to cost $100/mo for the ssl hostname addon. I love rstat.us, but not that much. Recently, however, heroku came out with the SSL Endpoint addon which is only $20/mo. This is much more within my budget :)

I also wanted to make sure that the Certificate Authority we went with was in line with rstat.us’ values. This is a project that started on the values of openness and simplicity, so I agonized a bit over our choice of CA. We ended up going with a free certificate from StartSSL for the reasons I mentioned in that thread.

Once you have a certificate, the instructions for the SSL Endpoint are pretty good. There are a few places that I either had issues with or think could use some further clarification:

Intermediate certs

In the SSL endpoint docs, there’s a part that says “If you have uploaded a certificate that was signed by a root authority but you get the message that it is not trusted, then something is wrong with the certificate. For example, it may be missing intermediary certificates.” This doesn’t say what you need to do to add the intermediary certificates that you may be missing.

Some certificate authorities will have intermediate certificates that have to be included in your .crt file. The “Purchasing an SSL Certificate” heroku docs explain how to cat your certificate with a root certificate. If you have an intermediate certificate file as well, first cat your certificate as they show in the instructions, then cat the intermediate certificate, then cat the root certificate. I figured this out by trying it and it worked, but I felt unsure since the docs from heroku and the CA didn’t explicitly say what order they should go in.

Add vs Edit CNAME

This may be obvious to everyone but me, but I thought I’d mention it anyway in case someone else has the same brain fart I did. The SSL endpoint docs say “Next, add a CNAME record in the DNS configuration that points from the domain name that will host secure traffic e.g. www.mydomain.com to the SSL endpoint hostname, e.g. tokyo-2121.herokussl.com.”

So I did exactly that– added a CNAME record. But we already HAD a CNAME record for www.rstat.us since we had already followed the heroku custom domains instructions. And CNAMES aren’t additive, hah. So yeah, if you already have a CNAME for the domain name you’re trying to enable ssl with, just edit that one.

Naked domain

This is the part I struggled with for a week. I got SSL all working for www.rstat.us according to the SSL endpoint docs– https://www.rstat.us worked great! I also had a 301 URL Redirect set up in our DNS records with NameCheap to redirect the naked domain rstat.us to www. This may be unpopular, but naked domains can’t be CNAMES and using A records for the naked domain is highly discouraged for availability reasons (see the naked domain section).

However, 301 redirects don’t care about the protocol– if you go to http://rstat.us, it redirects you to http://www.rstat.us, and if you go to https://rstat.us it (supposedly) redirects you to https://www.rstat.us. What I was seeing, though, if you went to https://rstat.us, was that the SSL handshake would just hang. This was very visible when doing a `curl -v https://rstat.us` on the command line– it would just get to the SSL handshake and wait forever.

The certificate was good for both rstat.us and www.rstat.us, so that wasn’t the problem. It looks like an ordering issue to me (correct me if I’m wrong)– request https://rstat.us, do the SSL handshake since it’s SSL, and THEN do whatever the DNS says to do– but the CNAME with www that makes SSL work is AFTER the 301 redirect specified in the DNS settings for the naked domain.

Heroku’s documented solution to this is “only circulating and publicizing the subdomain format of your secure URL.” It is left as an exercise for the reader to determine why this is an unacceptable solution.

Not mentioned in that page, but linked in its references, is a blog post by DNSimple introducing ALIAS records. This is something that, as far as I can tell, only DNSimple has implemented, and it basically turns a CNAME into an A record behind the scenes without any need for user intervention should the IP addresses that the CNAME resolves to change.

This StackOverflow question confirmed that the DNSimple ALIAS record would solve the problem I was having– so I set up a DNSimple account ($3/mo for up to 10 domains at the moment, but use my referral link and we both get a month free!</shameless-rstatus-promotion>), set up the following records:

ALIAS 	rstat.us 	www.rstat.us
CNAME 	www.rstat.us 	toyama-8790.herokussl.com

and changed the settings with NameCheap, where we have rstat.us registered, to use DNSimple’s DNS instead of NameCheap’s. Indeed, the ALIAS record magically makes all variations of http/https and naked domain/www work as desired!

Can I have my devops merit badge now?

This entry was posted in devops, hosting, ssl. Bookmark the permalink.

10 Responses to Enable SSL with Heroku for https access

  1. Anthony Eden says:

    Nice, well written, post Carol. If you don’t mind I think I’ll take what you’ve written up here and turn it into an FAQ question and answer in the DNSimple knowledge base.

    Regarding the URL forwarding not handling SSL, the reason is that a URL forwarding is not really a DNS record type, rather it is produces one or more A records which point to an HTTP server. The HTTP server is then responsible for issuing the 301 redirect when it receives HTTP requests. In order for an HTTP server to respond to SSL requests you would need to have your SSL certificate and private key on the server since it is the HTTP server that negotiates the SSL connection. It is impractical to have a shared URL forwarding server that allows customers to upload their SSL certificates, so no one does it (as far as I know).

    • Carol says:

      Hi aeden! Sorry I didn’t notice this comment until just now– that would be awesome if you use this in the DNSimple kb!

      And thank you for the extra details!

  2. Colin Dean says:

    <3 DNSimple. Any person willing to run their own DNS server should just spend the 1 beer/month to let DNSimple handle it. I'd figured out BIND pretty well in the ~8 years I've been using it, but dealing with it had always been painful with no end to the pain in sight.

    They also have a great API and already have a gem:

    https://github.com/aetrion/dnsimple-ruby

    (Unless of course there’s a serious security reason not to use a hosted DNS solution)

  3. Thanks for figuring out what to do with intermediary certificates. Heroku needs to add that to their documentation!

  4. Apparently, if you install the heroku SSL doctor plugin, you can just do:

    heroku certs:add path/to/my/certs/and/key/files/*

    and it will figure out how to upload everything for you without having to concatenate any files.

  5. Billy says:

    Hi Carol,

    The part about adding versus editing the CNAME was (is) very unclear on heroku’s side. Thanks for clearing that up!

    Billy

  6. Pingback: StartSSL certificate with a Heroku app « C Sharp solutions

  7. Thank you Carol!

    I thought this would be much more difficult. The documentation at Heroku is not quite clear about setting up SSL for the bare domain, so I was surprised that it’s as simple as that.

  8. Lori says:

    Hello Carol,
    Thanks for the post. Ive been struggling with this issue. I’d really like to have http://hillarykeel.com display in the address bar without the redirect to http://www.hillarykeel.com displaying when the user types in hillarykeel.com (a herokuapp). Im having the same problem with another domain I bought (both from Namecheap) where I have URL Redirect to an existing site with a Canadian host. What am I doing wrong? Namecheap has CName(Alias) as an option. Is the dnssimple system any different, apart from a prettier user experience for a newbie? Would it be better for me to change the nameservers? Is the temporary, free Namecheap hosting causing the unpredictable results?

  9. Lori says:

    Of course, today it’s working fine….but maybe the last portion of my previous post:

    Namecheap has CName(Alias) as an option. Is the dnssimple system any different, apart from a prettier user experience for a newbie?

    Is still something I’m wondering. Maybe you could post that and not the previous. Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>