# Quadlet network: the private bridge of the voice pair (rootless). # # Install path on dankclaw: ~/.config/containers/systemd/frank-tts-engine.network # Unit name: frank-tts-engine-network.service (podman network name: # systemd-frank-tts-engine — quadlet prefixes "systemd-", so probe the runtime # name, never the filename; see [[Container Network Namespaces]]). # # WHY A PRIVATE BRIDGE FOR A PAUSE THAT LOOKS PUBLIC-FACING. frank-tts (:7772, # published, the one endpoint consumers address) and frank-tts-engine (:8880, # never published, the arm A qwentts.cpp server behind it) could both have # stayed on the fleet-wide dankclaw_default and resolved each other by name. # They are split off anyway, for two reasons: # # 1. THE HOST-LOOPBACK TRAP. The phase-1 shape in `scripts/frank-tts.env` still # names `host.containers.internal:8880` as the upstream, on the assumption the # engine runs on the host and publishes `127.0.0.1:8880`. That cannot work: # netavark DNATs published ports only, a published port is not on any podman # bridge, and a container cannot reach the host's own loopback bind — the same # shape that 502'd hermes, and the reason the signal-relay hop needs a host LAN # bind instead ([[Container Network Namespaces]], [[Homepage Status Probes]]). # Putting both containers on one committed network removes the guess: the # façade dials the engine's container DNS name on the network that owns it, and # the engine publishes nothing at all. # # 2. THE ENGINE HAS NO AUTH AND NO QUEUE LIMIT WORTH THE NAME. `tts-server` # answers anyone who can open a socket, and at `--max-batch 1` a second # caller simply waits behind the first. Left on dankclaw_default every # container on that net — open-webui, hermes, the *arr proxies — could drive # a CPU synthesiser that occupies every other core on a box that also serves # two text endpoints. On this bridge the only dialer is frank-tts: the engine # publishes no port, so not even the host has an address to reach it at, and # diagnostics go through `podman exec` instead. # # Kernel bridge, not slirp4netns: the 2026-08-22 open-webui incident (a dead # per-container userspace helper left a container that accepted TCP and reset # every request for two days, logging nothing). A bridge has no such helper. # # Subnet registry on dankclaw (rootless): # 10.88.0.0/16 default "podman" bridge # 10.89.0.0/24 gitea (systemd-gitea) # 10.89.1.0/24 compose stack (dankclaw_default) # 10.89.2.0/24 searxng (systemd-searxng) # 10.89.3.0/24 open-webui (systemd-open-webui) # 10.89.4.0/24 open-notebook (systemd-open-notebook) # 10.89.5.0/24 voice pair (systemd-frank-tts-engine) <- this file # Pinned so the two container IPs stay deterministic across reboots, like the # other pinned nets; 10.89.5.0/24 was the next unclaimed /24 in this registry. [Network] Driver=bridge Subnet=10.89.5.0/24 Gateway=10.89.5.1