Filesystem layout¶
A complete map of every path convocate touches.
Shell host¶
Configuration (root-owned, mode 0750 unless noted)¶
/etc/convocate/
├── status_host_ed25519_key # SSH host key for tcp/223 listener (mode 0600)
├── status_host_ed25519_key.pub # Public half
├── status_authorized_keys # Pubkeys allowed to push status events (one per agent)
├── rsyslog-ca/
│ ├── ca.crt # Per-cluster ECDSA P-256 CA
│ ├── ca.key # CA private key (mode 0600)
│ ├── server.crt # Shell-side rsyslog TLS cert
│ └── server.key # Server key (mode 0600)
└── agent-keys/
└── <agent-id>/ # One subdirectory per registered agent
├── agent-host # Plain text: "host[:port]"
├── shell_to_agent_ed25519_key # Shell's private key for tcp/222 (mode 0600)
├── shell_to_agent_ed25519_key.pub # Public half
├── agent_to_shell_ed25519_key.pub # Agent's public key for tcp/223 verification
└── host_key.pub # Pinned agent host key
Runtime / state¶
/var/lib/convocate/
└── dnsmasq-hosts # Auto-generated; rewritten on session DNS change
/var/log/convocate-agent/
└── <agent-id>.log # rsyslog-routed; per-agent container log file
dnsmasq integration¶
rsyslog integration¶
/etc/rsyslog.d/
└── 10-convocate-server.conf # TLS listener on :514, route to /var/log/convocate-agent/
/etc/logrotate.d/
└── convocate-agent-logs # Daily rotate of the per-agent log files
Systemd¶
Binary¶
/usr/local/bin/
├── convocate # TUI binary
├── convocate-host # Provisioner / updater
└── convocate-agent # Required when shell + agent on same box
Agent host¶
Configuration (root-owned, mode 0750 unless noted)¶
/etc/convocate-agent/
├── agent-id # Stable 8-char random ID, generated once
├── ssh_host_ed25519_key # SSH host key for tcp/222 listener (mode 0600)
├── ssh_host_ed25519_key.pub # Public half (pinned on the shell side)
├── authorized_keys # Pubkeys allowed to dial in (typically one per shell)
├── shell-host # Plain text: where to push status events
├── current-image # Plain text: convocate:vX.Y.Z (the active tag)
├── agent_to_shell_ed25519_key # Agent's private key for tcp/223 push (mode 0600)
├── agent_to_shell_ed25519_key.pub
└── rsyslog-tls/
├── ca.crt # Copy of the cluster CA (for trust chain)
├── client.crt # Per-agent TLS client cert
└── client.key # Client key (mode 0600)
Sessions (writable by claude user)¶
/home/claude/
├── <uuid>/ # One per session
│ ├── session.json # Session metadata
│ ├── .claude/ # Per-session Claude CLI state
│ ├── .skel/ # Skel files (CLAUDE.md etc.) on first start
│ └── ... (project files, conversation history, anything created during use)
└── <uuid>.lock # PID-owned lock file when an op is in flight
rsyslog client¶
Systemd¶
/etc/systemd/system/
├── convocate-agent.service # The agent main loop
└── convocate-sessions.slice # Cgroup parent for all session containers
# (CPUQuota = nproc*90%, MemoryMax = MemTotal*90%)
Cron / scheduled¶
/etc/cron.daily/
└── convocate-image-prune # Drop convocate:* tags no container references
/etc/logrotate.d/
└── convocate-agent-logs # Local rotation if rsyslog forwarding fails
Binary¶
Optional Anthropic integration (read-only bind-mounted into containers)¶
/usr/local/bin/claude # Anthropic Claude CLI; mounted at the same path
# in every session container (read-only)
/home/claude/.claude/ # The agent's claude-user Claude config; bind-
# mounted into every session as ~/.claude-shared/
# (read-only). Sessions write their own ~/.claude/
# which starts empty and persists per session.
/home/claude/.ssh/ # Mounted read-only into every session
/home/claude/.gitconfig # Same
Inside a session container¶
/home/claude/ # Bind-mounted from <agent>:/home/claude/<uuid>/
├── .claude/ # Per-session Claude state (writable)
├── .claude-shared/ # Bind-mounted from <agent>:/home/claude/.claude/ (RO)
├── .ssh/ # Bind-mounted from <agent>:/home/claude/.ssh/ (RO)
├── .gitconfig # Bind-mounted (RO)
├── CLAUDE.md # From the skel; tells Claude Code project conventions
└── (working files, project checkouts, etc.)
/usr/local/bin/claude # Bind-mounted from agent (RO)
/var/run/docker.sock # Bind-mounted from agent for Docker-in-Docker
# (this is a known trust-boundary; see security)
Permission summary¶
| Path | Owner | Mode | Why |
|---|---|---|---|
/etc/convocate*/ |
root:root | 0750 | Config; not readable by claude user |
*.key files |
root:root | 0600 | Private keys |
*.pub / *.crt |
root:root | 0644 | Public material |
agent-id, current-image, shell-host |
root:root | 0644 | Plain-text config |
/var/lib/convocate/dnsmasq-hosts |
root:root | 0644 | Read by dnsmasq |
/var/log/convocate-agent/*.log |
root or syslog | 0640 | rsyslog-routed |
/home/claude/<uuid>/ |
claude:claude | 0700 | Per-session, claude-only |
/home/claude/<uuid>.lock |
claude:claude | 0644 | Lock file |