Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for [Terraform] Static Website Infrastructure on AWS
Artem
Artem

Posted on • Edited on • Originally published atartem.lol

     

[Terraform] Static Website Infrastructure on AWS

Deploying a static website is one of the easiest task a web developer faces. There is a number of solutions allowing to complete the deployment process in a matter of few minutes, and several buttons clicks. What a wonderful world we live in! However, this approach has one huge limitation. You don't really own the underlying infrastructure. I claim that there is a way you can both do the deployment fast, and own the underlying infrastructure. You can Terraform it!

This article is not a guide, but an artifact documenting my journey on the way to deploy a personal blog and its underlying infrastructure. You might want to check outthe beginning of the journey, where I share my Continuous Deployment setup.

TLDR, I have a static Hugo website hosted in S3 bucket. Now it is time to make it production ready!

Let's define the final specs:

  • Domain name (using AWS Route53)
  • Distributed by CDN (using AWS Cloudfront)
  • SSL/TLS support (using AWS Certificate Manager)

Step 1: Get a Domain Name

This step is pretty much manual. AWS has a detailed instruction ongetting a domain. Note, that AWS automatically creates a hosted zone, and name serve (NS) record for you. It is important that you have an existing valid hosted zone before proceeding to the next step. If you need more information on how to create a new hosted zone, or configure the NS record, please refer tothis part of the AWS guide.

Step 2: Provision the AWS Resources

This article assumes you already know some Terraform. If you are not familiar with it, I have anintroductory level article to get you going. For more detailed introduction, refer to theTerraform learning center.

I will be using Terraform Cloud in order to store my state. Read more about this configuration on theTerraform website. You can also modify the templates to configure Terraform to use the local backend.

Templates Folder Structure

├── main.tf├── outputs.tf├── variables.auto.tfvars└── variables.tf
Enter fullscreen modeExit fullscreen mode

main.tf

This is the complete template I use for my website setup. It not only provisions the AWS resources (S3, Route53, Cloudfront, and etc), but also credentials for the CircleCI deployment. If you are not interesting in setting up the CI/CD pipeline, you can exclude IAM User and the Policy from the template.

Remember, Terraform will store the keys in itsstate as a plaintext. You are responsible for keeping their secrecy.

terraform{required_version="~> 0.12.25"backend"remote"{hostname="app.terraform.io"organization="example-organization"workspaces{name="example-workspace"}}}provider"aws"{version="~> 2.0"region=var.region}data"aws_route53_zone""static_bucket_zone"{name=var.domain_name}resource"aws_s3_bucket""static_bucket"{bucket=var.domain_nameacl="public-read"force_destroy=truewebsite{index_document="index.html"}policy=<<-EOT    {      "Version": "2012-10-17",      "Statement": [          {              "Sid": "PublicReadGetObject",              "Effect": "Allow",              "Principal": "*",              "Action": [                  "s3:GetObject"              ],              "Resource": [                  "arn:aws:s3:::${var.domain_name}/*"              ]          }      ]    }  EOT}resource"aws_acm_certificate""static_bucket_certificate"{domain_name=var.domain_namevalidation_method="DNS"tags={terraform="true"}lifecycle{create_before_destroy=true}}resource"aws_route53_record""static_bucket_record"{zone_id=data.aws_route53_zone.static_bucket_zone.zone_idname=var.domain_nametype="A"alias{name=aws_cloudfront_distribution.static_bucket_distribution.domain_namezone_id=aws_cloudfront_distribution.static_bucket_distribution.hosted_zone_idevaluate_target_health=false}}resource"aws_acm_certificate_validation""static_bucket_certificate"{certificate_arn=aws_acm_certificate.static_bucket_certificate.arntimeouts{create="20m"}}resource"aws_cloudfront_distribution""static_bucket_distribution"{origin{custom_origin_config{http_port="80"https_port="443"origin_protocol_policy="http-only"origin_ssl_protocols=["TLSv1","TLSv1.1","TLSv1.2"]}domain_name=aws_s3_bucket.static_bucket.website_endpointorigin_id=var.domain_name}enabled=truedefault_root_object="index.html"default_cache_behavior{viewer_protocol_policy="redirect-to-https"compress=trueallowed_methods=["GET","HEAD"]cached_methods=["GET","HEAD"]target_origin_id=var.domain_namemin_ttl=0default_ttl=86400max_ttl=31536000forwarded_values{query_string=falsecookies{forward="none"}}}aliases=[var.domain_name]restrictions{geo_restriction{restriction_type="none"}}viewer_certificate{acm_certificate_arn=aws_acm_certificate_validation.static_bucket_certificate.certificate_arnssl_support_method="sni-only"}}resource"aws_iam_user""circle_ci_user"{name="circle-ci"}resource"aws_iam_access_key""circle_ci_access_key"{user=aws_iam_user.circle_ci_user.name}resource"aws_iam_user_policy""circle_ci_policy"{name="circle-ci-policy"user=aws_iam_user.circle_ci_user.namepolicy=<<-EOT    {      "Version": "2012-10-17",      "Statement": [          {              "Effect": "Allow",              "Action": "s3:*",              "Resource": [                  "arn:aws:s3:::${var.domain_name}",                  "arn:aws:s3:::${var.domain_name}/*"              ]          }      ]    }  EOT}
Enter fullscreen modeExit fullscreen mode

variables.tf

variable"domain_name"{type=stringdescription="Website root domain name"}variable"region"{type=stringdescription="AWS region to create resources"}
Enter fullscreen modeExit fullscreen mode

outputs.tf

Again, if you don't use CI/CD, this part can be safely ignored.

output"circle_ci_access_key"{value=aws_iam_access_key.circle_ci_access_key.id}output"circle_ci_access_key_secret"{value=aws_iam_access_key.circle_ci_access_key.secret}
Enter fullscreen modeExit fullscreen mode

variables.auto.tf

Note, that adding auto suffix to a Terraform variables definition will make the file load automatically.

domain_name="example.com"region="us-east-1"
Enter fullscreen modeExit fullscreen mode

Step 3: Enjoy the Result

After the provisioning is successfully completed, it may still take few minutes for the Cloudfront, and Route53 configurations to fully sync. If you used the AWS CDN services with your domain name before, it is a good idea toinvalidate cache.


You can find my final result atartem.lol. If you have any questions, or run into issues trying to provision the infrastructure using my template please let me know in comments!

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
    Santa Rosa, CA
  • Education
    San Francisco State University
  • Work
    Cloud Security Engineer at Virtru
  • Joined

More fromArtem

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