Documentation · Deployment

Run Warden as a systemd user service

Warden runs in the foreground with warden or warden serve. To keep it running without a terminal, install a per-OS-user systemd unit with warden service.

Commands

warden service install            # --host, --port, --config, --root accepted
warden service install --port 7402  # install on 127.0.0.1:7402
warden service start
warden service stop
warden service restart
warden service status
warden service logs
warden service logs --follow
warden service uninstall

The user unit is written to ~/.config/systemd/user/warden.service and managed with systemctl --user and journalctl --user-unit warden.service. This is a per-OS-user systemd service; system-wide mode (warden service install --system) is a documented follow-up and is not yet supported.

Install behavior

service install resolves the executable to a stable absolute path, refuses empty, relative or transient paths, and writes the unit atomically with a versioned integrity header. It records --config, --host/--port (or the legacy --listen) and --root; the resolved host and port survive restart and reboot. An existing unit that is not managed by Warden is never overwritten or removed silently, and lifecycle commands refuse to operate on a foreign or hand-modified unit.

  • Install is a transaction.
  • Warden preserves the prior managed unit bytes and inspects the prior systemd enablement and activity before mutating anything.
  • Only exactly-recreatable states are accepted — enablement enabled, enabled-runtime, disabled and activity active, inactive — and masked, static, linked, generated, transient, failed, reloading and other non-restorable states are refused before any file or lifecycle change; unmask or stop the service first.
  • On a failure, rollback restores the prior unit bytes and reproduces the exact prior enablement and activity states, distinguishing persistent from runtime enablement so runtime-only enablement is restored without leaving a persistent link; a failed fresh install is stopped and disabled while the unit is still loaded, then removed and systemd is reloaded.
  • A byte-identical unit already enabled and active is a genuine no-op — nothing is rewritten, reloaded or restarted.
  • An unchanged unit that is inactive or disabled receives only the lifecycle steps needed to reach the installed state, and a changed configuration reloads systemd and restarts the service.
  • Installation never enables user lingering automatically; the service survives logout only when your user manager is allowed to run without a session (loginctl enable-linger "$USER").
  • The unit records the executable's current absolute path, so moving or deleting the binary breaks the service until you reinstall. status reports the effective listener: new host/port units use their recorded listener, while legacy --listen units resolve it from durable configuration; it also reports enabled/running state, PID, version, listen address and a live health check of the public GET /api/setup/status endpoint, exiting nonzero when the service is failed or missing. uninstall preserves Warden accounts, configuration and databases.

Multi-user GitHub credential isolation

  • Warden is multi-user and does not inherit the host account's GitHub CLI authentication for every account.
  • Agent subprocesses scrub inherited GH_CONFIG_DIR, GH_TOKEN, GITHUB_TOKEN and GH_HOST, and OpenCode's XDG directories are isolated, so gh finds no configuration by default.
  • To grant one account access to the host GitHub CLI deliberately, set that account's environment in System → Access → Accounts → that account → Environment overrides (for example GH_CONFIG_DIR=/home/nick/.config/gh); only that account's subprocesses receive it, and token values are never displayed or written to the audit log or transcript.
  • This grants that account the GitHub permissions of the Warden service OS user, so only grant it to accounts you trust.

Persistence and lingering

The installed service runs independently of the terminal that launched it. Closing that terminal does not stop the service; warden service uninstall (or systemctl --user stop warden.service) is how you stop it deliberately. The unit belongs to your OS user's systemd user manager, so it normally starts when that manager starts — your first login or boot, depending on the distribution.

If Warden should keep running after you log out, or start at boot before any interactive login, the user manager must be allowed to run without a session. That is what lingering enables:

loginctl show-user "$USER" -p Linger
loginctl enable-linger "$USER"

Warden never enables lingering automatically, because it changes what the host runs without a login session — enable it deliberately only when unattended operation is actually required. The recorded unit also contains the absolute executable path that was current at install time; moving or deleting that executable breaks the service until you reinstall.