Cloud-Native Static Platform on AWS
Designed and deployed a secure, globally distributed static delivery platform using AWS S3, CloudFront, Route 53, and ACM — fully provisioned with Terraform and deployed via GitHub Actions with keyless IAM OIDC authentication.
Traditional public S3 static hosting exposes the origin directly, lacks security controls, and offers no CDN performance. Any direct S3 URL bypasses HTTPS enforcement and rate limiting.
CloudFront acts as the single secure entry point. The S3 bucket is fully private — accessible only via Origin Access Control. Terraform provisions every resource. GitHub Actions deploys with IAM OIDC (no long-lived keys).
Public S3 buckets expose the origin URL directly — anyone can bypass CloudFront and hit the bucket with no rate limiting, no caching, and no HTTPS enforcement. Origin Access Control (OAC) locks the bucket to CloudFront only via SigV4-signed requests, keeping the origin fully private.
CloudFront provides global edge delivery, automatic HTTPS termination, and a 1TB/month free tier. For a static portfolio, it's more performant and cheaper than running an EC2 instance, and removes all server maintenance overhead.
Manual console setups are not reproducible and don't survive team collaboration or disaster recovery. Terraform makes the entire infrastructure version-controlled, reviewable, and re-deployable from scratch in minutes.
Next.js static export generates index.html files inside directories. Without a viewer-request rewrite, direct navigation to /projects/ returns AccessDenied from S3. A lightweight CloudFront Function rewrites clean URLs to their index.html equivalent at the edge — no Lambda cold starts needed.
CloudFront Functions must be published before they can be attached to a distribution behaviour — creating the function is not enough.
Next.js static export requires trailingSlash: true in next.config.ts so every page exports as /route/index.html, which aligns with the CloudFront URL rewrite logic.
ACM certificates for CloudFront must be requested in us-east-1 regardless of where your S3 bucket is — this is a hard CloudFront requirement.
Terraform state files must never be committed to Git. The .terraform/ directory and *.tfstate files should be in .gitignore from day one.