
How I Host a Static Website on AWS for Just a Few Dollars a Month
Amazon S3 + CloudFront + Route 53: a simple, secure, and scalable setup
If you have a portfolio, blog, documentation site, or landing page built with plain HTML, React, Vue, or a static site generator like Hugo or Astro, you don't need a server to host it. AWS lets you serve it from Amazon S3 behind CloudFront, which is fast, secure, and very cheap.
In this post I'll walk through the architecture and the steps to set it up.
The Architecture
The flow is simple:
- A user types your domain name.
- Route 53 resolves the domain to your CloudFront distribution.
- CloudFront serves cached content from the edge location nearest the user, over HTTPS.
- On a cache miss, CloudFront fetches the file from a private S3 bucket.
The key design choice is that the bucket stays private. Only CloudFront can read from it, using Origin Access Control (OAC). Nobody can bypass your CDN and hit the bucket directly.
Why Not Just Use S3 Website Hosting?
S3 can host a website on its own, but it has limitations:
- No HTTPS support on the S3 website endpoint with a custom domain
- The bucket must be public
- Content is served from a single Region, so users far away see higher latency
Adding CloudFront fixes all three.
Step-by-Step Setup
Step 1: Create the S3 bucket
- Open the S3 console and create a bucket with a unique name.
- Keep Block all public access turned on.
- Upload your site files (
index.html, CSS, JS, images).
Step 2: Create a CloudFront distribution
- Choose your S3 bucket as the origin.
- Under origin access, select Origin access control (OAC) and create a new one.
- Set the default root object to
index.html. - Enable redirect from HTTP to HTTPS.
Step 3: Update the bucket policy
CloudFront will offer a ready-made policy to copy. Paste it into your bucket's permissions so that only your distribution can read objects. It looks like this:
json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"Version": "2012-10-17",
"Statement": {
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": { "Service": "cloudfront.amazonaws.com" },
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::YOUR-ACCOUNT-ID:distribution/YOUR-DISTRIBUTION-ID"
}
}
}
}Step 4: Add a custom domain and certificate
- Request a free public certificate in AWS Certificate Manager (ACM). For CloudFront, it must be created in the us-east-1 Region.
- Add your domain as an alternate domain name (CNAME) on the distribution and attach the certificate.
- In Route 53, create an A record (alias) pointing your domain to the CloudFront distribution.
Step 5: Deploy updates
Whenever you change your site, sync the files and invalidate the cache:
bash
1
2
aws s3 sync ./build s3://YOUR-BUCKET-NAME --delete
aws cloudfront create-invalidation --distribution-id YOUR-DISTRIBUTION-ID --paths "/*"Cost
For a low-traffic site, the bill is usually small: pennies for S3 storage, a minimal CloudFront charge, and about $0.50 per month for a Route 53 hosted zone, plus your domain registration. Pricing changes, so check the AWS pricing pages and set up a billing alert before you start.
Best Practices
- Keep the bucket private and use OAC instead of public access.
- Use cache headers so static assets (CSS, JS, images) are cached for a long time.
- Version your assets (for example
app.a1b2c3.js) so you can avoid frequent invalidations. - Automate deployments with GitHub Actions or AWS CodePipeline.
- Enable CloudFront logging or monitoring if you need visibility into traffic.
- Consider AWS Amplify Hosting if you want a more managed experience with built-in CI/CD.
Key Takeaways
- S3 + CloudFront is a reliable pattern for hosting static sites.
- A private bucket with OAC is more secure than public website hosting.
- You get HTTPS, global caching, and low cost with no servers to manage.
Have you hosted a site this way, or do you prefer Amplify? Share your setup in the comments.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article