Skip to content

OPNsense Automation & Tooling Landscape

Initial research: 2026-02-09 Purpose: Evaluate tools for increasing IaC coverage and operational insight

Structural Challenge

The OPNsense REST API doesn't expose system-level settings (hostname, SSH config, interface assignments, certificates). This forces a two-tier approach:

  • API-based tools for data-heavy subsystems (firewall, DHCP, DNS, IDS, etc.)
  • SSH/config.xml tools for system plumbing (identity, interfaces, SSH hardening)

Every serious OPNsense automation project uses both methods.

Ansible Collections

oxlorg.opnsense (our primary collection)

  • GitHub: O-X-L/ansible-opnsense (437 stars)
  • Galaxy: oxlorg.opnsense (formerly ansibleguy.opnsense, renamed Sep 2024)
  • Version: 25.7.8 (Nov 2024)
  • Method: REST API via httpx
  • Modules: ~90+ (we currently use ~15)

Module Categories

Category Modules Our Usage
Base/General list, reload, raw, service, system raw heavily
Firewall alias, rule, rule_multi, rule_purge, savepoint alias, rule, savepoint
NAT nat_source, nat_one_to_one Not used
Interfaces interface_vlan, interface_vxlan, interface_vip, interface_lagg, interface_loopback, interface_gre, interface_bridge, interface_gif interface_gif
Routing route, gateway Not used
FRR (Dynamic Routing) 25+ modules (BGP, OSPF, RIP, BFD) Not used
Unbound DNS unbound_general, unbound_acl, unbound_forward, unbound_dot, unbound_host, unbound_host_alias, unbound_dnsbl unbound_forward, unbound_host
DHCP (KEA) dhcp_general, dhcp_subnet, dhcp_reservation, dhcp_controlagent All used
VPN - WireGuard wireguard_server, wireguard_peer, wireguard_show, wireguard_general Not used
VPN - OpenVPN openvpn_client, openvpn_server, openvpn_static_key, openvpn_status Not used
VPN - IPSec 11 modules Not used
IDS/IPS ids_action, ids_general, ids_ruleset, ids_rule, ids_user_rule, ids_policy Not used (using raw)
Traffic Shaper shaper_pipe, shaper_queue, shaper_rule Not used
HAProxy 16 modules Not used
Monit monit_service, monit_alert, monit_test Not used
ACME/Certs acme_account, acme_action, acme_general, acme_validation, acme_certificate Not used
Users/Access user, group, privilege Not used
Other package, cron, syslog package used

High-Value Unused Modules

Module Gap It Closes Coverage Impact
gateway Gateway definitions (WAN_GW, HE_TUNNELV6) Tier 3 → Tier 1
user, group User/group management Tier 3 → Tier 1
monit_service, monit_alert, monit_test Monit monitoring (4 services, 10 tests) Tier 3 → Tier 1
nat_source Outbound NAT rules Tier 3 → Tier 1
route Static routes Tier 3 → Tier 1
ids_general, ids_ruleset Replace raw IDS calls with idempotent modules Better idempotency
syslog Replace raw syslog calls Better idempotency
cron Replace raw cron calls Better idempotency
unbound_general Replace raw Unbound general/advanced calls Better idempotency
unbound_dot Replace raw DoT upstream calls Better idempotency
unbound_dnsbl Replace raw DNSBL calls Better idempotency

Known Gaps (No Module Available)

  • System identity (hostname, domain, timezone) — no API
  • SSH configuration — no API
  • Interface assignments — no API
  • Port forwarding / DNAT — open issue, planned for v26.1
  • Certificate management (non-ACME) — open issue
  • NAT mode (automatic/hybrid/manual) — not managed
  • Node Exporter — no dedicated module (using raw)
  • SNMP (net-snmp) — no dedicated module (using raw)

puzzle.opnsense (SSH/config.xml complement)

  • GitHub: puzzle/puzzle.opnsense (39 stars)
  • Version: 2.0.0 (Nov 2025)
  • Method: SSH + direct config.xml manipulation via Python lxml
  • Maintained by: Puzzle ITC (Swiss IT company)

Modules

