A Terraform demo showcasing a corporate website architecture using AWS CloudFront, S3, and Application Load Balancer (ALB) for serving both static and dynamic content. Features document management and API endpoints.
This demo implements a web application with the following components:
- Purpose: Content delivery network
- Two Origins:
- S3 bucket for static assets (images, CSS, JS)
- ALB for dynamic content (APIs, HTML pages)
- Three Behaviors:
/static/*→ S3 (CachingOptimized policy, 1-year TTL)/api/*→ ALB (CachingDisabled policy, all headers forwarded)/*(default) → ALB (HTML pages with HTTPS redirect)
- Features: Compression, HTTP/3, Origin Access Control (OAC)
- Purpose: Private storage for static assets
- Security: Origin Access Control (OAC) - only CloudFront can access
- Features: Versioning enabled, public access blocked
- Assets: CSS, JavaScript, SVG images, logos
- Cache Headers:
public, max-age=31536000, immutable
- Purpose: Distributes traffic across EC2 instances
- Location: Public subnets across multiple AZs
- Health Checks:
/healthzendpoint - Target Group: EC2 instances in private subnets
- Security: Allows traffic from CloudFront IP ranges
- Purpose: Serves dynamic content and API endpoints
- Instance Type: t3.micro (configurable)
- Count: 2 instances (configurable)
- Location: Private subnets for security
- Web Server: Flask application server
- API Endpoints:
/api/contact,/api/newsletter,/api/careers,/healthz - Features: File upload/download, corporate document management
- VPC: 10.0.0.0/16 CIDR block
- Public Subnets: 2 AZs with Internet Gateway access
- Private Subnets: 2 AZs with NAT Gateway access
- Security Groups: Configured for CloudFront traffic
- DNS: Enabled for hostname resolution
- Document management system
- Static asset caching via CloudFront
- Dynamic API endpoints
- File upload/download functionality
- Social media integration
- AWS CLI configured with appropriate permissions
- Terraform >= 1.0
- AWS Account with sufficient permissions for:
- CloudFront distributions
- S3 buckets and policies
- VPC, subnets, security groups
- EC2 instances and Auto Scaling Groups
- IAM roles and policies
# Clone and navigate to the project
git clone <repository-url>
cd tf-aws-cloudfront-s3-alb-demo
# Initialize Terraform
terraform init
# Review the plan
terraform plan
# Deploy the infrastructure
terraform apply
# Note the outputs, especially:
# - cloudfront_url: Your demo website URL
# - s3_bucket_name: Static assets bucket
# - alb_url: Direct ALB access (for testing)# Get the CloudFront URL from outputs
terraform output cloudfront_url
# Open in browser: https://your-cloudfront-domain.cloudfront.net- Upload files using the file upload form
- Download uploaded files
- Delete files from the corporate document library
- View file metadata (size, modification date)
Expected Behavior:
- Files stored in S3
corporate/directory - Secure file access via presigned URLs
- Real-time file listing updates
- Click "Test Contact API" button → Calls
/api/contact - Click "Test Newsletter API" button → Calls
/api/newsletter - Click "Test Careers API" button → Calls
/api/careers - Click "Check Health" button → Calls
/healthz
Expected Behavior:
- Always fresh responses (no caching)
- Different instance IDs on refresh (load balancing)
- Real-time data (current timestamps)
- Corporate branding in responses
- CSS, JavaScript, and SVG files served from CloudFront
- Social media icons (Twitter/X, LinkedIn, GitHub)
- Company logo and favicon
Expected Headers:
X-Cache: Hit/Miss statusX-Cache-Hit: Cache hit detailsX-Amz-Cf-Pop: Edge location (e.g.,LAX3-C1)X-Amz-Cf-Id: CloudFront request IDCache-Control:public, max-age=31536000, immutable
/static/style.css- Corporate website styles/static/script.js- Interactive JavaScript functionality/static/logo.svg- TechCorp Solutions logo/static/twitter.svg- Twitter/X social media icon/static/linkedin.svg- LinkedIn social media icon/static/github.svg- GitHub social media icon/static/favicon.svg- Website favicon/static/robots.txt- SEO robots file
/api/contact- Contact form submission/api/newsletter- Newsletter signup/api/careers- Job application submission/healthz- Health check endpoint
/upload- File upload endpoint/download/<filename>- File download via presigned URL/delete/<filename>- File deletion endpoint
# Check distribution status
aws cloudfront get-distribution --id <distribution-id>
# Verify behaviors
aws cloudfront get-distribution-config --id <distribution-id>Validation Points:
- ✅ Distribution is deployed and enabled
- ✅ Two origins configured (S3 and ALB)
- ✅ Three behaviors configured correctly
- ✅ OAC is attached to S3 origin
- ✅ Compression and HTTP/3 enabled
# List bucket contents
aws s3 ls s3://<bucket-name>/
# Check bucket policy
aws s3api get-bucket-policy --bucket <bucket-name>
# Verify public access is blocked
aws s3api get-public-access-block --bucket <bucket-name>Validation Points:
- ✅ Bucket is private (no public access)
- ✅ Static assets are uploaded
- ✅ Bucket policy allows CloudFront OAC only
- ✅ Versioning is enabled
# Check ALB status
aws elbv2 describe-load-balancers --names <alb-name>
# Check target group health
aws elbv2 describe-target-health --target-group-arn <target-group-arn>Validation Points:
- ✅ ALB is active and healthy
- ✅ Target group has healthy instances
- ✅ Health checks are passing
- ✅ Security groups allow CloudFront traffic
# Check instance status
aws ec2 describe-instances --filters "Name=tag:Project,Values=cf-s3-alb-demo"
# Check Auto Scaling Group
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names <asg-name>Validation Points:
- ✅ Instances are running and healthy
- ✅ Auto Scaling Group has desired capacity
- ✅ Instances are in private subnets
- ✅ Apache is running and serving content
# Check VPC configuration
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=cf-s3-alb-demo-vpc"
# Check subnets
aws ec2 describe-subnets --filters "Name=vpc-id,Values=<vpc-id>"Validation Points:
- ✅ VPC is created with correct CIDR
- ✅ Public and private subnets in different AZs
- ✅ NAT Gateways are active
- ✅ Route tables are configured correctly
# Test cache behavior with curl
curl -I https://your-cloudfront-domain.cloudfront.net/static/logo.svg
# Check response headers
# First request: X-Cache: Miss
# Second request: X-Cache: Hit# Test from different regions (if you have access)
# Use online tools like:
# - GTmetrix
# - WebPageTest
# - PingdomAfter deployment, you'll get:
- cloudfront_url: Main demo website URL
- cloudfront_domain_name: CloudFront distribution domain
- s3_bucket_name: Static assets bucket name
- alb_url: Direct ALB access URL (for testing)
- vpc_id: VPC identifier
- public_subnet_ids: Public subnet IDs
- private_subnet_ids: Private subnet IDs
# Destroy all resources
terraform destroy
# Note: CloudFront distributions can take 15+ minutes to delete
# S3 buckets with versioning may need manual cleanup- Low Latency: Static assets cached at edge locations globally
- High Availability: Multi-AZ deployment with Auto Scaling
- Security: Private S3 bucket with OAC, ALB in public subnets
- Cost Effective: Pay only for resources used, CloudFront pricing
- Scalable: Auto Scaling Group handles traffic spikes
- Global Reach: 200+ edge locations worldwide
# Check S3 bucket policy
aws s3api get-bucket-policy --bucket <bucket-name>
# Verify OAC configuration
aws cloudfront get-origin-access-control --id <oac-id># Check ALB target group health
aws elbv2 describe-target-health --target-group-arn <target-group-arn>
# Check security groups
aws ec2 describe-security-groups --group-ids <security-group-id># Check CloudFront behaviors
aws cloudfront get-distribution-config --id <distribution-id>
# Verify cache policies
aws cloudfront get-cache-policy --id <cache-policy-id>- Check CloudFront edge location in response headers
- Verify static assets are being cached
- Check ALB target group health
- Monitor CloudWatch metrics
- CloudFront: Pay per request and data transfer
- S3: Pay for storage and requests
- ALB: Pay per hour and per LCU
- EC2: Pay for instance hours (t3.micro is free tier eligible)
- NAT Gateway: Pay per hour and data processed
Estimated Monthly Cost: $10-20 for demo usage