DEV Community

Nazrul Hassan
Nazrul Hassan

Posted on

Hosting React static website on AWS S3 with terraform

Nowadays, hosting a static website is fairly easy, thanks to AWS S3 and infrastructure-as-code tools like Terraform. In this post, I will walk you through the entire process of building a static React application and hosting it on AWS S3 while managing our infrastructure with Terraform.

Prerequisites

Make sure you have the following set up:

  1. Node.js and npm: To create and build React applications.
  2. AWS Account: To host your static website in AWS S3.
  3. Terraform: For infrastructure management.
  4. AWS Cli: To interact with AWS resources.

Step 1: Build Static Application With React

First we create our react application using create react app.

npx create-react-app my-static-site
cd my-static-site
Enter fullscreen mode Exit fullscreen mode

Once your application is ready, run it locally with

npm start

When your application is ready , build your static files:

npm run build

This command will create a build directory in your React project that will contain your static files.

Step 2: Set up Terraform

Lets set up our Terraform configuration to create s3 bucket and host our React static application.

Create a main.tf(by convention we call it main.tf you could name it anything you like) in your project directory.

provider "aws" {
  region = "us-east-1"  // any region you want your aws configured to
  access_key = "your-aws-access-key" //if aws cli is configured then you dont need this
  secret_key = "your-aws-secret-key" //if aws cli is configured then you dont need this 
}

Enter fullscreen mode Exit fullscreen mode

run this command in your console, this command will initialize the working directory and download required plugins.

terraform init

Now include the following commands in your main.tf:
for creating a S3 bucket.

resource "aws_s3_bucket" "example" {
  bucket = "your-unique-s3-bucket-name" 

}
Enter fullscreen mode Exit fullscreen mode

Unblock your S3 bucket to allow public access. This is necessary for the next step, where we will create a bucket policy:

resource "aws_s3_bucket_public_access_block" "example" {
  bucket = aws_s3_bucket.example.id 
  block_public_acls = false
  block_public_policy = false
  ignore_public_acls = false
  restrict_public_buckets = false  
}
Enter fullscreen mode Exit fullscreen mode

We now utilize the aws_iam_policy_document data source, which allows us to create IAM JSON policies. Notably, in the resources section, we specify both the bucket itself and "/*" to encompass all objects within that bucket. This distinction is important because our actions include both s3:ListBucket and s3:GetObject. The s3:GetObject action applies to individual objects, while the s3:ListBucket action pertains to the entire S3 bucket.

data "aws_iam_policy_document" "example" {
  statement{

    principals {
      type = "AWS"
      identifiers = ["*"]
    }    

    effect = "Allow"
    actions = [
      "s3:GetObject",
      "s3:ListBucket"
    ]

    resources = [
      aws_s3_bucket.example.arn ,
      "${aws_s3_bucket.example.arn}/*"
    ]
  }

}
Enter fullscreen mode Exit fullscreen mode

Next, we create our bucket policy, utilizing the JSON policy generated by the aws_iam_policy_document data source from above step.

resource "aws_s3_bucket_policy" "example" {
  bucket = aws_s3_bucket.example.id 
  policy = data.aws_iam_policy_document.example.json

}
Enter fullscreen mode Exit fullscreen mode

Now above commands in your main.tf run this command in console, this will generate an execution plan and show you the changes that this script will bring about.
terraform plan

Now run
terraform apply

type yes to create the architecture

Now, we will upload the react static application that we created above to our AWS s3 bucket(run npm run build command before running below command).

aws s3 sync build s3://your-bucket-name

Once your file is uploaded, go to your main.tf and add these block

resource "aws_s3_bucket_website_configuration" "example" {
  bucket = aws_s3_bucket.example.id 
  index_document {
    suffix = "index.html"    
  }

}
Enter fullscreen mode Exit fullscreen mode

This code will enable your bucket for static website hosting. If everything is set up correctly, you will see a link in the static website section under the permissions of your bucket.

It will look something like this

http://my-static-site-bucket.s3-website-us-east-1.amazonaws.com

Top comments (0)