As all of you know, hooking up custom domain with cloud services can be pain it the butt. Long story short, it’s because whole idea of cloud (computing, hosting, whatever) is flexibility pushed to the boundaries. Scaling up and down, dynamic adding and removing resources when necessary, so in the end you are simply unable to point your finger at specific server in server room and say – “Here. This box is running my app.”. And forget about stable IP address. Or better – forget about IP address at all, cause your resources are spread on multiple boxes in multiple locations. At standard, heroku will give you with semi-static url to your app. That’s it.
On the other hand, custom domains and whole DNS system is almost as old as whole Internet concept, and are all about persistence. You want to be able to point your finger and know what is where. You have to set your A or AAAA record to specific IP address. And you can’t point A record to heroku provided subdomain – it’s against the spec, and simply won’t work.
So how to combine those two worlds? Simplest way is to use DNS record called CNAME which is basically an alias to other (canonical) domain/subdomain (ex. provided by heroku for your app). This works just fine with domains like blog.myapp.com, but what when we want our app to be available under myapp.com? Bummer, you can’t – again it’s, against the spec. You can’t use CNAME to resolve apex/root domain.
What to do when DNS spec is as old and outdated as author of this post? Well, just ignore the part that says “you can’t do it” and choose DNS provider that thinks the same. It’s called “CNAME flattening” and it’s awesome and easy to use feature, done automatically by Cloudflare.
You will need:
- Custom domain
- Heroku account with app running (I was dumb and lost some time because i was trying to point to empty app this placeholder page you see after creating a new one – which seemed to be a good idea at the time, and believe me, it isn’t)
- Cloudflare account with domain hooked up (just register there, and point your domain to DNS addresses provided by them)
Go to your heroku account, select app from dashboard and go to settings. Under “Domains and certificates” you will find a “Add domain” button. Just click it and type your domain name. You will see that new domain will appear with DNS target looking like: myapp.com.herokudns.com
If you prefer to use heroku CLI you can use domains command. ex. > heroku domains:add myapp.com # add domain > heroku domains # display domains connected to your app
DNS target is, well, the target for your DNS server obviously.
Go to your Cloudflare account and select DNS button from top menu. In the form for adding new records, select CNAME, type your domain name into Name input, and myapp.com.herokudns.com in Domain name input. It might look a bit confusing, but that’s how the CNAME record works – domain name is the canonical name to which your alias will be resolved.
Depending on when you have pointed your domain to Cloudflare name servers it may take up to 24 hours to propagate. After some time, you can check if it works, and if you have app running it should.
If you left default heroku page with “There is nothing here, yet”, you will see cloudflare error. It’s because this default page isn’t returning http status 200 (it’s just fancy looking 502 ‘bad gateway’ error), despite it looks like valid html. After you start your app it should be fine.