Private network: grintest¶
The non-prod VMs (grintest-dev-01, future grintest-uat-01) share a single
Hetzner Cloud private network. This is preparation for inter-VM traffic
(uat ↔ monitoring, future split of services across VMs, future Hetzner Load
Balancer attachment) and a hard isolation boundary for internal services.
Topology¶
| Field | Value |
|---|---|
| Network name | grintest |
| IP range | 10.0.0.0/16 |
| Subnet (EU Central) | 10.0.1.0/24 |
| Network gateway | 10.0.0.1 |
| Provider zone | eu-central |
VM assignments¶
| VM | Private IP | Public IPv4 | Public IPv6 | Role |
|---|---|---|---|---|
grintest-dev-01 |
10.0.1.1 |
178.104.246.247 |
2a01:4f8:1c19:d159::1 |
dev |
grintest-uat-01 |
(future) | (future) | (future) | uat |
Interface naming¶
The private network interface name is hardware-dependent and assigned by
the kernel via systemd-udev's predictable network interface naming. On
the current dev VM (CX23) it is enp7s0. On other VM types it may be
ens10, enp1s0, etc.
Always confirm per-VM with ip -4 -br addr show rather than hardcoding the
name in service configs. Where possible, bind services to the IP address
(10.0.1.x), not the interface name.
Service-binding convention¶
Internal services bind only to the private interface (ens10,
10.0.1.x), never to 0.0.0.0. This applies to:
- PostgreSQL
- Redis
- Kafka brokers (if reintroduced)
- OpenTelemetry Collector (gRPC
4317, HTTP4318) - Any future internal queue / cache
The convention is enforced at three layers:
- Service config — bind to
10.0.1.2explicitly in compose / Coolify. - Hetzner Cloud Firewall — drops the service ports from the public
internet (
firewall.md). - Host
ufw— same allow-list as the cloud firewall, last line of defence.
External access for developers (pgAdmin, RedisInsight, psql, etc.) goes
through an SSH tunnel — see db-access.md. No internal
service is exposed on the public internet.
Terraform shape (forward-looking)¶
When the YAML/Markdown here migrates to Terraform, the network resource maps to:
resource "hcloud_network" "grintest" {
name = "grintest"
ip_range = "10.0.0.0/16"
}
resource "hcloud_network_subnet" "eu_central" {
network_id = hcloud_network.grintest.id
type = "cloud"
network_zone = "eu-central"
ip_range = "10.0.1.0/24"
}
resource "hcloud_server_network" "dev" {
server_id = hcloud_server.dev.id
network_id = hcloud_network.grintest.id
ip = "10.0.1.1"
}