Seamlessly Migrating Frontend Deployment Across AWS Accounts

Mubarak Alhazan - Oct 3 - - Dev Community

How to Move S3 Buckets, CloudFront Distributions, and Route 53 Hosted Zones

migration gif

Introduction

I recently worked on a project to migrate an entire application deployment from one AWS account to another. While migrating individual resources between accounts is common, I couldn't find a clear, straightforward guide on how to move a frontend deployment. This left me piecing together different AWS resources and best practices to ensure a smooth transition.

The frontend we were working with is a React application deployed using a typical AWS architecture: an S3 bucket to host the static files, a CloudFront distribution placed in front to improve performance and security, and a Route 53 hosted zone to route traffic to the CloudFront distribution. Given how common this setup is in AWS, I wanted to share the step-by-step process of migrating this architecture across AWS accounts.

In this article, we’ll walk through how to efficiently migrate the entire Frontend architecture while ensuring minimal downtime and a smooth transition for our deployment.

Pre-Migration Checklist

Before starting the migration, it's important to identify the key AWS resources involved and ensure we have everything prepared to make the transition seamless. Here's a checklist of what we'll need to migrate:

Resources To Migrate

  • S3 Buckets

    In our case, we have four S3 buckets, each holding the static assets for different application portals.

  • CloudFront Distributions

    Each S3 bucket has an associated CloudFront distribution, improving performance and security. Like the S3 buckets, we will migrate four CloudFront distributions — one for each bucket.

  • ACM Certificate

    We need an ACM certificate to enable SSL and secure our frontend applications. Since all the applications are under the same domain, we can create a single ACM certificate and use it across all CloudFront distributions. This will ensure that each application serves traffic over HTTPS.

  • Route 53 DNS Records

    For each subdomain, there is a corresponding DNS record in Route 53 that routes traffic to the correct CloudFront distribution. Additionally, we'll need to create DNS records to validate the ACM certificate.

In this guide, we’ll walk through the process for one frontend app, but the same steps can be repeated for the remaining applications.

Access and Permissions

To migrate these resources without issues, you need access to both the source AWS account (where the resources currently reside) and the target AWS account (where the resources will be moved). Adequate permissions to create, modify, and delete the mentioned resources in both accounts will ensure a smooth migration. Here is an IAM policy for all the access required for this migration.

Migrating S3 Buckets

The first step in the migration is moving the static assets from the S3 buckets in the source AWS account to new buckets in the target AWS account. Here's how we approach this migration:

  1. Creating a New Bucket in the Target Account

    Since S3 bucket names must be globally unique, you might not be able to create a new bucket with the same name as the one in the source account.

    In addition, make sure that the new bucket is configured for static website hosting, which is crucial for serving your React application. You can enable this feature via the AWS Console or the AWS CLI. You can refer to this resource to learn more about setting up an S3 bucket for static website hosting.

  2. Copying Static Assets to the Target Bucket

    Once the new bucket is created, the next step is to transfer the static assets (such as HTML, CSS, JS, and media files) from the source bucket to the target bucket. You can achieve this with the following method:

    Method 1: Using AWS CLI

    aws s3 sync s3://source-bucket-name s3://destination-bucket-name --acl bucket-owner-full-control
    

    This command ensures that all files from the source bucket are copied to the target bucket, with appropriate access permissions (bucket-owner-full-control).

    Method 2: Manual Download and Upload

    For smaller sets of files, you can download the assets from the source bucket and upload them to the new bucket via the AWS Console. While this method is simple, it’s not ideal for large datasets or continuous deployment.

    Method 3: Using a CI/CD Pipeline to Deploy to the Target Bucket

    In our case, an existing CI/CD pipeline deployed our React frontend directly to the S3 bucket from GitHub. Instead of manually copying the files, we updated the pipeline to deploy to the new bucket in the target account. After switching the pipeline’s destination, we triggered a redeployment to ensure that the latest version of the application was in the new S3 bucket.

    This method is preferable because having a CI/CD pipeline allows for ongoing updates to the application. You can follow this resource to learn how to create a CodePipeline that deploys a React app to an S3 bucket.

Migrating ACM Certificates

One important aspect of migrating a frontend deployment is ensuring SSL certificates are set up to secure your applications. In AWS, these certificates are managed through the AWS Certificate Manager (ACM), but it's important to note that ACM certificates cannot be transferred between AWS accounts. This means we need to create a new certificate in the target account.

To start, navigate to the Certificate Manager in the AWS Console of the target account. Select Request a certificate and choose a public certificate, as it will be used with CloudFront.

