feat(edge): Terraform for the China-facing relay and Cloudflare DNS
Adds terraform/edge, a root module with two providers: - Cloudflare 5.28.1: CNAMEs to the existing tunnel, plus an opt-in resource that can take the tunnel ingress list over when manage_tunnel_config is true. It is off by default because that resource REPLACES the whole list, and the tunnel is remotely managed from the dashboard today. - Tencent Cloud 1.83.38: VPC, subnet, security group with three rules, key pair, one CVM relay with cloud-init (WireGuard listener, forwarding sysctls, Caddy), and DNSPod A records for the .cn hostnames. The design keeps the homelab inbound-free: the relay terminates TLS in China and forwards over a WireGuard tunnel the cluster dials outbound. Cloudflare keeps serving every existing hostname untouched. Verified: terraform init succeeds for both providers, fmt clean, validate reports 0 errors, and plan resolves to 10 creates with placeholder variables. Provider-side name validation caught a real bug during that run: key pair and security group names allow only letters, digits and underscore, so the derived names use underscores. Not applied. Credentials come from CLOUDFLARE_API_TOKEN, TENCENTCLOUD_SECRET_ID and TENCENTCLOUD_SECRET_KEY; the WireGuard private key is TF_VAR only. State is local and git-ignored like terraform/zitadel. Blocked on facts this module cannot invent: the real .cn domain, whether it has an ICP filing, the CVM image ID, the operator CIDR, and the homelab WireGuard public key.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
# Cloudflare side of the edge.
|
||||
#
|
||||
# The tunnel itself is remotely managed today: its token lives in
|
||||
# k8s/apps/cloudflared and the public hostnames are configured in the Zero
|
||||
# Trust dashboard. Terraform can own the DNS records without owning the tunnel,
|
||||
# which is the safe half: a record change is reversible, a tunnel config rewrite
|
||||
# removes every hostname the plan does not list.
|
||||
|
||||
locals {
|
||||
# CNAME target of every remotely-managed tunnel.
|
||||
tunnel_target = "${var.tunnel_id}.cfargotunnel.com"
|
||||
}
|
||||
|
||||
resource "cloudflare_dns_record" "tunnel" {
|
||||
for_each = toset(var.cloudflare_tunnel_hostnames)
|
||||
|
||||
zone_id = var.cloudflare_zone_id
|
||||
name = each.value
|
||||
type = "CNAME"
|
||||
content = local.tunnel_target
|
||||
proxied = true
|
||||
ttl = 1 # 1 = automatic, required when proxied is true
|
||||
comment = "cloudflared tunnel; managed by terraform/edge"
|
||||
}
|
||||
|
||||
# Optional: take the tunnel configuration into Terraform. Off by default.
|
||||
# Applying it REPLACES the whole ingress list. Import first:
|
||||
# terraform import cloudflare_zero_trust_tunnel_cloudflared_config.this \
|
||||
# <account_id>/<tunnel_id>
|
||||
resource "cloudflare_zero_trust_tunnel_cloudflared_config" "this" {
|
||||
count = var.manage_tunnel_config ? 1 : 0
|
||||
|
||||
account_id = var.cloudflare_account_id
|
||||
tunnel_id = var.tunnel_id
|
||||
|
||||
config = {
|
||||
ingress = concat(
|
||||
[for host, service in var.tunnel_ingress : { hostname = host, service = service }],
|
||||
[{ service = "http_status:404" }],
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user