Skip to content

Instantly share code, notes, and snippets.

@iml1111
Last active October 15, 2023 19:58
Show Gist options
  • Save iml1111/a213b0255d2deb2948e7c3d9b726b1e5 to your computer and use it in GitHub Desktop.
Save iml1111/a213b0255d2deb2948e7c3d9b726b1e5 to your computer and use it in GitHub Desktop.
[Terraform] AWS에 정적 웹사이트 인프라 배포하기
# S3
resource "aws_s3_bucket" "website" {
bucket = var.s3_bucket_name
force_destroy = true
}
resource "aws_s3_bucket_website_configuration" "website_configure" {
bucket = aws_s3_bucket.website.bucket
index_document {
suffix = "index.html"
}
error_document {
key = "error.html"
}
}
resource "aws_s3_bucket_ownership_controls" "website_ownership_controls" {
bucket = aws_s3_bucket.website.id
rule {
object_ownership = "BucketOwnerPreferred"
}
}
resource "aws_s3_bucket_public_access_block" "website_public_access_block" {
bucket = aws_s3_bucket.website.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
resource "aws_s3_bucket_acl" "website_acl" {
depends_on = [
aws_s3_bucket_ownership_controls.website_ownership_controls,
aws_s3_bucket_public_access_block.website_public_access_block,
]
bucket = aws_s3_bucket.website.id
acl = "public-read"
}
data "aws_iam_policy_document" "website_policy_document" {
statement {
sid = "PublicReadAccess"
actions = [
"s3:GetObject"
]
resources = [
"${aws_s3_bucket.website.arn}/*"
]
principals {
type = "AWS"
identifiers = ["*"]
}
}
depends_on = [ aws_s3_bucket.website ]
}
resource "aws_s3_bucket_policy" "website_policy" {
bucket = aws_s3_bucket.website.id
policy = data.aws_iam_policy_document.website_policy_document.json
depends_on = [
aws_s3_bucket.website,
aws_s3_bucket_acl.website_acl,
]
}
data "template_file" "deployer_role_policy_file" {
template = file("./deployer_role_policy.json")
vars = {
bucket = var.s3_bucket_name
}
}
resource "aws_iam_policy" "site_deployer_policy" {
count = var.deployer != null ? 1 : 0
name = "${var.s3_bucket_name}.deployer"
path = "/"
description = "Policy allowing to publish a new version of the website to the S3 bucket"
policy = data.template_file.deployer_role_policy_file.rendered
}
resource "aws_iam_policy_attachment" "site-deployer-attach-user-policy" {
count = var.deployer != null ? 1 : 0
name = "${var.s3_bucket_name}-deployer-policy-attachment"
users = [var.deployer]
policy_arn = aws_iam_policy.site_deployer_policy.0.arn
}
# Cloudfront
resource "aws_cloudfront_distribution" "cdn" {
enabled = true
is_ipv6_enabled = false
price_class = "PriceClass_200"
http_version = "http2"
origin {
origin_id = aws_s3_bucket.website.id
domain_name = aws_s3_bucket_website_configuration.website_configure.website_endpoint
custom_origin_config {
origin_protocol_policy = "http-only"
http_port = "80"
https_port = "443"
origin_ssl_protocols = ["TLSv1"]
}
}
default_root_object = "index.html"
custom_error_response {
error_code = "404"
error_caching_min_ttl = "360"
response_code = "200"
response_page_path = "/404.html"
}
default_cache_behavior {
allowed_methods = ["GET", "HEAD", "DELETE", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD"]
forwarded_values {
query_string = true
cookies {
forward = "none"
}
}
min_ttl = "0"
default_ttl = "300" //3600
max_ttl = "1200" //86400
target_origin_id = aws_s3_bucket.website.id
viewer_protocol_policy = "redirect-to-https"
compress = true
}
# This is required to be specified even if it's not used.
restrictions {
geo_restriction {
restriction_type = "none"
locations = []
}
}
viewer_certificate {
acm_certificate_arn = var.acm-certificate-arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1"
}
aliases = ["${var.sub_domain}.${var.domain}"]
tags = {
Name = "IML"
}
}
# Route53
data "aws_route53_zone" "website_domain_zone" {
name = var.domain
}
resource "aws_route53_record" "webstie_domain_record" {
zone_id = data.aws_route53_zone.website_domain_zone.zone_id
name = "${var.sub_domain}.${var.domain}"
type = "A"
alias {
name = aws_cloudfront_distribution.cdn.domain_name
zone_id = aws_cloudfront_distribution.cdn.hosted_zone_id
evaluate_target_health = false
}
}
output "s3_website_endpoint" {
value = aws_s3_bucket_website_configuration.website_configure.website_endpoint
}
output "route53_domain" {
value = aws_route53_record.webstie_domain_record.fqdn
}
output "cdn_domain" {
value = aws_cloudfront_distribution.cdn.domain_name
}
provider "aws" {
region = "ap-northeast-2"
}
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
/* backend "s3" {
bucket = "terraform-states"
key = "static_web_infra.terraform.tfstate"
region = "ap-northeast-2"
encrypt = true
dynamodb_table = "terraform-state-lock"
acl = "bucket-owner-full-control"
} */
}
variable "domain" {
default = "example.com"
}
variable "sub_domain" {
default = "static"
}
variable "s3_bucket_name" {
type = string
description = "The name of the S3 bucket to create."
default = "static-website-by-iml"
}
variable "acm-certificate-arn" {
type = string
default = "arn::XXX..."
}
variable "deployer" {
type = string
default = "YOUR_IAM_USER_NAME"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment