Deny outbound SSH on autonomous-agent hosts (kai-server, ser8) #332

Closed
opened 2026-06-15 13:16:01 +00:00 by coilysiren · 1 comment
Owner

Goal

kai-server and ser8 are the intended hosts for autonomous agents. Autonomous-agent hosts should not be able to initiate outbound SSH — blast-radius containment so a compromised or misbehaving agent on the box can't pivot to the rest of the fleet or to external hosts.

Why now

This is surfacing out of a rethink of the Ansible execution model (see discussion below). The current infrastructure/ansible setup runs local-only on every box (ansible_connection: local, inventory is bare localhost). Part of moving off hand-running sync on every host is deciding which hosts may hold SSH egress and which must not. The two autonomous-agent candidates land firmly in the "must not" column.

Key distinction driving this: agent SSH egress is separate from Kai's SSH egress. Kai is always hands-on-keyboard for fleet ops. The hardening here targets the host's ability to open outbound SSH (and by extension any agent process on it), not Kai's interactive sessions.

Scope

  • Define the egress-deny mechanism (host firewall rule — ufw/nftables outbound deny on port 22, or equivalent) as an Ansible role so it's declarative and converged, not hand-applied.
  • Apply to kai-server and ser8.
  • Confirm it does not break inbound SSH (these hosts stay reachable as targets — e.g. for a future push-based Ansible control node connecting in).
  • Confirm it does not break the tailnet control plane or any required outbound (git pull over https, package mirrors, SSM, otel).
  • Document the policy: which fleet hosts may hold SSH egress, which may not, and why.

Notes

  • Losing outbound SSH does not block these hosts from being inbound push targets, so this is compatible with a future move to push-based Ansible from a workstation control node.
  • Bootstrap ordering: ensure the deny rule is applied late enough that initial provisioning still works, or carries an explicit allowlist for the control node.
## Goal `kai-server` and `ser8` are the intended hosts for autonomous agents. Autonomous-agent hosts should not be able to initiate outbound SSH — blast-radius containment so a compromised or misbehaving agent on the box can't pivot to the rest of the fleet or to external hosts. ## Why now This is surfacing out of a rethink of the Ansible execution model (see discussion below). The current `infrastructure/ansible` setup runs local-only on every box (`ansible_connection: local`, inventory is bare `localhost`). Part of moving off hand-running sync on every host is deciding which hosts may hold SSH egress and which must not. The two autonomous-agent candidates land firmly in the "must not" column. Key distinction driving this: **agent SSH egress is separate from Kai's SSH egress.** Kai is always hands-on-keyboard for fleet ops. The hardening here targets the *host's* ability to open outbound SSH (and by extension any agent process on it), not Kai's interactive sessions. ## Scope - [ ] Define the egress-deny mechanism (host firewall rule — `ufw`/`nftables` outbound deny on port 22, or equivalent) as an Ansible role so it's declarative and converged, not hand-applied. - [ ] Apply to `kai-server` and `ser8`. - [ ] Confirm it does not break inbound SSH (these hosts stay reachable as targets — e.g. for a future push-based Ansible control node connecting *in*). - [ ] Confirm it does not break the tailnet control plane or any required outbound (git pull over https, package mirrors, SSM, otel). - [ ] Document the policy: which fleet hosts may hold SSH egress, which may not, and why. ## Notes - Losing *outbound* SSH does not block these hosts from being *inbound* push targets, so this is compatible with a future move to push-based Ansible from a workstation control node. - Bootstrap ordering: ensure the deny rule is applied late enough that initial provisioning still works, or carries an explicit allowlist for the control node.
Author
Owner

Backlog burndown 2026-06-17: closing low-priority (P3/P4) to bring the open count to a manageable level. Nothing lost — reopen if this resurfaces. Batch tag: burndown-2026-06.

Backlog burndown 2026-06-17: closing low-priority (P3/P4) to bring the open count to a manageable level. Nothing lost — reopen if this resurfaces. Batch tag: `burndown-2026-06`.
coilysiren 2026-06-17 08:22:30 +00:00
Sign in to join this conversation.
No description provided.