Deploy Angular/React website on a custom domain using AWS S3, Cloudfront and route 53

If you are here, I am pretty sure you already have an Angular/React application ready to be deployed and a domain registered with any of the domain registrars. In this article, we will be deploying on a domain registered from GoDaddy. I am sure the process would be the same for other domain registrars as well.

Some prerequisites…

What is DNS(Domain Name Server) ?

We know that each device connected to the internet has a public IP address. DNS is the phonebook of the internet. It keeps a mapping of domain names to its IP address which domain names like, is easier for humans to remember than IP addresses which is just a sequence of numbers. Route53 is a highly scalable DNS web service provided by AWS.

What is S3 ?

S3 (Simple storage solution) which is also an AWS service is used to store any file/object on the cloud through a web service interface or programmatically. There is a concept of buckets in s3 which is just like creating folders. One thing to keep in mind is whenever you create a bucket it must have a unique name across all the s3 buckets available on the internet and you need to select a region where you want to store the bucket. More on this later.

What is Cloudfront?

One drawback of s3 is if the bucket is hosted in the US and someone from Asia is trying to access the content of that bucket. It will take a lot of time for the content to load since the content has to take a lot of hopes before reaching Asia. This problem is solved using CDN(Cloudfront Distribution Network). Cloudfront Distribution Network caches the content of your s3 bucket in different regions. So whenever you try to access any content of s3 via CDN, CDN first checks if the content is cached in the edge region, serves it if already available. And if the content is not cached yet, it will fetch the content from the original source and cache it for further use.

How Exactly is my website served using CloudFront, route 53 and s3?

Before we get into the steps it’s important to understand the flow of how your website is actually served. If you understand this flow, Trust me it wouldn’t take more than 30mins to complete the entire steps. I personally struggled a lot while doing this because there are some critical things which you need to take care of and none of the blogs I read mentioned it.

To start in simple terms just look at the image above. S3 stores the code of your website. Cloudfront is a way to cache and load your files stored from s3 faster. Route53 is the DNS service which maps your domain name to server ip address which then fetches the content from the cloudfront and sends back the response.

