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,136 @@
|
||||
variable "cloudflare_api_token" {
|
||||
description = "Cloudflare API token with Zone:DNS:Edit and, for tunnel config, Account:Cloudflare Tunnel:Edit."
|
||||
type = string
|
||||
sensitive = true
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "cloudflare_zone_id" {
|
||||
description = "Zone ID of the existing public zone (riotpiao.com)."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cloudflare_account_id" {
|
||||
description = "Account ID. Required only when manage_tunnel_config is true."
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "tunnel_id" {
|
||||
description = "UUID of the cloudflared tunnel that the DNS records point at."
|
||||
type = string
|
||||
}
|
||||
|
||||
# The dashboard remains the source of truth for the remotely-managed tunnel
|
||||
# today. Setting this true hands that config to Terraform, which then rewrites
|
||||
# the whole ingress list: every hostname not listed in tunnel_ingress is
|
||||
# removed from the tunnel. Import first and read the plan before applying.
|
||||
variable "manage_tunnel_config" {
|
||||
description = "Take ownership of the remotely-managed tunnel configuration."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "tunnel_ingress" {
|
||||
description = "hostname => origin service, used only when manage_tunnel_config is true."
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
# ── DNS records managed in the Cloudflare zone ───────────────────────────────
|
||||
# These names already exist, created by hand in the dashboard. Adopt them with
|
||||
# `terraform import` before the first apply, or Terraform will try to create a
|
||||
# second record with the same name and Cloudflare will reject it.
|
||||
variable "cloudflare_tunnel_hostnames" {
|
||||
description = "Hostnames in the Cloudflare zone that must CNAME to the tunnel."
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
# ── China edge ───────────────────────────────────────────────────────────────
|
||||
variable "china_domain" {
|
||||
description = "The .cn domain served from Tencent Cloud, without a trailing dot."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "china_hostnames" {
|
||||
description = "Subdomains of china_domain that point at the Tencent relay."
|
||||
type = list(string)
|
||||
default = ["paperless", "img"]
|
||||
}
|
||||
|
||||
variable "tencent_secret_id" {
|
||||
description = "Tencent Cloud SecretId. Prefer TENCENTCLOUD_SECRET_ID in the environment."
|
||||
type = string
|
||||
sensitive = true
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "tencent_secret_key" {
|
||||
description = "Tencent Cloud SecretKey. Prefer TENCENTCLOUD_SECRET_KEY in the environment."
|
||||
type = string
|
||||
sensitive = true
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "tencent_region" {
|
||||
description = "Tencent Cloud region for the relay. Mainland regions need an ICP filing for the domain."
|
||||
type = string
|
||||
default = "ap-guangzhou"
|
||||
}
|
||||
|
||||
variable "tencent_availability_zone" {
|
||||
description = "Availability zone inside tencent_region."
|
||||
type = string
|
||||
default = "ap-guangzhou-6"
|
||||
}
|
||||
|
||||
variable "relay_instance_type" {
|
||||
description = "CVM spec for the relay. A relay only terminates TLS and forwards bytes."
|
||||
type = string
|
||||
default = "S5.SMALL2"
|
||||
}
|
||||
|
||||
variable "relay_image_id" {
|
||||
description = "CVM image ID. Find one with: tencentcloud images --image-name 'Ubuntu 24.04' (or the console)."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "relay_ssh_public_key" {
|
||||
description = "Public key injected into the relay for break-glass SSH. Never the private key."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "relay_admin_cidr" {
|
||||
description = "CIDR allowed to reach SSH on the relay. Keep it to the operator, not 0.0.0.0/0."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "wireguard_port" {
|
||||
description = "UDP port of the WireGuard listener on the relay."
|
||||
type = number
|
||||
default = 51820
|
||||
}
|
||||
|
||||
variable "wireguard_relay_private_key" {
|
||||
description = "WireGuard private key of the relay side. Generate with `wg genkey`; pass via TF_VAR_wireguard_relay_private_key."
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "wireguard_homelab_public_key" {
|
||||
description = "WireGuard public key of the homelab peer that dials the relay."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "wireguard_relay_address" {
|
||||
description = "Tunnel address of the relay side."
|
||||
type = string
|
||||
default = "10.88.0.1/24"
|
||||
}
|
||||
|
||||
variable "wireguard_homelab_address" {
|
||||
description = "Tunnel address of the homelab side."
|
||||
type = string
|
||||
default = "10.88.0.2/24"
|
||||
}
|
||||
Reference in New Issue
Block a user