Adding a new agent host¶
This is the end-to-end flow for getting a fresh Linux box into your convocate cluster as a new agent. Plan on ~15 minutes start to finish on a normal connection, plus however long the apt dist-upgrade takes.
Prerequisites¶
The new host must be:
- Ubuntu 22.04+ (or 24.04) — other distros aren't tested.
- Reachable from the operator workstation over SSH — TCP port 22 (or whatever your sshd is configured to use) must be open.
- Configured with NOPASSWD sudo for the connecting user —
required because
convocate-host installruns manysudocommands and won't pause for prompts. - Equipped with a working
claudeuser already, OR the connecting user must be able to create one. The firstconvocate-host installcall sets this up if absent.
For your operator side:
convocate-hostbinary present and onPATH(you got it from step 1 of Getting started).- An SSH keypair that the new host accepts (typically
~/.ssh/ id_ed25519). - The shell host already initialized via
convocate-host init-shell(the agent will need the shell host's address and rsyslog CA).
Step 1 — Provision the box (idempotent)¶
What this does on the target:
apt-get update && apt-get dist-upgrade -y- Installs base packages: docker, dnsmasq, jq, curl, git, ufw, ca-certificates, openssh-server
- Creates the
claudeuser (UID 1337, group 1337) with/home/claude - Sets timezone to
Etc/UTC - Configures ufw to allow
tcp/22and the agent'stcp/222 - Reboots the host if a kernel was upgraded
- Polls every 30s up to 10 minutes for it to come back
This step is idempotent — safe to run multiple times. Re-running is also the way you upgrade the OS later.
Step 2 — Initialize the agent¶
Once the box is back up:
--shell-host tells the new agent which host runs the shell-side
status listener (the tcp/223 socket). It's stamped into
/etc/convocate-agent/shell-host on the agent.
What init-agent does:
- Deploy the binary. Copies your local
convocate-agentto/usr/local/bin/convocate-agenton the target. - Run
convocate-agent installon the target. This: - Creates
/etc/convocate-agent/ - Generates a stable
agent-id(8-char random string) at/etc/convocate-agent/agent-id - Generates an ed25519 SSH host key at
/etc/convocate-agent/ssh_host_ed25519_key - Writes the systemd unit
/etc/systemd/system/convocate-agent.service - Writes
/etc/systemd/system/convocate-sessions.slicewithCPUQuota = nproc*90%andMemoryMax = MemTotal*90% - Drops
/etc/cron.daily/convocate-image-prune - Drops
/etc/logrotate.d/convocate-agent-logs - Mint two ed25519 peering keypairs:
shell→agentprivate + pub: lives on shell side under/etc/convocate/agent-keys/<agent-id>/. Pub also installed in the agent's authorized_keys so the shell can SSH in.agent→shellprivate + pub: private installed at/etc/convocate-agent/agent_to_shell_ed25519_keyon the agent. Pub installed in/etc/convocate/status_authorized_keyson the shell so the agent can authenticate when pushing status events.- Issue rsyslog TLS client cert. Generates an ECDSA P-256 key
pair on the agent, has the shell-side CA sign it, installs
client.crtandclient.keyunder/etc/convocate-agent/rsyslog-tls/plus the CA atca.crt. - Drop the rsyslog client config at
/etc/rsyslog.d/10-convocate-client.confto forward container logs to the shell host ontcp/514over TLS. - Transfer the container image. Runs
docker save | gzipon the shell side, scp's the tarball to a temp path on the agent, verifies SHA-256 on both ends, runsgunzip | docker load, thenrmon the temp file. - Stamp the active version at
/etc/convocate-agent/current-image. - Restart
convocate-agent.serviceso it picks up the new binary, the new host key, and the new shell-host config. - Restart the shell's
convocate-status.serviceso it picks up the new authorized key and starts accepting connections from this agent.
If any step fails, the install is aborted and the partial state is left in place for inspection — you can rerun the whole command, it's idempotent.
Step 3 — Verify¶
On the shell host:
In the TUI: press (N)ew. The agent picker should now offer the new
agent. Pick it, create a smoke-test session, attach with Enter, run
uname -a to confirm you're inside the container on the new host,
detach with Ctrl-B D, kill with (K), delete with (D).
On the new agent:
systemctl status convocate-agent
# active (running)
cat /etc/convocate-agent/current-image
# convocate:v0.0.x
docker images convocate
# should match the tag in current-image
journalctl -u convocate-agent -n 50 --no-pager
# should see "claude-agent: connection from <shell-host-ip>"
# and "status connected to <shell-host-ip>:223"
tail -n 20 /var/log/convocate-agent/<agent-id>.log
# (on the SHELL host, not the agent — this is where forwarded logs land)
If the agent shows up in the TUI but the shell-side log file is empty, TLS forwarding is misbehaving — see Troubleshooting.
Removing an agent¶
There's no explicit "deregister" command. To retire an agent:
- Delete or migrate every session on it (the TUI shows them per
agent;
(D)eleteeach, or save what you need first). - Stop the agent service on the agent host:
sudo systemctl stop convocate-agent.servicesudo systemctl disable convocate-agent.service - Remove the agent's keys directory on the shell host:
sudo rm -rf /etc/convocate/agent-keys/<agent-id> - Remove the corresponding entry from
/etc/convocate/status_authorized_keysso the agent can no longer push status events. - Restart the shell's
convocate-status.service.
After step 5 the agent is gone from the TUI on the next 15-second
refresh. The agent host is otherwise untouched — Docker images,
session directories under /home/claude/, etc., remain. Reuse the
machine or apt purge whatever you don't need.