Document the cross-host control-plane bridge (socat TCP on tailscale0 →
colibri-daemon Unix socket): FreeBSD rc.d vs Linux systemd parity, the
interface-scoped firewall gate (pf / ufw), the "tailnet boundary is the auth"
security model (no socket auth; scope :9190 via Tailscale ACL), and config
notes (TAILSCALE_IP_REQUIRED placeholder, socket-path parity, 0770 group).
Points at packaging/{freebsd,linux}/ for install. Linked from the architecture
index next to Control Plane. No real tailnet IPs (placeholders only).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.8 KiB
| title | description |
|---|---|
| Control-Plane Bridge | Reaching the Colibri control plane across hosts over the Tailscale mesh. |
Each host runs colibri-daemon listening on a Unix domain socket (local
only). The control-plane bridge exposes that socket as a TCP port on the
Tailscale interface so other mesh hosts can drive the control plane — create
tasks, register agents, watch terminals — without the socket ever being
reachable from the public internet.
operator / peer host bridged host
nc <tailnet-ip> 9190 ──tailscale0──▶ socat TCP-LISTEN:9190
│ (bind = this host's tailnet IP)
▼
UNIX-CONNECT /run/colibri/colibri.sock
│
▼
colibri-daemon
Implementations
The bridge is a thin socat front-end, supervised by the host's service
manager. Both sides are shipped in the repo:
| Host | Service | Packaging |
|---|---|---|
| FreeBSD | rc.d colibri_bridge |
packaging/freebsd/colibri_bridge.in |
| Linux | systemd colibri-bridge.service |
packaging/linux/ (unit + env + nft + README) |
Both run effectively:
socat TCP-LISTEN:9190,bind=<this-host-tailnet-ip>,fork,reuseaddr \
UNIX-CONNECT:/run/colibri/colibri.sock
The Linux unit adds freebind so socat can bind the tailnet address before
tailscaled has finished bringing it up, avoiding a boot-order race. The
bind=<tailnet-ip> keeps the listener off every other interface even if the
firewall is later changed — defence in depth, not the primary gate.
Network gate
The bridge port is opened only on the Tailscale interface, in the host's native firewall:
- FreeBSD (pf):
pass in quick on tailscale0 proto tcp to port 9190 keep state - Linux (ufw):
ufw allow in on tailscale0 to any port 9190 proto tcp
On a default-deny host (e.g. ufw), the public side is already blocked, so only
the interface-scoped allow is needed. The packaging/linux/colibri-bridge.nft
ruleset is provided for Linux hosts that do not run ufw (a default-accept
input chain); under ufw it is redundant.
Security model — the tailnet boundary is the auth
The control-plane socket has no authentication of its own. Once it is
bridged, any peer that can reach the host over the tailnet can issue the full
command set (spawn-agent, kill-agent, intake-task, terminal-*, …). That
makes the Tailscale boundary the access control:
- Scope the port to named peers with a Tailscale ACL on
:9190rather than relying on the firewall allow alone. - Treat any bridged host as granting control-plane authority to the whole tailnet unless an ACL narrows it.
Configuration notes
- No real tailnet IPs in git. Config templates ship the placeholder
TAILSCALE_IP_REQUIRED; the operator fills the host's own address at deploy time (tailscale ip -4). The FreeBSD rc.d defaults likewise refuse to start until the address is set. - Socket-path parity. The bridge connects to
/run/colibri/colibri.sock(FreeBSD:/var/run/colibri/colibri.sock); the daemon must be started with a matchingCOLIBRI_DAEMON_SOCKET. The daemon's default lives under$XDG_DATA_HOME, which a sandboxed unit (ProtectHome=yes) cannot reach — point both at the/runpath. - The bridge user must be in the daemon socket's group (the socket is
0770, owner + group).
Verify
From another tailnet host:
printf '{"cmd":"status"}\n' | nc -w2 <host-tailnet-ip> 9190
A healthy bridge returns the daemon's status JSON (including the daemon's
host), confirming reachability end to end over the mesh.