Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Static Website Infrastructure on AWS with Terraform
Bahaa Noah
Bahaa Noah

Posted on • Originally published atbahaanoah.com on

     

Static Website Infrastructure on AWS with Terraform

As a software engineer, you likely understand the importance of automation and reproducibility in your workflow. One way to achieve this is by usingTerraform, it was one of the technologies that I learned in 2022 and since then it has been the goto tool for me for any infrastructure work. In this post, I'll take you through how to use Terraform to create the necessary resources for hosting a static website on AWS, making your life a lot easier.

Required Utilities

Install these tools before proceeding:

  1. AWS CLI
  2. Terraform -Install Terraform

Configure the AWS CLI with a user that has sufficient privileges to create all the resources we will be using in this blog, and it's always a best practice to give least privileges rather than an admin access. Verify that the CLI can authenticate properly by runningaws sts get-caller-identity.

Overview

We will utilize the following services to create static website hosting infrastructure:

  1. AWS S3 Bucket as the hosting and storage for the website files and rearouses.
  2. Route 53 as DNS resolver.
  3. AWS Certificate Manager for securing the website and managing the ssl certificate.
  4. Amazon CloudFront to optimize the performance and improve security.

Using all of these services should be free of charge except for Route 53 will charge you around 00.51$ and in general if you are not in thefree tier you will be charged around 3$~4$ per month based on the traffic you are getting.

aws-static-website-hosting-infrastructure-diagram


Setting Up Variables

After setting up the tools, let's create the following environment variables to store commonly used values. First things first we will create ourmain.tf file and place the following in it.

