Act III · Keys
The hub is the only door
Secure multi-host mode: the agent attaches to the hub only. Hub reaches spokes over SSH only. Spokes execute localhost and cannot lateral-move via this fabric.
Enrollment
01
hub init --name ctrl-01
Keys, hub identity, empty inventory
02
hub issue-token --name web-03 --ttl 15m
Signed, TTL, one-time jti replay cache
03
spoke join --token … --hub user@hub:22
Token + SSH identity → inventory bay fills
04
ForceCommand → spoke session
Mesh path is not a login shell
Mesh vs bastion
| Full mesh | Hub/spoke | |
|---|---|---|
| Worker compromise | MCP-hop fleet | No lateral MCP |
| Inventory | Gossip / replicas | Hub is SoT |
| Agent attach | Any node | Hub only |
| Ops model | Mesh OS | Classic bastion |
Dual SSH identities — never conflate them. Mesh hop uses the hub client key
+ ForceCommand user for spoke_call. Ansible runs use a separate
identity. Putting interactive Ansible expectations on a ForceCommand-only user deadlocks runs.
Operators
Same surface as the agent
Enroll, group, hand the hub to OpenCode. Day-2 is a TUI, not a second product.
ansible-flow-mcp hub init --name ctrl-01 ansible-flow-mcp hub issue-token --name web-03 --ttl 15m ansible-flow-mcp spoke join --token "$TOKEN" --hub user@hub:22 --public-addr web-03.example.com ansible-flow-mcp hub session # MCP stdio for the agent ansible-flow-mcp tui # servers · groups · invite · OpenCode ansible-flow-mcp hub spoke-call --node web-03 --tool list_collections