Skip to main content

DAEMON MANAGEMENT

Warning

Daemon management is EXPERIMENTAL. The subcommands, service file format, and behavior may change in future releases.

swamp serve daemon manages swamp serve as a platform-native system daemon. On macOS it registers a launchd LaunchAgent; on Linux it creates a systemd user service.

Subcommands

enable

swamp serve daemon enable

Generates and registers a platform-native service definition with all serve flags baked in. The daemon starts immediately and will restart automatically on failure. Whether it starts on reboot depends on the service type — see Platform Details below.

✓ Daemon enabled — swamp serve will start automatically

Daemon-specific flags

Flag Description
--user Install as a per-user service (systemd --user / launchd agent). Without this flag on Linux, the unit is installed system-wide under /etc/systemd/system/. On macOS the service is always a LaunchAgent (per-user); --user is accepted but has no additional effect.

Forwarded serve flags

All swamp serve flags are forwarded to the service definition:

Flag Default Description
--config <path> Path to a YAML config file (default: .swamp/serve.yaml). See Serve Flags — Config file
--port <port> 9090 Port for the daemon to listen on
--host <host> 127.0.0.1 Host for the daemon to bind to
--cert-file <path> Path to PEM-encoded TLS certificate
--key-file <path> Path to PEM-encoded TLS private key
--auth-mode <mode> none Authentication mode: none (deprecated), token, or oauth
--admins <principals> Comma-separated principal IDs for admin access
--club-api-key-file <path> File holding the collective API key. The service definition stores the absolute path, never the key. A daemon does not inherit the enabling shell's environment, so this is how a daemon reads its key from a file
--grant-reload <mode> manual Policy snapshot reload: manual or auto
--remote-only (off) Disable local (loopback) execution — all steps must declare placement (env: SWAMP_REMOTE_ONLY)
--no-schedule Disable scheduled workflow execution
--webhook <spec> Register a webhook endpoint (repeatable)
--allowed-collectives Comma-separated collective slugs for OAuth admission
--allowed-users Comma-separated user identifiers for OAuth admission
--oauth-provider <url> OAuth authorization server URL
--oauth-client-id <id> OAuth client ID (env: SWAMP_OAUTH_CLIENT_ID). When set, serve never registers a client and needs the client's secret from --oauth-client-secret-file, SWAMP_OAUTH_CLIENT_SECRET_FILE, SWAMP_OAUTH_CLIENT_SECRET or a usable stored copy, or it refuses to start. When omitted, a client is registered on first start
--oauth-client-secret-file <path> Path to a file holding the secret of the client named by --oauth-client-id. Used for this run only and never stored. Overrides SWAMP_OAUTH_CLIENT_SECRET_FILE and SWAMP_OAUTH_CLIENT_SECRET. Refused without a client ID. Requires Swamp v20261103.225037.0-sha.5911dc9c or later
--keep-oauth-client-in-vault (off) Leave oauth-client-id and oauth-client-secret in the user vault when moving OAuth secrets into the control-plane store (env: SWAMP_KEEP_OAUTH_CLIENT_IN_VAULT). Off by default: anything that can read that vault can read the client secret. Requires Swamp v20261103.225037.0-sha.5911dc9c or later
--oauth-client-name <name> Override the OAuth client_name used during dynamic client registration. Default: swamp-serve-{repoName}-{hostname} (env: SWAMP_OAUTH_CLIENT_NAME)
--groups-field <field> Userinfo field the collectives are read from (default: collectives)
--trust-proxy Trust a reverse proxy's forwarding headers: the client IP, used for rate limiting, is read from the leftmost X-Forwarded-For entry instead of the connection's address, and dashboard sign-in takes the public scheme and host from X-Forwarded-Proto and X-Forwarded-Host
--verify-on-enroll Run a fleet probe on each enrolling worker before it becomes schedulable
--restricted-model-types <types> Comma-separated behavior types whose behaviors require admin on access:* to create, run, edit, delete, delete or rename data of, or reference from a changed workflow step. A leading @ is ignored when matching. See Restricted behavior types
--restricted-commands <cmds> Comma-separated server commands that require admin authority (e.g. datastore.namespace.list,extension.install)
--trusted-hosts <hosts> Comma-separated hostnames or host:port entries to trust for Host header and browser Origin validation; a public address on a port other than 443 is given as host:port (env: SWAMP_TRUSTED_HOSTS)
--group-refresh-interval <duration> 4h How often to re-fetch IdP group memberships for active server tokens. Accepts seconds (14400), explicit units (4h, 30m), or 0 to disable. Requires --auth-mode oauth (env: SWAMP_GROUP_REFRESH_INTERVAL)
--approve-requires-explicit-grant Require a grant that names approve to decide a manual approval gate. Requires --auth-mode token or oauth (env: SWAMP_APPROVE_REQUIRES_EXPLICIT_GRANT)
--auto-resume (off) Resume a suspended run once an approval made through serve decides its last gate (env: SWAMP_AUTO_RESUME)
--dashboard (off) Enable the web dashboard at /dashboard (env: SWAMP_DASHBOARD)
--repo-dir <dir> Repository directory (env: SWAMP_REPO_DIR)

