In our previous post, we leveraged AWS VPC Gateway Endpoint to establish secure connections to S3 over the AWS Private Network.
Continuing our journey into cloud, this installment will focus on harnessing the power of Amazon S3 for static website hosting. We will utilize Terraform to create modular components, streamlining the deployment process and ensuring scalability and maintainability.
You can use Amazon S3 to host a static website. On a static website, individual webpages include static content. They might also contain client-side scripts.
Architecture Overview:
Before we embark on the implementation, let's take a moment to understand the architecture we'll be working with:
Step 1: Create an S3 Bucket:
We'll begin by creating an S3 bucket with a unique name and configuring its public access settings and make it as static website.
####################################################
# S3 static website bucket
####################################################
resource "aws_s3_bucket" "my-static-website" {
bucket = var.bucket_name
tags = merge(local.common_tags, {
Name = "${local.naming_prefix}-s3-bucket"
})
}
####################################################
# S3 public access settings
####################################################
resource "aws_s3_bucket_public_access_block" "static_site_bucket_public_access" {
bucket = aws_s3_bucket.my-static-website.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
####################################################
# S3 bucket static website configuration
####################################################
resource "aws_s3_bucket_website_configuration" "static_site_bucket_website_config" {
bucket = aws_s3_bucket.my-static-website.id
index_document {
suffix = "index.html"
}
error_document {
key = "error.html"
}
}
Step 2: Implement Resource Policies:
To control access to our bucket and its contents, we'll establish resource policies. This could involve defining ownership controls using bucket and object ACLs or crafting resource policies.
####################################################
# S3 bucket policy
####################################################
resource "aws_s3_bucket_policy" "static_site_bucket_policy" {
bucket = var.bucket_name
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "PublicReadGetObject"
Principal = "*"
Action = [
"s3:GetObject",
]
Effect = "Allow"
Resource = [
"arn:aws:s3:::${var.bucket_name}",
"arn:aws:s3:::${var.bucket_name}/*"
]
},
]
})
depends_on = [aws_s3_bucket_public_access_block.static_site_bucket_public_access]
}
Instead of bucket resource policy, we can define bucket/object ACLs to define more granularity (code commented in github repo)
####################################################
# S3 bucket ownership controls and ACL (recommended if you want object level control).
####################################################
resource "aws_s3_bucket_ownership_controls" "static_site_bucket_ownership_controls" {
bucket = aws_s3_bucket.my-static-website.id
rule {
object_ownership = "BucketOwnerPreferred"
}
}
resource "aws_s3_bucket_acl" "static_site_bucket_acl" {
depends_on = [
# aws_s3_bucket_ownership_controls.static_site_bucket_ownership_controls,
aws_s3_bucket_public_access_block.static_site_bucket_public_access,
]
bucket = aws_s3_bucket.my-static-website.id
acl = "public-read"
}
Step 3: Upload Website Files:
With our bucket configured, we'll upload the necessary files comprising our static website.
####################################################
# Upload files to S3 Bucket
####################################################
resource "aws_s3_object" "provision_source_files" {
bucket = aws_s3_bucket.my-static-website.id
# webfiles/ is the Directory contains files to be uploaded to S3
for_each = fileset("webfiles/", "**/*.*")
key = each.value
source = "webfiles/${each.value}"
content_type = each.value
#acl = "public-read" #use this only if you are using Bucket and Object ACLs, defaults to private
}
Steps to Run Terraform
Follow these steps to execute the Terraform configuration:
terraform init
terraform plan
terraform apply -auto-approve
Upon successful completion, Terraform will provide relevant outputs.
Apply complete! Resources: 7 added, 0 changed, 0 destroyed.
Outputs:
static_site_endpoint = "http://my-s3-static-bucket-v1.s3-website-us-east-1.amazonaws.com"
Testing the outcome
S3 Bucket with objects:
Static website hosting enabled:
S3 Public Access Block:
S3 Bucket Policy:
A running website:
Cleanup
Remember to stop AWS components to avoid large bills.
terraform destroy -auto-approve
Notes:
1) In this tutorial, the website was accessed using S3 Bucket Endpoint which will have name of the bucket, we can hide it by creating a CNAME record in Route53 if you have a domain.
2) We can either use bucket policy (used in majority of cases), but we can use bucket ownership controls and bucket/object ACLs to define more granularity. (Code is commented in main.tf, all objects also need to use acl="public-read")
We've successfully set up a static website hosting solution using Amazon S3.
In our next tutorial, we'll explore the integration of Content Delivery Networks (CDNs) to further optimize website performance and enhance user experience.
Resources:
Github Link: https://github.com/chinmayto/terraform-aws-s3-static-website
S3 Static Website: https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html
Top comments (0)