From 1ee343dfca0202c0b72247e7fea065a89c16e123 Mon Sep 17 00:00:00 2001 From: sjat Date: Sun, 14 Jun 2026 17:38:51 +0200 Subject: [PATCH] feat(tf): open Caddy 80/443 + NetBird 3478 on askari (public_web) hetzner_vm gains a public_web bool (default false); offsite sets it true. Firewall adds 80/443 tcp + 3478 udp from anywhere (SSH-from-ubongo preserved). For M4 Caddy + NetBird. Co-Authored-By: Claude Opus 4.8 (1M context) --- terraform/environments/offsite/main.tf | 5 +++-- terraform/modules/hetzner_vm/main.tf | 25 +++++++++++++++++++++-- terraform/modules/hetzner_vm/variables.tf | 6 ++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/terraform/environments/offsite/main.tf b/terraform/environments/offsite/main.tf index a0aa80a..0b0666e 100644 --- a/terraform/environments/offsite/main.tf +++ b/terraform/environments/offsite/main.tf @@ -5,13 +5,14 @@ module "askari" { source = "../../modules/hetzner_vm" - name = "askari" - server_type = "cx23" # x86, 2 vCPU / 4 GB / 40 GB (CAX11/ARM was out of stock in + name = "askari" + server_type = "cx23" # x86, 2 vCPU / 4 GB / 40 GB (CAX11/ARM was out of stock in # every EU location 2026-06-14; cx23 is same-spec + cheaper) location = "hel1" # Helsinki image = "debian-13" ansible_ssh_pubkey = var.ansible_ssh_pubkey ssh_admin_cidrs = var.ssh_admin_cidrs + public_web = true # Caddy 80/443 + NetBird 3478 (M4) labels = { env = "offsite" group = "offsite_hosts" diff --git a/terraform/modules/hetzner_vm/main.tf b/terraform/modules/hetzner_vm/main.tf index 2228a9b..f360dce 100644 --- a/terraform/modules/hetzner_vm/main.tf +++ b/terraform/modules/hetzner_vm/main.tf @@ -26,14 +26,35 @@ resource "hcloud_ssh_key" "ansible" { resource "hcloud_firewall" "this" { name = "${var.name}-fw" - # SSH from the control node only. NetBird ports (UDP 3478, TCP 80/443) are added - # in M4 when the coordinator deploys (ADR-020); host nftables stays catalog-driven. + # SSH from the control node only. rule { direction = "in" protocol = "tcp" port = "22" source_ips = var.ssh_admin_cidrs } + + # Public web (Caddy 80/443) + NetBird STUN/TURN (3478/udp) — only when public_web + # (ADR-024, M4). Host nftables stays catalog-driven (ADR-020). + dynamic "rule" { + for_each = var.public_web ? ["80", "443"] : [] + content { + direction = "in" + protocol = "tcp" + port = rule.value + source_ips = ["0.0.0.0/0", "::/0"] + } + } + + dynamic "rule" { + for_each = var.public_web ? ["3478"] : [] + content { + direction = "in" + protocol = "udp" + port = rule.value + source_ips = ["0.0.0.0/0", "::/0"] + } + } } resource "hcloud_server" "this" { diff --git a/terraform/modules/hetzner_vm/variables.tf b/terraform/modules/hetzner_vm/variables.tf index 0cc73b8..faf92e2 100644 --- a/terraform/modules/hetzner_vm/variables.tf +++ b/terraform/modules/hetzner_vm/variables.tf @@ -28,6 +28,12 @@ variable "ssh_admin_cidrs" { type = list(string) } +variable "public_web" { + description = "Open the public web/NetBird ports (80/443 TCP, 3478 UDP) to the internet" + type = bool + default = false +} + variable "labels" { description = "Hetzner resource labels (metadata only)" type = map(string)