Setting up AWS CloudFront with Terraform
A comprehensive guide to deploying and configuring Amazon CloudFront CDN using Terraform Infrastructure as Code
Setting up AWS CloudFront with Terraform
Amazon CloudFront is a fast content delivery network (CDN) service that securely delivers data, videos, applications, and APIs to customers globally. This guide shows how to set up CloudFront using Terraform.
Video Tutorial
Learn more about managing AWS CloudFront with Terraform in this comprehensive video tutorial:
Prerequisites
- AWS CLI configured
- Terraform installed
- S3 bucket or origin server ready
- SSL certificate (optional)
- Basic understanding of CDN concepts
Project Structure
aws-cloudfront-terraform/
├── main.tf
├── variables.tf
├── outputs.tf
└── terraform.tfvars
Basic CloudFront Configuration
# main.tf
provider "aws" {
region = var.aws_region
}
# CloudFront distribution
resource "aws_cloudfront_distribution" "s3_distribution" {
enabled = true
is_ipv6_enabled = true
comment = "My CloudFront Distribution"
default_root_object = "index.html"
price_class = "PriceClass_100"
# Origin configuration
origin {
domain_name = aws_s3_bucket.website.bucket_regional_domain_name
origin_id = "S3-${aws_s3_bucket.website.id}"
s3_origin_config {
origin_access_identity = aws_cloudfront_origin_access_identity.oai.cloudfront_access_identity_path
}
}
# Default cache behavior
default_cache_behavior {
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "S3-${aws_s3_bucket.website.id}"
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
viewer_protocol_policy = "redirect-to-https"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}
# Restrictions
restrictions {
geo_restriction {
restriction_type = "none"
}
}
# SSL certificate
viewer_certificate {
cloudfront_default_certificate = true
}
tags = {
Environment = var.environment
}
}
# Origin Access Identity
resource "aws_cloudfront_origin_access_identity" "oai" {
comment = "OAI for ${var.project_name}"
}
Custom Domain and SSL Configuration
resource "aws_cloudfront_distribution" "custom_domain" {
# ... other configuration ...
aliases = ["cdn.${var.domain_name}"]
viewer_certificate {
acm_certificate_arn = aws_acm_certificate.cert.arn
minimum_protocol_version = "TLSv1.2_2021"
ssl_support_method = "sni-only"
}
}
# ACM Certificate
resource "aws_acm_certificate" "cert" {
provider = aws.us-east-1 # CloudFront requires certificates in us-east-1
domain_name = "cdn.${var.domain_name}"
validation_method = "DNS"
tags = {
Environment = var.environment
}
lifecycle {
create_before_destroy = true
}
}
Custom Cache Behaviors
resource "aws_cloudfront_distribution" "custom_behaviors" {
# ... other configuration ...
# API path pattern
ordered_cache_behavior {
path_pattern = "/api/*"
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD"]
target_origin_id = var.api_origin_id
forwarded_values {
query_string = true
headers = ["Authorization"]
cookies {
forward = "all"
}
}
viewer_protocol_policy = "https-only"
min_ttl = 0
default_ttl = 0
max_ttl = 0
}
# Static assets pattern
ordered_cache_behavior {
path_pattern = "/static/*"
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
target_origin_id = var.static_origin_id
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
viewer_protocol_policy = "redirect-to-https"
min_ttl = 0
default_ttl = 86400 # 24 hours
max_ttl = 31536000 # 1 year
}
}
Function Associations
# CloudFront Function
resource "aws_cloudfront_function" "url_rewrite" {
name = "url-rewrite"
runtime = "cloudfront-js-1.0"
comment = "URL rewrite function"
publish = true
code = file("${path.module}/functions/url-rewrite.js")
}
resource "aws_cloudfront_distribution" "with_functions" {
# ... other configuration ...
default_cache_behavior {
# ... other settings ...
function_association {
event_type = "viewer-request"
function_arn = aws_cloudfront_function.url_rewrite.arn
}
}
}
Variables Configuration
# variables.tf
variable "aws_region" {
description = "AWS region"
type = string
default = "us-west-2"
}
variable "project_name" {
description = "Project name"
type = string
}
variable "domain_name" {
description = "Domain name"
type = string
}
variable "environment" {
description = "Environment name"
type = string
default = "production"
}
variable "price_class" {
description = "CloudFront distribution price class"
type = string
default = "PriceClass_100"
}
Best Practices
-
Performance
- Use appropriate cache behaviors
- Configure proper TTL values
- Enable compression
- Use modern TLS versions
-
Security
- Use Origin Access Identity for S3
- Implement proper WAF rules
- Use custom SSL certificates
- Configure security headers
-
Cost Optimization
- Choose appropriate price class
- Use cache effectively
- Monitor usage patterns
- Clean up unused distributions
-
Monitoring
- Set up CloudWatch alarms
- Monitor cache hit ratios
- Track error rates
- Enable access logging
WAF Configuration
resource "aws_wafv2_web_acl" "cloudfront" {
name = "${var.project_name}-waf"
description = "WAF for CloudFront distribution"
scope = "CLOUDFRONT"
default_action {
allow {}
}
rule {
name = "AWSManagedRulesCommonRuleSet"
priority = 1
override_action {
none {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesCommonRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWSManagedRulesCommonRuleSetMetric"
sampled_requests_enabled = true
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "CloudFrontWAFMetric"
sampled_requests_enabled = true
}
}
Deployment Steps
- Initialize Terraform:
terraform init
- Plan the deployment:
terraform plan
- Apply the configuration:
terraform apply
Clean Up
Remove all resources when done:
terraform destroy
Common Use Cases
- Static Website Hosting
resource "aws_cloudfront_distribution" "website" {
# ... other configuration ...
custom_error_response {
error_code = 404
response_code = 200
response_page_path = "/index.html"
}
custom_error_response {
error_code = 403
response_code = 200
response_page_path = "/index.html"
}
}
- API Gateway Integration
resource "aws_cloudfront_distribution" "api" {
# ... other configuration ...
origin {
domain_name = replace(aws_apigatewayv2_api.main.api_endpoint, "https://", "")
origin_id = "ApiGateway"
custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "https-only"
origin_ssl_protocols = ["TLSv1.2"]
}
}
}
Conclusion
This setup provides a comprehensive foundation for deploying CloudFront using Terraform. Remember to:
- Plan your CDN architecture carefully
- Implement proper security measures
- Monitor performance and costs
- Keep your configurations versioned
- Test thoroughly before production deployment
The complete code can be customized based on your specific requirements and use cases.