terraform { required_providers { hcloud = { source = "hetznercloud/hcloud" version = "~> 1.45" } } } # Control-plane baseline host (API + MySQL + Redis). Deployed on a stable cloud # COMPLETELY UNRELATED to the data-plane node vendors (doc/04 §5.2): nodes can # all die without touching the control plane, and vice-versa. Carries NO proxy # traffic. # # Provisioned once and rarely changed — hence Terraform-managed. Application # bring-up (containers, migrations) is handled separately by the server deploy # pipeline, not here. resource "hcloud_server" "control_plane" { name = "pangolin-control-plane" server_type = var.server_type image = var.image location = var.location ssh_keys = var.ssh_key_ids labels = { role = "control-plane" project = "pangolin" } lifecycle { # Never recreate the control plane implicitly — it holds the user DB. prevent_destroy = true } } # Admin/SSH surface is never on the open internet (doc/06 §2). Inbound is locked # to the management allowlist; the public API is expected to sit behind a CDN / # reverse proxy terminated elsewhere. resource "hcloud_firewall" "control_plane" { name = "pangolin-control-plane" rule { direction = "in" protocol = "tcp" port = "22" source_ips = length(var.allowlist_cidrs) > 0 ? var.allowlist_cidrs : ["0.0.0.0/0", "::/0"] } } resource "hcloud_firewall_attachment" "control_plane" { firewall_id = hcloud_firewall.control_plane.id server_ids = [hcloud_server.control_plane.id] }