Add terraform

This commit is contained in:
2025-01-04 17:55:41 +09:00
parent 4b4d90bada
commit c1597aab10
10 changed files with 268 additions and 0 deletions

39
terraform/.gitignore vendored Normal file
View File

@@ -0,0 +1,39 @@
# Local .terraform directories
**/.terraform/*
# .tfstate files
*.tfstate
*.tfstate.*
# Crash log files
crash.log
crash.*.log
# Exclude all .tfvars files, which are likely to contain sensitive data, such as
# password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject
# to change depending on the environment.
*.tfvars
*.tfvars.json
*.tfbackend
# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json
# Ignore transient lock info files created by terraform apply
.terraform.tfstate.lock.info
# Include override files you do wish to add to version control using negated pattern
# !example_override.tf
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
*tfplan*
# Ignore CLI configuration files
.terraformrc
terraform.rc

48
terraform/.terraform.lock.hcl generated Normal file
View File

@@ -0,0 +1,48 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/cloudflare/cloudflare" {
version = "4.49.1"
constraints = "~> 4.0"
hashes = [
"h1:z4oKPWJNl2HKC+RMASmezyNnRY5+a6G4/mKcOpNBZIg=",
"zh:0b8b0d1e843e30538e62855b7c4b8d6a31b19213c238b5f92bfd88ef6c0e78f0",
"zh:485799332114da08e683f2b7ebf0d25f73d2f1542ebe30ef33fe66902b700120",
"zh:486a07fd96dabda4a3ae2a4314a27dc49a6eee5220fc92ecfd2e68821a0e5109",
"zh:5d8b76c8bbc99c5b1197c61ad32ae140b13d5785d5ff0297fc052d35f61eeea9",
"zh:66c75f38c6ec63c237dbd81e251c97f5c14e18191f20a45f23fbaa6409763c17",
"zh:792bcc98fddf3d65608a7a1977d4713bbcc2b3e70082d5c17f5511b50abcc2b9",
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
"zh:97e5dc2a26a786e7b91a4a57268c3fb00ecbf454762f0a4f4dd7f06059bbe391",
"zh:9ce3abaf4f92454ed1270f3797fd5293f234076e932d7120835f64c6c47f3d27",
"zh:9face526228efc7e80919293b5f7a6a7e2970269fd73368b34276ccf4f6b7a34",
"zh:caefbbdfbe506e72fb8f5db2c8cb84708a6758d787292ba64d396738954fb83a",
"zh:d0eac35becf8b05a5f9435702bcb6659a91d4ce45597d56b69ac7102491f722b",
"zh:dba8e44ec593123d993c8dc1a179128d398a0302c2dbab1f7c427b5eb0f69151",
"zh:dcc09dcc54879251c32562e1251b85cdcec3970257a00721915af80a236aa209",
"zh:e010fe2fd67d96e19b022333c90df7113878f059e020b15eff73c0fa0916cfcd",
]
}
provider "registry.terraform.io/germanbrew/dotenv" {
version = "1.1.4"
constraints = "~> 1.1.3"
hashes = [
"h1:/aw4/LKhgWwFO35NnOyfFSIybNIzslmXwED1+C6BEcA=",
"zh:13f6a4a4bb097e2b54a9fc5e8f737924d67215ce28c20b6ebf588a6ba829cd1d",
"zh:1ebea010aaba4ad838763a9781d8c3eda97b8d5136e09c1af07a06f7b59058be",
"zh:2876ef56721f2ab7c7e6a82118b0e40cfd3a7b5919aa41fc8ee5ea7e767d1f57",
"zh:421d1a464f4822262bcd3ad793e9e30ba3e5d235840af7e665d3aaaa961bbbed",
"zh:56a211b9d6cdb1fde4d4a2470e530016ac987ca0aa906c6c8d68e594de3e3573",
"zh:5de69319d66558c3c463d5578f4f8a43e48880a5313c0f41b064cc30e923d2d6",
"zh:60f32bba3971f0061759dbf386e6c17947a2e2da08909856a8816e2b8c9ea300",
"zh:85fd8eeb76885ecefe1880019a650bd0b8fc3862b767d30562016374ec4d7e91",
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
"zh:8c7c1f427fdbd2d9716bf686e2d83fde130c15af88cb2ad1c627c96010f52128",
"zh:91f9c38b663ff2a77c300f8eaa177db3f5cc614f93eecf0c2390af393040397f",
"zh:b00b06f5bdf2eae7dc5b5223aa190963d81d94e9bba3f3338af4cfb73d4ebc15",
"zh:b5a1174aedbb1b25bd3a783ca6af2a52469a185347a2ae5db6634b213df0744d",
"zh:baaadf8ee47ac956116e9e9048cedda8813823c3a00cdb986d3144f1de1ad01b",
"zh:ca62cd06d5928a4a38dc3378abcc6500e544071b070b9c4d80621c7475178993",
]
}

11
terraform/data.tf Normal file
View File

@@ -0,0 +1,11 @@
data "dotenv" "this" {
filename = "${path.module}/../.env"
}
data "cloudflare_zone" "this" {
zone_id = var.ZONE_ID
}
data "cloudflare_api_token_permission_groups" "all" {
}

5
terraform/locals.tf Normal file
View File

@@ -0,0 +1,5 @@
locals {
name = replace(var.REPOSITORY_NAME, ".", "-")
account_id = data.dotenv.this.entries.CLOUDFLARE_ACCOUNT_ID
web_domain = "www.${var.BASE_DOMAIN}"
}

33
terraform/main.tf Normal file
View File

@@ -0,0 +1,33 @@
terraform {
required_version = ">= 1.9"
backend "s3" {
region = "auto"
# Set these properties with `terraform.tfbackend`:
// bucket = "tfstate"
// key = "xxxxxxx.tfstate"
// access_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
// secret_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
// endpoints = { s3 = "https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.r2.cloudflarestorage.com" }
skip_credentials_validation = true
skip_metadata_api_check = true
skip_region_validation = true
skip_requesting_account_id = true
skip_s3_checksum = true
use_path_style = true
}
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 4"
}
dotenv = {
source = "germanbrew/dotenv"
version = "~> 1.1.3"
}
}
}

101
terraform/resources.tf Normal file
View File

@@ -0,0 +1,101 @@
resource "cloudflare_pages_project" "web" {
account_id = data.dotenv.this.entries.CLOUDFLARE_ACCOUNT_ID
name = local.name
production_branch = "main"
source {
type = "github"
config {
owner = var.REPOSITORY_OWNER
repo_name = var.REPOSITORY_NAME
production_branch = "main"
pr_comments_enabled = true
deployments_enabled = true
}
}
build_config {
build_command = "yarn build"
root_dir = "apps/web"
destination_dir = ".svelte-kit/cloudflare"
build_caching = true
}
deployment_configs {
preview {
environment_variables = {
PUBLIC_WEB_DOMAIN = local.web_domain
PUBLIC_WEB_TURNSTILE_SITEKEY = cloudflare_turnstile_widget.web.id
}
secrets = {
WEB_TURNSTILE_SECRET_KEY = cloudflare_turnstile_widget.web.secret
}
compatibility_date = "2024-09-18"
compatibility_flags = ["nodejs_compat"]
}
production {
environment_variables = {
PUBLIC_WEB_DOMAIN = local.web_domain
PUBLIC_WEB_TURNSTILE_SITEKEY = cloudflare_turnstile_widget.web.id
}
secrets = {
WEB_TURNSTILE_SECRET_KEY = cloudflare_turnstile_widget.web.secret
}
compatibility_date = "2024-09-18"
compatibility_flags = ["nodejs_compat"]
}
}
}
resource "cloudflare_pages_domain" "web" {
account_id = data.dotenv.this.entries.CLOUDFLARE_ACCOUNT_ID
project_name = cloudflare_pages_project.web.name
domain = local.web_domain
}
resource "cloudflare_record" "web" {
zone_id = data.cloudflare_zone.this.zone_id
name = local.web_domain
type = "CNAME"
content = cloudflare_pages_project.web.subdomain
ttl = 1
proxied = true
}
resource "cloudflare_turnstile_widget" "web" {
account_id = data.dotenv.this.entries.CLOUDFLARE_ACCOUNT_ID
name = "Widget for ${local.name}"
domains = [local.web_domain]
mode = "managed"
}
resource "cloudflare_workers_script" "redirect" {
account_id = data.dotenv.this.entries.CLOUDFLARE_ACCOUNT_ID
name = "redirect-${local.name}"
module = true
content = <<EOF
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
// Check if the hostname is the apex domain
if (url.hostname === '${var.BASE_DOMAIN}') {
// Redirect to www subdomain with a 301 status
url.hostname = '${local.web_domain}';
return Response.redirect(url.toString(), 301);
}
// If it's not the apex domain, just proceed with the original request
return fetch(request);
},
};
EOF
}
resource "cloudflare_workers_domain" "redirect" {
account_id = data.dotenv.this.entries.CLOUDFLARE_ACCOUNT_ID
hostname = var.BASE_DOMAIN
service = cloudflare_workers_script.redirect.name
zone_id = data.cloudflare_zone.this.zone_id
}

View File

@@ -0,0 +1,5 @@
bucket = "tfstate"
key = "website_staging.tfstate"
access_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
secret_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
endpoints = { s3 = "https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.r2.cloudflarestorage.com" }

View File

@@ -0,0 +1,4 @@
BASE_DOMAIN = "preview.0b4k3.com"
REPOSITORY_NAME = "website-staging"
REPOSITORY_OWNER = "0b4k3-website"
ZONE_ID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

19
terraform/variables.tf Normal file
View File

@@ -0,0 +1,19 @@
variable "REPOSITORY_NAME" {
description = "Name of the GitHub repository"
type = string
}
variable "REPOSITORY_OWNER" {
description = "Owner of the GitHub repository"
type = string
}
variable "BASE_DOMAIN" {
description = "Base domain for the site"
type = string
}
variable "ZONE_ID" {
description = "Zone ID of the domain"
type = string
}