Super simple AWS static website using Terraform

󰃭 2025-07-05 (updated: 2025-07-05 ) 346 words, 2 minutes

Short word on static websites

I’m not going to scratch the surface on the debate between static and dynamic sites. They both are tools and have their respective use cases.

I will, however, assume here that you want (or need) to deploy some static code using the simplest solution as possible.

Note on Terraform: The management of a Terraform stack is a bit out of scope for this article, I will not comment on state management. It is totally possible to use template code as a run-once solution.

Requirements

  1. AWS Account
  2. Route53 Domain
  3. Code to deploy
  4. Terraform installed

Make sure you can run aws sts get-caller-identity successfully on you shell.

Architecture

CDN included. Versioning on the bucket in case you mess up something.

+------+     +----------+     +---------+
|Client| ==> |Cloudfront| ==> |S3 Bucket|
+------+     +----------+     +---------+

Cost

  1. Domain annual cost.
  2. S3 storage, generally pretty low, depends on the size of your site.
  3. Traffic, Cloudfront is the cheapest way of getting data out of AWS.

The code

Using two modules:

Make sure to replace the < > fields with what suits you.

provider "aws" {
  alias  = "global"
  # Has to be us-east-1
  region = "us-east-1"
}

provider "aws" {
  region = <YOUR_REGION>
}

data "aws_route53_zone" "dns_zone" {
  # Like: example.com
  name = <YOUR_DOMAIN>
}
module "s3-static-website" {
  source  = "cn-terraform/s3-static-website/aws"
  version = "1.0.10"
  providers = {
    aws.main         = aws
    aws.acm_provider = aws.global
  }

  # Like: blog.example.com
  name_prefix         = <YOUR_SUBDOMAIN>
  website_domain_name = <YOUR_SUBDOMAIN>


  create_route53_hosted_zone = false
  route53_hosted_zone_id     = data.aws_route53_zone.dns_zone.zone_id
}
module "sync-dir" {
  source                = "MarioMoura/syncdir/aws"
  version               = "~> 0.0"
  # The directory where the static code is
  directory             = <LOCAL_DIR>
  bucket                = module.s3-static-website.website_bucket_id
  cache_control_default = "max-age=3600"
  cache_control_by_extension = {
    html = "max-age=7200"
  }
}

The next few commands will differ depending on your setup, generally a terraform init && terraform apply enough.

Warning: Notice that I left out the backend and provider version configuration. If you need guidance look here.

Probably something like this:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = <VERSION>
    }
  }
  backend "<TYPE>" {
    "<ARGUMENTS>"
  }
}