Skip to content

Terraform module to create a static site in AWS using CloudFront, S3, ACM, Route53, etc...

License

Notifications You must be signed in to change notification settings

loganmarchione/terraform-aws-static-site

Repository files navigation

terraform-aws-static-site

Terraform Checks Generate terraform docs

Terraform module to create a static site in AWS using CloudFront, S3, ACM, Route53, etc...

Explanation

An opinionated Terraform module to create a static site:

  • Separate S3 buckets for site files (e.g., HTML, CSS, etc...) and logging
  • S3 buckets are private
  • Logs move to Standard IA after 30 days and are expired after 365
  • Site files (e.g., HTML, CSS, etc...) can only be accessed through CloudFront (i.e., no direct access to files in S3)
  • Creates an ACM certificate for domain_name.tld and *.domain_name.tld (i.e., for subdomains like www.domain_name.tld)
  • Validates the ACM certificate using Route53 DNS
  • Creates A and AAAA records for domain_name.tld and www.domain_name.tld
  • CloudFront distribution using Origin Access Control to S3
  • CloudFront options for IPv6, TLS, HTTP versions, and more
  • Sane defaults for CloudFront HTTP headers

Requirements

  • You MUST already have a Route53 hosted zone and accompanying NS records created (this module does NOT do this for you) because ACM uses DNS for certficate validation. Below is an example of how to do this with Terraform.
resource "aws_route53_zone" "mydomain_com" {
  name = "domain.com"
}

resource "aws_route53_record" "mydomain_com_nameservers" {
  zone_id         = aws_route53_zone.mydomain_com.zone_id
  name            = aws_route53_zone.mydomain_com.name
  type            = "NS"
  ttl             = "3600"
  allow_overwrite = true
  records         = aws_route53_zone.mydomain_com.name_servers
}
  • The domain_name input into the module MUST match the Route53 hosted zone name (e.g., domain.com).
  • CloudFront can only use ACM certs generated in us-east-1. Some people (i.e., me) don't want their resources in us-east-1, except the ACM certificate and validation. Because of this, I had to add an extra provider configuration of aws.us-east-1 to those two resources. You NEED to add this extra provider to your root module and again when calling the module itself (below is an example).
# Default
provider "aws" {
  region                   = "us-east-2"
  shared_credentials_files = ["~/.aws/credentials"]
}

# Needed because CloudFront can only use ACM certs generated in us-east-1
provider "aws" {
  alias                    = "us-east-1"
  region                   = "us-east-1"
  shared_credentials_files = ["~/.aws/credentials"]
}

module "static_site_domain_com" {
  source = "github.com/loganmarchione/terraform-aws-static-site?ref=x.y.z"

  providers = {
    aws.us-east-1 = aws.us-east-1
  }

  # The domain name of the site (**MUST** match the Route53 hosted zone name (e.g., `domain.com`)
  domain_name   = "domain.com"

  # Since this is a static site, we probably don't need versioning, since our source files are stored in git
  bucket_versioning_logs = false
  bucket_versioning_site = false

  # CloudFront settings
  cloudfront_compress                     = true
  cloudfront_default_root_object          = "index.html"
  cloudfront_enabled                      = true
  cloudfront_function_create              = true
  cloudfront_function_filename            = "function.js"
  cloudfront_function_name                = "ReWrites"
  cloudfront_http_version                 = "http2and3"
  cloudfront_ipv6                         = true
  cloudfront_price_class                  = "PriceClass_100"
  cloudfront_ssl_minimum_protocol_version = "TLSv1.2_2021"
  cloudfront_ttl_min                      = 3600
  cloudfront_ttl_default                  = 86400
  cloudfront_ttl_max                      = 31536000
  cloudfront_viewer_protocol_policy       = "redirect-to-https"

  # IAM
  iam_policy_site_updating = false

  # Upload default files
  upload_index  = true
  upload_robots = true
  upload_404    = true
}

Usage

This documentation was generated automatically with terraform-docs

Requirements

Name Version
terraform >= 1.0.2
aws >= 5.15.0

Providers

