Static Website Hosting

Prerequisites

  • AWS account with appropriate permissions
  • Terraform >= 1.0
  • Domain name (optional, for custom domain)

Step 1: Create the S3 Bucket

module "website_bucket" {
  source  = "registry.patterneddesigns.ca/essentials/s3-bucket/aws"
  version = "3.0.0"

  bucket_name        = "my-static-website"
  versioning_enabled = true
}

Step 2: Configure CloudFront

resource "aws_cloudfront_origin_access_control" "main" {
  name                              = "website-oac"
  origin_access_control_origin_type = "s3"
  signing_behavior                  = "always"
  signing_protocol                  = "sigv4"
}

resource "aws_cloudfront_distribution" "website" {
  enabled             = true
  default_root_object = "index.html"

  origin {
    origin_id                = "s3"
    domain_name              = module.website_bucket.bucket_regional_domain_name
    origin_access_control_id = aws_cloudfront_origin_access_control.main.id
  }

  default_cache_behavior {
    target_origin_id       = "s3"
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods        = ["GET", "HEAD"]
    cached_methods         = ["GET", "HEAD"]

    forwarded_values {
      query_string = false
      cookies { forward = "none" }
    }
  }

  restrictions {
    geo_restriction { restriction_type = "none" }
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }
}

Step 3: Add Bucket Policy

resource "aws_s3_bucket_policy" "website" {
  bucket = module.website_bucket.bucket_id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "cloudfront.amazonaws.com" }
      Action    = "s3:GetObject"
      Resource  = "${module.website_bucket.bucket_arn}/*"
      Condition = {
        StringEquals = {
          "AWS:SourceArn" = aws_cloudfront_distribution.website.arn
        }
      }
    }]
  })
}

Step 4: Deploy and Upload Content

Run terraform apply and upload your website files:

aws s3 sync ./public/ s3://my-static-website/

Step 5: Access Your Website

Your website is now available at the CloudFront distribution URL shown in the Terraform output.