Deploying a static Hugo site to AWS doesn’t have to be a complex ordeal. With Terraform, you can automate the entire infrastructure setup, making future updates and maintenance a breeze. Here’s how to launch your Hugo creation into the cloud with minimal fuss.

Prerequisites

  • Hugo installed locally
  • AWS account with appropriate permissions
  • Terraform installed
  • Your Hugo site ready for deployment

Step 1: Set Up Your Terraform Configuration

Create a new file called main.tf with the following configuration:

provider "aws" {
  region = "us-east-1"
}

# S3 bucket for website hosting
resource "aws_s3_bucket" "hugo_site" {
  bucket = "your-hugo-site-bucket-name"
}

# Configure the bucket for website hosting
resource "aws_s3_bucket_website_configuration" "hugo_site" {
  bucket = aws_s3_bucket.hugo_site.id

  index_document {
    suffix = "index.html"
  }

  error_document {
    key = "404.html"
  }
}

# Make the bucket publicly accessible
resource "aws_s3_bucket_public_access_block" "hugo_site" {
  bucket = aws_s3_bucket.hugo_site.id

  block_public_acls       = false
  block_public_policy     = false
  ignore_public_acls      = false
  restrict_public_buckets = false
}

# Bucket policy to allow public access
resource "aws_s3_bucket_policy" "hugo_site" {
  bucket = aws_s3_bucket.hugo_site.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid       = "PublicReadGetObject"
        Effect    = "Allow"
        Principal = "*"
        Action    = "s3:GetObject"
        Resource  = "${aws_s3_bucket.hugo_site.arn}/*"
      }
    ]
  })
}

# CloudFront distribution for HTTPS and caching
resource "aws_cloudfront_distribution" "hugo_site" {
  origin {
    domain_name = aws_s3_bucket_website_configuration.hugo_site.website_endpoint
    origin_id   = "S3-${aws_s3_bucket.hugo_site.bucket}"
    
    custom_origin_config {
      http_port              = 80
      https_port             = 443
      origin_protocol_policy = "http-only"
      origin_ssl_protocols   = ["TLSv1.2"]
    }
  }

  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.hugo_site.bucket}"
    viewer_protocol_policy = "redirect-to-https"
    
    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }

    min_ttl     = 0
    default_ttl = 3600
    max_ttl     = 86400
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }
}

# Output the website and CloudFront URLs
output "website_endpoint" {
  value = aws_s3_bucket_website_configuration.hugo_site.website_endpoint
}

output "cloudfront_domain" {
  value = aws_cloudfront_distribution.hugo_site.domain_name
}

Step 2: Build and Deploy Your Hugo Site

Create a simple bash script (deploy.sh) to build and upload your site:

#!/bin/bash

# Build the Hugo site
hugo

# Initialize and apply Terraform
terraform init
terraform apply -auto-approve

# Upload the Hugo site to S3
aws s3 sync ./public/ s3://your-hugo-site-bucket-name/ --delete

echo "Deployment complete!"

Make the script executable: chmod +x deploy.sh

Step 3: Execute and Enjoy

Simply run ./deploy.sh and watch as your Hugo site gets:

  1. Built into static files
  2. Provisioned with AWS infrastructure via Terraform
  3. Uploaded to S3
  4. Made available globally through CloudFront

Going Further

This basic setup can be extended with:

  • Custom domain names
  • SSL certificates
  • Multiple environments
  • CI/CD pipeline integration

The beauty of using Terraform is that your infrastructure is now code - version controlled, repeatable, and easily modifiable for future enhancements.