Name Version
aws >= 5.15.0
aws.us-east-1 >= 5.15.0

Modules

No modules.

Resources

Name Type
aws_acm_certificate.site resource
aws_acm_certificate_validation.site resource
aws_cloudfront_distribution.site resource
aws_cloudfront_function.site resource
aws_cloudfront_origin_access_control.site resource
aws_cloudfront_response_headers_policy.site resource
aws_iam_policy.site_updating resource
aws_route53_record.site_a resource
aws_route53_record.site_a_www resource
aws_route53_record.site_aaaa resource
aws_route53_record.site_aaaa_www resource
aws_route53_record.site_caa resource
aws_route53_record.site_validation resource
aws_s3_bucket.logging resource
aws_s3_bucket.site resource
aws_s3_bucket_acl.logging resource
aws_s3_bucket_lifecycle_configuration.logging resource
aws_s3_bucket_logging.site resource
aws_s3_bucket_ownership_controls.logging resource
aws_s3_bucket_policy.site resource
aws_s3_bucket_public_access_block.logging resource
aws_s3_bucket_public_access_block.site resource
aws_s3_bucket_server_side_encryption_configuration.logging resource
aws_s3_bucket_server_side_encryption_configuration.site resource
aws_s3_bucket_versioning.logging resource
aws_s3_bucket_versioning.site resource
aws_s3_object._404 resource
aws_s3_object.index resource
aws_s3_object.robots resource
aws_route53_zone.site data source

Inputs

Name Description Type Default Required
bucket_versioning_logs State of bucket versioning for logs bucket bool false no
bucket_versioning_site State of bucket versioning for site bucket bool false no
cloudfront_compress To enable CloudFront compression or not bool true no
cloudfront_custom_error_responses The CloudFront custom error responses
list(object({
error_code = number
response_code = number
error_caching_min_ttl = number
response_page_path = string
}))
[
{
"error_caching_min_ttl": 60,
"error_code": 404,
"response_code": 404,
"response_page_path": "/404.html"
}
]
no
cloudfront_default_root_object The CloudFront default root object to display (this is null by default, so nothing will display at https://domain.com unless you set something here) string null no
cloudfront_enabled To enable CloudFront or not bool true no
cloudfront_function_create To create and associate a CloudFront function (this doesn't test the function, so make sure it works!) bool false no
cloudfront_function_filename The filename of the CloudFront function (the default is this AWS-provided function that appends index.html to requests that don't include a file name or extension (e.g., domain.com/foo) string "function.js" no
cloudfront_function_name The name of the CloudFront function string "MyFunction" no
cloudfront_http_version The CloudFront HTTP version string "http2" no
cloudfront_ipv6 To enable CloudFront IPv6 or not (also controls creation of two AAAA Route53 records) bool true no
cloudfront_price_class The CloudFront price class string "PriceClass_100" no
cloudfront_ssl_minimum_protocol_version The CloudFront minimum SSL protocol to use string "TLSv1.2_2021" no
cloudfront_ttl_default The CloudFront default cache time (seconds) number 86400 no
cloudfront_ttl_max The CloudFront maximum cache time (seconds) number 31536000 no
cloudfront_ttl_min The CloudFront minimum cache time (seconds) number 3600 no
cloudfront_viewer_protocol_policy The CloudFront viewer protocol policy to enforce (e.g., redirect HTTP to HTTPS) string "redirect-to-https" no
domain_name Domain name of the site and MUST match the Route53 hosted zone name (e.g., domain.com) string n/a yes
iam_policy_site_updating Optional IAM policy that provides permissions needed to update a static site (e.g., create CloudFront cache invalidation, update objects in S3, etc...) bool false no
upload_404 To push a 404.html page (useful if you want to test your custom error responses) or not bool false no
upload_index To push a test index.html page or not bool true no
upload_robots To push a restrictive robots.txt file (useful if you don't want a site to be indexed) or not bool false no

Outputs

Name Description
site_updating_iam_policy_arn Value of site_updating IAM policy ARN

About

Terraform module to create a static site in AWS using CloudFront, S3, ACM, Route53, etc...

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •