Updating the cluster¶
How to roll a new convocate version across all your agents. "Update" here means: new binary, new container image, new systemd unit if anything changed.
Build first, distribute second¶
Updates always start at the shell host. Pull the new code, rebuild, and reinstall locally:
make install does:
cp build/convocate*→/usr/local/bin/- Runs
convocate installto rebuild the container image with the new tag (the version string fromgit describe --tags)
After this, the shell host is on the new version. Existing agents are still on the previous one until you push.
Push to each agent¶
What this does:
- Verify connectivity. SSH into the agent. Refuse to proceed if
the connection fails or the agent's SSH host key has changed
(the shell pins host keys at
init-agenttime). - Refuse if a container is running on the old image. Or rather:
it warns and proceeds; the new image lives alongside the old
tag, and existing containers keep using their original tag until
(R)estart. This is the cluster-wide rolling upgrade story. - Deploy the new binary. Copies
convocate-agentto/usr/local/bin/convocate-agent. - Reload the systemd unit if it's been regenerated.
convocate- agent installrewrites the unit file each time; if the contents changed (new flags, new dependencies),systemctl daemon-reload systemctl restart convocate-agent.service.- Transfer the new container image. Same
docker save | gzip | scp | docker loadflow as ininit-agent, with SHA-256 verification. - Stamp
/etc/convocate-agent/current-imagewith the new tag. Subsequent(R)estartactions on existing sessions will pick this up; new(N)ewsessions get it immediately. - Restart the agent service so the new binary is in process.
Existing session containers keep running across the restart;
the agent re-discovers them on startup via
docker ps.
All agents in one shot¶
There's no built-in --all flag (yet). Wrap it in shell:
for agent in agent-a agent-b agent-c; do
echo "=== $agent ==="
sudo convocate-host update --host "$agent" || break
done
The || break makes the loop stop on the first failure, so you can
investigate and resume rather than push a half-broken cluster.
What survives an update¶
These persist across update:
- Every running session container (with its original image tag).
- Every session directory under
/home/claude/<uuid>/. - All ed25519 keys (host key, peering keys).
- All TLS certs (rsyslog CA + client).
- The
convocate-sessions.slicecgroup config (rewritten only if the underlyinginit-agenttemplate changed). - The agent's
agent-id.
Cutting sessions over to the new image¶
After update, existing sessions are still on their original image.
To move a session to the new image:
- From the TUI, highlight the session.
(K)to kill the container.- Wait until the row shows
-. (R)to restart.- The new container is built from the freshly-stamped image tag.
Do this session-by-session as opportunity allows — there's no "restart all sessions on this agent" button by design. Every cutover is a deliberate operator decision.
When update is not enough¶
If you've changed something in the systemd-unit template such that
the previously-installed unit can't be reloaded cleanly, run
init-agent again on that host. It's idempotent and will overwrite
anything that's drifted.
If you've changed the rsyslog/TLS pipeline, run init-shell first
(to regenerate CA artifacts), then init-agent for each agent
(to reissue client certs).
Rolling back¶
There is no rollback command. The image-prune cron deletes old image tags daily, so even if you saved the old tarball, after one prune cycle you'd have to rebuild the previous version from source.
If you need to roll back:
# On the shell host:
git checkout v0.0.x # the version you want to return to
make build
sudo make install # rebuilds image with that version's tag
# On every agent:
sudo convocate-host update --host <agent>
Sessions running on a tag that's already been pruned will keep
running (Docker holds the image alive while a container references
it), but they can't be (R)estarted without the operator first
re-pulling that tag.