S3 + CloudFront Static Website Example π#
Host a secure, globally-distributed static website using S3, CloudFront, WAF, and optional custom domain with HTTPS.
Architecture#
ββββββββββββ ββββββββββββββββ ββββββββββββ
β S3 Bucket βββββββ CloudFront βββββββ User β
β (Origin) β β (CDN + WAF) β β Browser β
ββββββββββββ ββββββββββββββββ ββββββββββββ
β
βΌ
ββββββββββββββββ
β WAF Web ACL β
β (Rate Limit β
β + Security)β
ββββββββββββββββFeatures#
- S3 Origin β Private bucket with CloudFront-only access (OAC)
- CloudFront CDN β Global edge network with HTTPS enforcement
- WAF β Rate limiting, managed rules, and bot control
- Custom Domain β Optional Route53 + ACM SSL certificate
- Versioning β S3 versioning for rollback and CI/CD
- Compression β Automatic content compression at edge
- Error Pages β Custom 403/404 error responses
Security Controls#
| Control | Implementation |
|---|---|
| Public Access | β Blocked via PublicAccessBlock |
| Origin Access | β CloudFront OAC (not OAI) |
| Encryption | β AES256 server-side |
| WAF Rate Limit | β 1000 req/min per IP |
| Managed Rules | β AWS Common Rule Set |
| Bot Control | β AWSManagedRulesBotControl |
Usage#
# Initialize
terraform init
# Deploy with CloudFront default domain
terraform apply
# Test
curl -I https://$(terraform output -raw cloudfront_domain)
# Deploy with custom domain
terraform apply \
-var="domain_name=example.com" \
-var="hosted_zone_id=Z1234567890"
# Deploy website content
aws s3 sync ./my-website/ s3://$(terraform output -raw s3_bucket_name)/ --delete
# Invalidate cache
aws cloudfront create-invalidation \
--distribution-id $(terraform output -raw cloudfront_distribution_id) \
--paths "/*"
# Clean up
terraform destroyLevel#
βββ Intermediate β S3, CloudFront, WAF, Route53
Files#
| File | Description |
|---|---|
main.tf |
Complete static website with S3, CloudFront, WAF, optional domain/HTTPS |