Add terraform
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
# Cloudflare
|
||||
CLOUDFLARE_ACCOUNT_ID="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
CLOUDFLARE_API_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
|
||||
39
terraform/.gitignore
vendored
Normal file
39
terraform/.gitignore
vendored
Normal 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
48
terraform/.terraform.lock.hcl
generated
Normal 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
11
terraform/data.tf
Normal 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
5
terraform/locals.tf
Normal 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
33
terraform/main.tf
Normal 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
101
terraform/resources.tf
Normal 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
|
||||
}
|
||||
5
terraform/terraform.tfbackend.example
Normal file
5
terraform/terraform.tfbackend.example
Normal file
@@ -0,0 +1,5 @@
|
||||
bucket = "tfstate"
|
||||
key = "website_staging.tfstate"
|
||||
access_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
secret_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
endpoints = { s3 = "https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.r2.cloudflarestorage.com" }
|
||||
4
terraform/terraform.tfvars.example
Normal file
4
terraform/terraform.tfvars.example
Normal 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
19
terraform/variables.tf
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user