Having covered the fundamental concepts of Terraform, from file structure and type constraints to functions and data sources, it’s time to apply that knowledge to a real-time project: hosting a static website using a private S3 bucket backed by a CloudFront Distribution. We will build this entire, production-ready architecture using Terraform.
Why We Use CloudFront in Front of S3
While S3 buckets can host static websites directly, this approach is problematic in production. Direct S3 serving often incurs higher data transfer and storage costs, requires the bucket to be publicly accessible (a major security risk), and makes the website vulnerable to DoS attacks.
To solve these challenges, we introduce Amazon CloudFront, a Content Delivery Network (CDN).
CloudFront creates Edge Locations—points of presence geographically close to your users worldwide. These edge locations serve two key purposes:
1. Speed and Cost: Edge locations cache frequently accessed files (like HTML, images, and CSS). When a user requests a file, it is served instantly from the nearest edge location rather than traversing continents to reach the origin S3 bucket. This reduces latency and lowers data transfer costs.
2. Security: By using CloudFront, we can keep the S3 bucket private. Only the CloudFront distribution is granted access to fetch files from the S3 bucket, ensuring users cannot access the bucket directly.
The Secure Architecture
Our goal is to provision an architecture that provides secure access to static files.
Architectural Flow: We need to establish authentication and authorization between the CloudFront Distribution and the private S3 bucket.
• Origin Access Control (OAC): This resource acts as the identity management system that allows only the specified CloudFront Distribution to access the private S3 bucket. This is the recommended, modern approach, replacing the deprecated Origin Access Identity (OAI).
• Bucket Policy: We must attach a bucket policy to the S3 bucket to authorize the CloudFront distribution to perform necessary actions, such as Get and List files, which are required for caching at the edge locations.
Diagram of the Concept:
Imagine users accessing the site globally. Instead of hitting the centralized S3 bucket directly, they hit the closest CloudFront edge location. If the file is cached (TTL, or Time To Live, default is around 24 hours), it’s served immediately. If not, the edge location securely retrieves the file from the private S3 bucket.
Terraform Implementation: Key Resources
To realize this architecture, we define several Terraform resources:
- S3 Bucket & Public Access Block: A private aws_s3_bucket is created, and we use the aws_s3_bucket_public_access_block resource to ensure public access is entirely disabled.
- Origin Access Control (OAC): Defines the secure identity for CloudFront interaction.
- S3 Bucket Policy: This resource grants the OAC identity s3:GetObject and other necessary permissions using a complex JSON structure, which must be encoded using the jsonencode() function in Terraform.
- Uploading Files: Instead of manually uploading static files, we use the aws_s3_object resource combined with iteration functions to upload everything in the local www directory.
- CloudFront Distribution: This resource defines the global CDN, referencing the OAC ID and setting cache behaviors (e.g., allowing only GET and HEAD methods).
This comprehensive approach allows us to deploy secure, high-performance static websites without manually touching the AWS console. While we implemented the core components, follow-up tasks include adding Route 53 DNS records, using an SSL certificate from ACM, and configuring custom error pages for a complete production solution.
Embed the video "14/30 - Host A Static Website In AWS S3 And Cloudfront (using terraform)" from @piyushsachdeva

Top comments (0)