← Course Index

S3 + CloudFront — Static Hosting

~25 min · AWS

Ref
Primary Source
AWS — Host a Static Website on S3

Official guide for deploying a static site or SPA to S3 with CloudFront. Read →

Why S3 + CloudFront for Static Sites

For static sites (HTML/CSS/JS, React/Next.js/Vue builds), you don't need an EC2 server at all. S3 stores files. CloudFront serves them from 300+ edge locations globally — your users get sub-50ms response times regardless of where they are.

User Browser CloudFront 300+ Edge Locations HTTPS · CDN · Cache S3 Bucket Your static files index.html, app.js, etc. ACM Cert Free HTTPS via CloudFront
S3 stores files · CloudFront caches and serves globally with HTTPS

Deploy to S3

# Create an S3 bucket
aws s3 mb s3://your-app-bucket --region us-east-1

# Build your app (React/Next.js/Vue)
npm run build

# Sync build output to S3
aws s3 sync ./dist s3://your-app-bucket   --delete   --cache-control "public, max-age=31536000, immutable"

# HTML files should not be cached aggressively
aws s3 cp dist/index.html s3://your-app-bucket/index.html   --cache-control "no-cache"

# Make bucket private (CloudFront will access it via OAC)
# Don't enable "public access" — use Origin Access Control instead

CloudFront Distribution Setup

# Key CloudFront settings:
# - Origin: your S3 bucket (use Origin Access Control, not public)
# - Origin Access Control (OAC): CloudFront-only access to S3
# - Default root object: index.html
# - Price class: Use only North America and Europe (cheaper)
# - Alternate domain: yourapp.com
# - SSL certificate: from ACM (must be in us-east-1!)
# - Error pages: 404 → /index.html (for SPAs with client-side routing)

# Invalidate cache after deploy (forces CloudFront to fetch fresh files)
aws cloudfront create-invalidation   --distribution-id E1234567890ABC   --paths "/*"

# Check distribution status
aws cloudfront get-distribution   --id E1234567890ABC   --query 'Distribution.Status'
⚠️ ACM must be in us-east-1

CloudFront only supports ACM certificates from the us-east-1 (N. Virginia) region, regardless of where your other resources are. Always request the cert there.

SPA Routing Fix

React/Vue SPAs handle routing client-side. CloudFront doesn't know about /about — it looks for an S3 object at that path and returns 403/404. Fix this in CloudFront error pages:

# CloudFront → Error pages → Create custom error response:
# HTTP error code: 403
# Response page path: /index.html
# HTTP response code: 200

# Same for 404 → /index.html → 200
# Your SPA's router will then handle the URL

Check Your Understanding

1. You deploy a React SPA to S3/CloudFront. Users get 403 errors when navigating directly to /dashboard. What's the fix?
2. You deploy new files to S3 but CloudFront still serves old content. What do you need to do?
3. ACM (AWS Certificate Manager) certificates for CloudFront must be in which region?