Deploy a Static Website in AWS S3 Using Terraform

Cloud Engineer | AWS Community Builder
Search for a command to run...

Cloud Engineer | AWS Community Builder
No comments yet. Be the first to comment.
You have a working Amazon EKS cluster and deployed pods. Now, your pods need secure, fine-grained access to AWS services like S3, DynamoDB, or Secrets Manager, but: You don't want to hardcode AWS cre

As your team and projects grow, managing a single EKS cluster can get complicated. You'll likely have different teams like a "Backend Team" and a "Frontend Team" all needing to deploy their applicatio

Serverless computing with AWS Lambda is one of the most powerful ways to run code in the cloud without managing servers. But when a Lambda function is placed inside a VPC (Virtual Private Cloud) to co

Modern developers want fast CI/CD but without storing long-lived AWS keys.By combining Amazon ECS (Fargate), Amazon ECR, GitHub Actions, and OpenID Connect (OIDC) you can deploy securely and automatic

Learn Bash Scripting: A Beginner's Guide Table of Contents Introduction Bash Scripting Basics Variables and User Input Conditional Statements Loops and Iterations Functions Working with Files Scripting Best Practices Conclusion 1. Introdu...

Individuals and businesses must have a web presence in today's digital world. Whether you're a developer trying to exhibit your portfolio or a firm launching a new product, rapidly and efficiently creating a website is critical. Amazon Web Services (AWS) delivers a dependable and cost-effective hosting platform. Terraform is a sophisticated infrastructure-as-code tool for defining and provisioning AWS resources. This blog will walk you through deploying a static website in AWS S3 using Terraform.
Before we dive into the deployment process, make sure you have the following prerequisites in place:
AWS Account: You need an AWS account to access AWS services.
Terraform Installed: Download and install Terraform from the official website.
AWS CLI: Install the AWS Command Line Interface (CLI) and configure it with your AWS credentials. You can install it from here.
Static Website Files: Prepare the static website files (HTML, CSS, JavaScript, images, etc.) you want to deploy. Place them in a directory.
Let's start by setting up your Terraform configuration. Create a file named main.tf and add the following code:
provider "aws" {
region = "us-east-1" # Change this to your desired region
access_key = "your key" # Add your AWS access key ID here
secret_key = "your secret key" # Add your AWS secret access key here
}
This block configures the AWS provider, specifying the AWS region and your access key and secret key. It tells Terraform which cloud provider to interact with and how to authenticate.
resource "aws_s3_bucket" "my-static-website" {
bucket = "mydemostaticwebsite-2324413" # give a unique bucket name
tags = {
Name = "my-demo-static-website"
}
}
Here, you define an S3 bucket resource using the aws_s3_bucket resource type. It creates an S3 bucket with the specified name and sets tags to provide metadata for the bucket.
resource "aws_s3_bucket_website_configuration" "my-static-website" {
bucket = aws_s3_bucket.my-static-website.id
index_document {
suffix = "index.html"
}
error_document {
key = "error.html"
}
}
This block configures the S3 bucket to act as a static website. It specifies the index document (the default file to load when accessing the website's root) and the error document (the page to display 404 errors).
resource "aws_s3_bucket_ownership_controls" "my-static-website" {
bucket = aws_s3_bucket.my-static-website.id
rule {
object_ownership = "BucketOwnerPreferred"
}
}
This block sets up ownership controls for the S3 bucket, ensuring that the bucket owner is preferred for objects within the bucket.
resource "aws_s3_bucket_public_access_block" "my-static-website" {
bucket = aws_s3_bucket.my-static-website.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
Here, you configure the public access block settings for the S3 bucket. In this example, public access is allowed for various locations. You can adjust these settings based on your security requirements.
resource "aws_s3_bucket_acl" "my-static-website" {
depends_on = [
aws_s3_bucket_ownership_controls.my-static-website,
aws_s3_bucket_public_access_block.my-static-website,
]
bucket = aws_s3_bucket.my-static-website.id
acl = "public-read"
}
This block sets the bucket access control list (ACL) for the S3 bucket, allowing public read access. It depends on the previous two blocks to ensure proper ownership controls and public access settings.

Keep index.html in the same directory where main.tf is located.
resource "aws_s3_object" "index_html" {
bucket = aws_s3_bucket.my-static-website.id
key = "index.html" # The name you want for the file in the S3 bucket
source = "index.html" # The path to your local index.html file
content_type = "text/html"
# Make the object publicly accessible
acl = "public-read"
}
This block uploads the index.html file from your local directory to the S3 bucket. It also sets the content type and makes the object publicly accessible.
output "website_url" {
value = "http://${aws_s3_bucket.my-static-website.bucket}.s3-website.us-east-1.amazonaws.com"
}
This block defines an output variable that displays the URL of your static website after Terraform applies the configuration. The URL is constructed using the bucket name and the S3 website endpoint.
resource "aws_s3_bucket_policy" "bucket-policy" {
bucket = aws_s3_bucket.my-static-website.id
policy = <<POLICY
{
"Id": "Policy",
"Statement": [
{
"Action": [
"s3:DeleteObject",
"s3:GetObject",
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::mydemostaticwebsite-2324413/*",
"arn:aws:s3:::mydemostaticwebsite-2324413"
],
"Principal": "*"
}
]
}
POLICY
}
This block defines an S3 bucket policy that allows various actions on objects within the bucket and sets the principal to "*" (anyone). This policy ensures public access to the bucket's contents.
The overall above code looks like this.
# main.tf
# Configure the AWS provider with your credentials and desired region
provider "aws" {
region = "us-east-1" # Change this to your desired region
access_key = "your key" # Add your AWS access key ID
secret_key = "your secret key" # Add your AWS secret access key here
}
# Create an S3 bucket and website configuration
resource "aws_s3_bucket" "my-static-website" {
bucket = "mydemostaticwebsite-2324413" # give a unique bucket name
tags = {
Name = "my-demo-static-website"
}
}
resource "aws_s3_bucket_website_configuration" "my-static-website" {
bucket = aws_s3_bucket.my-static-website.id
index_document {
suffix = "index.html"
}
error_document {
key = "error.html"
}
}
resource "aws_s3_bucket_ownership_controls" "my-static-website" {
bucket = aws_s3_bucket.my-static-website.id
rule {
object_ownership = "BucketOwnerPreferred"
}
}
resource "aws_s3_bucket_public_access_block" "my-static-website" {
bucket = aws_s3_bucket.my-static-website.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
resource "aws_s3_bucket_acl" "my-static-website" {
depends_on = [
aws_s3_bucket_ownership_controls.my-static-website,
aws_s3_bucket_public_access_block.my-static-website,
]
bucket = aws_s3_bucket.my-static-website.id
acl = "public-read"
}
# Upload index.html from the current directory to the S3 bucket and make it public
resource "aws_s3_object" "index_html" {
bucket = aws_s3_bucket.my-static-website.id
key = "index.html" # The name you want for the file in the S3 bucket
source = "index.html" # The path to your local index.html file
content_type = "text/html"
# Make the object publicly accessible
acl = "public-read"
}
# S3 static website URL
output "website_url" {
value = "http://${aws_s3_bucket.my-static-website.bucket}.s3-website.us-east-1.amazonaws.com"
}
# S3 bucket policy
resource "aws_s3_bucket_policy" "bucket-policy" {
bucket = aws_s3_bucket.my-static-website.id
policy = <<POLICY
{
"Id": "Policy",
"Statement": [
{
"Action": [
"s3:DeleteObject",
"s3:GetObject",
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::mydemostaticwebsite-2324413/*",
"arn:aws:s3:::mydemostaticwebsite-2324413"
],
"Principal": "*"
}
]
}
POLICY
}
Open your terminal and navigate to the directory containing your main.tf file.
Run the following Terraform commands:
terraform init
terraform init primarily initializes the AWS provider, installs the required provider plugin, validates the configuration files, sets up a local backend for state management, and prepares the project directory for further Terraform commands like terraform plan and terraform apply.

terraform apply --auto-approve
In the provided Terraform code, running terraform apply --auto-approve initiates applying infrastructure changes defined in the configuration without requiring manual confirmation. It automates the approval of changes, executes the planned actions, and provides the output, including the URL of the static website, as specified in the configuration. Use this flag cautiously and ensure you've reviewed your configuration carefully before applying changes, especially in production environments.
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Outputs:
website_url = "http://mydemostaticwebsite-2324413.s3-website.us-east-1.amazonaws.com"
Once the deployment is complete, Terraform will display the URL of your static website. You can access your website using this URL.

On clicking the website_url, you can access your webpage.
In this blog post, you've learned how to create a static website on Amazon S3 using Terraform. By automating the infrastructure setup with Terraform, you can quickly deploy and manage your static websites on AWS. This approach provides a cost-effective and scalable solution for hosting your web content. Start building and deploying your static websites on AWS today!