Murat ÖZDEMİR 9e20f2fcf8 chore(prod): capture production bootstrap access configuration
Document and commit the production bootstrap state after the initial Hetzner and Ansible rollout.

- switch Ansible prod runbooks to use the shared vault password file

- record production admin CIDRs, SSH key path, encrypted group vault, and encrypted per-host vault files

- add generated production inventory and the prod setup history notes from the first bootstrap

- keep root password login disabled while preserving key-based root access for Ansible bootstrap continuity

- document separate Hetzner projects and tokens for test/prod and commit the prod provider lock file

- remove the private Redis firewall allowance from the prod Terraform firewall and matching setup docs
2026-05-19 17:49:59 +03:00

282 lines
6.3 KiB
HCL

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 = "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 = "2379"
source_ips = [local.app_subnet_cidr]
description = "etcd client (Patroni + APISIX) from app subnet"
}
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"
}
}