Module Purpose Status
system_settings_general Hostname, domain, timezone Stable
system_settings_logging Logging configuration Stable
firewall_alias Firewall aliases Stable
interfaces_assignments Interface assignments Stable
system_access_users User management Deprecated (3.0.0)
system_high_availability_settings HA/CARP Deprecated (3.0.0)
firewall_rules Firewall rules Deprecated (3.0.0)

Key Value

Fills exactly the two gaps the API cannot:

  • system_settings_general → hostname, domain, timezone (currently 0% coverage)
  • interfaces_assignments → interface-to-port mapping (currently 0% coverage)

Puzzle ITC themselves use both collections in production: puzzle.opnsense for system settings, oxlorg.opnsense for everything else.

Rosa-Luxemburgstiftung-Berlin/ansible-opnsense (reference — do not adopt wholesale)

  • GitHub: Rosa-Luxemburgstiftung-Berlin/ansible-opnsense (23 stars)
  • Version: 26.1.0 (Jan 2026), active single-maintainer (Klaus Zerwes)
  • Method: SSH + config.xml fetch-edit-push (Ansible role, not collection)
  • Architecture: Fetches entire config.xml → patches via XPath (community.general.xml) → pushes entire file back + reloads all services
  • Scope: Comprehensive — sysctl, interfaces, NAT, VLANs, users, gateways, VPN, certs, HA, cron, monit, UPS
  • Risk: Full-file push conflicts with API-managed settings — designed as sole config tool, not a companion

Gap Coverage (what it can do that our API stack cannot)

Our Gap Covered? XPath Pattern
Sysctl tunables Yes /opnsense/sysctl/item[tunable/text()='...']/value
Interface assignments Yes /opnsense/interfaces/{{ name }}/{{ key }}
NAT mode + rules Yes /opnsense/nat/...
NTP servers Yes system/timeservers in general settings
Certificate management Yes Base64 cert/key/CA, UUID-aware
radvd/DHCPv6 No DHCPv4 only
SSH hardening No Not in scope
powerd/amdtemp No NUT only (UPS, not CPU power)

Strategic Value

Do not adopt the role — the full-file config.xml push would overwrite API-managed changes. Instead, mine the XPath patterns as reference for building our own surgical config.xml tasks using puzzle.opnsense SSH or community.general.xml within our existing role. The variable structures are clean and well-documented.

Proof of Concept (Validated)

We built a config.xml schema analyzer (scripts/opnsense-config-schema.py) and a sample Ansible task file (roles/opnsense/tasks/config-xml-sysctl.yml) that demonstrate:

  1. Schema extraction — reads config.xml and maps XPath patterns for any section
  2. Ansible var generation — outputs ready-to-paste variable YAML from current config
  3. Task generation — produces Ansible task YAML using community.general.xml
  4. Schema diffing — compares two config.xml versions and flags changes (the "self-maintaining" mechanism)

Tested against Owl's production config.xml (42 sysctl items, 7 interfaces, 1 cert). The diff tool successfully detected all simulated upgrade changes (version bump, added/removed tunables, new system fields, new interfaces).

# Extract schema for a section
python3 scripts/opnsense-config-schema.py extract config.xml -s sysctl

# Generate Ansible vars from current config
python3 scripts/opnsense-config-schema.py generate config.xml -s sysctl

# Detect schema drift after OPNsense upgrade
python3 scripts/opnsense-config-schema.py diff old-config.xml new-config.xml

# Generate Ansible task YAML for a section
python3 scripts/opnsense-config-schema.py task -s sysctl

The sysctl task file uses Rosa-Luxemburg's with_nested × fields pattern within our SSH play, keeping it safe alongside API-managed subsystems.

MCP Servers

Currently Using: vespo92/OPNSenseMCP

  • v0.9.4 (latest as of Feb 2026, published Dec 8, 2025)
  • 111 purpose-built tools, SSH access, auto-repair features
  • Development slowed after Dec 2025 burst

Alternative: Pixelworlds/opnsense-mcp-server (evaluated — not adopting)

  • GitHub: Pixelworlds/opnsense-mcp-server (23 stars)
  • npm: @richard-stovall/opnsense-mcp-server v0.5.3
  • 88 module tools wrapping 2,000+ API methods (752 core + 1,271 plugin)
  • Last commit: Jun 2025 — stale for 8+ months
  • No SSH access — API-only, so it has the same gaps as our oxlorg.opnsense stack

