relay: bind the host LAN IP, admit the podman bridge subnet only
169.254.1.2 is not a local address on this host (netavark runs its bridges in aardvark-dns' netns), so the relay cannot bind it — and a loopback bind refuses container traffic. Probe-socket proof: a host socket on 192.168.0.143:18094 answers the container's 169.254.1.2:18094 dial while the LAN IP refuses from the container. The relay binds 192.168.0.143:18093 and the deployer installs an iptables INPUT pair (ACCEPT 10.89.0.0/16, DROP rest) so the unauthenticated endpoint stays off the LAN.
This commit is contained in:
@@ -19,7 +19,7 @@ Alertmanager receives firing rules from Prometheus, groups and dedupes them, and
|
||||
|
||||
## Why the webhook address is `host.containers.internal`
|
||||
|
||||
The Signal relay is a host-side process, and the address it must bind is the one detail this design gets wrong once: **127.0.0.1 does not work**. From a bridge container, loopback is the container's own, and netavark DNATs *published* ports only — the LAN IP and the podman gateway are both refused for an unpublished host bind. `host.containers.internal` (169.254.1.2) is the one address that reaches a host-local listener from a bridge container, so the relay binds *that* address (measured 2026-09-17: a loopback bind refused the first webhook with `dial tcp 169.254.1.2:18093: connection refused`). 169.254.1.2 is link-local to the podman bridge — not on loopback, not on any LAN interface, reachable only from this host's containers — so the unauthenticated webhook endpoint stays off the wire.
|
||||
The Signal relay is a host-side process, and the address it must bind is the one detail this design gets wrong twice (2026-09-17). From a bridge container, loopback is the container's own, and netavark DNATs *published* ports only — so a relay bound to 127.0.0.1 refused the first webhook with `dial tcp 169.254.1.2:18093: connection refused`. The obvious fix — bind `host.containers.internal` itself — fails too: on this host netavark runs its bridges in aardvark-dns' netns, so 169.254.1.2 is not a local address in the host's namespace (`OSError: [Errno 99] Cannot assign requested address`). What works: bind the **host's LAN IP** (192.168.0.143) — netavark delivers the container's `169.254.1.2` dial to that address (proven with a probe socket: container → `169.254.1.2:18094` → host socket bound to `192.168.0.143:18094`, while the LAN IP refused from the container, the usual netavark quirk). Since that puts an unauthenticated endpoint on a host interface, the deployer installs an iptables INPUT pair admitting 18093/tcp from the podman bridge subnet (10.89.0.0/16) only — the rest of the LAN gets a DROP.
|
||||
|
||||
## The Signal relay
|
||||
|
||||
@@ -36,7 +36,7 @@ The Signal relay is a host-side process, and the address it must bind is the one
|
||||
./scripts/deploy.sh dankclaw --service alertmanager
|
||||
```
|
||||
|
||||
`deploy_observability` installs the quadlet unit, `copy_alertmanager_config` installs the config, and `install_signal_relay` copies the user unit, enables and restarts it, then waits on `169.254.1.2:18093/health` before the container's own `/-/healthy` wait. The planner selects `alertmanager` for its quadlet file, `shared/prometheus/alertmanager.yml`, and the two relay files; `prometheus` ships the `alerting:` block that points at `alertmanager:9093`.
|
||||
`deploy_observability` installs the quadlet unit, `copy_alertmanager_config` installs the config, and `install_signal_relay` copies the user unit, installs the iptables pair, enables and restarts the relay, then waits on `192.168.0.143:18093/health` before the container's own `/-/healthy` wait. The planner selects `alertmanager` for its quadlet file, `shared/prometheus/alertmanager.yml`, and the two relay files; `prometheus` ships the `alerting:` block that points at `alertmanager:9093`.
|
||||
|
||||
## Gotchas
|
||||
|
||||
|
||||
Reference in New Issue
Block a user