Skip to content

Commit

Permalink
feat: add terraform cloudflare (#492)
Browse files Browse the repository at this point in the history
  • Loading branch information
timtorChen authored Nov 27, 2024
1 parent 1fabc60 commit 6a26b03
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 0 deletions.
22 changes: 22 additions & 0 deletions terraform/.taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,25 @@ tasks:
- task: tf:output
vars:
DIR: grafana

## cloudflare
cloudflare:init:
cmds:
- task: tf:switch-init
vars:
DIR: cloudflare
cloudflare:plan:
cmds:
- task: tf:plan
vars:
DIR: cloudflare
cloudflare:apply:
cmds:
- task: tf:apply
vars:
DIR: cloudflare
cloudflare:output:
cmds:
- task: tf:output
vars:
DIR: cloudflare
68 changes: 68 additions & 0 deletions terraform/cloudflare/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions terraform/cloudflare/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
### Permission

```
timtor - Cloudflare Tunnel:Edit, Zero Trust:Edit, Account Settings:Read
- All zones - DNS:Edit
```
9 changes: 9 additions & 0 deletions terraform/cloudflare/data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
data "aws_ssm_parameter" "cloudflare" {
name = "/terraform/cloudflare"
}

data "cloudflare_accounts" "main" {}

data "cloudflare_zone" "main" {
name = local.zone
}
72 changes: 72 additions & 0 deletions terraform/cloudflare/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
terraform {
required_version = "~> 1.6.3"

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.46.0"
}
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 4.46.0"
}
random = {
source = "hashicorp/random"
version = "~> 3.6.3"
}
}
backend "s3" {
bucket = "amethyst-terraform-backend"
key = "homelab/cloudflare"
dynamodb_table = "tfstate-lock"
region = "us-west-2"
}
}

provider "cloudflare" {
api_token = local.cloudflare_token
}

locals {
cloudflare_token = jsondecode(data.aws_ssm_parameter.cloudflare.value)["cloudflare_token"]
cloudflare_tunnel_homelab_secret = jsondecode(data.aws_ssm_parameter.cloudflare.value)["cloudflare_tunnel_homelab_secret"]
}

locals {
zone = "timtor.dev"
zone_id = data.cloudflare_zone.main.zone_id
account_id = data.cloudflare_accounts.main.accounts[0].id
}

locals {
homelab_network_cidr = "192.168.248.0/21"
homelab_dns_server = ["192.168.248.1"]
homelab_private_domains = [
"drive.timtor.dev",
"grafana.timtor.dev",
"hass.timtor.dev",
"music.timtor.dev",
"photo.timtor.dev",
"rss.timtor.dev",
"s3-fast.timtor.dev",
"ui.timtor.dev",
"vault.timtor.dev"
]
homelab_public_ingress_rules = [
{
hostname = "grafana.timtor.dev"
service = "https://grafana.timtor.dev"
},
{
hostname = "kromgo.timtor.dev"
service = "https://kromgo.timtor.dev"
},
{
hostname = "flux.timtor.dev"
service = "https://flux.timtor.dev"
},
{
service = "http_status:404"
}
]
}
14 changes: 14 additions & 0 deletions terraform/cloudflare/record.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
resource "cloudflare_record" "homelab-public" {
for_each = { for index, rule in local.homelab_public_ingress_rules :
index => rule
if try(rule.hostname, null) != null
}

zone_id = local.zone_id
type = "CNAME"
name = split(".", each.value.hostname)[0]
content = "${cloudflare_zero_trust_tunnel_cloudflared.homelab.id}.cfargotunnel.com"
proxied = true
allow_overwrite = true

}
61 changes: 61 additions & 0 deletions terraform/cloudflare/zero-trust.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
resource "cloudflare_zero_trust_tunnel_cloudflared" "homelab" {
account_id = local.account_id
name = "homelab"
secret = local.cloudflare_tunnel_homelab_secret
}

resource "cloudflare_zero_trust_tunnel_cloudflared_config" "homelab" {
account_id = local.account_id
tunnel_id = cloudflare_zero_trust_tunnel_cloudflared.homelab.id

config {
warp_routing {
enabled = true
}
# "Networks > Tunnels > Public Hostname" on web
dynamic "ingress_rule" {
for_each = local.homelab_public_ingress_rules
iterator = rule
content {
hostname = try(rule.value.hostname, null)
service = rule.value.service
}
}
}
}

# "Networks > Tunnels > Private Network" on web, and the added
# private network item will reconcile to "Network > Routes"
resource "cloudflare_zero_trust_tunnel_route" "homelab" {
account_id = local.account_id
tunnel_id = cloudflare_zero_trust_tunnel_cloudflared.homelab.id
network = local.homelab_network_cidr
}

# default device profile
resource "cloudflare_zero_trust_device_profiles" "default" {
account_id = local.account_id
default = true
name = "Default"
description = "Default profile"
captive_portal = 180
allow_mode_switch = true
tunnel_protocol = "wireguard"
service_mode_v2_mode = "warp"
# TODO: support argument after 5.0.0
# lan_allow_minutes = 0
}

# local fallback domain is bound to account
resource "cloudflare_zero_trust_local_fallback_domain" "default" {
account_id = local.account_id

dynamic "domains" {
for_each = local.homelab_private_domains
iterator = domain
content {
suffix = domain.value
dns_server = local.homelab_dns_server
}
}
}

0 comments on commit 6a26b03

Please sign in to comment.