DEV Community

Cover image for Hosting a Static Website on AWS with S3 and CloudFront using Terraform
Atul Vishwakarma
Atul Vishwakarma

Posted on

Hosting a Static Website on AWS with S3 and CloudFront using Terraform

From Terraform Basics to Real-World Deployment 🚀

As part of my 30 Days of AWS Terraform challenge, Day 14 marked a major milestone in my learning journey: deploying a secure, scalable static website on AWS using Terraform.

This project brought together everything I’ve learned so far—Terraform resources, variables, loops, functions, data sources, and debugging—to build something practical and production-relevant.

Instead of just creating isolated AWS resources, I built a complete architecture for static website hosting using Amazon S3 + CloudFront, fully managed through Infrastructure as Code.


Why Not Just Host Directly on S3?

Hosting a static website directly from an S3 bucket is simple, but it has limitations:

  • Public bucket exposure increases security risks
  • No built-in global caching
  • Slower delivery for international users
  • Harder to scale professionally

To solve this, I implemented a better architecture:

âś… Private S3 bucket for secure storage
âś… CloudFront CDN for global delivery
âś… Origin Access Control (OAC) for secure access
âś… Terraform automation for repeatability


Architecture Overview 🏗️

Key AWS Components Used

1. Private S3 Bucket

I created an S3 bucket to store all website assets:

  • HTML files
  • CSS files
  • JavaScript files
  • Images

Important: Public access was fully blocked to ensure security.

2. Origin Access Control (OAC)

Instead of using the older OAI method, I configured:

Origin Access Control (OAC)

This securely allows CloudFront to fetch content from the private bucket.

3. Bucket Policy

Using Terraform, I wrote a bucket policy that:

  • Allows only CloudFront to access bucket objects
  • Prevents direct public access

This follows AWS security best practices.

4. CloudFront Distribution

CloudFront was used as the CDN layer to:

  • Cache files globally
  • Improve load times
  • Reduce latency
  • Add edge security

This made the project feel much closer to real-world production hosting.


Terraform Concepts Applied ⚙️

This project helped me apply several advanced Terraform concepts:

🔹 for_each + fileset

One of the coolest parts was automating file uploads.

Instead of uploading files manually, I used:

  • fileset() to scan all files in the project folder
  • for_each to upload them dynamically

This made the setup scalable and clean.

🔹 MIME Type Handling

Different file types need proper content types.

Using Terraform functions like lookup(), I dynamically mapped:

  • .html → text/html
  • .css → text/css
  • .js → application/javascript

This ensured browsers rendered the site correctly.

🔹 Modern AWS Provider Practices

While working on the project, I faced deprecation issues.

For example:

  • Older resource: aws_s3_bucket_object
  • Updated resource: aws_s3_object

Debugging these issues taught me an important lesson:

👉 Always refer to the latest Terraform provider documentation.


Key Challenges & Learnings đź’ˇ

This project was not just about deployment—it was about troubleshooting and problem-solving.

Some valuable lessons:

  • Writing correct S3 bucket policies is critical
  • Small syntax issues can break deployments
  • AWS provider updates matter a lot
  • Debugging Terraform errors improves confidence

One big takeaway:

Errors are not setbacks—they are part of the learning process.

Every issue I solved gave me a better understanding of AWS and Terraform internals.


What’s Next? 🔥

This setup is already solid, but to make it production-ready, the next logical steps are:

Future Enhancements

  • Add a custom domain using Route 53
  • Configure HTTPS with AWS ACM
  • Build CI/CD pipelines for automatic deployment
  • Add cache invalidation workflows

These are areas I’m excited to explore next.


Final Thoughts

Day 14 was one of the most rewarding milestones in this challenge so far.

This project showed me how Infrastructure as Code can be used not just to create resources, but to design secure, scalable, and professional cloud systems.

If you’re learning Terraform, I highly recommend trying a project like this. It ties together so many foundational concepts and gives you hands-on experience with real-world architecture.

I’d love to hear your thoughts:
Have you hosted static websites using Terraform? Any best practices or lessons you’ve learned?

Top comments (0)