I’ve been hosting a static site on DigitalOcean for some time. While it used to be free, I’ve now exhausted my resources and am currently billed $5 a month by DigitalOcean. Although this cost is minimal, Id really like to consolidate my side projects into one platform.
DigitalOcean offers an uncomplicated method to deploy React/static apps with auto GitHub deployment (which I highly recommend to anyone looking for a simple/easy solution) here. However, if you desire greater control and an even more cost-effective solution, AWS’s S3 and Cloudfront are great choices. AWS’s S3 bucket provides 5GB of free storage, and Cloudfront offers 1TB of free data transfer. This means we can reduce cost significantly for a small static website.
Create S3 bucket
Setting up an S3 bucket is straightforward:
-
Navigate to AWS S3 and choose
Create Bucket. -
Name the bucket: I recommend using a name similar to your domain, such as
<MY-DOMAIN>.com. -
Choose or note the bucket’s region: For instance, my default is set to
us-east-1.
For now, that’s all for the bucket setup. We’ll adjust permissions later based on Cloudfront’s requirements.
Ensure the following default settings are maintained:
- ACL Disabled
- Block All public access
- Bucket versioning disabled
- No Tags
- Server-side encryption with Amazon S3 managed keys (SSE-S3) selected
- Bucket Key enabled
Create Cloudfront Distribution
-
Navigate to AWS Cloudfront and choose
Create Distribution. -
When prompted for an
Origin domain, select the S3 bucket you created. -
For
Origin access, chooseOrigin access control settings (recommended). -
Create a control setting by clicking on the
Create control settingbutton. You can leave the defaults or add a description if desired. -
Under
Viewer protocol policy, I prefer to select “Redirect HTTP to HTTPS”. -
For
Default root object - optional, specify your site’s root file. Typically, this is “index.html”, but it could differ based on your site’s structure.
Once the distribution is created at the top of the browser it will ask you to copy the policies for the S3 bucket. Select copy and go back into your S3 bucket.
In your S3 bucket go to the bucket Permissions.
Edit your Bucket policy
It should look something like this
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<BUCKET_NAME>/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::<CLOUDFRONT_DISTRABUTION_ID>:distribution/<CLOUDFRONT_DISTRABUTION_ID>"
}
}
}
]
}
Create IAM User
- Navigate to the IAM management console in AWS.
-
Click on
Create user. -
Skip the option
Provide user access to the AWS Management Console - optional. -
On the
Permissions optionspage, chooseAttach policies directly. This will allow the user specific access permissions needed for deployment. -
Add
AmazonS3FullAccessandCloudFrontFullAccess(this probably isn’t the most secure if you are worried about super tight security. -
Once the user is created you will want to create an access key. Go back into the user that was created and select the
Security credentialstab selectCreate access keyunder theAccess keyssection. Select the use case I usedThird-party serviceadd a tag if desired. Download the csv or copy the actions to your clipboard. If you don’t download the csv or temporarily save these keys you will need to go through this process again
Create Github repo
If you’re reading this guide, I assume you’re familiar with creating GitHub repositories. If not, GitHub offers comprehensive documentation here.
Update Github action secrets
To secure your AWS credentials, use GitHub’s secrets management. Navigate to your GitHub repository’s settings, find the “Secrets” section, and add your AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.
Update Github actions
For deployment, create a GitHub action in your repo. I typically name it deploy.yml, but you can choose another name if you prefer.
name: Deploy to AWS
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Build React App
run: |
npm install
npm run build
- name: Deploy to S3
uses: jakejarvis/s3-sync-action@master
with:
args: --follow-symlinks --delete
env:
AWS_S3_BUCKET: <BUCKET_NAME>
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: 'us-east-1' # change this to your AWS region
SOURCE_DIR: 'build'
- name: Invalidate CloudFront Distribution
uses: chetan/invalidate-cloudfront-action@v1.3
with:
distribution: <CLOUDFRONT_DISTRABUTION_ID>
paths: '/*'
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: 'us-east-1' # change this to your preferred AWS region
DISTRIBUTION: <CLOUDFRONT_DISTRABUTION_ID>
PATHS: '/*'