Deploy a ReactJS Application to AWS S3 with Route53 and Cloud Front using GitHub Action for CI-CD
Tags: react, aws, github, cloud
Published: 2023-01-26 02:31:42

A good developer would always want to reduce repetitive, manual processes. Using CI/CD (Continuous Integration / Continuous Delivery) helps developers to automate processes so they can focus on other projects.

This blog post is going to explain how you can deploy a static react application in AWS S3 with a custom domain using Route53, SSL certification using certificate manager and using Cloud Front as CDN (Content Delivery Network). All while, make the deployment process automate using GitHub Actions. 

Before we start with the steps, the blog assumes that you already have a static react application in your desired GitHub repository.

**Now, the steps that we will take to set this up are:**

* Enlist a domain name in Route53. 

* Create a S3 bucket with the same root domain name and create 
 another S3 bucket but *www.* Subdomain name with redirect option 
 enabled. 

* We then create a custom SSL certificate using Certificate 
  Manager 

* We then create a Cloud Front distribution. 

* Add records in Route53. 

* Create a YAML file for GitHub actions auto deployment. 

* Test your deployment by visiting your domain in a web browser.

------

#Enlist a domain name in Router 53 

* Go to the AWS Route53 console (https://console.aws.amazon.com/route53/) 

* In the navigation pane, choose **Registered domains**. Choose `Register domain` button. 

* In the **Search for domain** box, enter the domain name that you want to register, then choose `Check`. Select the desired domain name and choose `Add to cart`



![Search for domain](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iomt1o0z8c3axqgvynpe.png)
* Review the domain name, contact information and pricing then choose `Continue` 

* Review and accept the terms and conditions. Choose `Complete purchase`. 

* You'll receive a confirmation email with instructions to confirm the domain registration 

* Log in to the email address that you provided as the registrant contact email address, open the email from AWS, and click on the link to confirm the domain registration. 

* Once you have confirmed the registration, the domain name will be available in the Route53 console, and you can start configuring DNS records for it. 

---

#Setting Up AWS S3

Now we are going to setup AWS S3 with the root domain name as the bucket name and having public access blocked for security. We need to install aws cli configured in your local pc. 

If you are not sure on how to configure them you can read the 

[Quick configure guide](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html) from amazon.

```bash
# create S3 bucket root domain
aws s3 mb s3://example --region us-east-1 
```
this code snippet creates an S3 bucket with example the bucket’s name instead of that add your root domain name.  

Then go to your aws s3 console and click on the refresh button and click on the s3 bucket with the root domain name you just created and click on `permission`.

![S3 bucket permission](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7qllaurbu0eq9hgjvkxa.png)

In here, edit the **Block public access** and click on all the check boxes. 

Now we must create another s3 bucket with *www. [domain_name] .com* this will be redirecting the bucket with domain name. 

Same way, create the bucket using aws cli  

```bash
# create S3 bucket with www. 
aws s3 mb s3://www.example.com --region us-east-1 
```
then in aws s3 console go into the bucket and in properties come down to Static Website Hosting and click `edit`. 

In the edit section click all appropriate options shown in the image. And then click `Save changes`.

![enable static hosting for redirecting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d3ray8h01k13fe2a3mnk.png) 

We have successfully created both the buckets.

---

#Setting up Custom SSL certificate

We are going to create a SSL certificate for the domain and all sub domain.  

```bash 
# create SSL certificate for example.net and *.example.net
aws acm request-certificate --domain-name example.net  --validation-method DNS --subject-alternative-names *.example.net --tag Key=Name,Value=example
```

Go to the certificate manager console and wait until the status changes to Issued. 

Once it is changed click on the certificate ID and click on the `Create records in Route 53`. 

![create record](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mmvlm6hs0q11lyjgtfvx.png)

---

#Setting up Cloud Front 

Now that we have our s3 buckets and SSL certificate configured we can configure the CDN for distribution of the website to the internet, for that we will be configuring CloudFront. Firstly, go in to the CloudFront dashboard using aws console. Click on the `Create distribution`.

![Create cloud front](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tgyjalx1w8krpkprp54i.png)

Then in the create distribution page select the options given in the image below. 

![cloud front settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lb5i0kjy2llrz0ha5anf.png)

It is important that you choose `Legacy access identities` and for `Origin access identity` create a new OAI and select that.

The Bucket policy must be `Yes, update the bucket policy`.  

Next in the Viewer protocol policy select `Redirect HTTP to HTTPS protocol` for secure connection.

![Viewer protocol policy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5osc5fo5vkj02oado7rk.png)

To route people who visit www. As the subdomain to your domain type it in the Alternate domain name section.

![Alternate domain name](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7554u36hefyubjhakgj9.png)

And in the custom SSL certificate click on the drop-down and you will be able to see the certificate that we created before, use that. Type index.html in default root object and enable `IPv6`. Keep rest of the options default. Once everything is configured click on `Create distribution`.


![custom SSL certificate](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8loamj81jajt6u03w30h.png)

----

#Add recodes to Route53

Once we have created the cloud front distribution we can now add records in the route53 which connects to CloudFront distribution with your domain name in route53. 

Go to the Router53 dashboad and click on **Hosted zone->[Domain name]**

![Hosted zone](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wr7p9rkw8ltvnsxv1fbw.png)

Once you are inside this click on `create record`
 
In the Quick create record we are 4 records.
2 records of IPv4 for the root domain and _www. [domain_name] .com_
2 records of IPv6 for the root domain and _www. [domain_name] .com_

![Quick create record](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c93rcnnewmu579rtemh5.png)

Basically, in the Recode name you leave it blank for root domain and the for the other type www. In the blank. Record type is going to be either `A-Routes trffic to an IPv4 address and some AWS resources` or `AAA-Routes traffic to an IPv6 address and some Aws resources`. 

Enable Alicas option. For both Route traffic to option is Alice to CloudFront distribution and Routing policy is Simple routing.

Do this for all the records by add another record. Once everything is added click on `Create record`.

You will see some this like this in the records tab.

![records tab](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wosr6hbvz2xid3q3udr6.png)

---

#GitHub Action Setup

Firstly, go to your desired GitHub repository. In this repository create a folder PATH `.github/workflows`. Afterwards create a `deploy-app.yaml` file in it. 

Next Copy this code snippet into the `deploy-app.yaml` file.

```java
# Name of workflow as seen in Github actions tab
name: CI-CD to S3 Bucket
# Run workflow only on push to main branch
on:
  push:
    branches:
      - main
jobs:
  # To build the project
  deploy-S3:
    runs-on: ubuntu-latest
    steps:
      - name: Checking out code
        uses: actions/checkout@v3

      - name: Installing Node.js
        uses: actions/setup-node@v3
        with:
          node-version: "16"
          
      - name: Installing dependencies
        run: npm install

      - name: Run test
        run: npm test

      - name: Building project
        run: npm run build
        if: success()

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-west-1

      - name: Deploy to S3 bucket
        run: aws s3 sync build/ s3://example --delete
        if: success()
```

This code snippet describes the action, the workflow is triggered on pushes to the main branch. It first checks out the code, installs the dependencies, run the tests, builds the React application, and then configures the AWS CLI with the necessary credentials. Finally, it uses the aws s3 sync command to upload the contents of the build/ directory to the specified S3 bucket.

It is also a good practice to use `if: success()` in the build and deploy step, so that it only runs if all previous steps are successful.

In the deploy to S3 bucket line add your s3 bucket url.

You will need to set environment variables for `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` in your GitHub Actions workflow settings or you can use secrets to store those.

##Add secrets to your repository

Final step is to add the secrets to your GitHub repository. For this Github Action, we need the access key ID and secret access key from IAM User as secrets called `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.
 
Go to your IAM User in AWS and click on your **account name -> Security credentials**.

Scroll down to Access Keys section and `Create access key`.

![Access Keys](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ojd1ghvaadyax0ktgld0.png)

Click the option `Applications running outside of AWS` and click `next`.

![Applications running outside of AWS option](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4p2fdehmzaex580kaak3.png)

This step is optional but for readability I prefer you to add appropriate tag to this access key. Then click on `Create access key`.

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

Copy the access key and secret access key in a separate file because this is the only time you can see the secret access key. Once you click Done you will not be able to see secret access key. You can also download the .csv file.

![access key info](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fnh5wtrbzf3nobzucmd1.png)

Now go back to your GitHub repository, it’s time to and the access keys to secrets.
To add the secrets, you have to go to the **`settings`->`Secrets and variables` -> `Actions`**
In there create `New repository secret`

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

And on the secrets page, you can add your 2 secrets `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`

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

---
#Grab a coffee and enjoy it

Lastly, you have to create a pull request from a feature branch into main branch and watch your actions deploying your app to S3 and website being served with in your domain name.


![github action result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uh4tji4572g37pvtc84g.png)

---

I created a project using this method. You can find the repository [here](https://github.com/RohithPrabakar/Resume-Website). If something is unclear let me know and I will adjust it.

---