CLI reference
aifw is the local command-line interface to the AiFw daemon — it talks directly to the SQLite database and the local pf engine, not to the HTTP API. Use it when:
- You’re on the appliance console (no UI) and need to inspect, recover, or change something.
- You want to script bulk imports or one-off changes without standing up an API client.
- You’re writing post-install hooks or HA failover scripts that run as root locally.
For remote / unprivileged callers, use the REST API instead — it does the same things but with full RBAC.
Global flags
aifw [--db <path>] <subcommand> [<args>...]
| Flag | Default | Notes |
|---|---|---|
--db <path> |
/var/db/aifw/aifw.db |
Path to the AiFw SQLite database. Override for tests or alternate installs. |
--help / -h |
— | Show help for any subcommand. |
--version |
— | Print the AiFw version string. |
Most list commands accept --json for machine-readable output. Most failures exit non-zero and print a one-line error to stderr.
Subcommand groups
| Subcommand | Purpose |
|---|---|
aifw init |
Initialise the AiFw database file |
aifw rules |
Manage firewall rules |
aifw nat |
Manage NAT rules |
aifw queue |
Manage traffic queues (CoDel / HFSC / PRIQ) |
aifw ratelimit |
Manage rate-limit rules |
aifw geoip |
Manage geo-IP filtering |
aifw vpn |
Manage WireGuard / IPsec tunnels |
aifw config |
Versioned config history, import / export, rollback |
aifw routes |
Manage static routes |
aifw dns |
Manage DNS nameservers + post-switch probe |
aifw dhcp |
Manage the DHCP server (rDHCP) |
aifw users |
Manage local users |
aifw reverse-proxy |
Control TrafficCop |
aifw update |
AiFw firmware + OS updates |
aifw multiwan |
Multi-WAN instances, gateways, groups, policies, leaks |
aifw cluster |
HA / cluster operations (CARP, pfsync, nodes, health) |
aifw interfaces |
Show network interfaces |
aifw status |
Show firewall status |
aifw reload |
Reload rules from DB and apply to pf |
aifw reconcile |
Reconcile kernel pf state and rc.conf against DB / pf.conf.aifw |
Source: aifw-cli/src/main.rs.
init
Initialise the database (run once at install time; the installer wizard does this for you).
aifw init
aifw init --path /var/db/aifw/aifw.db
rules
Manage stateful firewall rules in the aifw pf anchor.
# List rules
aifw rules list
aifw rules list --json
# Add a rule
aifw rules add \
--action pass --direction in --proto tcp \
--src any --dst any --dst-port 443 \
--interface em0 --priority 100 \
--label "https-inbound"
# Remove by UUID
aifw rules remove 8e2c1a9f-5c0e-4f7e-9a01-94f1b3a2e678
Field reference: action is pass / block / block-drop / block-return; direction is in / out / any; priority is 0–10000 (lower applies first).
nat
Manage NAT rules in the aifw-nat anchor.
aifw nat list
# Port-forward 443 to an internal host
aifw nat add \
--type dnat --interface em0 --proto tcp \
--dst any --dst-port 443 \
--redirect 10.0.0.20 --redirect-port 443 \
--label "ingress-https"
# Outbound NAT (masquerade)
aifw nat add \
--type masquerade --interface em0 --proto any \
--src 10.0.0.0/24 --dst any --redirect any
Supported NAT types: snat, dnat, masquerade, binat, nat64, nat46.
queue & ratelimit
Traffic shaping and connection-rate limits.
# Create a CoDel queue capped at 100 Mb/s on em0
aifw queue add \
--name uplink --interface em0 \
--type codel --bandwidth 100Mb --class default --default
aifw queue list
# Limit any single source IP to 60 new TCP/443 conns per minute
aifw ratelimit add \
--name https-flood --proto tcp \
--max-conn 60 --window 60 \
--table flooders --dst-port 443 --interface em0
Overload offenders land in the named pf table (flooders above) so you can block them with a rule.
geoip
Country-level allow / block rules + interactive lookup.
aifw geoip add --country CN --action block --label "block China"
aifw geoip list
aifw geoip lookup 8.8.8.8
# => US — Google LLC (AS15169)
aifw geoip remove <id>
vpn
WireGuard tunnels and IPsec SAs in one tree.
# WireGuard tunnel
aifw vpn wg-add --name road-warriors \
--interface wg0 --port 51820 --address 10.50.0.1/24
# Add a peer
aifw vpn wg-peer-add --tunnel <tunnel-id> \
--name laptop --pubkey <peer-public-key> \
--allowed-ips 10.50.0.10/32 --keepalive 25
# IPsec SA
aifw vpn ipsec-add --name site-to-site \
--src 198.51.100.5 --dst 203.0.113.7 \
--proto esp --mode tunnel
aifw vpn list
config
Versioned configuration: every aifw reload snapshots the active config so you can diff or roll back.
aifw config show
aifw config history --limit 20
# Diff version 17 against version 22
aifw config diff 17 22
# Rollback
aifw config rollback 17
# Export / import (full JSON dump)
aifw config export > backup.json
aifw config import backup.json
routes
Static routes (kernel-level, separate from multi-WAN policy routing).
aifw routes add --dest 10.20.0.0/16 --gateway 10.0.0.1 --metric 0
aifw routes list
aifw routes system # netstat -rn
aifw routes remove <id>
dns
Manage the resolver’s upstream nameservers and the post-switch probe (auto-rollback if :53 goes silent after a backend swap).
aifw dns list
aifw dns set "1.1.1.1, 9.9.9.9"
aifw dns probe on # enable auto-rollback
aifw dns probe off
aifw dns probe status
dhcp
Drive the rDHCP companion service end-to-end.
aifw dhcp status
aifw dhcp start | stop | restart
# Subnets and reservations
aifw dhcp subnets
aifw dhcp subnet-add \
--network 10.0.0.0/24 \
--pool-start 10.0.0.100 --pool-end 10.0.0.200 \
--gateway 10.0.0.1 --dns "10.0.0.1" \
--domain "lan" --lease-time 86400
aifw dhcp reservations
aifw dhcp reservation-add \
--mac aa:bb:cc:dd:ee:ff --ip 10.0.0.50 \
--hostname printer-1
aifw dhcp leases
aifw dhcp apply # write config + restart rDHCP
users
Local-account CRUD. For SSO / OAuth users use the API or the UI.
aifw users add --username alice --password "...." --role admin
aifw users list
aifw users disable <id>
aifw users enable <id>
aifw users remove <id>
Roles: admin / operator / viewer (see Auth & RBAC).
reverse-proxy
Control the local TrafficCop instance.
aifw reverse-proxy status
aifw reverse-proxy start | stop | restart
aifw reverse-proxy validate # dry-run validate generated YAML
aifw reverse-proxy apply # generate + write + reload
aifw reverse-proxy routers --json
aifw reverse-proxy services --json
aifw reverse-proxy middlewares
aifw reverse-proxy entrypoints
aifw reverse-proxy show-config # print generated YAML
update
AiFw firmware updates plus host OS / package updates.
# AiFw firmware
aifw update check
aifw update install # download + install latest
aifw update install --restart # also restart services
aifw update install --from /tmp/aifw.tar.xz # local tarball
aifw update rollback # revert to previous version
aifw update restart # bounce services after install
aifw update reboot # full reboot
# OS / packages
aifw update os-check
aifw update os-install
install and rollback do not restart services automatically — run aifw update restart (or pass --restart / -y) when you’re ready for the brief outage.
multiwan
Inspect and apply multi-WAN configuration.
aifw multiwan instances
aifw multiwan gateways # live health
aifw multiwan groups
aifw multiwan policies
aifw multiwan leaks
aifw multiwan flows # live pf flows tagged by FIB
aifw multiwan fib-info
aifw multiwan apply # recompile + apply all anchors
aifw multiwan seed-mgmt # seed management-escape leaks
# Force a probe outcome (testing only)
aifw multiwan probe <gateway-id> ok
aifw multiwan probe <gateway-id> fail
# Export / import the full multi-WAN config as JSON
aifw multiwan export > mwan.json
aifw multiwan import mwan.json
cluster
CARP + pfsync HA operations.
aifw cluster status --json
# CARP VIPs
aifw cluster carp list
aifw cluster carp add --vhid 10 --interface em0 \
--vip 192.0.2.1/24 --password "carp-shared-secret"
aifw cluster carp remove <id>
# pfsync
aifw cluster pfsync get
aifw cluster pfsync set --sync-interface em1 --sync-peer 10.99.0.2 \
--defer true --latency-profile conservative
# Cluster nodes
aifw cluster nodes list
aifw cluster nodes add --name node-b --address 10.99.0.2 --role secondary
# Health checks
aifw cluster health list
aifw cluster health add --name uplink --check-type ping \
--target 8.8.8.8 --interval-secs 10
aifw cluster health run # probe everything now
# Failover
aifw cluster promote # this node -> master immediately
aifw cluster demote # this node -> backup immediately
aifw cluster sync # pull a snapshot from peer
aifw cluster verify --json # exit non-zero if unhealthy
interfaces / status / reload / reconcile
Diagnostic + apply commands.
aifw interfaces # list interfaces with addresses + flags
aifw status # daemon + pf health summary
aifw reload # reload rules from DB and apply to pf
aifw reconcile # repair drift between DB, pf.conf.aifw, and rc.conf
reconcile is the safe choice when you suspect the kernel pf state has drifted from the database — for example after a manual pfctl -F or a partial freebsd-update run. It re-applies anchor hooks if missing and fixes rc.conf DNS-backend flags that disagree with the database.
Output formats
Subcommands that return lists accept --json to emit raw JSON for piping into jq or another tool:
aifw rules list --json | jq '.[] | select(.action == "block")'
aifw multiwan gateways | jq '.[] | {name, state}'
Subcommands without --json print human-readable tables.
Exit codes
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Generic error (validation, missing record, runtime failure) — reason on stderr |
2 |
Usage error (clap-level: bad args, unknown subcommand) |
aifw cluster verify is the most explicit user of non-zero exits — cron / monitoring scripts can rely on its exit code as a single-bit health signal.