Static Website on AWS – S3 + CloudFront with Terraform
Published Oct 16, 2025
⋅
1 minutes read

This project is a production‑minded static website stack on AWS that focuses on security, reliability, and simplicity. The infrastructure is declared in Terraform and follows best practices: private S3 origin behind CloudFront, encryption at rest, and managed Terraform state with locking.
What This Project Does
- Secure static hosting: CloudFront serves
index.htmlfrom a private S3 bucket via Origin Access Control (OAC). - Hardened storage: S3 public access is blocked; reads are allowed only through CloudFront by policy.
- Encryption‑first: server‑side encryption (SSE) on buckets.
- Productized IaC: separate bootstrap stack for remote state (S3 + DynamoDB locks); clean outputs after
apply.
Why I Built It
- Practice real‑world IaC patterns for static sites on AWS
- Security by default vs. public S3 website
- Repeatable deployment across environments
- Minimal yet production‑aligned, easy to extend with CI/CD
High‑Level Architecture
- CloudFront distribution serves content to users over HTTPS
- Private S3 origin; CloudFront reads via OAC
- Bucket policy allows reads only from the specific distribution
- Terraform state stored in versioned S3 with DynamoDB locks (bootstrap stack)

Key Components
S3 Bucket (Origin)
- Private bucket; Block Public Access enabled; SSE enabled
CloudFront Distribution
index.htmlas default root; HTTPS enforced; managed cache/headers policies; OAC to S3
Terraform State (Bootstrap)
- Versioned S3 bucket and a DynamoDB table for state locks; main stack uses this backend
How It Works (End‑to‑End)
- Terraform creates a private S3 bucket and uploads the site assets
- Provisions a CloudFront distribution + OAC
- Bucket policy restricts access to that distribution
- Users access the site via the CloudFront domain over HTTPS
Notable Defaults and Parameters
- Region defaults to
eu-central-1 - Resource names use a prefix and random suffix for collision resistance
Frontend
A minimalist single‑page HTML highlights the stack and learning goals while keeping bundle size small.
Security Posture
- S3 public access fully blocked
- Objects encrypted at rest
- Access mediated by CloudFront (OAC + strict bucket policy)
- Terraform state versioned and protected with locks
How to Deploy (high level)
- Bootstrap remote backend (S3 + DynamoDB locks)
- Configure backend in the main stack; run
terraform init/plan/apply - Upload site assets to S3; integrate CI/CD as needed
What I’d Improve Next
- CI/CD to plan on PRs and apply on main
- Custom domain + ACM TLS for CloudFront
- Cache invalidations on content updates
- Monitoring/alerts for CloudFront and error rates