---
name: warden-pf
description: Manage Warden networking and pf on the FreeBSD host. Use when creating or validating the Warden bridge, assigning 192.168.100.0/24, enabling NAT for jail egress, or debugging Clawdie jail connectivity on FreeBSD.
---

# Warden pf

Use this skill for the host-side networking layer that sits under Bastille and
the Warden jail runtime.

## Canonical network model

- bridge: `warden0`
- subnet: `192.168.100.0/24`
- host gateway: `192.168.100.1`
- control-plane jail: `controlplane`
- control-plane IP: `192.168.100.100`
- workers: `192.168.100.101+`
- public uplink on current host: `vtnet0`

## Responsibility split

- Bastille: creates and starts jails
- host networking: owns `warden0`
- `pf`: owns NAT and later filtering

Do not let Bastille policy and `pf` policy collapse into one step. Keep the
host bridge and firewall state explicit.

Use `freebsd-admin` when the fix is a host-level routing or forwarding change
rather than a `pf` rules change.

## Workflow

1. Read `references/network-model.md`
2. If you need the exact NAT rules, read `references/pf-rules.md`
3. If you need host validation or debugging, read `references/troubleshooting.md`
4. Prefer the scripts in `scripts/` for rendering and validating Warden `pf`
   state before writing or changing firewall rules

## Safe defaults

- start with minimal NAT only
- use a dedicated Warden include/snippet in `pf`, not scattered inline rules
- validate `warden0`, gateway, forwarding, and `pfctl -nf` before creating jails
- do not introduce per-jail Tailscale until basic Warden egress is stable

## Expected operator outcomes

- `warden0` exists on the host
- `warden0` has `192.168.100.1/24`
- `pf` NATs `192.168.100.0/24` out through `vtnet0`
- `controlplane` on `192.168.100.100` can reach Telegram and provider APIs
