Skip to content

OPNsense

The OPNsense adapter is FreeSDN’s primary firewall brain - it manages an OPNsense firewall/gateway over the OPNsense REST API. It covers 13 feature domains end-to-end and is the recommended choice when you need a fully orchestrated Layer 2/3 gateway alongside Omada or MikroTik limbs.

FactDetail
MaturityProduction
Gold-standard contractDG ✓ CB ✓ RR ✓ TS ✓ SSRF ✓ RG ✓
Feature domains13
DomainCapabilities
Firewall rulesRule CRUD, reorder, alias management
NATPort-forward, outbound NAT, 1:1 NAT
DHCPScopes, reservations, static mappings
DNSUnbound resolver config, overrides
VPNOpenVPN server/client CRUD, IPsec phase-1/phase-2 tunnels, WireGuard peers and interfaces
Cron / Scheduled tasksJob CRUD (create, update, delete), staging
RoutingStatic routes, routing table (read), gateway health (read)
IDS/IPSSuricata rule-set config, enable/disable, alert reads
Traffic shaperPipe and queue management
ServicesHAProxy, DHCP relay, NTP
DiagnosticsARP/NDP tables, gateway monitoring, live log tail
InterfacesInterface list, IP assignments, VLAN sub-interfaces, ARP/NDP tables
SystemSystem info, firmware status, CARP status (read-only), backup/restore of config.xml

Twelve of the 13 domains support read + stage + apply via the dual-gate pipeline. The Diagnostics domain exposes live direct-action endpoints (ping, traceroute, DNS lookup) that execute immediately rather than staging - nothing in that domain is genuinely state-changing, so the staging machinery would add latency and audit-log noise with no benefit.

GatewayDetailPage renders 18 tabs when the controller vendor is opnsense:

overview, interfaces, rules, NAT, aliases, DHCP, DNS, VPN, routing, services, IDS, shaper, diagnostics, logs, monitoring, sync, backups, system.

The adapter mounts 13 separate routers - one per feature domain:

/api/v1/gateway-opnsense-firewall/
/api/v1/gateway-opnsense-nat/
/api/v1/gateway-opnsense-dhcp/
/api/v1/gateway-opnsense-dns/
/api/v1/gateway-opnsense-vpn/
/api/v1/gateway-opnsense-routing/
/api/v1/gateway-opnsense-ids/
/api/v1/gateway-opnsense-shaper/
/api/v1/gateway-opnsense-services/
/api/v1/gateway-opnsense-diagnostics/
/api/v1/gateway-opnsense-system/
/api/v1/gateway-opnsense-interfaces/
/api/v1/gateway-opnsense-cron/

Staged changes are applied via the shared POST /api/v1/gateway-vpn/changes/{change_id}/apply endpoint using opnsense.* feature prefixes - the apply path dispatches to the correct OPNsense service based on the feature prefix (e.g., opnsense.firewall.*GatewayOpnsenseFirewallService). The /api/v1/gateway-firewall/ routes are Omada-only and never dispatch to OPNsense.

The OPNsense adapter authenticates with an API key + secret pair generated on the OPNsense firewall.

  1. Log in to OPNsense → System → Users → Edit the admin user (or create a dedicated freesdn user).
  2. Under API keys, click + to generate a new key.
  3. Copy the Key and Secret - the secret is shown only once.
  4. Ensure the user has the API privilege and, for write operations, the relevant service privileges.
FieldValue
credential_typeapi_key
api_keyThe key string from OPNsense
passwordThe secret string from OPNsense

Point host at the base HTTPS URL of your OPNsense instance:

https://opnsense.example.com

OPNsense defaults to port 443; include a port only if you have changed it (e.g., https://opnsense.example.com:4443).

Terminal window
# Create the controller record (credentials are stored inline; there is no credential_id parameter)
curl -X POST https://<freesdn-host>/api/v1/controllers \
-H "Cookie: freesdn_access=<token>" \
-H "X-CSRF-Token: <csrf>" \
-H "Content-Type: application/json" \
-d '{
"name": "opnsense-prod",
"controller_type": "opnsense",
"host": "https://opnsense.example.com",
"port": 443,
"site_id": "<site-uuid>",
"username": "<opnsense-api-key>",
"password": "<opnsense-api-secret>"
}'
# Trigger discovery
curl -X POST https://<freesdn-host>/api/v1/discovery/controllers/<controller-id> \
-H "Cookie: freesdn_access=<token>" \
-H "X-CSRF-Token: <csrf>"

OPNsense is typically the firewall protecting your environment - treat writes with care.

  1. Set ADAPTER_READ_ONLY=false in your environment file (.env.pro, .env.max, etc.).
  2. Restart the API: docker compose --env-file .env.pro up -d api.
  3. Stage a change in the FreeSDN UI (e.g., add a firewall rule). The change is persisted to the pending-changes table and nothing is sent to OPNsense yet.
  4. Navigate to Pending Changes, review the staged row, and confirm with force: true.

Both conditions must be satisfied simultaneously. A staged change sitting in pending will remain there indefinitely until you explicitly apply it.

OPNsense is the recommended brain in the FreeSDN layered network architecture. In this role it:

  • Holds the authoritative canonical VLAN list for the site.
  • Distributes VLANs to connected limbs (Omada switches, MikroTik access ports) via the POST /api/v1/network/vlans/distribute endpoint.
  • Exposes drift detection - compare the desired canonical VLAN state against what is running on each limb at GET /api/v1/network/vlans/alignment.
  • CARP HA pair status is readable; orchestrated failover promotion is not supported.
  • pfBlockerNG and Suricata package management beyond built-in IDS rule-set config is out of scope.

All product names, logos, and brands are property of their respective owners. FreeSDN is an independent project and is not affiliated with or endorsed by the vendors it integrates with. See Trademarks.