modularise?
This commit is contained in:
204
main.tf
204
main.tf
@@ -8,202 +8,10 @@ provider "aws" {
|
||||
provider "cloudflare" {
|
||||
}
|
||||
|
||||
locals {
|
||||
common_tags = {
|
||||
Project = var.project_name
|
||||
Environment = var.environment
|
||||
ManagedBy = "terraform"
|
||||
Domain = var.site_domain
|
||||
}
|
||||
}
|
||||
|
||||
# block with type resource, uses provider's aws_s3_bucket resource type and names it site
|
||||
resource "aws_s3_bucket" "site" {
|
||||
# presumably
|
||||
bucket = var.site_domain
|
||||
|
||||
tags = local.common_tags
|
||||
}
|
||||
|
||||
# necessary to allow public users to eventually hit the s3 bucket
|
||||
resource "aws_s3_bucket_public_access_block" "site" {
|
||||
bucket = aws_s3_bucket.site.id
|
||||
|
||||
block_public_acls = false
|
||||
block_public_policy = false
|
||||
ignore_public_acls = false
|
||||
restrict_public_buckets = false
|
||||
}
|
||||
|
||||
# name says it all
|
||||
resource "aws_s3_bucket_website_configuration" "site" {
|
||||
bucket = aws_s3_bucket.site.id
|
||||
|
||||
# Note that this isn't an =, i don't know why
|
||||
index_document {
|
||||
suffix = "index.html"
|
||||
}
|
||||
|
||||
error_document {
|
||||
key = "error.html"
|
||||
}
|
||||
}
|
||||
|
||||
# This controls the ownership of the objects inside the bucket upon upload
|
||||
# If possible, this sets the ownership of objects to the bucket owner
|
||||
resource "aws_s3_bucket_ownership_controls" "site" {
|
||||
bucket = aws_s3_bucket.site.id
|
||||
|
||||
rule {
|
||||
object_ownership = "BucketOwnerPreferred"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_acl" "site" {
|
||||
|
||||
bucket = aws_s3_bucket.site.id
|
||||
|
||||
acl = "public-read"
|
||||
depends_on = [
|
||||
aws_s3_bucket_ownership_controls.site,
|
||||
aws_s3_bucket_public_access_block.site
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
# Public read access for website objects only (not bucket itself)
|
||||
resource "aws_s3_bucket_policy" "site" {
|
||||
bucket = aws_s3_bucket.site.id
|
||||
|
||||
policy = jsonencode({
|
||||
Version = "2012-10-17"
|
||||
Statement = [
|
||||
{
|
||||
Sid = "PublicReadGetObject"
|
||||
Effect = "Allow"
|
||||
Principal = "*"
|
||||
Action = "s3:GetObject"
|
||||
Resource = "${aws_s3_bucket.site.arn}/*"
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
depends_on = [
|
||||
aws_s3_bucket_public_access_block.site
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
# Cloudflare time
|
||||
|
||||
# data block is about retrieving data from ext. source, not configuring a resource that lives in state
|
||||
data "cloudflare_zones" "domain" {
|
||||
# why a filter?
|
||||
filter {
|
||||
name = var.site_domain
|
||||
}
|
||||
}
|
||||
|
||||
# DNS setup
|
||||
resource "cloudflare_record" "site_cname" {
|
||||
zone_id = data.cloudflare_zones.domain.zones[0].id
|
||||
name = var.site_domain
|
||||
value = aws_s3_bucket_website_configuration.site.website_endpoint
|
||||
type = "CNAME"
|
||||
ttl = 1
|
||||
proxied = true
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "www" {
|
||||
zone_id = data.cloudflare_zones.domain.zones[0].id
|
||||
name = "www"
|
||||
value = var.site_domain
|
||||
type = "CNAME"
|
||||
ttl = 1
|
||||
proxied = true
|
||||
}
|
||||
|
||||
# S3 bucket versioning for content protection
|
||||
resource "aws_s3_bucket_versioning" "site" {
|
||||
bucket = aws_s3_bucket.site.id
|
||||
versioning_configuration {
|
||||
status = "Enabled"
|
||||
}
|
||||
}
|
||||
|
||||
# Access logging bucket for monitoring
|
||||
# resource "aws_s3_bucket" "access_logs" {
|
||||
# bucket = "${var.site_domain}-access-logs"
|
||||
#
|
||||
# tags = merge(local.common_tags, {
|
||||
# Purpose = "access-logs"
|
||||
# })
|
||||
# }
|
||||
|
||||
# resource "aws_s3_bucket_public_access_block" "access_logs" {
|
||||
# bucket = aws_s3_bucket.access_logs.id
|
||||
#
|
||||
# block_public_acls = true
|
||||
# block_public_policy = true
|
||||
# ignore_public_acls = true
|
||||
# restrict_public_buckets = true
|
||||
# }
|
||||
|
||||
# Enable access logging for the main site bucket
|
||||
# resource "aws_s3_bucket_logging" "site" {
|
||||
# bucket = aws_s3_bucket.site.id
|
||||
#
|
||||
# target_bucket = aws_s3_bucket.access_logs.id
|
||||
# target_prefix = "access-logs/"
|
||||
# }
|
||||
|
||||
# Lifecycle rules for cost management
|
||||
resource "aws_s3_bucket_lifecycle_configuration" "site" {
|
||||
bucket = aws_s3_bucket.site.id
|
||||
|
||||
rule {
|
||||
id = "cleanup_old_versions"
|
||||
status = "Enabled"
|
||||
|
||||
noncurrent_version_expiration {
|
||||
noncurrent_days = 90
|
||||
}
|
||||
filter {
|
||||
prefix = ""
|
||||
}
|
||||
}
|
||||
|
||||
rule {
|
||||
id = "cleanup_incomplete_uploads"
|
||||
status = "Enabled"
|
||||
|
||||
abort_incomplete_multipart_upload {
|
||||
days_after_initiation = 7
|
||||
}
|
||||
filter {
|
||||
prefix = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Lifecycle rules for access logs
|
||||
# resource "aws_s3_bucket_lifecycle_configuration" "access_logs" {
|
||||
# bucket = aws_s3_bucket.access_logs.id
|
||||
#
|
||||
# rule {
|
||||
# id = "delete_old_logs"
|
||||
# status = "Enabled"
|
||||
#
|
||||
# expiration {
|
||||
# days = 90
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
|
||||
resource "cloudflare_page_rule" "https" {
|
||||
zone_id = data.cloudflare_zones.domain.zones[0].id
|
||||
target = "*.${var.site_domain}/*"
|
||||
actions {
|
||||
always_use_https = true
|
||||
}
|
||||
module "static_website" {
|
||||
source = "./modules/static-website"
|
||||
|
||||
site_domain = var.site_domain
|
||||
project_name = var.project_name
|
||||
environment = var.environment
|
||||
}
|
||||
|
||||
141
modules/static-website/main.tf
Normal file
141
modules/static-website/main.tf
Normal file
@@ -0,0 +1,141 @@
|
||||
locals {
|
||||
common_tags = {
|
||||
Project = var.project_name
|
||||
Environment = var.environment
|
||||
ManagedBy = "terraform"
|
||||
Domain = var.site_domain
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket" "site" {
|
||||
bucket = var.site_domain
|
||||
|
||||
tags = local.common_tags
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_public_access_block" "site" {
|
||||
bucket = aws_s3_bucket.site.id
|
||||
|
||||
block_public_acls = false
|
||||
block_public_policy = false
|
||||
ignore_public_acls = false
|
||||
restrict_public_buckets = false
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_website_configuration" "site" {
|
||||
bucket = aws_s3_bucket.site.id
|
||||
|
||||
index_document {
|
||||
suffix = "index.html"
|
||||
}
|
||||
|
||||
error_document {
|
||||
key = "error.html"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_ownership_controls" "site" {
|
||||
bucket = aws_s3_bucket.site.id
|
||||
|
||||
rule {
|
||||
object_ownership = "BucketOwnerPreferred"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_acl" "site" {
|
||||
bucket = aws_s3_bucket.site.id
|
||||
|
||||
acl = "public-read"
|
||||
depends_on = [
|
||||
aws_s3_bucket_ownership_controls.site,
|
||||
aws_s3_bucket_public_access_block.site
|
||||
]
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_policy" "site" {
|
||||
bucket = aws_s3_bucket.site.id
|
||||
|
||||
policy = jsonencode({
|
||||
Version = "2012-10-17"
|
||||
Statement = [
|
||||
{
|
||||
Sid = "PublicReadGetObject"
|
||||
Effect = "Allow"
|
||||
Principal = "*"
|
||||
Action = "s3:GetObject"
|
||||
Resource = "${aws_s3_bucket.site.arn}/*"
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
depends_on = [
|
||||
aws_s3_bucket_public_access_block.site
|
||||
]
|
||||
}
|
||||
|
||||
data "cloudflare_zones" "domain" {
|
||||
filter {
|
||||
name = var.site_domain
|
||||
}
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "site_cname" {
|
||||
zone_id = data.cloudflare_zones.domain.zones[0].id
|
||||
name = var.site_domain
|
||||
value = aws_s3_bucket_website_configuration.site.website_endpoint
|
||||
type = "CNAME"
|
||||
ttl = 1
|
||||
proxied = true
|
||||
}
|
||||
|
||||
resource "cloudflare_record" "www" {
|
||||
zone_id = data.cloudflare_zones.domain.zones[0].id
|
||||
name = "www"
|
||||
value = var.site_domain
|
||||
type = "CNAME"
|
||||
ttl = 1
|
||||
proxied = true
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_versioning" "site" {
|
||||
bucket = aws_s3_bucket.site.id
|
||||
versioning_configuration {
|
||||
status = "Enabled"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_lifecycle_configuration" "site" {
|
||||
bucket = aws_s3_bucket.site.id
|
||||
|
||||
rule {
|
||||
id = "cleanup_old_versions"
|
||||
status = "Enabled"
|
||||
|
||||
noncurrent_version_expiration {
|
||||
noncurrent_days = 90
|
||||
}
|
||||
filter {
|
||||
prefix = ""
|
||||
}
|
||||
}
|
||||
|
||||
rule {
|
||||
id = "cleanup_incomplete_uploads"
|
||||
status = "Enabled"
|
||||
|
||||
abort_incomplete_multipart_upload {
|
||||
days_after_initiation = 7
|
||||
}
|
||||
filter {
|
||||
prefix = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "cloudflare_page_rule" "https" {
|
||||
zone_id = data.cloudflare_zones.domain.zones[0].id
|
||||
target = "*.${var.site_domain}/*"
|
||||
actions {
|
||||
always_use_https = true
|
||||
}
|
||||
}
|
||||
14
modules/static-website/outputs.tf
Normal file
14
modules/static-website/outputs.tf
Normal file
@@ -0,0 +1,14 @@
|
||||
output "website_bucket_name" {
|
||||
description = "Name (id) of the bucket"
|
||||
value = aws_s3_bucket.site.id
|
||||
}
|
||||
|
||||
output "bucket_endpoint" {
|
||||
description = "Bucket endpoint"
|
||||
value = aws_s3_bucket_website_configuration.site.website_endpoint
|
||||
}
|
||||
|
||||
output "domain_name" {
|
||||
description = "Website endpoint"
|
||||
value = var.site_domain
|
||||
}
|
||||
20
modules/static-website/variables.tf
Normal file
20
modules/static-website/variables.tf
Normal file
@@ -0,0 +1,20 @@
|
||||
variable "site_domain" {
|
||||
type = string
|
||||
description = "The domain name of the site"
|
||||
}
|
||||
|
||||
variable "project_name" {
|
||||
type = string
|
||||
description = "Name of the project for resource tagging"
|
||||
default = "tuffas"
|
||||
}
|
||||
|
||||
variable "environment" {
|
||||
type = string
|
||||
description = "Environment name (e.g., dev, staging, prod)"
|
||||
|
||||
validation {
|
||||
condition = contains(["dev", "staging", "prod"], var.environment)
|
||||
error_message = "Environment must be one of: dev, staging, prod."
|
||||
}
|
||||
}
|
||||
14
modules/static-website/versions.tf
Normal file
14
modules/static-website/versions.tf
Normal file
@@ -0,0 +1,14 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = "~> 5.92"
|
||||
}
|
||||
cloudflare = {
|
||||
source = "cloudflare/cloudflare"
|
||||
version = "~> 2.19.2"
|
||||
}
|
||||
}
|
||||
|
||||
required_version = ">= 1.2"
|
||||
}
|
||||
55
moved.tf
Normal file
55
moved.tf
Normal file
@@ -0,0 +1,55 @@
|
||||
moved {
|
||||
from = aws_s3_bucket.site
|
||||
to = module.static_website.aws_s3_bucket.site
|
||||
}
|
||||
|
||||
moved {
|
||||
from = aws_s3_bucket_acl.site
|
||||
to = module.static_website.aws_s3_bucket_acl.site
|
||||
}
|
||||
|
||||
moved {
|
||||
from = aws_s3_bucket_lifecycle_configuration.site
|
||||
to = module.static_website.aws_s3_bucket_lifecycle_configuration.site
|
||||
}
|
||||
|
||||
moved {
|
||||
from = aws_s3_bucket_ownership_controls.site
|
||||
to = module.static_website.aws_s3_bucket_ownership_controls.site
|
||||
}
|
||||
|
||||
|
||||
moved {
|
||||
from = aws_s3_bucket_policy.site
|
||||
to = module.static_website.aws_s3_bucket_policy.site
|
||||
}
|
||||
|
||||
moved {
|
||||
from = aws_s3_bucket_public_access_block.site
|
||||
to = module.static_website.aws_s3_bucket_public_access_block.site
|
||||
}
|
||||
|
||||
moved {
|
||||
from = aws_s3_bucket_versioning.site
|
||||
to = module.static_website.aws_s3_bucket_versioning.site
|
||||
}
|
||||
|
||||
moved {
|
||||
from = aws_s3_bucket_website_configuration.site
|
||||
to = module.static_website.aws_s3_bucket_website_configuration.site
|
||||
}
|
||||
|
||||
moved {
|
||||
from = cloudflare_record.www
|
||||
to = module.static_website.cloudflare_record.www
|
||||
}
|
||||
|
||||
moved {
|
||||
from = cloudflare_record.site_cname
|
||||
to = module.static_website.cloudflare_record.site_cname
|
||||
}
|
||||
|
||||
moved {
|
||||
from = cloudflare_page_rule.https
|
||||
to = module.static_website.cloudflare_page_rule.https
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
output "website_bucket_name" {
|
||||
description = "Name (id) of the bucket"
|
||||
value = aws_s3_bucket.site.id
|
||||
value = module.static_website.website_bucket_name
|
||||
}
|
||||
|
||||
output "bucket_endpoint" {
|
||||
description = "Bucket endpoint"
|
||||
value = aws_s3_bucket_website_configuration.site.website_endpoint
|
||||
value = module.static_website.bucket_endpoint
|
||||
}
|
||||
|
||||
output "domain_name" {
|
||||
description = "Website endpoint"
|
||||
value = var.site_domain
|
||||
value = module.static_website.domain_name
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user