swamp serve daemon enable does not carry SWAMP_OAUTH_CLIENT_ID into the service definition. Pass --oauth-client-id instead.

Example with a custom port and TLS:

swamp serve daemon enable --port 8080 --cert-file cert.pem --key-file key.pem --auth-mode token

disable

swamp serve daemon disable

Unloads the running daemon and removes the service definition.

✓ Daemon disabled — service definition removed

status

swamp serve daemon status

Reports the daemon's enabled/running state, PID, and log path:

Status:  running
Enabled: yes
PID:     65055
Logs:    ~/Library/Logs/swamp

When no daemon is configured:

Status: not configured
Run swamp serve daemon enable to set up the daemon

Platform Details

macOS (launchd)

enable writes a LaunchAgent plist under ~/Library/LaunchAgents/. The plist uses KeepAlive to restart the process on exit and ThrottleInterval set to 10 seconds to prevent rapid restart loops. LaunchAgents are per-user services — they run only while the user is logged in and start again on the next login, not on reboot itself.

Linux (systemd)

Without --user, enable writes a system-wide unit under /etc/systemd/system/. System services start on boot and run independently of any user session.

With --user, enable writes a user service unit under ~/.config/systemd/user/. User services run only while the user has an active login session. To make a user service start on boot without logging in, enable lingering: loginctl enable-linger $USER.

Both use Restart=always with RestartSec=10.

Swamp data and config directories

Swamp loads every extension — including extensions already pulled into the repository — through an embedded runtime under the Swamp data directory: SWAMP_HOME when set, otherwise ~/.swamp resolved from HOME (or USERPROFILE).

Every Swamp process needs a swamp-club.com credential to start — see Swamp Account Requirement. The daemon reads the credential that swamp auth login stores in auth.json, and the cached proof in auth_verified.json, from the Swamp config directory, resolved in this order:

Priority Directory
1 $SWAMP_CONFIG_DIR
2 $SWAMP_HOME/config
3 $XDG_CONFIG_HOME/swamp
4 ~/.config/swamp

enable sets both SWAMP_HOME and SWAMP_CONFIG_DIR in the generated service definition — Environment= lines in the systemd unit, EnvironmentVariables entries in the launchd plist. Each is the absolute path of that directory as resolved in the environment of the user who ran enable, so the daemon reads the same credentials that user is signed in with. Sign in as that user before running enable.

A daemon that does not own the config directory, such as a system service running as root, reads the credential and proof but never writes to the directory. A running serve renews its proof once it is over 7 days old and holds the renewed proof in memory. The proof on disk is kept fresh by the signed-in user's own Swamp runs; if that user runs nothing for 14 days, it expires and the daemon must reach swamp-club.com when it next starts.

swamp worker daemon enable sets SWAMP_CONFIG_DIR the same way. A worker daemon enabled by a version without the account requirement lacks it. When it finds no credential at all, it passes through its serve as a remote worker; re-run swamp worker daemon enable as the signed-in user to give it the user's credential. Serve daemons already set SWAMP_CONFIG_DIR and need no change.

A running daemon is checked when it starts, not on every request.

A service definition written by hand must set SWAMP_HOME or HOME. When none of SWAMP_HOME, HOME, or USERPROFILE is set, extension loading is disabled and Swamp logs a warning beginning Extension loading is unavailable: no swamp data directory found (none of SWAMP_HOME, HOME, or USERPROFILE is set). Scheduled workflows that use pulled or user extension types then fail with Unknown model type.

Warning

Setting SWAMP_HOME without SWAMP_CONFIG_DIR moves the config directory to $SWAMP_HOME/config. The daemon then cannot find the auth.json that swamp auth login wrote, fails to start in any --auth-mode, and is restarted every 10 seconds. A hand-written service definition that sets SWAMP_HOME must also set SWAMP_CONFIG_DIR to the directory holding those credentials (~/.config/swamp by default):

Environment=SWAMP_HOME=/opt/swamp
Environment=SWAMP_CONFIG_DIR=/home/alice/.config/swamp

Versions from 20260921.211448.0 up to, but not including, 20260930.184839.0 set only SWAMP_HOME, so a token or oauth daemon they installed cannot start. Re-run swamp serve daemon enable to rewrite the service definition.

File Permissions

Service definition files are written with 0600 permissions. This is because the service definition may contain webhook secrets or other sensitive flags passed to swamp serve. To avoid embedding literal secrets in the service definition, use the @env=, @file=, or @vault= indirection prefixes — see Serve Flags: Secret indirection.