Building VTS

The Official VTS Engineering Blog

Route53 SSL Naked Domain Redirect

By Karl Baum

In a previous post, I wrote about the “shortcut” we took in configuring our naked domain to point to our Heroku app within Amazon Route 53. To recap, we pointed an A record directly at the IP address of our Heroku application. Unfortunately Heroku application IP addresses tend to change from time to time. This meant that we needed to monitor our naked domain to ensure it was still functioning. We set this up back in January and every now and then over the last 10 months, our root domain would stop working. Each time it would stop working, we would get an alert, and I would dutifully log into the Route 53 console and update the A record to point at the new IP address. Well, for some unknown reason, the IP address changed two consecutive nights and each morning when I awoke, I saw the alerts and had to fix our root domain. I was finally convinced that this “shortcut” was not good enough.

As outlined in this article, Heroku recommends pointing an Alias record directly at an S3 bucket and configuring that S3 bucket to redirect. The problem with this approach is that it does not support SSL. That means that http://vts.com will correctly redirect to http://www.vts.com but https://vts.com will cause the browser to show a security error. Fortunately, instead of pointing our alias at an S3 bucket, we can point it to a cloudfront distribution with our SSL certificate installed. We then can point our cloudfront distribution at Heroku as our origin server. Our application deployed at Heroku can then perform the redirect of https://vts.com to https://www.vts.com.

Upload the SSL Cert

First, we needed to make our SSL certificate available within our Amazon Cloudfront account. We installed the aws command line tool and configured it with our api key and secret. Then we copied the appropriate SSL certificate files into ourcurrent directory, and ran:

1
2
3
4
5
6
aws iam upload-server-certificate \
--server-certificate-name vts_com  \
--certificate-body file://vts_com.crt \
--private-key file://vts_com.key \
--certificate-chain file://vts_com_bundle.pem \
--path /cloudfront/

Create the Cloudfront Distrubution

Once that certificate was uploaded, we then created our cloudfront distribution configuring it to use our certificate. We logged into the AWS console, navigated to cloudfront and clicked the “Create Distribution” button. On the next screen, we clicked “Get Started” under Web. First within the Origin Domain Name, we entered the certificate end point of our app. We found this value by running the heroku certs command. For us, this was vts.herokuapp.com.

1
2
3
4
$ heroku certs -a vts
Endpoint           Common Name(s)      Expires               Trusted
-----------------  ------------------  --------------------  -------
vts.herokuapp.com  *.vts.com, vts.com  2016-01-08 23:59 UTC  True

Under “Origin Protocol Policy”, we picked “Match Viewer”. If you forget this, you’ll end with infinite redirects when trying to hit your apex domain under ssl.

Origin Settings

For forward headers and forward cookies, we clicked “All”. This cloudfront distribution will not cache anything but that’s ok. We want all requests to pass straight through to our application.

Default Cache Behavior

For forward query strings, we picked yes. This will ensure that the full url will be redirected properly. For example, if the browser requests:

1
https://vts.com/foo?bar=true

This should redirect to:

1
https://www.vts.com/foo?bar=true

Without query carrying over the query string, we’d have have the foo but no bar.

Under “Alternate Domain Names”, we entered in our naked/root/apex domain vts.com

Query and Alternate

For SSL Certificate, we hit the “Custom SSL Certificate (stored in AWS IAM)” radio button and picked our certificate from the dropdown. This was “vts_com” for us.

Under “Custom SSL Client Support”, we selected “Only Clients that Support Server Name Indication (SNI)”. Browser support should not be an issue unless your users are running IE6.

SSL Config

Everything else was left default and we clicked “Create Distribution”. The cloudfront distribution should take around 15 minutes to become “Enabled”.

Alias from Route 53 Naked Domain

Now that the Cloudfront distribution routes requests to our application on Heroku, we need to create a Route 53 alias that points at the cloudfront distribution. From the aws console, we navigated to Route 53 and then our vts.com hosted zone. From there we created a new A record for vts.com. We picked “Yes” under Alias and selected our Cloudfront distribution under Alias Target. Everything else remained the same and we clicked “Create”.

Route 53 A Record

The Redirects from your App

All that is left now is that we need to make sure we were redirecting https://vts.com to https://www.vts.com. We are using rails 3 and we have something like this within our routes.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
def query_params_to_query(request)
  query_params = request.params.except(:path, :format)
  query_params.any? ? "?#{query_params.to_query}" : ""
end

#redirect apex http://viewthespace.com http://vts.com domain to www.vts.com
constraints(host: %r{^vts.com}) do
  redirect_action = ->(params, _request) do
    "https://www.vts.com/#{params[:path]}#{query_params_to_query(_request)}"
  end
  root to: redirect(redirect_action)
  match '/*path', to: redirect(redirect_action)
end

Summary

Summary of our Route 53 Alias record setup

Route 53 does not allow you to point your root domain at a CNAME. In order get this done and support SSL, we used a route 53 Alias to a cloudfront distribution which directed traffic to our VTS application which redirects the root domain vts.com to the www.vts.com subdomain.