How to 301 Redirect to a new domain with AWS S3 & CloudFront
Tags: webdev, aws, programming, tutorial
Published: 2023-03-09 00:11:49

## Motivation

Recently I made the decision to rebrand a [side project of mine](https://extensionkit.io/?ref=devto) which involved changing the domain name from **ChromeExtensionKit.com** to **ExtensionKit.io**. At it's core, it wasn't a difficult move, however the old domain had reasonably good SEO and search ranking so I wanted to ensure that I maintained that as much as possible through a permanent 301 redirect of the old domain. The main challenge was that the domain pointed to a single static site so I didn't have easy access to a server where I could add a simple `.htaccess`.

I looked at a couple of options such as spinning up a quick Lambda to perform the 301 redirect and even looked at handling the redirection at the DNS level, however I ultimately settled on the AWS S3 and CloudFront approach as it was both the easiest and cheapest option. This blog post will go over how to setup a 301 permanent redirect from an old domain to a new domain with HTTPS support and 1:1 mapping of paths (for example, `oldsite.com/page1` redirects to `newsite.com/page1`).

For this walkthrough, we will assume that we are moving a fake domain **oldsite.com** to a new (also fake) domain **newsite.com**. This will also assume that the new domain (newsite.com in this example) is already setup and supports HTTPS traffic.

## 1. Configuring Route53

The first step is to create a new Hosted Zone in AWS Route53. To get started, login to the AWS console and head over to Route53. Once there, simply add in your old domain that you'll be moving into the domain name field. All other options can be kept as the defaults.

![Route53](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a2ni7fywud7vbdf2zbag.png)

Next, go to where you have your old domain hosted and update it to point to the nameservers provided by AWS. We will come back to Route53 to connect AWS resources later.

## 2. Creating a certificate

After pointing your old domain to AWS, you'll need to ensure it utilizes HTTPS. This can be accomplished easily within AWS by heading over to Certificate Manager. Once there, click **Request a certificate** and ensure public certificate is selected. After that, enter your domain you just added in step 1 under the Fully Qualified Domain Name field.

![Request certificate](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/anchn9n6mczyawpuhp2x.png)

After creating, you will see that the domain requires validation to prove that you own it. Under the **Domains** section, click the **Create records in Route 53** button which will open Route53 once again where you can add the required txt record that proves ownership. Once that is complete, you should see status of **Issued** on the certificate page after a bit of time.

## 3. Setting up S3

Next we will setup the redirecting mechanism. This is accomplished via S3 in website hosting mode. Head over to S3 and create a new bucket with the name of your old domain (or some other unique name) and ensure **Block all public access** is unchecked.

Once created, navigate into the bucket and open the **Properties** tab. At the bottom, click **Edit** under **Static website hosting**. Once there, enable **Static website hosting** and choose **Redirect requests for an object** as the hosting type. Finally, enter your new domain as the host name and choose **https** as the protocol. This should look like the following:


![S3 website hosting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0orfjt1a7zkzlypq6lk4.png)

After creating it, copy down the **Bucket website endpoint** as you'll need this later when setting up CloudFront. It should be in the form of `http://{bucketname}.s3-website-{region}.amazonaws.com`.

## 4. Setting up CloudFront

Now that we have the old domain setup and the redirect to the new domain in place, we need to tie it together and support HTTPS traffic via CloudFront (as the current redirect will not support HTTPS redirection). Head over to CloudFront and click **Create distribution** to create a new distribution.

Under the **Origin** section, enter your bucket website endpoint URL you copied in Step 3 above and put that into the **Origin domain**. It is important that you paste in the S3 website endpoint and not select the bucket itself or it will not work as expected. Every other setting in this section can be left as the default.

Next, under the **Settings** section, either keep the **Price class** as the default or change to another to slightly reduce cost (for example, NA and Europe). After that, click **Add item** under **Alternate domain name (CNAME)** and add your old domain (in this case, we will use `oldsite.com`). Finally, under the **Custom SSL certificate**, find and select the certificate created in Step 2 (in should appear in the list if done correctly). Every other setting in this section can be left as the default.

![Cloudfront settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fa9snhax1jv6kdy8scxe.png)

Finally, click **Create distribution** to finish the process and wait for the distribution status to change to **Enabled**.

## 5. Tying it all together

The final step in the process is to head back over to Route53 and tie everything together. Open up Route53 and head into your Hosted Zone created in Step 1. Once there, click **Create Record** and choose `A` as the Record type and enable the **Alias** checkbox. From there, select **Alias to CloudFront distribution** in the first dropdown and select the distribution you just created in the second dropdown. This should look something like:


![Route53 linked to CloudFront](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/56ymamdh424do2ba5sbt.png)

Once complete, give it some time to fully propagate and you should be ready to verify. This final step effectively linked the domain to CloudFront, which behind the scenes uses the certificate we created to enable HTTPS and pushes traffic to our S3 bucket which in turn redirects to the new domain.

## 6. Verifying the redirect

After completing steps 1-5, you are ready to verify the redirect is working as intended. It is worth noting that if you don't see the changes active immediately, you may need to give it a bit of time to propagate fully. Once you've given it enough time, you can either visit the old url and enure you're automatically redirected to the new one, or you can perform a `curl` command that'll also return the 301 status. To perform this, simply enter the following into your terminal:

```
curl -I https://oldsite.com
```

After running, you should see something similar to the following:

```
HTTP/2 301
content-length: 0
location: https://newsite.com
date: Fri, 03 Mar 2023 21:48:18 GMT
server: AmazonS3
x-cache: Hit from cloudfront
via: 1.1 someid.cloudfront.net (CloudFront)
x-amz-cf-pop: some-cf-pop
x-amz-cf-id: some-cf-id
age: 10000
```

You should notice at this point that the status is **301** signifying the permanent redirect and the **location** is your new domain.

One final step that is beneficial when performing a domain move is to notify Google so you don't lose SEO rankings. For more information on their Change of Address Tool, [click here](https://support.google.com/webmasters/answer/9370220?hl=en).

## TL;DR

You can setup a permanent 301 Redirect from an old domain to a new one easily and cost effectively using AWS. Make sure your new domain is active and supports HTTPS, then perform the following:

1. Add your old domain Route53
2. Create a certificate for the old domain using Certificate Manager
3. Create an S3 bucket in website hosting mode and redirect to your new domain
4. Create a CloudFront distribution for the old domain using the cert from step 2 to support HTTPS and link to S3 website endpoint created in step 3
5. Add an Alias record in Route53 for the old domain that points to the CloudFront distribution in step 4

At a high level, this strategy uses S3 website hosting mode to redirect to the new domain by creating a CloudFront distribution in front of the old domain (to allow for HTTPS redirects) pointing to the S3 bucket.