- Anglicized setup and facts markdown file names for better consistency. - Updated 01-swarm-init-multinode.md to highlight Ansible automation of Swarm initialization and labeling. - Overhauled 03-infra-stack-changes.md to describe the single monolithic file strategy and reflect current Redis, RabbitMQ, and etcd cluster configurations. - Fixed minor overrides and typos in Patroni templates and Ansible bootstrap documents. - Restructured README and roadmap mapping to align with the renamed setup documents.
8.0 KiB
01 - Private Network Port Matrix
This file defines the ports that must be opened inside the Hetzner private network for test and prod environments. Public ingress is limited to 22/tcp, 80/tcp, and 443/tcp, with one current test-only exception: 51820/udp is public on the test DB node for WireGuard. Vault 8200/tcp will not be opened publicly.
This matrix must be treated as the source for Terraform Hetzner firewall and Ansible firewalld rules.
Network Plan
Test
| Subnet | CIDR | Purpose |
|---|---|---|
| App/Swarm | 10.10.10.0/24 |
iklim-app-01 |
| DB | 10.10.20.0/24 |
iklim-db-01 |
Prod
| Subnet | CIDR | Purpose |
|---|---|---|
| App/Swarm | 10.20.10.0/24 |
iklim-app-01/02/03 |
| DB | 10.20.20.0/24 |
iklim-db-01/02/03 |
Public Ingress Standard
Public ingress:
| Port | Protocol | Source | Target | Requirement |
|---|---|---|---|---|
22 |
TCP | Admin IP/CIDR | All nodes | SSH management |
80 |
TCP | Internet | iklim-app-01 (gateway) |
HTTP / ACME redirect |
443 |
TCP | Internet | iklim-app-01 (gateway) |
HTTPS |
51820 |
UDP | 0.0.0.0/0, ::/0 |
iklim-db-01 in test only |
WireGuard VPN — authentication with cryptographic key |
Critical ports that will not be opened publicly:
| Port | Service |
|---|---|
8200/tcp |
Vault |
5432/tcp |
PostgreSQL |
27017/tcp |
MongoDB |
6379/tcp |
Redis |
5672/tcp, 15672/tcp, 61613/tcp, 15674/tcp |
RabbitMQ |
2377/tcp, 7946/tcp, 7946/udp, 4789/udp |
Docker Swarm |
9180/tcp |
APISIX Admin API |
9090/tcp |
Prometheus |
3000/tcp |
Grafana |
Docker Swarm Private Ports
Required ports between Docker Swarm nodes:
| Port | Protocol | Source | Target | Description |
|---|---|---|---|---|
2377 |
TCP | Swarm nodes | Swarm manager nodes | Swarm control plane / join |
7946 |
TCP | All Swarm nodes | All Swarm nodes | Node discovery / gossip |
7946 |
UDP | All Swarm nodes | All Swarm nodes | Node discovery / gossip |
4789 |
UDP | All Swarm nodes | All Swarm nodes | Overlay VXLAN data path |
In test, these ports are effectively required for a single Swarm node, but they can be defined inside the app subnet to make adding workers easier later.
In prod, these ports must be open between all iklim-app-* nodes inside the 10.20.10.0/24 app/swarm subnet.
Source: Docker overlay network documentation, https://docs.docker.com/engine/network/drivers/overlay/
Application and Infra Service Private Ports
These ports will not be opened publicly. Access will be allowed only from required sources inside the private network or Docker overlay.
| Port | Protocol | Service | Source | Target | Note |
|---|---|---|---|---|---|
8200 |
TCP | Vault API/UI | Swarm app nodes / runner | Vault service/node | Public closed. Runtime services must reach Vault through private/overlay |
6379 |
TCP | Redis | Swarm app nodes | Redis service/node | Public closed |
5672 |
TCP | RabbitMQ AMQP | Swarm app nodes | RabbitMQ service/node | Public closed |
15672 |
TCP | RabbitMQ Management | Admin CIDR or private ops | RabbitMQ service/node | Public closed; preferably VPN/bastion |
61613 |
TCP | RabbitMQ STOMP | Required app nodes | RabbitMQ service/node | Public closed |
15674 |
TCP | RabbitMQ Web STOMP | Required app/gateway nodes | RabbitMQ service/node | Public closed |
2379 |
TCP | etcd client | APISIX service/node | etcd service/node | Public closed |
2380 |
TCP | etcd peer | etcd cluster nodes | etcd cluster nodes | May not be needed for a single replica; required if clustered |
9180 |
TCP | APISIX Admin API | Admin CIDR or private ops | APISIX service/node | Public closed |
9090 |
TCP | Prometheus UI/API | Admin CIDR or private ops | Prometheus service/node | Public closed |
3000 |
TCP | Grafana UI | Admin CIDR or private ops | Grafana service/node | Public closed |
The current prod root stack is docker-stack-infra_db-prod.yml; Vault is deployed separately with docker-stack-vault.yml through vault-bootstrap.sh. Public traffic is expected to enter through SWAG on 80/443. Private service reachability is provided by the iklimco-net overlay and by the explicit host-mode DB/cluster ports listed below.
DB Node Ports
DB runtime services are deployed as Docker Swarm services. Prod currently uses Patroni/PostgreSQL, etcd, and a MongoDB replica set in docker-stack-infra_db-prod.yml; the required firewall ports are below.
PostgreSQL / PostGIS (Patroni + etcd)
The prod environment uses PostgreSQL managed with Patroni + etcd. In the test environment, replication and HA ports are not required because there is a single node.
| Port | Protocol | Source | Target | Note |
|---|---|---|---|---|
5432 |
TCP | App/Swarm subnet | PostgreSQL nodes (Patroni-managed) | Application JDBC — connects to all nodes, driver finds the primary |
5432 |
TCP | DB subnet | PostgreSQL nodes | Patroni replication (pg_basebackup and WAL streaming) |
8008 |
TCP | DB subnet | PostgreSQL nodes | Patroni REST API — leader election, health check |
2379 |
TCP | DB subnet | etcd nodes | etcd client — Patroni -> etcd access |
2380 |
TCP | DB subnet | etcd nodes | etcd peer — raft protocol inside the etcd cluster |
MongoDB
| Port | Protocol | Source | Target | Note |
|---|---|---|---|---|
27017 |
TCP | App/Swarm subnet | MongoDB node/replica set endpoint | Application DB connection |
27017 |
TCP | DB subnet | MongoDB replica set nodes | Replica set internal traffic |
If sharding is added later, additional MongoDB roles such as 27018/27019 may come up; they will not be opened at this stage.
Test Private Rules
Minimum for the test environment:
| Source | Target | Ports |
|---|---|---|
10.10.10.0/24 |
10.10.10.0/24 |
2377/tcp, 7946/tcp, 7946/udp, 4789/udp |
10.10.10.0/24 |
10.10.20.0/24 |
5432/tcp, 27017/tcp |
10.10.10.0/24 |
10.10.10.0/24 |
8200/tcp, 6379/tcp, 5672/tcp, 61613/tcp, 15674/tcp |
| Admin CIDR or VPN | 10.10.10.0/24 |
9000/tcp, 15672/tcp, 9180/tcp, 9090/tcp, 3000/tcp |
Because the DB node is single-node in test, PostgreSQL/MongoDB replication ports inside the DB subnet may not be actively used.
Prod Private Rules
Minimum for the prod environment, including Patroni + etcd:
App subnet (swarm firewall) — traffic inside itself:
| Source | Target | Ports |
|---|---|---|
10.20.10.0/24 |
10.20.10.0/24 |
2377/tcp, 7946/tcp, 7946/udp, 4789/udp (Swarm) |
10.20.10.0/24 |
10.20.10.0/24 |
8200/tcp, 5672/tcp, 61613/tcp, 15674/tcp (application services) |
| Admin CIDR or VPN | 10.20.10.0/24 |
15672/tcp, 9180/tcp, 9090/tcp, 3000/tcp |
App -> DB traffic (there is no related rule in the swarm firewall; it is allowed in the db firewall):
| Source | Target | Ports |
|---|---|---|
10.20.10.0/24 |
10.20.20.0/24 |
5432/tcp, 27017/tcp (DB access) |
10.20.10.0/24 |
10.20.20.0/24 |
2377/tcp, 7946/tcp, 7946/udp, 4789/udp (Swarm — DB worker join) |
DB subnet (db firewall) — traffic between DB nodes:
| Source | Target | Ports |
|---|---|---|
10.20.20.0/24 |
10.20.20.0/24 |
5432/tcp, 27017/tcp (DB replication) |
10.20.20.0/24 |
10.20.20.0/24 |
2379/tcp, 2380/tcp (etcd client/peer) |
10.20.20.0/24 |
10.20.20.0/24 |
8008/tcp (Patroni REST API) |
DB -> App traffic (allowed in the swarm firewall):
| Source | Target | Ports |
|---|---|---|
10.20.20.0/24 |
10.20.10.0/24 |
2377/tcp, 7946/tcp, 7946/udp, 4789/udp (Swarm — manager ports) |
Acceptance Criteria
- The public firewall does not open
8200/tcp. - DB ports are not open publicly.
- Swarm ports are open only between Swarm app and DB subnets.
- The App/Swarm subnet reaches the DB subnet only through required DB ports.
- The DB subnet is not opened to the app subnet with broad permissions.
- Admin UI ports are restricted through admin CIDR/VPN/private ops instead of public access.