AWS Builder Center
How I Host a Static Website on AWS for Just a Few Dollars a Month

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:
  1. A user types your domain name.
  2. Route 53 resolves the domain to your CloudFront distribution.
  3. CloudFront serves cached content from the edge location nearest the user, over HTTPS.
  4. 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.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article