How do I set up DNS for an apex domain (no www) pointing to a Heroku app?
(Note: root, base, apex domains are all the same thing. Using interchangeably for google-foo.)
Traditionally, to point your apex domain you'd use an A record pointing to your server's IP. This solution doesn't scale and isn't viable for a cloud platform like Heroku, where multiple and frequently changing backends are responsible for responding to requests.
For subdomains (like www.example.com
) you can use CNAME records pointing to your-app-name.herokuapp.com
. From there on, Heroku manages the dynamic A records behind your-app-name.herokuapp.com
so that they're always up-to-date. Unfortunately, the DNS specification does not allow CNAME records on the zone apex (the base domain). (For example, MX records would break as the CNAME would be followed to its target first.)
Back to root domains, the simple and generic solution is to not use them at all. As a fallback measure, some DNS providers offer to setup an HTTP redirect for you. In that case, set it up so that example.com
is an HTTP redirect to www.example.com
.
Some DNS providers have come forward with custom solutions that allow CNAME-like behavior on the zone apex. To my knowledge, we have DNSimple's ALIAS record and DNS Made Easy's ANAME record; both behave similarly.
Using those, you could setup your records as (using zonefile notation, even tho you'll probably do this on their web user interface):
@ IN ALIAS your-app-name.herokuapp.com.
www IN CNAME your-app-name.herokuapp.com.
Remember @
here is a shorthand for the root domain (example.com
). Also mind you that the trailing dots are important, both in zonefiles, and some web user interfaces.
See also:
- Doing DNS right with Heroku
- Avoiding Naked Domains and DNS A-records
Remarks:
Amazon's Route 53 also has an ALIAS record type, but it's somewhat limited, in that it only works to point within AWS. At the moment I would not recommend using this for a Heroku setup.
Some people confuse DNS providers with domain name registrars, as there's a bit of overlap with companies offering both. Mind you that to switch your DNS over to one of the aforementioned providers, you only need to update your nameserver records with your current domain registrar. You do not need to transfer your domain registration.
To point your apex/root/naked domain at a Heroku-hosted application, you'll need to use a DNS provider who supports CNAME-like records (often referred to as ALIAS or ANAME records). Currently Heroku recommends:
- ALIAS at DNSimple
- ANAME at DNS Made Easy
- ANAME at easyDNS
- ALIAS at PointDNS
- CNAME at CloudFlare
Whichever of those you choose, your record will look like the following:
Record: ALIAS
or ANAME
Name: empty or @
Target: example.com.herokudns.com.
That's all you need.
However, it's not good for SEO to have both the www version and non-www version resolve. One should point to the other as the canonical URL. How you decide to do that depends on if you're using HTTPS or not. And if you're not, you probably should be as Heroku now handles SSL certificates for you automatically and for free for all applications running on paid dynos.
If you're not using HTTPS, you can just set up a 301 Redirect record with most DNS providers pointing name www
to http://example.com
.
If you are using HTTPS, you'll most likely need to handle the redirection at the application level. If you want to know why, check out these short and long explanations but basically since your DNS provider or other URL forwarding service doesn't have, and shouldn't have, your SSL certificate and private key, they can't respond to HTTPS requests for your domain.
To handle the redirects at the application level, you'll need to:
- Add both your apex and www host names to the Heroku application (
heroku domains:add example.com
andheroku domains:add www.example.com
) - Set up your SSL certificates
- Point your apex domain record at Heroku using an ALIAS or ANAME record as described above
- Add a CNAME record with name
www
pointing towww.example.com.herokudns.com.
- And then in your application, 301 redirect any www requests to the non-www URL (here's an example of how to do it in Django)
- Also in your application, you should probably redirect any HTTP requests to HTTPS (for example, in Django set
SECURE_SSL_REDIRECT
toTrue
)
Check out this post from DNSimple for more.