Deploy a Secure Static Website on AWS with S3, CloudFront, WAF and ACM
Static websites are cheap, fast and hard to break β which makes them a perfect fit for marketing sites, documentation and landing pages. In this guide we'll host one properly on AWS: a private S3 bucket for storage, CloudFront as the global CDN, ACM for HTTPS, and AWS WAF for a layer of protection. This is the exact pattern we teach in the DevOps with AWS program.
The architecture at a glance
The request path looks like this:
User β CloudFront (HTTPS + WAF) β S3 (private, via Origin Access Control)
The golden rule: the S3 bucket is never public. All traffic flows through CloudFront, which is the only thing allowed to read from the bucket.
1. Store the site in a private S3 bucket
Create a bucket and upload your built site (for example the dist/ folder). Keep Block Public Access switched on. We are not using S3 static website hosting β CloudFront will read the objects directly.
2. Put CloudFront in front with Origin Access Control
Create a CloudFront distribution and set the S3 bucket as the origin. Instead of the legacy Origin Access Identity, use the newer Origin Access Control (OAC). CloudFront then signs its requests to S3, and you attach a bucket policy that allows only that distribution to s3:GetObject.
A few settings worth getting right:
- Redirect HTTP to HTTPS in the viewer protocol policy.
- Set a default root object of
index.html. - Add a response headers policy for security headers (HSTS,
X-Content-Type-Options, a Content-Security-Policy).
3. Add a free TLS certificate with ACM
Request a public certificate in AWS Certificate Manager for your domain (e.g. example.com and www.example.com). Validate it with DNS by adding the CNAME records ACM gives you.
Important: CloudFront only reads certificates from the us-east-1 region. Request the certificate there, even if your bucket lives elsewhere.
Once validated, attach the certificate to your distribution and add your domain as an alternate domain name (CNAME).
4. Protect the edge with AWS WAF
Attach a Web ACL to the distribution. A sensible starting point:
- The AWS Managed Rules β Common Rule Set (covers common web exploits).
- A rate-based rule to blunt request floods.
- Optional geo or IP rules if your audience is regional.
5. Point DNS and ship
In Route 53 (or your DNS provider), create an alias / CNAME record pointing your domain at the CloudFront distribution. Give DNS a few minutes, then load the site over https:// and confirm the padlock.
Why this setup is worth the effort
- Security: the bucket is private; WAF filters malicious traffic at the edge.
- Speed: CloudFront caches content close to your users worldwide.
- Cost: for most small sites this runs for a few dollars a month or less.
- Reliability: no servers to patch or keep alive.
That's the same production pattern that powers many real company websites β and something you'll build end-to-end, with your own domain, during the course.
Want to learn this hands-on, live?
Join Waitlist