2

I have an application running on Heroku in 2 regions, eu and us. Let's say: myapp-eu.herokuapp.com and myapp-us.herokuapp.com.

I would like to setup a geolocation dns that points users to the nearest region when they visit our site at www.myapp.com.

What I've done until now is using Amazon Route 53 to setup 2 CNAME record:

  • www.myapp.com CNAME myapp-eu.herokuapp.com (when the geo is eu)
  • www.myapp.com CNAME myapp-us.herokuapp.com (when the geo is us)

But Heroku does not accept the same CNAME to be used in 2 different apps.

Anyone has successfully setup a geo dns that works with Heroku please?

Thanks!

  • One solution I've found is to use 2 additional servers outside heroku router, in which I would install haproxy. So, I'd have haproxy-eu and haproxy-us that point to heroku apps correspondingly. In each of these proxies, I would modify the host header to by-pass heroku host checking. But it's seem over complicated :). The question now is that whether there is a dns server that support geolocation and host header modification? – passkey1510 Feb 28 '16 at 12:49

1 Answers1

0

I was going to post the solution with HAProxy, which I think I have given as an answer here before (though a search didn't turn it up).

That (or something similar, you could also use varnish or nginx) will be the only viable approach, given the global app namespace limitation of Heroku, since no DNS service can do what you are wanting -- host header rewrites cannot be accomplished with DNS configuration alone. The request will have to pass through a system of some kind that can rewrite the header in flight.

However, you would only need one proxy, not two. Here's why:

If the hostname is myapp.example.com, then configure the US Heroku deployment to simply expect that hostname.

Then don't configure the EU deployment to expect a custom hostname; you'll be using the non-vanity hostname myapp-eu.herokuapp.com.

Route 53 would be configured to return the Heroku endpoint as the answer for US queries, and the proxy endpoint for EU requests. The proxy would rewrite the host header to myapp-eu.herokuapp.com and send the request to the Heroku EU endpoint, but US requests would go directly to the Heroku US endpoint, which would expect the hostname the client is already using.

You could also avoid the proxy and use CloudFront as the proxy, instead. Note that this solution only works with 2 destinations -- US and EU in this case -- due to the global configuration restrictions of CloudFront (only 1 CloudFront distribution can be configured for a given incoming hostname)... but for this solution, 1 is all we need. One destination (US) uses a direct connect and requires no rewrite, while the other destination (EU) proxies through CloudFront and gets a rewrite.

Create a CloudFront distribution. Configure it to expect requests for myapp.example.com. Configure it to use the non-vanity Heroku EU endpoint hostname, myapp-eu.herokuapp.com as its custom origin server, and do not configure it to whitelist the Host header from the original request. Whitelist any other headers you do require. Optionally, disable caching. CloudFront will then rewrite the Host: header from myapp.example.com to the configured Origin server hostname, which would be the EU endpoint.

Then, as before, configure Route 53 to return the US Heroku endpoint CNAME for requests from locations that should go to the US endpoint, but to return the CloudFront dxxxxxxxx.cloudfront.net CNAME for requests from locations that should go to the EU endpoint.

Either way, you'll be paying for transport of the traffic you send to the endpoint that goes through the proxy or CloudFront, so you might want to use that for the endpoint that you expect to see the lower amount of traffic... so you may want to transpose EU and US in the above examples, which arbitrarily assume US would see more traffic, so it routes directly.

Neither of these solutions should add significant round-trip time to requests. If you go the proxy route, you are likely to find that a very small machine, like the t2.micro or t2.nano can handle more traffic that you might expect, since processing a minimal.

Michael - sqlbot
  • 21,988
  • 1
  • 57
  • 81