Hosting a static website in Amazon S3 is quite simple. In fact, this very website is hosted as such.

However, every single time I configured something by hand on the AWS Console, I ended up regretting and blaming my laziness.

Here’s a very simple Terraform stack to get started:

variable host {
    type = string
    default = "myblog.com"
}

data "aws_iam_policy_document" "bucket_policy" {
  statement {
    actions = ["s3:GetObject"]

    resources = [
      "arn:aws:s3:::${var.host}/*",
    ]
  }
}

resource "aws_s3_bucket" "myblog" {
    bucket = var.host

    policy = data.aws_iam_policy_document.bucket_policy.json
    
    website {
        index_document = "index.html"
        error_document = "404.html"
    }
}

output "website_endpoint" {
    value = aws_s3_bucket.myblog.website_endpoint
}

This terraform stack will create an S3 bucket, configured for Static Website Hosting and emit an output value with the S3 generated DNS public name to access the website.

That hostname is not going to be nice or comfortable, so, the next step is to put that in the DNS settings for our domain. I use Cloudflare, so the next logical step for me is to create a DNS CNAME.

Again, we can do this by hand, on the Cloudflare dashboard, or following Infrastructure as Code rules, by using the Terraform Cloudflare provider.

resource "cloudflare_record" "root" {
  zone_id = var.cloudflare_zone_id
  name    = var.host
  value   = aws_s3_bucket.myblog.website_endpoint
  type    = "CNAME"
  ttl     = 60
}

This does assume you have already set up your Cloudflare provider, and have a cloudflare_zone_id variable.