refactor(ai-stack)!: derive the rule's ports #32

Merged
claudiomaradonna merged 1 commit from refactor/ai-stack-derive-ports into main 2026-10-08 10:52:11 +02:00
Collaborator

Why

ai-stack's port file opened ai_stack_ports (default [3000, 8080]), while compose published ai_stack_localai_port and ai_stack_localagi_port. Changing a publish port left the firewall rule on the old one unless ai_stack_ports changed in step.

What changed

  • BREAKING: ai_stack_ports is removed. The rule lists ai_stack_localagi_port and ai_stack_localai_port itself, with the same defaults.
  • The README describes the rule by the publish ports.
  • Stacked on #30, which edits the same port file and README. This branch contains #30's commits; merge it after #30. The new commit is refactor(ai-stack)!: derive the rule's ports.

Verification

  • make check passed. Its firewall_render gate renders the changed port file.
  • Loading the port file as firewall-apply does gives [3000, 8080] with the defaults and follows overridden publish ports.
  • Not run: make test (no podman in the agent sandbox). The firewall-apply scenarios assert { 3000, 8080 }, which is unchanged with the defaults.

Risks and follow-ups

  • The rule restricts nothing until the Docker publish bypass is fixed. This keeps it correct for then.
  • castrum-fleet's companion PR drops kneazles' ai_stack_ports (same values) and corrects its ai_stack_sources note. It can merge in either order relative to this one.
## Why ai-stack's port file opened `ai_stack_ports` (default `[3000, 8080]`), while compose published `ai_stack_localai_port` and `ai_stack_localagi_port`. Changing a publish port left the firewall rule on the old one unless `ai_stack_ports` changed in step. ## What changed - **BREAKING:** `ai_stack_ports` is removed. The rule lists `ai_stack_localagi_port` and `ai_stack_localai_port` itself, with the same defaults. - The README describes the rule by the publish ports. - **Stacked on #30**, which edits the same port file and README. This branch contains #30's commits; merge it after #30. The new commit is `refactor(ai-stack)!: derive the rule's ports`. ## Verification - `make check` passed. Its `firewall_render` gate renders the changed port file. - Loading the port file as firewall-apply does gives `[3000, 8080]` with the defaults and follows overridden publish ports. - Not run: `make test` (no podman in the agent sandbox). The firewall-apply scenarios assert `{ 3000, 8080 }`, which is unchanged with the defaults. ## Risks and follow-ups - The rule restricts nothing until the Docker publish bypass is fixed. This keeps it correct for then. - castrum-fleet's companion PR drops kneazles' `ai_stack_ports` (same values) and corrects its `ai_stack_sources` note. It can merge in either order relative to this one.
warden is deprecated. No tenant enables it, so no host's configuration
changes; a host that still carries a warden chain loses it at its next
firewall-apply run.

The role goes, with its entry in service_roles and MOLECULE_ROLES, its
catalogue row and the docs that used it as an example (per-host flags
now cite zram, the --tags examples ai-stack). firewall-apply's default
scenario keeps its "switched on with no admitted source gets an empty
chain" case through swarm with no peers group and no sources; peered
keeps swarm and ai-stack as its restricted rules; the firewall_render
fixture drops it.

One-off cleanup, as root, on a host that ran warden:

  systemctl --user -M warden@ disable --now warden.service
  loginctl terminate-user warden
  while pgrep -u warden >/dev/null; do sleep 1; done
  loginctl disable-linger warden
  userdel -r warden
  grep '^warden:' /etc/subuid /etc/subgid   # remove any line left
  rm -rf /etc/warden /usr/local/bin/warden

and remove the LocalAGI agent's MCP entry that pointed at warden. The
wait matters: terminate-user returns while rootless containers are
still stopping, and userdel refuses a user with live processes.

BREAKING CHANGE: the warden role and every warden_* variable are gone.
ai_stack_localrecall_port published LocalRecall (default 8082) for
warden's jail sessions; ai_stack_network_subnet pinned ai-net so
warden's rule could admit it; attachable let warden's jails join ai-net.
With warden gone all three serve nothing, and the publish put
LocalRecall on the LAN wherever a host kept the default, because Docker
publishes past the castrum table.

LocalRecall now publishes no port, and ai-net is a plain bridge; only
localagi reaches LocalRecall, through LOCALAGI_LOCALRECALL_URL. The
published-service assert checks LocalAI and LocalAGI only. The compose
and env templates lose their escalation-path comments; the README,
defaults, port-file comment, ADVANCED_USAGE's ai_mainframes row and the
migration doc follow (step 1 records the old ports, step 6 probes them).
The molecule scenario asserts that localrecall has no ports and ai-net
no other key.

A local render with the role's defaults differs from main only in the
header comment, attachable and localrecall's ports. On the one
ai_mainframes host, which already set the port empty, ai-net loses
attachable. Compose recreates a network whose config-hash label
changed, restarting the stack once, but may reuse one an older Compose
created without that label. After the live run,

  docker network inspect ai-stack_ai-net --format '{{.Attachable}}'

prints false once ai-net was recreated. If it prints true, or compose
refuses, run `docker compose down` in ai_stack_root, then the play.

BREAKING CHANGE: ai_stack_localrecall_port and ai_stack_network_subnet
are removed; LocalRecall is no longer published and ai-net is no longer
attachable.
ai_stack_gpu_enabled's README bullet and defaults comment said
docker-engine's assert requires a registered nvidia runtime. The assert
accepts either that or an NVIDIA CDI spec, as docker-engine's README
says, so a DGX-style host with only a CDI spec read as unsupported.
The port file opened ai_stack_ports (default [3000, 8080]) while compose
published ai_stack_localai_port and ai_stack_localagi_port, so changing
a publish port left the firewall rule on the old one unless
ai_stack_ports was changed in step.

The rule now lists the two publish ports itself, with the same defaults,
and ai_stack_ports is gone. With the role's defaults the rule still
opens [3000, 8080]; overriding the publish ports moves it with them.
The rule restricts nothing until the Docker publish bypass is fixed
(docs/ARCHITECTURE.md#firewall), so this matters from then on.

Stacked on the warden removal, which edits the same port file and
README.

BREAKING CHANGE: ai_stack_ports is removed; the rule follows
ai_stack_localai_port and ai_stack_localagi_port.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
claudiomaradonna/castrum!32
No description provided.