(AWS) Host Your React App on AWS S3 with SSL

Kenta Kodashima
Nerd For Tech
Published in
6 min readOct 9, 2020

Hosting a React app on AWS S3 with SSL could be a bit tricky to set up. In this article, I will show you how you can configure everything.

Prerequisites

  • You have aws-cli installed
  • You have an AWS account
    Note: You might get charged if you’re not on the free tier

My Environment

  • aws-cli version 1.17.9
  • macOS Catalina Version 10.15.6
  • create-react-app version 3.4.1

1. Create an S3 bucket

First, create an S3 bucket on AWS. You can use the default settings for most of the options except for the permissions. Uncheck the “Block all public access” option to allow anyone to access your website.

Create a bucket to host your react app

2. Configure the bucket to host a React app

Next, click on your newly created bucket, navigate to Permissions > Bucket Policy and add the following policy. Replace {your_bucket_name} with your S3 bucket name.

{
"Version": "2008-10-17",
"Id": "PublicRead",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::{your_bucket_name}/*"
}
]
}

Then, also add the following configuration to the CORS configuration next to the Bucket Policy tab. You can remove unwanted AllowedMethod as necessary.

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="
http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

Now, go to Permissions > Static website hosting and enable it by checking the Use this bucket to host a website option. Under the Index document section, put your app’s entry filename. You also need to put something under the Error document section not to show the ugly default error page. If you don’t have an error page yet, you can just put your entry filename for now.

Enable static website hosting

3. Create an AWS certificate for SSL

At this point, you should be able to host a static website on this S3 bucket. Next, let’s move on to the SSL part. To be able to access the website via https, you need a certificate tied with your domain. On the AWS console, go to Certificate Manager and click on the “Get started” button under the Provision certificates section.

Note: Before you create a certificate, make sure that you’re currently in the “US West (N. California)us-west-1” region. Otherwise, it can’t be used later to configure your CloudFront distribution.

Certificate Manager

On the next page, you will be asked what kind of certificate you are requesting. Choose the Request a public certificate option there and add your domain including subdomains that you wish to have.

Add domains to the certificate

Then, you will be asked to select a validation method. I recommend that you select DNS validation.

Choose a validation method

You can skip Step 3: Add tags if you don’t want to add any tags to it. After going through all steps here, you will need to create a CNAME record on your DNS manager following the instructions on the page. Name would be the host name and Value would be where it should point at.

Instructions to add a CNAME record to your DNS manager

Note: If your DNS manager does not allow a value with an underscore at the beginning, you can just remove the underscore.

4. Create a CloudFront distribution

Now, you are going to create a CloudFront distribution to serve your React app through https. Navigate to the CloudFront page and click on the “Create distribution” button. Then, select Web as the delivery method.

Select Web as the delivery method

On the next screen, you are going to configure the following things.

Origin Domain Name

Put your S3 bucket’s URL. You can find it under Permissions > Static website hosting > Endpoint of your S3 bucket. If you just select your S3 bucket name here, it won’t be able to handle page refresh.

Origin Custom Headers:

This is needed to be configured to make sure that the requests come from this specific CloudFront distribution. You can put anything as Header Name and Value. I always put something like below.

Origin Custom Headers:
Header Name = Referer
Value = any-value-to-identify-the-distribution

Default Cache Behavior Settings

In this section, you can configure your distribution’s cache behaviour.

  • Viewer Protocol Policy
    In order to make sure that the app always uses https, the “Redirect HTTP to HTTPS” or “HTTPS Only” option is recommended.
  • Allowed HTTP Methods
    You can just choose the list of HTTP methods you want to allow caching.
  • Cache and origin request settings
    You can either choose a cache policy that you need or use legacy cache settings to manually set the values. If you want to have more control over the caching time, select “Use legacy cache settings” for “Cache and origin request settings” and “Customize” for “Object Caching”. In that way, you can define the values for Minimum TTL, Maximum TTL and Default TTL manually.
Cache Behavior Settings

Distribution Settings

Under this section, configure the following things.

  • Alternate Domain Names (CNAMEs)
    Put the domain names that you want to use for your app.
  • SSL Certificate
    Select the certificate that you created in the previous step of this article. Your certificate must have been created in the “US West (N. California)us-west-1” region to be listed as an option here.

5. Add a CNAME record pointing to the CloudFront distribution on your DNS manager

Now you have a CloudFront distribution tied with your S3 bucket where actual website data exists. In order to let your domain know where it should point at, add a CNAME record on your DNS manager. The record should be something like below.

CNAME record:
Name: example.com
Value: assignedcfdomain.cloudfront.net

6. Deploy your React app

Finally, build your React app and deploy it to the S3 bucket. If you have multiple environments to build with different env files like staging and production, you might find the following scripts useful. Make sure you have installed aws-cli and configured your profile correctly. For the following scripts to work properly, you need to name your env files as .env.environment-name .

"build": "sh -ac '. .env.${REACT_APP_ENV}; react-scripts build'",
"build:staging": "REACT_APP_ENV=staging npm run build",
"build:production": "REACT_APP_ENV=production npm run build",
"deploy:staging": "aws s3 sync build/ s3://staging.your-bucket-name --acl public-read --profile your-profile-name",
"deploy:production": "aws s3 sync build/ s3://your-bucket-name --acl public-read --profile your-profile-name"

Now, your web app should be properly served via https protocol if you type in your domain on your browser.

That’s everything for this article. Please don’t hesitate to let me know if I’m missing something.

References:

--

--

Kenta Kodashima
Nerd For Tech

I'm a Software Engineer based in Vancouver. Personal Interests: Books, Philosophy, Piano, Movies, Music, Studio Ghibli.