Architecture
Components, execution flow, the allowlist model, and where state lives.
Components
ctrl-exec-dispatcher(ced)- The control host binary. Manages the CA, handles agent pairing, dispatches commands to agents, and maintains the agent registry. The CLI is stateless — each invocation opens connections, collects results, and exits.
ctrl-exec-agent(cea)- The daemon running on each remote host. Listens on port 7443 over mTLS. Enforces the local script allowlist. Executes scripts on request, captures output, and returns results. Holds no state that cannot be reconstructed from its configuration files.
ctrl-exec-api-
An optional HTTP API server running on the control host. Exposes the same run, ping, and discovery operations as the CLI as JSON endpoints. Shares the same CA and config as
ced. Useful for integration with external tools and automation pipelines.
Execution Flow
A ced run host-a backup-mysql invocation proceeds as follows:
cedreads its config and the agent registry to resolvehost-ato an IP and port.- If an auth hook is configured, it is called with the full request context. A non-zero exit aborts the request.
cedchecks the concurrency lock forhost-a:backup-mysql. If the script is already running on that host, the request is rejected.cedopens an mTLS connection tohost-a:7443. Both sides verify the peer certificate against the CA. The agent also checks the ctrl-exec cert serial against its stored value.cedsends a JSON request body containing the script name, arguments, request ID, username, and token.- The agent validates the script name against its allowlist. If not present, the request is denied.
- If an agent-side auth hook is configured, it is called after allowlist validation.
- The agent forks and executes the script. The full request context is piped as JSON to the script's stdin.
- The agent captures stdout, stderr, and exit code, logs the result, and returns it to
ced. cedlogs the result with the same request ID and prints output.
For multi-host dispatch, steps 4–10 run in parallel for each host.
The Agent Allowlist
The allowlist is defined in /etc/ctrl-exec-agent/scripts.conf on each agent — a simple key-value file mapping a short name to an absolute script path:
backup-mysql = /opt/ctrl-exec-scripts/backup-mysql.sh
check-disk = /opt/ctrl-exec-scripts/check-disk.sh
Only names present in this file can be requested. Script names are restricted to alphanumeric characters and hyphens. The allowlist reloads on SIGHUP without a restart.
All persistent state is files on disk. The dispatcher holds no runtime state. Multiple instances sharing the same state files serve requests interchangeably.
Persistent State
/etc/ctrl-exec/- CA key and certificate, ctrl-exec key and certificate, auth hook. The CA key is the root of trust for the deployment.
/etc/ctrl-exec-agent/- Agent key and certificate, CA certificate, config, allowlist, stored ctrl-exec serial, optional revocation list.
/var/lib/ctrl-exec/agents/- Agent registry. One JSON file per paired agent. Written atomically.
/var/lib/ctrl-exec/locks/-
Transient concurrency lock files. One per active
host:scriptpair. Not preserved across restarts. /var/lib/ctrl-exec/runs/- Run results stored by the API server. Keyed by request ID, retained for 24 hours.
Reference Documentation
Full command reference and all configuration keys: REFERENCE
Internals, module structure, and wire format: DEVELOPER