feat(cli): background the VPN daemon with re-exec + clean shutdown

`sunbeam connect` now fork-execs itself with a hidden `__vpn-daemon`
subcommand instead of running the daemon in-process. The user-facing
command spawns the child detached (stdio → log file, setsid for no
controlling TTY), polls the IPC socket until the daemon reaches
Running, prints a one-line status, and exits. The user gets back to
their shell immediately.

- src/cli.rs: `Connect { foreground }` instead of unit. Add hidden
  `__vpn-daemon` Verb that the spawned child runs.
- src/vpn_cmds.rs: split into spawn_background_daemon (default path)
  and run_daemon_foreground (used by both `connect --foreground` and
  `__vpn-daemon`). Detached child uses pre_exec(setsid) and inherits
  --context from the parent so it resolves the same VPN config.
  Refuses to start if a daemon is already running on the control
  socket; cleans up stale socket files. Switches the proxy bind from
  16443 (sienna's existing SSH tunnel uses it) to 16579.
- sunbeam-net/src/daemon/lifecycle: add a SocketGuard RAII type so the
  IPC control socket is unlinked when the daemon exits, regardless of
  shutdown path. Otherwise `vpn status` after a clean disconnect would
  see a stale socket and report an error.

End-to-end smoke test against the docker stack:
  $ sunbeam connect
  ==> VPN daemon spawned (pid 90072, ...)
      Connected (100.64.0.154, fd7a:115c:a1e0::9a) — 2 peers visible
  $ sunbeam vpn status
  VPN: running
    addresses: 100.64.0.154, fd7a:115c:a1e0::9a
    peers: 2
    derp home: region 0
  $ sunbeam disconnect
  ==> Asking VPN daemon to stop...
      Daemon acknowledged shutdown.
  $ sunbeam vpn status
  VPN: not running
This commit is contained in:
2026-04-07 14:57:15 +01:00
parent 7019937f6f
commit 27a6f4377c
5 changed files with 208 additions and 52 deletions

View File

@@ -84,6 +84,7 @@ wfe-yaml = { version = "1.6.3", registry = "sunbeam" }
async-trait = "0.1"
hostname = "0.4.2"
whoami = "2.1.1"
libc = "0.2.184"
[dev-dependencies]
wiremock = "0.6"