This is my comprehensive guide on how to implement a fast and efficient redirect from a naked or root domain to a www subdomain (eg redirect example.com to www.example.com), or vice versa.

So we will also consider the opposite, ie redirect www domain to non-www if thats what you want instead (ie redirect www.example.com to example.com) .

We will be using Amazon Web Services (AWS) by setting up Route 53, Cloudfront and S3 to redirect root domain to www.

So if you’re looking for a fast and CDN cached way to redirect your Route 53 apex domain, or want to know how to configure a Cloudfront distribution to handle these redirects, this guide has you covered.

Table of Contents

Note on terminology

Apex domains refer to the domain without any subdomain (e.g., example.com).

They are also known as base, bare, naked, root apex, or zone apex domains.

So in this guide, naked, root and apex domain are used interchangeably to mean the same thing.

Redirect with S3 and Cloudfront, or in your application?

Redirecting the apex domain to the www subdomain using AWS infrastructure offers several advantages over handling the redirection at the application server level. Here are some reasons to use AWS infrastructure as per this guide:

  • High Availability: AWS infrastructure is designed for high availability and fault tolerance. By using services like S3 and Cloudfront, you benefit from AWS’s robust infrastructure that is less likely to fail compared to individual application servers.
  • CDN Caching: Cloudfront can easily cache the redirection response, which means that the redirect can be served from a CDN edge location closer to the requester. This results in faster response times and a better user experience.
  • Separation of Concerns: Keeping the redirection logic out of your application simplifies your codebase and reduces the potential for errors. AWS handles the redirection at the infrastructure level, allowing your application to focus on its core functionality.
  • Static Website Compatibility: AWS infrastructure can handle redirects even for static websites, where you might not have control over the application logic. This makes it possible to implement redirects without needing to modify the website’s code or rely on server-side processing.

The Step-by-Step guide

Below is a step by step guide.

By following the steps outlined in this tutorial, you’ll ensure that visitors accessing your apex domain are automatically redirected to the www version of your site, and that that redirect happens as fast as possible.

Let me know if you hit any snags, but I have tested these steps a few times!

What we will achieve

We’ll set up the AWS infrastructure to seamlessly redirect traffic to the www subdomain, ensuring the redirects are fast (by caching them in the Cloudfront CDN).

The end goal is to direct all traffic from the root domain (e.g., example.com) to the www subdomain (e.g., www.example.com).

Additionally, we’ll make sure all http traffic is redirected to https for the root domain.

A note on “redirect chains”

When redirecting a user from their requested domain to the one we want them to visit, it’s best to do so with as few ‘hops’ as possible.

If a redirection takes a user through multiple redirected requests before reaching the final destination, it’s called a “redirect chain”.

By using a website performance analysis tool like Ahrefs Site Audit, any “redirect chains” will be highlighted as areas for improvement.

This guide relies on the S3 static hosting’s ability to always redirect to https so that even http requests to your starting domain will always redirect in 1 hop.

In other words, we avoid http://example.com to https://example.com to https://www.example.com(2 redirects needed).

Instead we aim for http://example.com to https://www.example.com directly .

Prerequisites

To follow this tutorial, you’ll need:

  1. An AWS account
  2. A domain name registered with a domain registrar (I recommend namecheap.com)

Step 1: Configure Route 53 DNS Zone

First, we need to create a DNS zone in Route 53 for our domain. This will allow us to manage the DNS records for our domain within AWS.

  1. Sign in to the AWS Management Console and navigate to the Route 53 service.
  2. Click “Hosted zones”, then click “Create hosted zone”.
  3. Enter your domain name e.g., example.com) in the “Domain Name” field and leave selected “Public Hosted Zone”. Click “Create hosted zone”.

Step 2: Updating Domain’s Name Servers with Route 53

Take note of the four Name Servers provided by Route 53, under the NS record as you will need to update your domain’s nameservers with your domain registrar to point to these.

