All Articles
How-to·6 min read

Serve a Static Site with S3 and CloudFront

A static site on S3 behind CloudFront is fast, cheap, and secure — if you wire it up correctly. Here is the setup that avoids the common traps.

Part of: AWS Cloud Engineer

Hosting a static site on AWS is one of the best-value setups there is: pennies of storage, a global CDN, and free HTTPS. But the naive "make the bucket public" version is both insecure and slow. Here is the way that is actually recommended.

Step 1: Private Bucket, No Public Access

Do not enable S3 static website hosting or make the bucket public. Keep it fully private and let CloudFront be the only thing that reads it:

S3 bucket → Block all public access: ON
Upload your built site (index.html, assets, ...) to the bucket

Step 2: Put CloudFront in Front

Create a CloudFront distribution with the bucket as its origin, using Origin Access Control so only CloudFront can read the bucket:

CloudFront → Create distribution
  Origin: your-bucket.s3.region.amazonaws.com
  Origin access: Origin access control (OAC)
  Viewer protocol policy: Redirect HTTP to HTTPS

CloudFront then generates a bucket policy that grants itself read access — copy it onto the bucket. Users hit the CDN edge; the bucket stays private.

Step 3: Handle SPA Routing

A single-page app serves every route from index.html. Without help, a refresh on /dashboard returns a 403. Add a CloudFront custom error response to rewrite those to the app entry point:

Custom error response:
  HTTP error code: 403  →  Response page path: /index.html  →  Response code: 200

Step 4: Set Cache Headers and Invalidate on Deploy

Cache hashed assets aggressively and index.html briefly, then invalidate on each deploy so users get the new version:

aws s3 sync ./dist s3://your-bucket --delete aws cloudfront create-invalidation --distribution-id ABC123 --paths "/*"

Summary

Keep the S3 bucket private, front it with CloudFront using Origin Access Control, add HTTPS redirect and a 403→index.html rule for SPA routing, and invalidate the cache on deploy. The result is a globally fast, secure, near-free static site — without ever exposing the bucket to the public internet.

#AWS#S3#CloudFront#Hosting

Want to go deeper?

AWS Cloud Engineer

View Course