Skip to main content

Command Palette

Search for a command to run...

Static Website Hosting on AWS using Terraform

Updated
5 min read
Static Website Hosting on AWS using Terraform

👩‍💻 Project Overview

In this beginner-level DevOps project, we will use Terraform to provision infrastructure on AWS Cloud for hosting a static website. This project is designed to help you understand how to automate cloud resource creation using Infrastructure as Code (IaC) principles.

  • In this project, I explored how to host a basic static website in the cloud using Terraform and AWS S3, aiming to simplify the deployment process through automation.

    Instead of manually setting up the infrastructure, I used Terraform scripts to define everything needed—such as the S3 bucket, website settings, access policies, and file uploads. This approach turned a potentially time-consuming task into a quick, repeatable process.

    By automating the creation and configuration of cloud resources, I was able to deploy a fully functional website in just a few steps. It demonstrates how anyone with basic technical skills can manage cloud infrastructure more efficiently using Infrastructure as Code (IaC).

    🔧 What the Project Shows:

    • How to use Terraform to automate AWS infrastructure setup.

    • How to configure an S3 bucket for static website hosting.

    • The benefits of avoiding manual steps for faster, error-free deployment.

Objectives

  • Create an S3 bucket using Terraform.

  • Upload index.html and error.html to the bucket.

  • Enable static website hosting on the bucket.

  • Make the bucket and objects publicly accessible.

  • Output the website URL after deployment.

Project Folder Structure

Step 1: Prerequisites

  • AWS account with IAM user credentials.

  • Terraform installed: https://www.terraform.io/downloads

  • Basic understanding of AWS and Terraform commands.

Step 2: Write Terraform Configuration

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>Akshatha Site</title>
  <style>
    body {
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      background-color: #f0f8ff;
      color: #333;
      margin: 0;
      padding: 0;
    }

    header {
      background-color: #6a5acd;
      color: white;
      text-align: center;
      padding: 2rem 1rem;
    }

    main {
      padding: 2rem;
      text-align: center;
    }

    footer {
      background-color: #333;
      color: white;
      text-align: center;
      padding: 1rem 0;
      position: fixed;
      width: 100%;
      bottom: 0;
    }

    a {
      color: #6a5acd;
      text-decoration: none;
    }

    a:hover {
      text-decoration: underline;
    }
  </style>
</head>
<body>
  <header>
    <h1>Welcome to Akshatha Site</h1>
    <p>Your personal space on the web</p>
  </header>

  <main>
    <h2>About Me</h2>
    <p>Hello! I'm Akshatha. I'm enthusiastic about AWS, DevOps, and cloud-based development.</p>
    <p>This is a sample website showcasing my interests and projects.</p>

    <h2>Projects</h2>
    <ul style="list-style: none; padding-left: 0;">
      <li>✔️ AWS S3 Static Website Hosting</li>
      <li>✔️ Terraform Infrastructure as Code</li>
      <li>✔️ CI/CD with GitHub Actions</li>
    </ul>

    <h2>Contact</h2>
    <p>Email: akshatha@example.com</p>
    <p>LinkedIn: <a href="https://linkedin.com/in/yourprofile" target="_blank">linkedin.com/in/yourprofile</a></p>
  </main>

  <footer>
    <p>© 2025 Akshatha Site. All rights reserved.</p>
  </footer>
</body>
</html>

error.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>Error</title>
  <style>
    body {
      margin: 0;
      padding: 0;
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      background-color: #f8d7da;
      color: #721c24;
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100vh;
      flex-direction: column;
    }

    .error-box {
      text-align: center;
      border: 1px solid #f5c6cb;
      background-color: #f1b0b7;
      padding: 40px;
      border-radius: 10px;
      box-shadow: 0 0 10px rgba(0,0,0,0.1);
    }

    h1 {
      font-size: 3rem;
      margin-bottom: 10px;
    }

    p {
      font-size: 1.2rem;
    }

    a {
      display: inline-block;
      margin-top: 20px;
      padding: 10px 20px;
      background-color: #721c24;
      color: #fff;
      text-decoration: none;
      border-radius: 5px;
    }

    a:hover {
      background-color: #501318;
    }
  </style>
</head>
<body>
  <div class="error-box">
    <h1>Oops!</h1>
    <p>Something went wrong or the page you're looking for doesn't exist.</p>
    <a href="index.html">Go Back Home</a>
  </div>
</body>
</html>

provider.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# Configure the AWS Provider
provider "aws" {
  region = "ap-south-1"
}

variables.tf

variable "bucketname" {
  default = "mybucket_static_aks1234_2035"

}

main.tf

resource "random_id" "bucket_id" {
  byte_length = 4
}
resource "aws_s3_bucket" "mybucket_25" {
  bucket = "my-unique-bucket-${random_id.bucket_id.hex}"

}
resource "aws_s3_bucket_ownership_controls" "mybucket_25" {
  bucket = aws_s3_bucket.mybucket_25.id

  rule {
    object_ownership = "BucketOwnerPreferred"
  }
}
resource "aws_s3_bucket_public_access_block" "mybucket_25" {
  bucket = aws_s3_bucket.mybucket_25.id

  block_public_acls   = false
  block_public_policy = false
  ignore_public_acls = false
  restrict_public_buckets = false
}
resource "aws_s3_bucket_acl" "mybucket_25" {
  depends_on = [ 
    aws_s3_bucket_ownership_controls.mybucket_25,
    aws_s3_bucket_public_access_block.mybucket_25,
  ]
  bucket = aws_s3_bucket.mybucket_25.id
  acl    = "public-read"
}
# Resource to avoid error "AccessControlListNotSupported: The bucket does not allow ACLs"
resource "aws_s3_bucket_ownership_controls" "public_storage" {
  bucket = aws_s3_bucket.mybucket_25.id
  rule {
    object_ownership = "ObjectWriter"
  }
}
resource "aws_s3_object" "index" {
  bucket = aws_s3_bucket.mybucket_25.id
  key="index.html"
  source="index.html"
  acl="public-read"
  content_type="text/html"
}

resource "aws_s3_object" "error" {
  bucket = aws_s3_bucket.mybucket_25.id
  key="error.html"
  source="error.html"
  acl="public-read"
  content_type="text/html"
}
resource "aws_s3_bucket_website_configuration" "website" {
  bucket=aws_s3_bucket.mybucket_25.id
  index_document {
    suffix="index.html"
  }
  error_document {
   key="error.html"  
  }
  depends_on=[aws_s3_bucket_acl.mybucket_25]
}

The provided Terraform code is designed to automatically set up static website hosting, apply bucket policies, and configure public access settings for your AWS S3 bucket. However, it's important to customize the configuration to suit your specific project needs.

Please ensure you:

  • Replace the bucket name with a unique name.

  • Adjust the AWS region as per your deployment preference.

  • Modify any other configurations (like tags, access controls, or file paths) to fit your use case.

Always review the Terraform configuration carefully and refer to the official documentation for updates and best practices. This will help ensure that your setup is not only functional but also secure, efficient, and aligned with your infrastructure goals.

output.tf

To conveniently access your website URL right from your terminal or code editor—without having to log into the AWS Console—you can define an output variable in Terraform.

output "website"{
    value=aws_s3_bucket.mybucket_25.website_endpoint
    description = "The public IP of the EC2 instance"
   # value =aws_s3_bucket.mybucket_25.public_ip
}