So when you type in the URL. This is what happens

  1. Request is sent to the DNS server which resolves the hostname ( into a Public IP address. (
  2. DNS routes the request to Cloudfront POP (Edge Location).
  3. In the Edge Location, Cloudfront checks it’s cache if the requested file is available. If the file exists, CloudFront returns it to the requested client machine. If the file is not present in the cache, then CloudFront forwards the requests to Amazon S3, fetches the content from s3, and returns to the user. Also caches the content for future requests.

Now let’s deploy our website. I will be using as an example custom domain where we want to deploy our frontend application.

Step 1:

We will create two s3 buckets with the same name as your domain name. Make sure to select the US East (N Virginia) as the region for the buckets and deselect Block public access option. The name of the two buckets would look like this


Click on the Create bucket. It will open up a popup something like shown below. Enter your bucket name For eg. Select the region as the US East (N. Virginia). Don’t touch the copy settings. Click Next

Next, you will see the configure options screen. Keep the default configuration, don’t change anything. Click next.

Next is setting the permissions for the bucket. This is important. By default the block all public access button will be checked, you need to uncheck it and click on the I acknowledge button.

Finally in step 4 just review the options once and click on create bucket

Repeat this process twice. Once with the bucket name and once with bucketname as

Step 2: Giving the bucket public access and enabling static website hosting

Once both the buckets are created. We need to give public read access to both the buckets.

Go inside the bucket. Select Permissions and then select bucket policy. Copy the policy below making sure you change the YOUR_BUCKETNAME with your bucket name Eg. or Paste it in the textbox and click save

  "Version": "2008-10-17",
  "Statement": [
      "Sid": "AllowPublicRead",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::YOUR_BUCKETNAME/*"

Follow the above steps for both the buckets. The objects in the bucket are now publicly accessible.

Let’s now enable static website hosting on both the buckets

This step is going to be different for both the buckets.

Go to properties Select Static Website hosting. Click on the use of this bucket to host a website. Fill in index.html in index document and index.html in error document. (If you have a custom error page you can enter that filename.html). For now, I would use index.html for both index document and error document. Click save

For the bucket without the prefix of www.

Go to properties. Select Static Website hosting. Click on “use this bucket to host a website”. Select redirect requests and enter in the bucket name. Click Save.

So far we have created two buckets, given public read object access, and enabled static website hosting on it. Make sure the bucket shows a yellow public access beside the bucket name.

Step 3 – uploading website on s3

If you are deploying an Angular application. Run ng build –prod. This will create a dist folder which has the productionised code. Open bucket and upload all the files in the root bucket itself.

Note:- upload all the files and not the folder. The root directory must have index.html and all the files.

The bucket should look something like this.

Awesome! Your website is deployed on s3 now. Go inside your bucket. In the properties select static website hosting. You will find an endpoint, copy the link and open in the new tab.

If your website loads, you have done everything correctly so far. And if it doesn’t you must have missed something, just read the above steps again and check if you missed anything.

Step 4 – Request a certificate if you have bought your domain from Godaddy or other domain registrars.

If you have registered your domain other than via route 53 than it is important to verify that the domain belongs to you.

Go to the Certificate Manager in AWS Services. Click on request for certificate and select public certificates. In the add domain name add two domains

  • *

The * signifies any sub-domains within your domain. Click Next.

Now login to the domain registrar account. In my case it is Godaddy. Select the domain name and go to Manage DNS Option.
It should look something like this

Click on ADD, select a CNAME Record from the dropdown. You will see two text inputs with the labels Host and Points to. In the CSV exported file from route53, copy the first Record Name but exclude the domain name from it. For eg the record name will show something like this Just copy _34c5df753f510e5911f322d1066aeb24 this and paste it in the host*. Next copy the record value without the last period into the Points to input field. For eg. in my CSV file the record value is Just paste _e47dd09b646f951f2a687219bbb63077.tfmgdnztqk.acm-validations.AWS (Notice the last dot is removed)

Do this twice for each row in the downloaded CSV. This means adding two CNAME records. Once you are done with this. Go back to AWS certificate manager, within a couple of minutes the status in the certificate manager should change from pending to Issued.

Good job! Now AWS knows that you are the owner of this domain.

Step 5 – Creating CloudFront distribution for s3 buckets

Go to AWS services and search for CloudFront.
Click on create distribution.
Select Get started for Web.
The origin domain name will give options to select the bucket. DON’T SELECT FROM THE DROPDOWN. I myself struggled for more than half a day to figure out this. So the problem is if you select from the dropdown your home page of the website will load perfectly fine. But if you try to go to some subroutes directly from URL it gives access denied error. For eg. will load but if you go directly to it gives access denied. 
So you need to manually enter the origin domain nameIn my case, the URL looks something like this (Keep in mind we are creating CloudFront distribution for the bucket with www in the prefix)

As soon as you enter the origin domain name most of the other fields will get prefilled. Next in viewer protocol policy select redirect http to https.

Enter your domain in the Alternate Domain names (Again just to double-check we are doing this process for the bucket with www as prefix, hence add

Select Custom SSL, It will show a dropdown with all the domains you have verified using the certificate manager. Select the domain you want to deploy on.

Next in Default root object enter index.html

That’s all, now click on create distribution and grab a cup of coffee. It takes around 10-15 minutes for CloudFront to create distribution.

After the CloudFront is deployed it will show an Enabled state besides the CloudFront name.

Copy the text below domain name (, open the link in a new tab. If your web application loads, congratulations, the major part of the process is done. Now we just need to load this CloudFront URL for our custom domain

Repeat the same process for the bucket without the ‘www’ prefix Finally, you should have two CloudFront distributions.

In Your AWS services go to route 53, Select hosted zones from the left panel. Click on create hosted zones. On the right-hand side, you will see an option to enter the domain name. Add your domain name (DO NOT ADD www prefix here only the domain name) For eg.

Click create

Two record sets will be created automatically. One will be of type NS (Name Server) with four values and the other one will be of type SOA (Start of Authority) record. Now we need to add the Name servers in our GoDaddy DNS configuration. Login again to your respective domain registrars account. In my case, it’s GoDaddy and go to the Manage DNS option.

You will see a NameServers option which says default nameservers. Click on Change.

Click on Enter my own Nameservers

Add all the four Name server values from AWS hosted zones for your domain

Click on save.

It will take about a minute for the changes to reflect. Once it’s done. You will see using custom nameserver below the NameServer.

Go back to route53 in the hosted zones.

Select the domain name. Click on create recordset. Enter www besides the domain name. Select yes in the Alias. Click on the input box it will give a dropdown, select the CloudFront distribution for bucket and click create.

Create one more recordset. Keep the Name field empty this time and select yes in alias. From the dropdown select the CloudFront URL for ‘’ (bucket without the ‘www’ prefix) bucket and click create.

That’s all, you are done. Open up a new tab and go to your website (Sometimes it might take some time for the website to load on the custom domain but shouldn’t take more than half an hour).

If the article was helpful do follow us on linked in for more such article updates.

 11,993 total views,  5 views today

How did you like the article?