Any changes to nameservers configuration will need to propagation around the DNS system, which can take some time but typically won’t take too long.

Example: namecheap

On namecheap.com for example, find the domain in the Domain List, click “Manage”, and then this option is available under the “Domain” tab, in the “Nameservers” section. Change the option to “Custom DNS”, and enter the nameservers provided by Route 53 and save the changes with the little green tick. Note, it does not matter if you enter the nameserver host names with the trailing dot or not.

Namecheap custom nameserver configuration

Namecheap custom nameserver configuration

Testing with dig

To verify that your nameserver updates have propagated correctly, you can use the dig command-line tool.

Run the following command, replacing “example.com” with your domain name:

dig NS example.com`

The output should display the updated nameservers provided by Route 53. Keep in mind that DNS propagation can take some time, so if the changes are not reflected immediately, wait a few minutes and try again.

Step 3: Create SSL Certificate in Certificate Manager

Next, we’ll create an SSL certificate for our naked domain using AWS Certificate Manager.

Request a certificate from AWS

Request a certificate from AWS

  1. Navigate to the Certificate Manager service in the AWS Management Console.
  2. Select “N. Virginia” (us-east-1) as the current region, from the drop-down menu in the top right of the AWS Console interface.
  3. Click “Request certificate” in the main nav, and choose “Request a public certificate”. Click Next.
  4. Enter your apex domain and www subdomain (e.g., example.com and www.example.com) in the “Domain names”/”Fully qualified domain name” field. After entering the first, use the ‘Add another name to this certificate’ button to add the second.
  5. Choose “DNS validation” for the “Validation method”, as it is easy to set up directly in the next steps, since we are using Route53 for DNS. Click “Request”
  6. Now view the certificates configuration page (refresh the “Certificates” table if it has not yet appeared), and under the Domains section click “Create records in Route 53”.
  7. Confirm that the table contains 2 rows, one for the naked domain, and one for the www domain, then click “Create records”
  8. Once validated, the certificate status will change to “Issued” from “Pending validation”

Note, if you just setup DNS as per the previous steps, it may take a sometime for the DNS validation to complete.

Step 4: Create and Configure S3 Bucket for Redirect

Now, we’ll create an S3 bucket named according to the domain we are redirecting from.

  1. Navigate to the S3 service in the AWS Management Console.
  2. Click “Create bucket” and then select a region, for example the us-east-1 (US East N. Virginia) region. The region is not that important as we will place a Cloudfront distribution in front of it.
  3. Enter the domain name without protocol or slashes as the bucket name:
  4. if redirecting from the root domain to the www subdomain (ie example.com to www.example.com), you will enter example.com as the bucket name
  5. or if redirecting from the www to the root domain (www.example.com to example.com) then enter www.example.com as the bucket name.
  6. Leave everything else as is and then click “Create bucket” at the end of the form.
  7. Select your newly created bucket and click the “Properties” tab.
  8. Scroll to “Static website hosting”, then click “Edit”
  9. Enable it by selecting “Enable” then choose “Redirect requests for an object”.
  10. In the “Host name” field, enter the domain you wish to redirect to :
  11. if redirecting from the root domain to the www subdomain (ie example.com to www.example.com), you will enter www.example.com as the Host name
  12. or if redirecting from the www to the root domain (www.example.com to example.com) then enter example.com as the Host name.
  13. Under the protocol option, select https , this will ensure when redirected the user is taken to the https version of the destination URL.
  14. Click “Save changes”.
  15. Take note of the bucket’s public endpoint URL (e.g., http://example.com.s3-website-us-east-1.amazonaws.com), that will now be displayed under the “Static website hosting” under the “Properties” tab. We will need it in the next step.

Testing with curl

Note you can now test this work using curl:

curl -vvv "http://example.com.s3-website-us-east-1.amazonaws.com/"

*   Trying 54.231.129.13:80...
* Connected to example.com.s3-website-us-east-1.amazonaws.com (12.123.123.10) port 80
> GET / HTTP/1.1
> Host: example.com.s3-website-us-east-1.amazonaws.com
> User-Agent: curl/8.4.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< x-amz-id-2: ...
< x-amz-request-id: ...
< Date: Mon, 05 Feb 2024 11:18:32 GMT
< Location: https://www.example.com/
< Server: AmazonS3
< Content-Length: 0
<
* Connection #0 to host example.com.s3-website-us-east-1.amazonaws.com left intact

You should see a 301 redirect with your desired target domain in the Location header.

Step 5: Create Cloudfront Distribution

We’ll now create a Cloudfront distribution using the S3 bucket’s public endpoint URL as a backend. This will cache the 301 response from S3 and make it available on the CDN.

Create a distribution on Cloudfront which uses your S3 bucket as an origin host

Create a distribution on Cloudfront which uses your S3 bucket as an origin host

  1. Navigate to the Cloudfront service in the AWS Management Console.
  2. Click “Create distribution”, then paste your S3 bucket’s public host name into the “Origin domain” field (ie the URL we saw in step 11 above, but without the protocol http:// prefix).
  3. Under “Web Application Firewall (WAF)” select one option. If you enable it you will pay a monthly fee. I disable it by selecting “Do not enable security protections” to not incur the extra charge.
  4. Under the “Settings” section on the same form, find the “Alternate domain name (CNAME)” subsection. Click the “Add item” button and then:
  5. if redirecting from the root domain to the www subdomain (ie example.com to www.example.com), you will enter example.com as the the Alternate domain name
  6. or if redirecting from the www to the root domain (www.example.com to example.com) then enter www.example.com as the Alternate domain name
  7. Under “Custom SSL Certificate”, select the SSL certificate you created earlier in Certificate Manager. You will be able to identify it by the domain name listed in its name.
  8. Click “Create Distribution” and wait for the distribution status to change to “Deployed” (on the Distributions list page it will be shown as Status “Enabled” with a green tick).
  9. Take note of the Cloudfront “Distribution domain name” (e.g., d12345abcdef.cloudfront.net) shown on this page, so you can check it in the next step.

Cloudfront distribution alternative domain name configuration

Cloudfront distribution alternative domain name configuration

Step 6: Configure Route 53 A Alias Record

Finally, we’ll configure an A Alias record in Route 53 to point our naked domain to the Cloudfront distribution.

  1. Navigate to the Route 53 service in the AWS Management Console.
  2. Click “Hosted zones” in the left menu and select your domain’s hosted zone that we created in the first step.
  3. Click “Create record”. If you are presented with a wizard with a number of square icons/options, click the link on the right that says “Switch to quick create”. You should now be on the “Quick create record” screen.
  4. For the “Record name” field:
  5. if redirecting from the root domain to the www subdomain (ie example.com to www.example.com), you will leave this blank
  6. or if redirecting from the www to the root domain (www.example.com to example.com) then enter www as the Record Name.
  7. Choose “A – Routes traffic to an IPv4 address and some AWS resources” as the record type.
  8. Switch on the “Alias” switch. You should see a drop down now under “Route traffic to”
  9. Choose “Alias to CloudFront distribution” and then select your Cloudfront distribution you created in the previous step from the list. If everything is setup right it will be the only option there. If not see the troubleshoot section below.
  10. Click “Create records”.

Step 7: Testing with curl

To test everything is working, use curl to make a request for your starting domain that should now be redirected.

$ time curl -vvv "https://example.com"

...
> GET / HTTP/2
> Host: example.com
> User-Agent: curl/8.4.0
> Accept: */*
>
< HTTP/2 301
< content-length: 0
< location: https://www.example.com/
< date: Mon, 05 Feb 2024 11:56:46 GMT
< server: AmazonS3
< x-cache: Miss from cloudfront
< via: 1.1 123.cloudfront.net (CloudFront)
< x-amz-cf-pop: ...
< x-amz-cf-id: ...

real	0m0.376s
user	0m0.012s
sys	0m0.012s

The first time you make the request you should notice x-cache: Miss from cloudfront in the response. Here the round trip for the request took 376ms from my laptop.

Now retry the request:

$ time curl -vvv "https://example.com"

...
< HTTP/2 301
...
< x-cache: Hit from cloudfront
...
< age: 171
...

real	0m0.137s
user	0m0.012s
sys	0m0.013s

You will now see x-cache: Hit from cloudfront and the age header, showing the response is now cached.

The total request time should now also be much faster (137ms instead of 376ms)!

Try both http and https to check the Location header is correct (it redirects to www. with https in this example):

$ curl -vvv "http://example.com"

...
< HTTP/1.1 301 Moved Permanently
...
< Location: https://www.example.com/

Managing Cached Redirects and Invalidations

One advantage of using Cloudfront for our naked domain to www subdomain redirect is that the redirect response will be cached within the CDN. This results in faster response times for users, as their requests are quickly redirected from the edge locations closest to them.

However, if you encounter an issue with your redirect or need to change the destination location, you’ll need to create an invalidation on your Cloudfront distribution to clear the previous cached response.

Here’s how to create an invalidation:

  1. Navigate to the Cloudfront service in the AWS Management Console.
  2. Select your distribution and click on the “Invalidations” tab.
  3. Click “Create Invalidation”.
  4. To invalidate all objects in your distribution, enter /* in the “Object Paths” field. If you only need to invalidate specific paths, enter them instead. Multiple object paths can be entered by separating them with a newline.
  5. Click “Invalidate”.

Creating an invalidation ensures that all cached copies of your specified objects are removed from Cloudfront edge locations. The next time a user requests one of these objects, Cloudfront will fetch a fresh copy from your S3 bucket and update its cache accordingly.

It’s worth noting that invalidating everything (/*) should be done cautiously, as it can impact performance while new content is fetched and cached across edge locations. However, since our use case primarily involves redirects rather than serving large amounts of static content, this approach is acceptable for most scenarios.

Remember that each AWS account has a limit of 1,000 free invalidation path requests per month; additional invalidation path requests incur charges. For more information on Cloudfront pricing and invalidation costs, refer to AWS CloudFront Pricing.

Troubleshooting Common Issues

In this section, we’ll cover some common issues you might encounter while setting up a naked domain to www subdomain redirect in AWS using S3 and Cloudfront.

Issue 1: Incorrect S3 Bucket Backend Path

If you notice that the redirect is not working as expected, ensure that the path specified for the S3 bucket backend in the Cloudfront distribution configuration is correct. To verify this:

  1. Navigate to the Cloudfront service in the AWS Management Console.
  2. Click on your Cloudfront distribution, then click on the “Origins and Origin Groups” tab.
  3. Check if the “Origin Domain Name” field contains the correct public endpoint URL of your S3 bucket (without the “http://” prefix). If not, update it and save changes.

Issue 2: Missing Domain Names in Cloudfront Configuration

Another possible issue could be due to missing domain names in your Cloudfront distribution’s CNAMEs configuration. This will mean you cannot select your desired Cloudfront distribution when setting up Route 53 and the A record Alias.

To resolve this:

  1. Navigate to the Cloudfront service in the AWS Management Console.
  2. Click on your Cloudfront distribution, then click on the “Settings” tab.
  3. Scroll down to find “Alternate Domain Names (CNAMEs)” and ensure that your initial or starting domain (e.g., example.com) is listed here. If not, add it and save changes.

Conclusion

Your naked domain should now redirect to the www subdomain using HTTPS. It may take some time for the DNS changes to propagate.

Once complete, you can test the redirect by entering your naked domain (e.g., example.com) in your browser, and you should be automatically redirected to the www subdomain (e.g., www.example.com).

Or vice versa, if that is what you setup!