resource "hcloud_firewall" "app" { name = "${local.name_prefix}-firewall-app" rule { direction = "in" protocol = "tcp" port = "22" source_ips = var.admin_allowed_cidrs description = "SSH — admin CIDRs only" } rule { direction = "in" protocol = "tcp" port = "80" source_ips = ["0.0.0.0/0", "::/0"] description = "HTTP public" } rule { direction = "in" protocol = "tcp" port = "443" source_ips = ["0.0.0.0/0", "::/0"] description = "HTTPS public" } rule { direction = "in" protocol = "tcp" port = "2377" source_ips = [local.app_subnet_cidr] description = "Docker Swarm control plane" } rule { direction = "in" protocol = "tcp" port = "7946" source_ips = [local.app_subnet_cidr] description = "Docker Swarm node discovery (TCP)" } rule { direction = "in" protocol = "udp" port = "7946" source_ips = [local.app_subnet_cidr] description = "Docker Swarm node discovery (UDP)" } rule { direction = "in" protocol = "udp" port = "4789" source_ips = [local.app_subnet_cidr] description = "Docker Swarm VXLAN overlay" } rule { direction = "in" protocol = "tcp" port = "2377" source_ips = [local.db_subnet_cidr] description = "Docker Swarm control plane from DB subnet" } rule { direction = "in" protocol = "tcp" port = "7946" source_ips = [local.db_subnet_cidr] description = "Docker Swarm node discovery (TCP) from DB subnet" } rule { direction = "in" protocol = "udp" port = "7946" source_ips = [local.db_subnet_cidr] description = "Docker Swarm node discovery (UDP) from DB subnet" } rule { direction = "in" protocol = "udp" port = "4789" source_ips = [local.db_subnet_cidr] description = "Docker Swarm VXLAN overlay from DB subnet" } rule { direction = "in" protocol = "tcp" port = "8200" source_ips = [local.app_subnet_cidr] description = "Vault API — private only, never public" } rule { direction = "in" protocol = "tcp" port = "6379" source_ips = [local.app_subnet_cidr] description = "Redis" } rule { direction = "in" protocol = "tcp" port = "5672" source_ips = [local.app_subnet_cidr] description = "RabbitMQ AMQP" } rule { direction = "in" protocol = "tcp" port = "61613" source_ips = [local.app_subnet_cidr] description = "RabbitMQ STOMP" } rule { direction = "in" protocol = "tcp" port = "15674" source_ips = [local.app_subnet_cidr] description = "RabbitMQ Web STOMP" } rule { direction = "in" protocol = "tcp" port = "15672" source_ips = [local.app_subnet_cidr] description = "RabbitMQ Management — private, via SWAG on 443" } rule { direction = "in" protocol = "tcp" port = "9000" source_ips = [local.app_subnet_cidr] description = "APISIX Dashboard — private, via SWAG on 443 (IP restricted)" } rule { direction = "in" protocol = "tcp" port = "9180" source_ips = [local.app_subnet_cidr] description = "APISIX Admin API — internal only, accessed by Dashboard via Docker overlay" } rule { direction = "in" protocol = "tcp" port = "9090" source_ips = [local.app_subnet_cidr] description = "Prometheus — private, accessed by Grafana via Docker overlay" } rule { direction = "in" protocol = "tcp" port = "3000" source_ips = [local.app_subnet_cidr] description = "Grafana — private, via SWAG on 443 (IP restricted)" } labels = { environment = local.environment role = "app" } } resource "hcloud_firewall" "db" { name = "${local.name_prefix}-firewall-db" rule { direction = "in" protocol = "tcp" port = "22" source_ips = var.admin_allowed_cidrs description = "SSH — admin CIDRs only" } rule { direction = "in" protocol = "tcp" port = "5432" source_ips = [local.app_subnet_cidr] description = "PostgreSQL from app subnet" } rule { direction = "in" protocol = "tcp" port = "5432" source_ips = [local.db_subnet_cidr] description = "PostgreSQL replication within DB subnet" } rule { direction = "in" protocol = "tcp" port = "27017" source_ips = [local.app_subnet_cidr] description = "MongoDB from app subnet" } rule { direction = "in" protocol = "tcp" port = "27017" source_ips = [local.db_subnet_cidr] description = "MongoDB replica set internal traffic" } rule { direction = "in" protocol = "tcp" port = "2377" source_ips = [local.app_subnet_cidr] description = "Docker Swarm control plane from app subnet" } rule { direction = "in" protocol = "tcp" port = "7946" source_ips = [local.app_subnet_cidr] description = "Docker Swarm node discovery (TCP) from app subnet" } rule { direction = "in" protocol = "udp" port = "7946" source_ips = [local.app_subnet_cidr] description = "Docker Swarm node discovery (UDP) from app subnet" } rule { direction = "in" protocol = "udp" port = "4789" source_ips = [local.app_subnet_cidr] description = "Docker Swarm VXLAN overlay from app subnet" } rule { direction = "in" protocol = "tcp" port = "2379" source_ips = [local.db_subnet_cidr] description = "etcd client port within DB subnet" } rule { direction = "in" protocol = "tcp" port = "2380" source_ips = [local.db_subnet_cidr] description = "etcd peer port within DB subnet" } rule { direction = "in" protocol = "tcp" port = "8008" source_ips = [local.db_subnet_cidr] description = "Patroni REST API within DB subnet" } labels = { environment = local.environment role = "db" } }