Skip to main content

Swamp Worker

@figy/swamp-workerv2026.10.17.2· MIT· 7d agoWORKFLOWS
01README

Site-specific: deploy a swamp worker to a set of fi.gy hosts over SSH — and completely remove it — driving the generic @svendowideit/swamp-worker model with @swamp/ssh. WHAT IT DOES

The concrete, private half of the worker setup: it supplies the fi.gy node set and runs the whole fan-out in one idempotent workflow. Run it once to enlist a set of hosts and again to upgrade them — it installs the swamp binary where absent, upgrades it where it differs, writes each node's systemd user unit and starts it, and fails unless the unit is active. Two matching workflows keep the fleet current: worker-rotate refreshes enrollment tokens without ever stranding a worker, and worker-teardown removes every worker and revokes its token so it can never re-enrol. Change the worker once on the orchestrator and re-run to reconcile every host. It is site-specific by design and useless without the fi.gy node set; the portable model is @svendowideit/swamp-worker and the SSH transport is @swamp/ssh.

INSTALL

swamp extension pull @figy/swamp-worker

DEPENDENCIES

@svendowideit/swamp-worker and @swamp/ssh (pulled separately), a reachable fi.gy swamp serve the workers dial, and OpenSSH key access to the nodes. The serve must speak the same worker protocol as the release installed on the nodes, so keep it current with swamp model method run swamp-serve updateBinary. A figy-trusted swamp repo (swamp extension trust add figy) so the pull resolves.

RUN

# Create the generic worker model once. `identity` namespaces the worker;
# `swampBinPath` MUST be the swamp binary on THIS orchestrator (it mints the
# tokens) and is the same path the provisioning script installs on each node;
# `otelSettingsModel=otel` wires each worker unit to export OTel logs,
# metrics and traces to the fi.gy gateway.
swamp model create @svendowideit/swamp-worker worker \
  --global-arg identity=figy \
  --global-arg swampBinPath=~/.local/bin/swamp \
  --global-arg otelSettingsModel=otel

# Install OR upgrade a set of nodes in one command; re-run it to reconcile.
swamp workflow run @figy/swamp-worker-upgrade \
  --input serveUrl=wss://swamp.x1yoga.fi.gy \
  --input 'hosts=[{"name":"host1","address":"host1.lan"}]'

# Rotate the enrollment tokens before they expire (never stranding a
# worker), bumping the generation each time — schedule this.
swamp workflow run @figy/swamp-worker-rotate \
  --input serveUrl=wss://swamp.x1yoga.fi.gy \
  --input 'hosts=[{"name":"host1","address":"host1.lan"}]' \
  --input generation=2

# Completely remove the deployed workers: the removal script runs on every
# node and each token is revoked on the orchestrator.
swamp workflow run @figy/swamp-worker-teardown \
  --input 'hosts=[{"name":"host1","address":"host1.lan"}]'

CONFIGURE

All three take hosts (the node set, each {name, address}), identity (worker identity, default figy, matching the generic model's global) and the SSH defaults sshUser, sshPort, sshKey and strictHostKeyChecking; upgrade also takes serveUrl (required), version (release to install, default latest) and duration (token lifetime, default 30d); rotate also takes generation (required) and previousSuffix. The generic model's globals (binary path, dirs, concurrency) are set on the worker model instance.

UPGRADE

Install and upgrade are the same workflow: re-run @figy/swamp-worker-upgrade to bring every node's worker up to version (default latest) and reconcile its unit. It is idempotent, reuses each node's staged token, and needs no new inputs.

WHAT IT INSTALLS

Nothing itself — it drives @svendowideit/swamp-worker on each node, which installs a systemd user unit swamp-worker-<identity>.service, the worker cache dir, and 0600 token/env files, and enables user lingering; and @swamp/ssh, the SSH transport. With otelSettingsModel=otel on the worker model, each worker unit also exports OTel logs, metrics and traces to the fi.gy gateway, attributed to the swamp-worker service with a per-node host=. Each node also needs a running systemd user manager (systemctl --user, i.e. a live logind and user@<uid>.service). No cron triggers or webhooks.

02Workflows3
@figy/swamp-worker-upgradeee24e09a-b60f-4b71-a4ef-06b2b463099d

Install or upgrade the fi.gy swamp workers in one idempotent run — the same command whether a node has no worker yet or already runs one. For each node it renders the per-node provisioning script, mints one enrollment token per node (`mintToken`, per-target, staged 0600 on the orchestrator, reused on re-run), copies each node its own token over SSH with @swamp/ssh, and runs the provisioning script on every node. The script installs the swamp binary when it is absent, or upgrades it to the reque

deployRender, stage tokens, deliver, provision (install or upgrade), verify.
1.render— Render the per-node provisioning script (host label filled from each node's own hostname) into a `provision` resource.
2.mint-token— Mint one enrollment token per node on the orchestrator and stage that node's plaintext in its own 0600 file (never in swamp data). Per-target and idempotent: a slow node touches only its own token/file, and a re-run reuses an already-staged token instead of minting a fresh one. Serialised (`concurrency: 1`) so the calls never contend on the shared model lock.
3.deliver-tokens— Copy each node its own token over SSH (scp) to a fixed staging path on the node, so the secret never appears in a command line or swamp data. The provisioning script then installs it to its final 0600 location.
4.provision— Run the provisioning script on every node: install or upgrade the swamp binary, lock the token, write the systemd user unit and start it.
@figy/swamp-worker-rotated2a9fad6-36b0-45dd-9738-f8f44bd21f53

Rotate the enrollment tokens of deployed swamp workers before they expire — without ever stranding a worker. Mints a **new** token per node under a generation name (`<identity>-<node>-g<gen>`), delivers it over SSH, re-runs the provisioning script so the unit restarts onto the new token (the old token is still valid at that moment), then revokes the **previous** token. Because the new token is minted and delivered *before* the old one is revoked, a worker is never left without a valid token. R

rotateMint new, deliver, restart onto it, revoke old, verify.
1.render— Render the provisioning script (for the apply step).
2.mint-new— Mint the new token per node under the generation name `<identity>-<node>-g<gen>`, staged 0600 (reused if a re-run staged it). Per-target; serialised so the calls never contend on the model lock.
3.deliver-new— Copy each node its new token over SSH (to the node's staging path).
4.apply— Run the provisioning script: installs the new token and, because it changed, restarts the unit onto it. The previous token is still valid.
5.revoke-previous— Revoke the previous token on the orchestrator (the worker is already on the new one) and drop its staged file. purgeFile=false — the canonical token file now holds the new live token. Serialised to avoid the model lock.
@figy/swamp-worker-teardown4f8ec40a-e7d9-437a-8ad3-110e79bc3f7f

Completely remove the workers @figy/swamp-worker-bootstrap deployed to a set of hosts, over SSH. Renders the per-node removal script with @svendowideit/swamp-worker, runs it on every node with @swamp/ssh (stop, disable and delete the unit, cache dir, token/env files), then revokes each node's enrollment token on the orchestrator so a worker can never re-enrol. The same `hosts` input as the bootstrap: swamp workflow run @figy/swamp-worker-teardown \ --input 'hosts=[{"name":"host1","a

teardownRender removal, run it on the nodes, revoke the tokens, verify.
1.render-removal— Render the per-node removal script (paths portable with $HOME) into a `removal` resource.
2.remove-on-nodes— Run the removal script on every node over SSH: stop, disable and delete the unit and its artifacts.
3.revoke-tokens— Revoke each node's enrollment token on the orchestrator, so a worker can never re-enrol. Only this identity's tokens (one per node) are revoked.
03Previous Versions1
2026.10.17.1MIT
04Stats
A
100 / 100
Downloads
4
Archive size
11.0 KB
  • Has README or module doc2/2earned
  • README has a code example1/1earned
  • README is substantive1/1earned
  • Most symbols documented1/1earned
  • No slow types (deprecated)1/1earned
  • Dependencies pass trust audit2/2earned
  • Has description1/1earned
  • Platform support declared (or universal)2/2earned
  • License2/2earned
  • Verified public repository2/2earned
05Platforms