As part of the request, you need to add subdomains the certificate will secure. These subdomains represent the frontend applications, which will later be served through CloudFront distributions. Here’s a visual representation of what that looks like:

acm creation

After adding the necessary subdomains, you can leave the other settings at their defaults and proceed to request the certificate.

At this point, the certificate request will be marked as "Validation in progress." Since we selected DNS validation, AWS will provide CNAME records that need to be added to the DNS configuration of your domain. This step is crucial, as it verifies ownership of the subdomains. The pending validation status will appear like this:

validation status

Next, you’ll need to add the provided DNS validation records to the hosted zone in the source account. This is required to complete the validation process. Take note that Route 53 automatically pre-fills the base domain when adding the CNAME records, so you only need to enter the part before it.

Once the DNS records are in place, ACM will automatically detect the validation, and the certificate’s status will change to Issued. With the certificate validated, you’re now ready to attach it to your CloudFront distributions in the following steps.

Migrating CloudFront Distributions

Similar to ACM certificates, CloudFront distributions cannot be directly transferred between AWS accounts. As a result, we’ll need to recreate the distribution in the target account.

To begin, navigate to the CloudFront section in the AWS Console of the target account and select Create Distribution. During the creation process, you’ll need to choose the origin domain, which in this case is the S3 bucket containing the static assets for your application. Make sure you select the correct bucket and use website endpoint.

Once the origin is set, adjust the other settings based on your specific requirements for caching, behavior, or access logging.

In the Settings section of the distribution setup, you’ll need to specify the alternate domain name (CNAME), which is the subdomain that you want to associate with the distribution (e.g. blog.poly4.dev). Additionally, you’ll need to attach the SSL certificate that was created in the previous step. This ensures that the subdomain can securely communicate with the CloudFront distribution over HTTPS. Here's an example of what it looks like:

Cloudfront subdomains

Before finalizing the distribution creation, there’s an important step: Remove the subdomain from the existing distribution in the source account. This is because a subdomain cannot be assigned to two CloudFront distributions at the same time. You may need to wait for the changes in the source distribution to deploy.

Once you’ve created the new distribution, copy the distribution endpoint URL, which looks something like d1234abcdef.cloudfront.net.

The final step is to update the DNS records in the Route 53 hosted zone for the subdomain. Replace the old CloudFront distribution endpoint with the new one, so that traffic to the subdomain routes to the newly created CloudFront distribution.

Migrating Route 53 Hosted Zones

At this stage, resources in the target account — such as S3, CloudFront, and ACM certificates — serve traffic for the application. However, to minimize downtime, the DNS records in the source account were updated first, ensuring that the traffic routing remained uninterrupted during the transition.

The next step is to migrate the hosted zones to the target account to manage DNS records within the same account as other resources. Navigate to Route 53 in the AWS Console of the target account and select Create Hosted Zone. Use the same domain name as the one in the source account.

After creating the new hosted zone, you need to manually add all the DNS records from the source account to the new hosted zone in the target account. Each record must match exactly, including the record types (A, CNAME, TXT, etc.), values, TTLs, and other configurations. If you have a large number of DNS records, manually recreating them can be time-consuming. Here is a resource that explains how to export and import DNS records between hosted zones using the AWS CLI.

Once the records are added, compare the DNS records between the source and target accounts to ensure everything matches.

The final step is to update the name server records at your domain registrar to point to the new hosted zone in the target account. The name servers are provided by AWS when you create the hosted zone and can be found in the Hosted Zone details tab. This ensures that future traffic is routed through the new hosted zone in the target account.

Post-Migration

After successfully migrating all resources and updating DNS records, it is essential to allow time for DNS propagation. It is recommended to wait at least 48 hours to ensure traffic has fully propagated to the new resources. During this time, monitor your application to verify that everything is functioning as expected.

After confirming that the migration is complete and the new resources are handling traffic smoothly, you can optionally delete the resources in the source account. This ensures no residual costs or conflicts from the old infrastructure.

Conclusion

Migrating a front-end deployment between AWS accounts can seem complex due to the individual services involved—S3, CloudFront, ACM, and Route 53. However, by breaking down the process step-by-step, it becomes more manageable.

In this guide, we walked through the necessary stages to ensure a smooth migration, from setting up new resources in the target account to updating DNS records and minimizing downtime.

Thank you for reading

You can follow me on Linkedin and subscribe to my YouTube Channel where I also share more valuable content. Also, Let me know your thoughts in the comment section.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .