× HomeMath BoardArchiveType

Introduction

Setting up a static website on AWS can be a straightforward process when using Terraform to manage your infrastructure. In this guide, we'll walk you through the steps required to configure and deploy a static website on AWS using Terraform. We'll cover topics such as creating an S3 bucket, setting up a Route53 domain, configuring SSL certificates, and deploying your website.

By the end of this guide, you'll have a fully functional static website hosted on AWS that is accessible via your own custom domain name with SSL encryption provided by AWS Certificate Management. This guide assumes a basic understanding of AWS services, Terraform, and web development. Let's get started!

Step 1: Creating an S3 Bucket for Website Hosting

To start, you'll need an AWS account and the AWS CLI installed. Begin by configuring your Terraform project. In your Terraform configuration file, specify the creation of an S3 bucket for website hosting. You can use a configuration like this:

resource "aws_s3_bucket" "static_site" {

  bucket = "${var.bucket_name}"

 

  website {

    index_document = "index.html"

    error_document = "error.html"

  }

}

 

resource "aws_s3_bucket_website_configuration" "static_site" {

  bucket = aws_s3_bucket.static_site.id

 

  index_document {

    suffix = "index.html"

  }

 

  error_document {

    key = "error.html"

  }

}

 

resource "aws_s3_bucket_public_access_block" "s3_bucket_public_access_block" {

  bucket = aws_s3_bucket.static_site.id

 

  block_public_acls       = false

  block_public_policy     = false

  ignore_public_acls      = false

  restrict_public_buckets = false

}

 

resource "aws_s3_bucket_ownership_controls" "s3_bucket_acl_ownership" {

  bucket = aws_s3_bucket.static_site.id

  rule {

    object_ownership = "BucketOwnerPreferred"

  }

 

  depends_on = [aws_s3_bucket_public_access_block.s3_bucket_public_access_block]

}

 

resource "aws_s3_bucket_acl" "s3_bucket_acl" {

  bucket = aws_s3_bucket.static_site.id

  acl    = "public-read"

  depends_on = [aws_s3_bucket_ownership_controls.s3_bucket_acl_ownership]

}

 

resource "aws_s3_bucket_policy" "static_site" {

  bucket = aws_s3_bucket.static_site.id

  policy = jsonencode({

    Version = "2012-10-17",

    Statement = [

      {

        Principal = "*",

        Action = [

          "s3:*"

        ]

        Effect = "Allow",

        Resource = [

          "${aws_s3_bucket.static_site.arn}",

          "${aws_s3_bucket.static_site.arn}/*"

        ],

      },

      {

        Sid = "PublicReadGetObject",

        Principal = "*",

        Action = [

          "s3:GetObject"

        ],

        Effect = "Allow",

        Resource = [

          "${aws_s3_bucket.static_site.arn}",

          "${aws_s3_bucket.static_site.arn}/*"

        ],

      }

    ],

  })

  depends_on = [aws_s3_bucket_public_access_block.s3_bucket_public_access_block]

}

 

Step 2: Configuring Cloud Front for Content Delivery

After creating the S3 bucket for website hosting, you'll need to configure CloudFront for content delivery. Start by creating a new CloudFront distribution in your Terraform configuration file. You can use a configuration like this:

resource "aws_cloudfront_distribution" "s3_distribution" {

  origin {

    domain_name = aws_s3_bucket.static_site.bucket_regional_domain_name

    origin_id   = "S3-${var.bucket_name}"  # Provide a unique origin ID

  }

 

  enabled             = true

  comment             = "CloudFront distribution for S3-based static site"

  default_root_object = "index.html"

 

  default_cache_behavior {

    allowed_methods  = ["GET", "HEAD"]

    cached_methods   = ["GET", "HEAD"]

    target_origin_id = "S3-${var.bucket_name}"  # Use the same origin ID as defined above

 

    forwarded_values {

      query_string = false

      cookies {

        forward = "none"

      }

    }

 

    viewer_protocol_policy = "redirect-to-https"

    min_ttl                = 0

    default_ttl            = 3600

    max_ttl                = 86400

  }

 

  price_class = "PriceClass_200"  # Use appropriate price class

 

  restrictions {

    geo_restriction {

      restriction_type = "none"

    }

  }

 

  aliases = [ "${var.custom_domain}" ]

 

  viewer_certificate {

     acm_certificate_arn     = "${aws_acm_certificate.sample_cert.arn}"

    ssl_support_method       = "sni-only"

    minimum_protocol_version = "TLSv1.1_2016"

  }

}

 

This configuration sets up CloudFront to use the S3 bucket as its origin, with the default cache behavior set to redirect HTTP traffic to HTTPS and a minimum time-to-live of 0 seconds. Additionally, it sets up SSL encryption using the SSL certificate created in the next step.

Step 3: Creating an SSL Certificate

To enable SSL encryption for your static website, you'll need to create an SSL certificate using AWS Certificate Manager. In your Terraform configuration file, add a resource to create the certificate. You can use a configuration like this:

resource "aws_acm_certificate" "example" {

  domain_name       = var.domain_name

  validation_method = "DNS"

}

 

resource "aws_route53_record" "cert_validation" {

  zone_id = aws_route53_zone.main.zone_id

  name    = aws_acm_certificate.example.domain_validation_options.0.resource_record_name

  type    = aws_acm_certificate.example.domain_validation_options.0.resource_record_type

  records = [aws_acm_certificate.example.domain_validation_options.0.resource_record_value]

  ttl     = "60"

}

 

This configuration creates an SSL certificate for your domain name using DNS validation.

With these steps, you now have a fully functional static website hosted on AWS, with SSL encryption provided by AWS Certificate Management and content delivery through CloudFront.

Step 4: Setting up a Route53 Domain

For a personalized domain name, set up a Route53 hosted zone and configure a record that points to your S3 bucket. The Terraform configuration for the Route53 record might look like this:

resource "aws_route53_zone" "my_domain" {

  name = "${var.custom_domain}"

}

 

resource "aws_route53_record" "cloudfront_a_record" {

  zone_id = aws_route53_zone.my_domain.zone_id

  name    = "${var.custom_domain}"

  type    = "A"

 

  alias {

    name                   = aws_cloudfront_distribution.s3_distribution.domain_name

    zone_id                = aws_cloudfront_distribution.s3_distribution.hosted_zone_id

    evaluate_target_health = false

  }

}

 

resource "aws_route53_record" "validation_record" {

  for_each = {

    for dvo in aws_acm_certificate.sample_cert.domain_validation_options : dvo.domain_name => dvo

  }

 

  name    = each.value.resource_record_name

  type    = each.value.resource_record_type

  zone_id = aws_route53_zone.my_domain.zone_id

  records = [each.value.resource_record_value]

  ttl     = "300"

}

 

Step 5: Deploying Your Website

Now you can upload your website files to the S3 bucket using the AWS CLI or the AWS Management Console. Once uploaded, your website will be accessible via the CloudFront distribution and your custom domain name. Any changes you make to your website can be redeployed simply by uploading the updated files to the S3 bucket. Congratulations, you now have a fully functional static website hosted on AWS with SSL encryption and content delivery through CloudFront!

Notice that you also need to keep in mind of updating your domain's DNS records to point to the CloudFront distribution. Otherwise, there will not be anything new show up via your domain.

To deploy via terraform, simply run

terraform init

terraform apply

 

These commands initialize and apply your Terraform configuration, creating your S3 bucket, CloudFront distribution, and Route53 record. Upon completion, your website will be hosted on AWS and available through your custom domain name.