terraform {  required_version = "~> 1.0"  required_providers {    aws = {      source = "hashicorp/aws"      version = "~> 4.0"    }  }}locals {  # change that to your domain name  domain_name = "bahaanoah.com"  # I like to tag everything that's being created by terraform  tags = {    "terraform" = true  }}# I will be using UAE region but feel free to use whichever you preferprovider "aws" {  region = "me-central-1"}
Enter fullscreen modeExit fullscreen mode

Create S3 Bucket

At this step we are going to create S3 bucket with public access and add website configuration to it usingResource: aws_s3_bucket.

Creates3.tf file and add the following code:

resource "aws_s3_bucket" "this" {  bucket = local.domain_name  tags = local.tags  force_destroy = true}resource "aws_s3_bucket_policy" "allow_public_access" {  bucket = aws_s3_bucket.this.id  policy = jsonencode(    {      Statement = [        {          Action = "s3:GetObject"          Effect = "Allow"          Principal = "*"          Resource = "arn:aws:s3:::${local.domain_name}/*"          Sid = "Stmt1661600983594"        },      ]      Version = "2012-10-17"    }  )}resource "aws_s3_bucket_versioning" "this" {  bucket = aws_s3_bucket.this.id  versioning_configuration {    status = "Disabled"  }}resource "aws_s3_bucket_website_configuration" "this" {  bucket = aws_s3_bucket.this.bucket  index_document {    suffix = "index.html"  }  error_document {    key = "404/index.html"  }}
Enter fullscreen modeExit fullscreen mode

Once done go ahead and apply what we have created so far.

terraform initterraform apply
Enter fullscreen modeExit fullscreen mode

Create Route 53 Hosted Zone

At this step will create a hosted zone to manage our dns records usingResource: aws_route53_zone.

Createroute53.tf file and place the code below:

resource "aws_route53_zone" "primary" {  name = local.domain_name  tags = local.tags}
Enter fullscreen modeExit fullscreen mode

Go ahead and apply the changes.

terraform apply
Enter fullscreen modeExit fullscreen mode

After applying this change you should see a hosted zone with NS and SOA records created in route 53, copy the NS record values and update your domain nameservers, in my case I have my domain registered inGodaddy all I needed to do is change the default nameservers and use custom nameservers the add the NS values from AWS there.

Issue SSL Certificate

We will issue SSL certificate using AWS Certificate Manager withResource: aws_acm_certificate and create some DNS records in route 53 to validate it at this step.

Createacm.tf file and place the code below:

# if you are using different region from us-east-1 you will need to do that step # because cloudfront only works with certificates issued in us-east-1provider "aws" {  alias = "virginia"  region = "us-east-1"}resource "aws_acm_certificate" "this" {  domain_name = local.domain_name  validation_method = "DNS"  tags = local.tags  lifecycle {    create_before_destroy = true  }  provider = aws.virginia}resource "aws_route53_record" "validation" {  for_each = {    for dvo in aws_acm_certificate.this.domain_validation_options : dvo.domain_name => {      name = dvo.resource_record_name      record = dvo.resource_record_value      type = dvo.resource_record_type    }  }  allow_overwrite = true  name = each.value.name  records = [each.value.record]  ttl = 60  type = each.value.type  zone_id = aws_route53_zone.primary.zone_id  provider = aws.virginia  depends_on = [    aws_acm_certificate.this,    aws_route53_zone.primary  ]}
Enter fullscreen modeExit fullscreen mode

Go ahead and apply the changes.

terraform apply
Enter fullscreen modeExit fullscreen mode

If you connected your domain to the NS record from previous step it should take a couple of minutes and your certificate status will change to "Issued"

Create CloudFront

At this step we will create CloudFront withResource: aws_cloudfront_distribution and connect it to theS3 Bucket we created earlier, then eventually create an A record in thehosted zone we created that's aliased to this cloudfront distribution.

Createcloudfront.tf file and place the code below:

resource "aws_cloudfront_distribution" "this" {  origin {    domain_name = aws_s3_bucket_website_configuration.this.website_endpoint    origin_id = aws_s3_bucket_website_configuration.this.website_endpoint    connection_attempts = 3    connection_timeout = 10    custom_origin_config {      http_port = 80      https_port = 443      origin_keepalive_timeout = 5      origin_protocol_policy = "http-only"      origin_read_timeout = 30      origin_ssl_protocols = [        "TLSv1",        "TLSv1.1",        "TLSv1.2",      ]    }  }  enabled = true  is_ipv6_enabled = true  aliases = [local.domain_name]  default_cache_behavior {    allowed_methods = ["GET", "HEAD"]    cached_methods = ["GET", "HEAD"]    target_origin_id = aws_s3_bucket_website_configuration.this.website_endpoint    viewer_protocol_policy = "redirect-to-https"    compress = true    min_ttl = 0    default_ttl = 3600     max_ttl = 86400    smooth_streaming = false    forwarded_values {      query_string = false      cookies {        forward = "none"      }    }  }  restrictions {    geo_restriction {      locations = []      restriction_type = "none"    }  }  tags = local.tags  viewer_certificate {    acm_certificate_arn = aws_acm_certificate.this.arn    cloudfront_default_certificate = false    minimum_protocol_version = "TLSv1.2_2021"    ssl_support_method = "sni-only"  }  depends_on = [    aws_s3_bucket.this,    aws_acm_certificate.this  ]}
Enter fullscreen modeExit fullscreen mode

Go ahead and apply the changes.

terraform apply
Enter fullscreen modeExit fullscreen mode

Once applied let's create the DNS record, openroute53.tf file and add the code below:

# update the resource name to your domain nameresource "aws_route53_record" "bahaanoah-com" {  name = local.domain_name  type = "A"  zone_id = aws_route53_zone.primary.zone_id  alias {    name = aws_cloudfront_distribution.this.domain_name    zone_id = aws_cloudfront_distribution.this.hosted_zone_id    evaluate_target_health = false  }}
Enter fullscreen modeExit fullscreen mode

Go ahead and apply the changes.

terraform apply
Enter fullscreen modeExit fullscreen mode

If you reached that point and got everything to be working well done!, you should have your infrastructure up and running, go ahead and upload your website in the S3 bucket we created and check it out.

Cleanup

If you are not going to use it and was just trying and would like to clean up destroy everything to avoid any charges in the future.

terraform destroy
Enter fullscreen modeExit fullscreen mode

Conclusion

Terraform is a powerful tool for automating the process of creating and managing infrastructure on AWS. By using the services outlined in this post, you can easily set up a secure and performant static website that is easy to maintain and update. However, it is important to keep in mind that this is just the basic setup and there are many other options and features that can be added and configured for different needs and use cases.

As a next step, I would suggest to have a look at thisgithub repository that's containing the code I used to create the Infrastructure for my website it's pretty much the same as we explained with some extra steps for www redirection. I would also recommend having a look atCloudFront Invalidation to manage your cache better and finally if you are working in a team I suggest to have some CI/CD pipeline to automate your infrastructure deployments with some code review process in place, find out more hereRunning Terraform in Automation.

Thanks for reading, I hope this was helpful. Please feel free toreach out if you need more help or have any suggestions.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

  • Location
    Dubai, UAE
  • Education
    Bachelor's Degree of Computer Science
  • Work
    Senior Software Engineer
  • Joined

Trending onDEV CommunityHot

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp