cs-agent runs on every ComputeStacks node as the node's local data plane — a
single native binary, managed by systemd, that:
- Backs up volumes — scheduled borg backups, restores, and on-demand backup export to S3 (streamed as a presigned download).
- Programs the node firewall — renders published-port DNAT/forwarding into a native
cs_agentnftables table (replacing the old iptables shell-out). - Serves customer metadata — an HTTP API on
:8500that returns per-project metadata from an embedded SQLite store (replacing Consul KV for the/db/space; no value-size cap).
As of v2.0.0 the agent ships as a native systemd service installed from a signed apt repo — it is no longer run as a Docker container. The container image is retained for local development only. See
CHANGELOG.mdfor the v2.0.0 upgrade/rollback runbook andpackaging/README.mdfor the release + apt-distribution details.
- Debian 12 or 13 (the agent uses the
iptables/nftables backend present there). - Docker — the agent talks to the Docker socket and manages container firewall rules.
- Consul — still required for coordination until that workload is moved off it.
The agent is distributed as a .deb from the ComputeStacks signed apt repo. Add the
keyring and source once per node, then install:
# Trust the ComputeStacks signing key (one shared key for all CS packages)
curl -fsSL https://repo.computestacks.com/public/computestacks.gpg.asc \
| gpg --dearmor | sudo tee /etc/apt/keyrings/computestacks.gpg >/dev/null
# Add the repo (one source line for the whole ComputeStacks repo)
echo "deb [signed-by=/etc/apt/keyrings/computestacks.gpg] https://repo.computestacks.com/public stable main" \
| sudo tee /etc/apt/sources.list.d/computestacks.list
sudo apt-get update && sudo apt-get install -y cs-agentInstalling places the binary at /usr/bin/cs-agent and a systemd unit at
/lib/systemd/system/cs-agent.service, and enables the service for boot. On a fresh
node the service won't actually start until it's configured (see below) — the unit is
gated by ConditionPathExists=/etc/computestacks/agent.yml.
The agent reads /etc/computestacks/agent.yml. A fully-commented sample is installed at
/usr/share/doc/cs-agent/agent.sample.yml (also agent.sample.yml in
this repo):
sudo install -Dm600 /usr/share/doc/cs-agent/agent.sample.yml /etc/computestacks/agent.yml
sudoedit /etc/computestacks/agent.yml
sudo systemctl restart cs-agentNotable settings:
store.data_dir— where the embedded SQLite data plane lives (control.db+ a metadata DB per project).metadata.listen_addr— must stay:8500; it's baked into customer containers asmetadata.internal:8500. Because the agent binds:8500, Consul's HTTP listener moves to:8502on upgraded nodes (see the CHANGELOG upgrade steps).metadata.admin_token_hash— sha256 of the per-node admin bearer the controller uses.backups.*— borg schedule, encryption key, and the SSH/NFS backup repo.backups.export.s3— S3 target for backup export (inert untilbucketis set).
systemctl status cs-agent
sudo systemctl restart cs-agent
journalctl -u cs-agent -f # follow logs (SyslogIdentifier=cs-agent)
cs-agent -version # print version / commit / build dateThe agent runs as root — it needs the Docker socket and NET_ADMIN for firewall
management.
sudo apt-get update && sudo apt-get upgrade # move to the latest published version
apt list -a cs-agent # list all available versions
sudo apt-get install --allow-downgrades cs-agent=<version> # roll back to a specific versionEvery published version stays in the apt pool, so rollback is a normal downgrade —
except across a non-additive SQLite migration. See the rollback
notes and the CHANGELOG.md upgrade runbook.
The Docker image is kept for local development only:
make build-container # build ghcr.io/computestacks/node-agent:latestBuild and run the native binary directly (it reads ./agent.yml or
/etc/computestacks/agent.yml):
go build -o cs-agent .Install Go dependencies with go mod download.
NOTE: Do not run
go get -uto update Go modules. Docker has not used semantic versioning in quite some time, so the update-all command will replace the current Docker API with an older version and break the build. Update a single module withgo get <mod>@<version>instead.
Releases are automated: pushing a vX.Y.Z tag runs
.github/workflows/release.yml, which builds the binaries,
packages the .deb with GoReleaser, and publishes them to the signed apt repo. See
packaging/README.md for the full release + distribution design.