colibri/packaging/linux/colibri-bridge.service
Sam & Claude 3b00b49e03
Some checks failed
CI / markdown (pull_request) Has been cancelled
CI / rust (pull_request) Has been cancelled
CI / agent-jail-pkgs (pull_request) Has been cancelled
CI / port (pull_request) Has been cancelled
docs(packaging): Linux/systemd colibri-bridge + domedog network facts
Linux peer of packaging/freebsd/colibri_bridge.in: bridge the colibri-daemon
control-plane Unix socket to TCP 9190 on the Tailscale interface so mesh hosts
can reach the control plane.

- colibri-bridge.service: systemd unit running socat under sandboxing, BindsTo
  the daemon, freebind so it can bind the tailnet IP before tailscaled is up.
- colibri-bridge.env.example: tunables (systemd parallel to the rc.d sysrc vars).
- colibri-bridge.nft: nftables ruleset for hosts WITHOUT ufw.
- README: install steps + the verified domedog host facts (tailnet IP, ufw
  default-deny posture, 8443=CloudPanel and its public exposure) + open
  questions for the cross-host (hermes) review.

Network gate already applied on domedog: `ufw allow in on tailscale0 to any
port 9190 proto tcp`. The systemd unit is proposed pending the hermes review.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 01:03:29 +02:00

66 lines
2.7 KiB
Desktop File

[Unit]
# Colibri control-plane TCP bridge — Linux/systemd peer of the hermes rc.d
# service in packaging/freebsd/colibri_bridge.in.
#
# Bridges the colibri-daemon Unix socket to a TCP port on the Tailscale
# interface so other mesh hosts can reach the Colibri control plane. socat runs
# in the foreground; systemd supervises it (restart on crash, journald logs) —
# the systemd equivalent of FreeBSD running socat under daemon(8).
Description=Colibri control-plane TCP bridge (Tailscale -> Unix socket)
Documentation=https://code.smilepowered.org/clawdie/colibri
After=network-online.target tailscaled.service colibri-daemon.service
Wants=network-online.target
# Ordering + lifecycle: the bridge is useless without the daemon, and the
# socket vanishes if the daemon stops — so bind our lifecycle to it.
Requires=colibri-daemon.service
BindsTo=colibri-daemon.service
# Keep retrying while we wait for tailscaled to assign the address at boot
# (paired with freebind below, this race is largely moot, but be forgiving).
StartLimitIntervalSec=0
[Service]
Type=exec
# Must be a user in the colibri-daemon socket's group (the daemon chmods its
# socket 0770 owner+group). On domedog that is the daemon's own user.
User=clawdija
Group=clawdija
# Tunables live here (systemd parallel to the rc.d sysrc vars). See
# colibri-bridge.env.example.
EnvironmentFile=/etc/colibri/bridge.env
# Refuse to start until the daemon socket actually exists, mirroring the rc.d
# prestart check (clearer failure than a socat connect error).
ExecStartPre=/usr/bin/test -S ${COLIBRI_BRIDGE_SOCKET}
# bind=<tailscale-ip> keeps us off every other interface even if the firewall
# is flushed. freebind (Linux IP_FREEBIND, no privilege needed) lets socat bind
# the tailnet address before tailscaled has finished bringing it up, avoiding a
# boot-order race — the one place this unit improves on the FreeBSD version.
ExecStart=/usr/bin/socat -d \
TCP-LISTEN:${COLIBRI_BRIDGE_LISTEN_PORT},bind=${COLIBRI_BRIDGE_LISTEN_ADDR},freebind,fork,reuseaddr \
UNIX-CONNECT:${COLIBRI_BRIDGE_SOCKET}
Restart=on-failure
RestartSec=2
# --- hardening: socat needs only TCP + Unix sockets and no privileges ---
NoNewPrivileges=yes
ProtectSystem=strict
# ProtectHome=yes is safe ONLY while the socket lives outside /home (it does, by
# default, under /run). If you repoint COLIBRI_BRIDGE_SOCKET into a home dir,
# relax this to read-only or the connect will fail.
ProtectHome=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectControlGroups=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
RestrictAddressFamilies=AF_INET AF_UNIX
RestrictNamespaces=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
[Install]
WantedBy=multi-user.target