Files
homelab/terraform/edge/tencent.tf
T

131 lines
4.5 KiB
Terraform
Raw Normal View History

# The relay: one small CVM in Tencent Cloud that terminates TLS for the .cn
# domain and forwards over WireGuard to the homelab ingress.
#
# Why a relay and not Cloudflare: mainland clients reach a Tencent edge far
# faster than a Cloudflare edge, and Cloudflare's China network is an
# Enterprise product. The homelab keeps zero inbound exposure because the
# tunnel is dialled outbound from the cluster.
#
# ICP FILING: a mainland resource serving HTTP/HTTPS for a domain requires an
# ICP filing naming that domain. Without it this instance accepts the
# connection and the mainland network resets the HTTP layer. Put the relay in a
# non-mainland region (ap-hongkong, ap-singapore) when no filing exists.
resource "tencentcloud_vpc" "edge" {
name = "${replace(var.china_domain, ".", "_")}_edge"
cidr_block = "10.66.0.0/16"
}
resource "tencentcloud_subnet" "edge" {
name = "${replace(var.china_domain, ".", "_")}_edge"
vpc_id = tencentcloud_vpc.edge.id
availability_zone = var.tencent_availability_zone
cidr_block = "10.66.1.0/24"
}
resource "tencentcloud_key_pair" "edge" {
key_name = "${replace(var.china_domain, ".", "_")}_edge"
public_key = var.relay_ssh_public_key
}
resource "tencentcloud_security_group" "edge" {
name = "${replace(var.china_domain, ".", "_")}_edge"
description = "TLS + WireGuard for the ${var.china_domain} relay; SSH from the operator only"
}
resource "tencentcloud_security_group_rule" "ssh" {
security_group_id = tencentcloud_security_group.edge.id
type = "ingress"
ip_protocol = "tcp"
port_range = "22"
cidr_ip = var.relay_admin_cidr
policy = "accept"
}
resource "tencentcloud_security_group_rule" "tls" {
security_group_id = tencentcloud_security_group.edge.id
type = "ingress"
ip_protocol = "tcp"
port_range = "80,443"
cidr_ip = "0.0.0.0/0"
policy = "accept"
}
resource "tencentcloud_security_group_rule" "wireguard" {
security_group_id = tencentcloud_security_group.edge.id
type = "ingress"
ip_protocol = "udp"
port_range = tostring(var.wireguard_port)
cidr_ip = var.relay_admin_cidr
policy = "accept"
}
# cloud-init: WireGuard listener, forwarding sysctls, and Caddy for TLS.
# The relay never holds application credentials; it forwards bytes.
locals {
relay_user_data = <<-EOT
#cloud-config
package_update: true
packages: [wireguard, wireguard-tools, caddy]
write_files:
- path: /etc/wireguard/wg0.conf
permissions: "0600"
content: |
[Interface]
Address = ${var.wireguard_relay_address}
ListenPort = ${var.wireguard_port}
PrivateKey = ${var.wireguard_relay_private_key}
[Peer]
PublicKey = ${var.wireguard_homelab_public_key}
AllowedIPs = ${var.wireguard_homelab_address}
PersistentKeepalive = 25
- path: /etc/sysctl.d/99-wireguard.conf
content: |
net.ipv4.ip_forward = 1
runcmd:
- sysctl --system
- systemctl enable --now wg-quick@wg0
- systemctl enable --now caddy
EOT
}
resource "tencentcloud_instance" "relay" {
instance_name = "${replace(var.china_domain, ".", "_")}_edge"
availability_zone = var.tencent_availability_zone
image_id = var.relay_image_id
instance_type = var.relay_instance_type
vpc_id = tencentcloud_vpc.edge.id
subnet_id = tencentcloud_subnet.edge.id
security_groups = [tencentcloud_security_group.edge.id]
key_ids = [tencentcloud_key_pair.edge.id]
allocate_public_ip = true
# Outbound only needs a few Mbps; inbound TLS is the same order.
internet_max_bandwidth_out = 20
system_disk_type = "CLOUD_PREMIUM"
system_disk_size = 50
user_data = local.relay_user_data
tags = {
role = "china-edge"
domain = var.china_domain
}
}
# DNS for the .cn domain lives at DNSPod (Tencent). Each subdomain resolves to
# the relay's public address, and the relay proxies to the homelab over the
# tunnel. The "中国境内" line is the default line; no separate line records.
resource "tencentcloud_dnspod_record" "china" {
for_each = toset(var.china_hostnames)
domain = var.china_domain
sub_domain = each.value
record_type = "A"
record_line = "默认"
value = tencentcloud_instance.relay.public_ip
ttl = 600
remark = "China edge relay; origin is the homelab ingress over WireGuard"
}