Redirecting a WWW Subdomain on AWS

Posted by Niky Morgan on February 25, 2018

While the instructions for redirecting a www subdomain to the apex (base) domain on an AWS-hosted site may not encompass many steps, I had to employ a fair amount of googling and testing in order to get this working on my site. My website is nikym.org, and I wanted to ensure that any requests to www.nikym.org redirected to nikym.org. Furthermore, I wanted any requests to an HTTP version of the site to redirect to the HTTPS version.

Redirecting to HTTPS makes sense because it is a more secure connection. Data passed between the client and the server is encrypted, which mitigates at least some security issues. Search engines and browsers both are doing what they can to promote HTTPS over HTTP. Google gives a search ranking boost to HTTPS sites and there is also a speed increase with HTTPS.

Redirecting a www subdomain to the apex domain can also help boost search rankings because it consolidates the search results to one domain. It is also just good practice to have a canonical URL to use consistently across the site. It helps search engines decide which link to the site to display, a process called URL canonicalization. There are different opinions about whether a naked domain is preferable to a www URL. A naked domain is simpler for users, but for a scalable application a www domain gives the flexibility of using a CNAME record to redirect traffic.

My goal is simplicity, so I like the look of the apex domain. When I first moved my site to AWS, I followed a combination of blogs and instruction pages. While I thought I had a redirect setup for my www subdomain, I didn’t realize until recently that this wasn’t the case. I had another mistake in a different AWS service which made it appear as if the redirect was working (compensating errors). My settings resulted in the right assets being served to the www domain, but it was actually circumventing the redirect so the URI was not changing.

Per Amazon’s instructions, to create a static site requires two S3 buckets to store assets. One bucket named after the apex domain holds the assets (nikym.org in my case) and has a public view policy. The second bucket (www.nikym.org) is empty, but has a setting under Properties which specifies to redirect all requests to the apex domain. (After experimenting I established that the empty bucket does not need to be public in order to redirect.)

Route 53 is the AWS DNS service. The domain’s hosted zone needs to have A records for the apex and www subdomain which point to their respective S3 buckets. If the A record shares a name with an S3 bucket, then the S3 bucket should automatically show up as an option in the Alias Target dropdown for the A record.

For a static website that consists of Route 53 and S3, this is enough to create a working redirect. Route 53 will direct all www domain requests to the www bucket which has already been setup to redirect to the apex domain. However, my situation was more complex because I was using a Cloudfront distribution. When Cloudfront is involved, Cloudfront connects to the S3 bucket (so it can distribute its assets) and Route 53 then connects to the Cloudfront distribution for that bucket instead of the bucket itself.

Cloudfront makes troubleshooting this issue more complex because it can take time to create a new distribution and update existing distributions. Updating DNS records can also take up to 30 minutes, so testing any changes becomes a long process.

After searching the forums and blogs, I tried adding a CNAME record for the www subdomain which pointed to the apex. With a CNAME I could specify that one domain resolve to another, but it didn’t go through a redirect.

When I directly accessed the www S3 bucket through its endpoint, the redirect worked as expected. That meant something was going wrong before a request hit my bucket: the request to www.nikym.org was probably never even hitting my bucket. With that discovery, I checked Cloudfront next. Cloudfront was the intermediary between my assets and the DNS service, so I tried removing pieces of the puzzle until the behavior changed.

After a few tries I found success. While reading the AWS documentation I had misunderstood and set up my apex and www domains as alternate domain names on the same Cloudfront distribution. On Route 53 the A records for my apex and www domains had the Alias Target of this shared distribution. The assets in my apex domain S3 bucket were getting distributed to both domains. I was right that I was never even hitting the www bucket. I removed the www domain from the apex Cloudfront distribution and created a separate distribution pointing to its own S3 bucket. Now I could update the A record for my www domain on Route 53 to the new Cloudfront distribution. With that piece in place, the redirect worked as planned.

The overall application flow is as follows. User makes a request to www.nikym.org. Through the DNS process this request gets sent to Route 53 which passes this traffic onto the www Cloudfront distribution. From there it hits the S3 bucket and receives notice to redirect to the apex domain. This info is sent back to the user’s computer which makes a new request to nikym.org (which the user may not even notice). This request gets sent to Route 53 and routed to the apex Cloudfront distribution. Then it gets sent to the apex S3 bucket which responds with the assets for the webpage. Phew, what a trek!