Why Not Adopt

  • Poor AI ergonomics: Tools are thin wrappers around raw API methods (e.g., core_unbound_settings_get). Claude must already know the OPNsense API schema to use them effectively — the tool names don't describe what they do.
  • No domain logic: No auto-repair, no diagnostics, no compound operations. vespo92 has purpose-built tools like routing_diagnostics and nat_fix_dmz that chain multiple API calls.
  • Stale development: No commits since Jun 2025 vs. vespo92's Dec 2025 activity.
  • Massive tool surface: 88 tools pollute the MCP tool namespace. Most are never useful in a conversation.

When It Might Help

If we hit a specific API endpoint that vespo92 doesn't cover, the Pixelworlds source code is a good reference for the endpoint URL and parameter schema. But installing it as a running MCP server adds no value over using oxlorg.opnsense.raw in Ansible or the Python API client.

Monitoring MCP Servers

Server Stars What It Enables
grafana/mcp-grafana (official) 2,300 Query dashboards, PromQL via Grafana, manage alerts. 40+ tools.
pab1it0/prometheus-mcp-server ~200 Direct PromQL queries, metric discovery. Docker-based.
kaznak/alertmanager-mcp 8 Alert retrieval, silence management.

The Grafana MCP can proxy PromQL through Grafana's datasource, making a separate Prometheus MCP optional. Point at http://192.168.194.131:3000.

Terraform Provider

browningluke/terraform-provider-opnsense

  • GitHub: browningluke/terraform-provider-opnsense (141 stars)
  • Version: 0.16.1 (Nov 2025) — pre-1.0, not production-ready
  • Manages: firewall aliases/rules, NAT, VIPs, VLANs, IPsec, routes, gateways
  • Partially implemented: DHCP (Kea), Unbound DNS, WireGuard
  • Watch for 1.0 release before adopting

config.xml Analysis Tools

opnDossier

  • GitHub: EvilBit-Labs/opnDossier (Go, 12 stars)
  • Security analysis: insecure protocols, weak configs, credential exposure
  • Dead rule detection: unreachable/duplicate firewall rules
  • Unused resource detection: interfaces, aliases, services
  • Export: JSON, YAML, Markdown
  • Runs fully offline/airgapped

OPNReport

  • GitHub: AndyX90/OPNReport (Python, 67 stars)
  • Converts config.xml to readable Markdown/YAML documentation

Python API Client

O-X-L/opnsense-api-client

  • Same maintainer as our Ansible collection
  • 150+ modules, dry-run support, proper typing
  • pip install oxl-opnsense-client
  • Useful for one-off scripts outside Ansible's declarative model

Monitoring & Observability

Prometheus Exporters (already deployed)

  • AthennaMind/opnsense-exporter (221 stars, v0.0.12, Jan 2026) — our standard

Log Analysis (future consideration)

Tool Stack Fit for Us
LogSense2Loki Syslog → JSON → Loki → Grafana Best fit (lightweight, uses existing Grafana)
opnsense-grafana-loki Alloy → Loki → Grafana geo maps Alternative Loki path
pfelk (1,200 stars) Full ELK stack Gold standard but resource-heavy
OPNsense-Dashboard (655 stars) InfluxDB + Grafana + Graylog Full monitoring stack

Action Plan

Quick Wins (use existing oxlorg.opnsense modules)

  1. Switch raw → dedicated modules for IDS, syslog, cron, Unbound — fixes idempotency
  2. Add gateway module — manage WAN_GW, HE_TUNNELV6
  3. Add user/group modules — manage admin accounts
  4. Add monit_* modules — manage service monitoring

Medium-Term

  1. Install puzzle.opnsense — hostname/domain/timezone + interface assignments
  2. Build surgical config.xml tasks — mine Rosa-Luxemburg XPath patterns for sysctl, NAT, certs
  3. Add grafana/mcp-grafana MCP server — monitoring queries in Claude sessions
  4. Run opnDossier against Owl + Blue configs — automated security audit baseline

Watch List

  1. browningluke Terraform provider — monitor for 1.0
  2. LogSense2Loki — firewall log analysis in Grafana when ready