Amazon S3 (Simple Storage Service) is a versatile object storage service that offers industry-leading scalability, data availability, security, and performance. One of its many use cases is static website hosting. In this blog post, we'll explore how to set up an S3 bucket for static website hosting using Terraform.
Why Use S3 for Static Website Hosting?
- Highly scalable and reliable
- Cost-effective for static content
- Easy to integrate with CDNs like CloudFront
- Supports custom domain names
- Automatic versioning and backup options
Prerequisites
Before we begin, ensure you have:
- An AWS account
- Terraform installed on your local machine
- AWS CLI configured with appropriate credentials
Step-by-Step Implementation
1. Set Up the Terraform Configuration
Create a new directory for your Terraform project and initialize it:
mkdir s3-static-website
cd s3-static-website
terraform init
2. Create the Main Terraform File
Create a file named main.tf with the following content:
provider "aws" {
region = "us-west-2" # Change this to your preferred region
}
resource "aws_s3_bucket" "static_website" {
bucket = "your-unique-bucket-name" # Change this to a unique name
acl = "public-read"
website {
index_document = "index.html"
error_document = "error.html"
}
tags = {
Name = "Static Website Bucket"
}
}
resource "aws_s3_bucket_policy" "static_website_policy" {
bucket = aws_s3_bucket.static_website.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "PublicReadGetObject"
Effect = "Allow"
Principal = "*"
Action = "s3:GetObject"
Resource = "${aws_s3_bucket.static_website.arn}/*"
},
]
})
}
output "website_endpoint" {
value = aws_s3_bucket.static_website.website_endpoint
}
3. Explanation of the Terraform Code
- aws_s3_bucket resource: Creates an S3 bucket with website hosting enabled.
- acl = "public-read": Makes the bucket contents publicly readable.
- website block: Configures the bucket for static website hosting, specifying index and error documents.
- aws_s3_bucket_policy resource: Attaches a policy to the bucket allowing public read access to all objects.
- output block: Displays the website endpoint URL after Terraform applies the configuration.
4. Deploy the Infrastructure
Run the following commands to create the S3 static website:
terraform plan
terraform apply
5. Upload Your Website Content
After the infrastructure is created, you can upload your website files to the S3 bucket:
aws s3 sync ./your-website-folder s3://your-unique-bucket-name
Advanced Configurations
Custom Domain with Route 53
To use a custom domain, you can add the following Terraform code:
resource "aws_route53_zone" "main" {
name = "yourdomain.com"
}
resource "aws_route53_record" "website" {
zone_id = aws_route53_zone.main.zone_id
name = "www.yourdomain.com"
type = "A"
alias {
name = aws_s3_bucket.static_website.website_domain
zone_id = aws_s3_bucket.static_website.hosted_zone_id
evaluate_target_health = false
}
}
CloudFront Distribution
To improve performance and security, you can add a CloudFront distribution:
resource "aws_cloudfront_distribution" "s3_distribution" {
origin {
domain_name = aws_s3_bucket.static_website.bucket_regional_domain_name
origin_id = "S3-${aws_s3_bucket.static_website.id}"
}
enabled = true
default_root_object = "index.html"
default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "S3-${aws_s3_bucket.static_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 {
geo_restriction {
restriction_type = "none"
}
}
viewer_certificate {
cloudfront_default_certificate = true
}
}
Conclusion
Using Terraform to set up an S3 static website provides a scalable, cost-effective, and easily manageable solution for hosting static content. By leveraging AWS services like Route 53 and CloudFront, you can further enhance your website's performance and security.
Remember to always follow AWS best practices, especially regarding security and cost optimization. Happy hosting!