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 setting
button. 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 options
page, chooseAttach policies directly
. This will allow the user specific access permissions needed for deployment. -
Add
AmazonS3FullAccess
andCloudFrontFullAccess
(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 credentials
tab selectCreate access key
under theAccess keys
section. Select the use case I usedThird-party service
add 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: '/*'
Now that all the fun stuff is over we can add a domian name
Update URL with Namecheap(This might be different if you use a different domain provider)
To ensure users can access your static website via your custom domain name (e.g., www.example.com
), you’ll need to configure your domain in Namecheap to point to the AWS Cloudfront distribution. Here’s how you can achieve this:
-
Get Your Cloudfront Domain Name: After creating your Cloudfront distribution, AWS provides a domain name for that distribution. It usually looks something like
d12345abcdexample.cloudfront.net
. -
Login to Namecheap:
- Visit the Namecheap website and sign in to your account.
-
From the dashboard, navigate to
Domain List
on the left sidebar. -
Click on the
Manage
button next to the domain you want to update.
-
Update DNS Records:
-
In the domain management page, go to the
Advanced DNS
tab. -
Here, you’ll likely see existing DNS records. You’ll need to add a new CNAME record.
-
For the
Host
field, if you want to usewww
(as inwww.example.com
), enterwww
. -
For the
Value
field, enter the Cloudfront distribution domain name, e.g.,d12345abcdexample.cloudfront.net
. -
Ensure the TTL (Time to Live) is set to
Automatic
.
-
For the
-
If you want to redirect the root domain (e.g.,
example.com
) to your Cloudfront distribution, you can add another CNAME record:-
For the
Host
field, enter@
. -
For the
Value
field, again input your Cloudfront domain name.
-
For the
-
In the domain management page, go to the
- SSL/TLS Configuration: Ensure that your Cloudfront distribution is set up to handle HTTPS requests, and that you have an SSL certificate (either from AWS Certificate Manager or another provider) associated with it.
- Propagation: After updating your DNS settings, it may take anywhere from a few minutes to 48 hours for the changes to propagate across the internet. During this period, some users might still see the old site, or the site might be inaccessible for a short while.