OPNsense Admin ๐Ÿ›ก๏ธ

Your OpenCode agent that only speaks OPNsense. No raw pfctl, no iptables, no hand-edited firewall configs โ€” if it can’t go through the OPNsense API into config.xml, opnsense won’t build it that way. It refuses the wrong shape and hands you the OPNsense-native design instead.

โ— LIVE API-first ยท config.xml โ˜… stalane/opnsense
opn-* skills
6
firewall ยท vpn ยท system ยท services ยท diagnostics ยท plugins
API shape
/api/*
module / controller / command ยท Basic key+secret
Apply discipline
staged โ†’ live
search โ†’ add/set โ†’ apply ยท backup first
Docs stance
verified
endpoints checked vs docs.opnsense.org

๐Ÿ”Œ API shape: one base, every plane

GET retrieves ยท POST mutates/executes ยท JSON bodies ยท per-user effective privileges ยท docs.opnsense.org/development/api.html
PlaneModules
firewallfilter (rules + apply) ยท alias (+ GeoIP/URL tables) ยท source_nat ยท d_nat ยท one_to_one ยท npt ยท filter_util/rule_stats
vpnipsec ยท openvpn ยท wireguard โ€” instances, peers, keys, status
systemfirmware ยท core (services/backups) ยท auth ยท trust (certs) ยท routes/routing ยท HA/CARP
servicesunbound (+DNSBL) ยท kea/dnsmasq/dhcrelay ยท ids (Suricata) ยท monit ยท ntpd ยท syslog ยท trafficshaper
diagnosticsdiagnostics (ping/capture/lookup) ยท syslog files ยท core/service ยท Insight/NetFlow ยท health graphs
pluginshaproxy ยท caddy ยท acmeclient ยท crowdsec ยท tailscale/zerotier ยท telegraf/nodeexporter
export OPN_HOST=fw.example.com OPN_KEY=<key> OPN_SECRET=<secret>
curl -s -u "$OPN_KEY:$OPN_SECRET" \
  "https://$OPN_HOST/api/firewall/filter/searchRule" \
  -d '{"current":1,"rowCount":25,"sort":{},"searchPhrase":""}'

๐Ÿ›  Skill router

one plane per skill ยท thin files, heavy reuse
SkillPlane
opn-firewallfilter rules ยท aliases ยท NAT ยท apply flow
opn-vpnIPsec ยท OpenVPN ยท WireGuard
opn-systemfirmware ยท backups ยท users/keys ยท HA ยท certs
opn-servicesUnbound ยท DHCP ยท IDS/IPS ยท Monit ยท NTP
opn-diagnosticshealth ยท logs ยท NetFlow ยท capture ยท triage
opn-pluginsHAProxy ยท Caddy ยท ACME ยท CrowdSec ยท mesh

โ›” Hard rule: OPNsense-only

refuse the shape, redirect to the equivalent
Asked forBuilt instead
Raw pfctl / pf.conf editsfirewall/filter + alias via API
iptables / nftablesfirewall/filter rules + apply
Manual NAT scriptssource_nat / d_nat / 1:1 / NPT
Hand-rolled VPN configswireguard / openvpn / ipsec modules
Cron scripts poking pfcore/cron + configd actions
External DNS/DHCP boxesunbound / kea / dnsmasq on-box
Reverse-proxy VPShaproxy / caddy plugins

โฌ‡ Install into your harness

OpenCode ยท an OPNsense firewall with an API key (System โ€ฃ Access โ€ฃ Users)
cp agent/opnsense.md ~/.config/opencode/agents/
cp -r skills/* ~/.config/opencode/skills/
  • Restart OpenCode, verify with opencode agent list (expect opnsense).
  • Host / key / secret travel per command as env vars โ€” never stored in the repo, never logged.
  • Safety default: search โ†’ stage โ†’ apply, config.xml backup before mutating sessions, confirm before production apply.

โœ” Verification record

measured, not claimed
  • API shapes verified 29 Sep 2026 โ€” firewall plane (filter/searchRule/addRule/setRule/delRule/toggleRule/apply, alias/*, NAT controllers, filter_util/rule_stats) read against the live API reference; all other planes cite module/controller names from the same reference, parameters copied from GUI /api/ traffic.
  • Unknown-parameter rule banked: repeat the action in the GUI with devtools open, copy the /api/ request verbatim โ€” never invent model fields.
  • Gotchas banked: staged writes are not live before apply/reconfigure; automation-namespace rules are separate from core GUI rules; curl -k is lab-only.