clawdie-ai/docs/public/architecture/jail-networking.md
Operator & Codex 54f612edf2 Fix browser jail registry slot
---
Build: pass | Tests: pass — 2383 passed (175 files)
2026-05-11 14:53:12 +02:00

3.3 KiB

title
Jail Networking Strategy

This document defines the current networking model for Clawdie on FreeBSD.

Current Host Network

Typical host interfaces:

  • public uplink such as vtnet0
  • tailscale0 if Tailscale is enabled on the host
  • lo0 host loopback
  • warden0 private bridge for Bastille jails

Use one private Warden subnet on the host:

  • bridge: warden0
  • subnet: operator-configurable (AGENT_SUBNET_BASE / registry)
  • host gateway: <subnet>.1

Reserved low service slots:

  • <subnet>.2 git
  • <subnet>.3 cms
  • <subnet>.4 Local AI Models
  • <subnet>.5 optional db
  • <subnet>.6 browser

Worker and automation ranges:

  • <subnet>.101+ workers
  • <subnet>.150+ ephemeral browser task clones

Internal Naming

Use home.arpa as the default internal namespace:

  • AGENT_DOMAIN=home.arpa for local DNS zones unless a real public domain is configured
  • AGENT_INTERNAL_DOMAIN=<agent>.home.arpa for the host FQDN
  • ai.home.arpa for the operator controlplane where that alias is configured
  • cms.home.arpa and git.home.arpa for shared admin surfaces
  • <tenant>.home.arpa for additive tenant homes
  • <site>.<tenant>.home.arpa for tenant sites

Do not use .local as the default internal zone. It conflicts with mDNS behavior and makes deterministic local resolution harder.

The platform DNS step renders /usr/local/etc/dnsmasq.conf, enables the dnsmasq rc.d service, and binds the local zone on both 127.0.0.1 and the Warden gateway address. That gives the host and jails the same resolver view for home.arpa names.

PF Baseline

Minimum useful PF example:

ext_if = "vtnet0"
warden_net = "<subnet>.0/24"

nat on $ext_if from $warden_net to any -> ($ext_if)
pass quick on warden0 inet from $warden_net to any keep state

That is enough to let VNET jails reach package mirrors, Telegram, providers, and other outbound services.

Exposure Model

Clawdie no longer assumes host nginx ownership of every public surface.

The intended web-serving path is:

  • cms serves nginx internally on the jailed subnet
  • public exposure happens through PF, an existing reverse proxy, or a direct jail IP
  • docs.clawdie.si can be fronted by host nginx or another edge proxy and forwarded to the cms jail

This is the main reason the service jails keep fixed low addresses on the private Warden network.

Tailscale

Preferred order:

  1. host-only Tailscale
  2. optional subnet routing of your chosen Warden subnet (for example 192.168.72.0/24)
  3. only later, per-jail Tailscale if a specific jail truly needs its own identity

Do not copy host resolver assumptions blindly into VNET jails.

Validation

The host should prove:

  • warden0 exists
  • warden0 has <subnet>.1/24
  • forwarding is enabled
  • PF loads cleanly
  • VNET jails can reach the internet

The host and jails should prove:

  • ai.home.arpa resolves locally
  • cms.home.arpa resolves locally
  • git.home.arpa resolves locally
  • tenant homes and sites such as atlas.home.arpa and blog.atlas.home.arpa resolve locally when enabled

Use just setup -- --step dns to render and apply the dnsmasq zone. Use just doctor afterwards; it verifies dnsmasq service state, listener addresses, and every registered host through both loopback and gateway resolver probes.