Terraform module to create a static website with S3 bucket, Cloudfront distribution, ACM TLS certificate, and IAM user for deployments https://registry.terraform.io/modules/santiagon610/static-website-cloudfront-acm/aws/
Find a file
2025-03-20 18:21:25 -04:00
.gitignore chore: clean up resource naming (#9) 2024-07-12 00:37:24 -04:00
.opentofu-version chore(deps): allow aws provider v5 (#10) 2025-03-20 18:21:25 -04:00
cloudfront_index_handler.js minimum viable product (#1) 2022-01-31 20:43:13 -05:00
debug.tf cleanup of the README, relocate debug output (#2) 2022-01-31 21:18:16 -05:00
LICENSE chore(deps): allow aws provider v5 (#10) 2025-03-20 18:21:25 -04:00
main.tf chore(deps): allow aws provider v5 (#10) 2025-03-20 18:21:25 -04:00
moved.tf chore: clean up resource naming (#9) 2024-07-12 00:37:24 -04:00
outputs.tf chore: clean up resource naming (#9) 2024-07-12 00:37:24 -04:00
README.md chore(deps): allow aws provider v5 (#10) 2025-03-20 18:21:25 -04:00
resources.tf chore: clean up resource naming (#9) 2024-07-12 00:37:24 -04:00
variables.tf feat: parameterize geoblock, add IP allow list via WAF (#6) 2024-06-01 17:21:21 -04:00

AWS Static Website w/ CloudFront Distribution, ACM Cert, and IAM User

Want to host a static website on AWS simply and (theoretically) cheaply? Let S3, CloudFront, ACM, and Route 53 do the magic for you with this module.

Features

  • S3 bucket
    • IAM user with permissions to S3 Bucket
  • CloudFront distribution
  • ACM TLS certificates
  • Route 53 records
  • Automatic certificate verification via Route 53
  • Lambda@Edge to handle index.html in subdirectories
  • WAFv2 IP Allow List

Terraform versions

I've tested this on OpenTofu 1.9.0, and seems to be fine. If you find an problem, feel free to raise an issue.

Example Usage

# Production Website
module "prod_website" {
  source          = "santiagon610/static-website-cloudfront-acm/aws"
  version         = "~> 0.1"
  staticsite_name = "Production Website"
  aws_region      = "us-west-2"
  oai_comment     = "prod-website-oai"
  domain_list = [
    "www.example.com",
    "prod.example.com",
    "example.com"
  ]
  s3_bucket_name = "mycompany-website-prod"
  tags = {
    pizza     = "pepperoni"
    doughnuts = "magic"
  }
  index_document           = "index.html"
  error_document           = "404.html"
  dns_zone_id              = aws_route53_zone.example_com.id
  deployer_iam_user        = true
  deployer_iam_user_name   = "prod-website-deployer"
  cloudfront_index_handler = true
  ip_allow_list = [
    "1.2.3.4/32",
    "2.3.4.0/24"
  ]
}

Requirements

Name Version
terraform >= 1.0
aws >= 4.0

Providers

Name Version
aws >= 4.0

Modules

No modules.

Resources

Name Type
aws_acm_certificate.this resource
aws_acm_certificate_validation.this resource
aws_cloudfront_distribution.this resource
aws_cloudfront_function.index_handler resource
aws_cloudfront_origin_access_identity.this resource
aws_iam_access_key.deployer resource
aws_iam_user.deployer resource
aws_iam_user_policy.deployer resource
aws_route53_record.cert_validation resource
aws_route53_record.cloudfront_a resource
aws_s3_bucket.this resource
aws_s3_bucket_acl.this resource
aws_s3_bucket_cors_configuration.this resource
aws_s3_bucket_policy.this resource
aws_s3_bucket_website_configuration.this resource
aws_wafv2_ip_set.this resource
aws_wafv2_web_acl.this resource

Inputs

Name Description Type Default Required
allowed_countries Allowed countries to access Cloudfront hosted resources list(string)
[
"US",
"CA",
"GB",
"MX",
"IN",
"DE",
"NL",
"FR",
"BR",
"JP",
"SG",
"TW",
"KR",
"CO",
"ES",
"AU",
"CH",
"IT",
"PH",
"HK",
"SE",
"CR"
]
no
aws_region AWS region for region-specific resources string "us-east-1" no
cloudfront_index_handler Create Lambda@Edge function to handle index files for subdirectories bool true no
deployer_iam_user Create an IAM user with ability to deploy to the newly created S3 bucket bool false no
deployer_iam_user_name Create an IAM user with ability to deploy to the newly created S3 bucket string "my-static-site-deployer" no
dns_ttl Time to live for DNS records number 60 no
dns_zone_id AWS Route 53 zone ID for DNS zone into which records will be placed string "" no
domain_list List of domains for Cloudfront distribution and ACM certificate list(string)
[
"example.com",
"www.example.com",
"mysite.example.com"
]
no
error_document Default error document for static website string "error.html" no
index_document Default index document for static website string "index.html" no
ip_allow_list List of IP addresses allowed to access Cloudfront hosted resources. If an empty list, all IPs within the allowed countries are allowed to access the static site. list(string) [] no
oai_comment Descriptive string for Origin Access Identity string "undefined" no
s3_bucket_name Name for S3 bucket into which static website will be placed string "s3-bucket-my-static-site" no
skip_acl Skips creation of the ACL for accounts in which this is disallowed bool false no
staticsite_name Descriptive name for static site string "My Static Site" no
tags Optional tags map(string)
{
"pizza": "Pepperoni"
}
no

Outputs

Name Description
deployer_creds Credentials for the deployer user. Useful as an output for programmatic processes to grab via the Terraform state JSON.
distribution_id Cloudfront distribution ID

Authors

License

Unlicense