Using Terraform to Deploy Your S3 Website Using Cloud front

Using Terraform to Deploy Your S3 Website Using Cloud front
Techiio-author
Written by Sagar RabidasNovember 19, 2021
17 min read
Terraform
1 VIEWS 0 LIKES 0 DISLIKES SHARE
0 LIKES 0 DISLIKES 1 VIEWS SHARE
Techiio-author
Sagar Rabidas

Software Developer

In this blog, we use Terraform to Deploy Your S3 Website Using Cloud front.

If you want to skip all of the fun the repo with the code we are using is located here. Also, before you get started here go check out my article on creating an S3 website bucket module. This article will be building on the groundwork set there and will assume you have an S3 bucket module.

S3 Bucket Code

For this article, I am going to assume that you already have an S3 website created and just want to get it deployed to Cloudfront using Terraform. If that happens to not be the case here is the code we are working with.

Main. tf

resource "aws_s3_bucket" "prod_website" {  
  bucket_prefix = var.bucket_prefix  
  acl    = "public-read"     website {    
    index_document = "index.html"    
    error_document = "error.html"   
 
  }
}
resource "aws_s3_bucket_policy" "prod_website" {  
  bucket = aws_s3_bucket.prod_website.id   policy = <<POLICY
{    
    "Version": "2012-10-17",    
    "Statement": [        
      {            
          "Sid": "PublicReadGetObject",            
          "Effect": "Allow",            
          "Principal": "*",            
          "Action": [                
             "s3:GetObject"            
          ],            
          "Resource": [
             "arn:aws:s3:::${aws_s3_bucket.prod_website.id}/*"            
          ]        
      }    
    ]
}
POLICY
}

Variables.tf

variable "bucket_prefix" {  
  type        = string  
  description = "Name of the s3 bucket to be created."
} 
variable "region" {  
  type        = string  
  default     = "us-east-1"  
  description = "Name of the s3 bucket to be created."
}

Outputs.tf

output "s3_bucket_id" {
  value = aws_s3_bucket.prod_website.id
}

Use these files as the basis for your code. We will just be updating them with our Cloudfront code.

Cloudfront Code in main. tf

So the code we are going to be adding to our main. tf file is this:

​​resource "aws_cloudfront_distribution" "s3_distribution" {
  origin {
    domain_name = "${aws_s3_bucket.prod_website.bucket_regional_domain_name}"
    origin_id   = "${local.s3_origin_id}"
#   s3_origin_config {
    #     origin_access_identity = "origin-access-identity/cloudfront/ABCDEFG1234567"
    #   }
  }
enabled             = true
  is_ipv6_enabled     = true
  comment             = "Some comment"
  default_root_object = "index.html"
# logging_config {
  #   include_cookies = false
  #   bucket          = "mylogs.s3.amazonaws.com"
  #   prefix          = "myprefix"
  # }
#aliases = []
default_cache_behavior {
    allowed_methods  = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = "${local.s3_origin_id}"
forwarded_values {
      query_string = false
cookies {
        forward = "none"
      }
    }
viewer_protocol_policy = "allow-all"
    min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400
  }
# Cache behavior with precedence 0
  ordered_cache_behavior {
    path_pattern     = "/content/immutable/*"
    allowed_methods  = ["GET", "HEAD", "OPTIONS"]
    cached_methods   = ["GET", "HEAD", "OPTIONS"]
    target_origin_id = "${local.s3_origin_id}"
forwarded_values {
      query_string = false
      headers      = ["Origin"]
cookies {
        forward = "none"
      }
    }
min_ttl                = 0
    default_ttl            = 86400
    max_ttl                = 31536000
    compress               = true
    viewer_protocol_policy = "redirect-to-https"
  }
# Cache behavior with precedence 1
  ordered_cache_behavior {
    path_pattern     = "/content/*"
    allowed_methods  = ["GET", "HEAD", "OPTIONS"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = "${local.s3_origin_id}"
forwarded_values {
      query_string = false
cookies {
        forward = "none"
      }
    }
min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400
    compress               = true
    viewer_protocol_policy = "redirect-to-https"
  }
price_class = "PriceClass_200"
restrictions {
    geo_restriction {
      restriction_type = "whitelist"
      locations        = ["US", "CA", "GB", "DE"]
    }
  }
tags = {
    Environment = "production"
  }
viewer_certificate {
    cloudfront_default_certificate = true
  }
}

​​I am just going to break down a few specific pieces of this. First, let’s look at the domain_name argument.

resource "aws_cloudfront_distribution" "s3_distribution" {
  origin {
    domain_name = "${aws_s3_bucket.prod_website.bucket_regional_domain_name}"
    origin_id   = "${local.s3_origin_id}"

We want to set this argument to

aws_s3_bucket.prod_website.bucket_regional_domain_name because that is the resource addressing that will be used to pull the domain name information.

Next is the origin_id argument.

resource "aws_cloudfront_distribution" "s3_distribution" {
  origin {
    domain_name = "${aws_s3_bucket.prod_website.bucket_regional_domain_name}"
    origin_id   = "${local.s3_origin_id}"

I do not have this in use for this example, but if you want to set an origin_id you can just use the commented out expression:

    #   s3_origin_config {
    #     origin_access_identity = "origin-access-identity/cloudfront/ABCDEFG1234567"
    #   }
  }

For default_root_object we have it set to index.html since that is a good default.

  enabled             = true
  is_ipv6_enabled     = true
  comment             = "Some comment"
  default_root_object = "index.html"

All of this code can just be added to the main.tf file that contains our bucket and bucket policy.

Cloudfront Code in variables. tf

There is none!

<div style=”width:100%;height:0;padding-bottom:67%;position:relative;”><iframe src=”https://giphy.com/embed/F9hQLAVhWnL56" width=”100%” height=”100%” style=”position:absolute” frameBorder=”0" class=”giphy-embed” allowFullScreen></iframe></div><p><a href=”https://giphy.com/gifs/F9hQLAVhWnL56">via GIPHY</a></p>

Cloudfront Code in outputs.tf

We also want to add this to the outputs.tf file.

output "s3_bucket_domain_name" {    
  value = aws_s3_bucket.prod_website.bucket_domain_name
}

That way our parent module can get the bucket domain name of our child module.

If you looked at my repo you may also notice a few other outputs. These you will only want to use in specific scenarios, but more on that in future articles!

Usage

You should now have everything you need. After configuring your AWS provider in your code the below example will get your website created.

module prod_website {
  source = "YOUR SOURCE URL"
  bucket_prefix = "SOME BUCKET NAME"
}

terraform
cloudfront
S3Website
1 VIEWS 0 LIKES 0 DISLIKES SHARE
0 LIKES 0 DISLIKES 1 VIEWS SHARE
Was this blog helpful?
techiio-price-plantechiio-price-plantechiio-price-plantechiio-price-plantechiio-price-plan
You must be Logged in to comment
Code Block
Techiio-author
Sagar Rabidas
Software Developer
Techiio-followerTechiio-followerTechiio-followerTechiio-followerTechiio-follower
+8 more
300 Blog Posts
14 Discussion Threads
Trending Technologies
15
Software40
DevOps46
Frontend Development24
Backend Development20
Server Administration17
Linux Administration26
Data Center24
Sentry24
Terraform23
Ansible83
Docker70
Penetration Testing16
Kubernetes21
NGINX20
JenkinsX17
Techiio-logo

Techiio is on the journey to build an ocean of technical knowledge, scouring the emerging stars in process and proffering them to the corporate world.

Follow us on:

Subscribe to get latest updates

You can unsubscribe anytime from getting updates from us
Developed and maintained by Wikiance
Developed and maintained by Wikiance