Skip to content

Security

This guide covers secure configuration of opnsense2otel, including API key management, TLS, and least-privilege access.

OPNsense API key creation

  1. Log in to the OPNsense web UI.
  2. Navigate to System > Access > Users.
  3. Create a dedicated monitoring user (do not use the root account).
  4. Assign the user to a group with only the required permissions.
  5. Scroll to the API keys section and click + to generate a new key pair.
  6. Save the downloaded file - it contains the key and secret.

Avoid root API keys

API keys generated for the root user have full access to all OPNsense APIs, including write operations. Always create a dedicated monitoring user and grant only the ACL units required by the collectors you enable.

OPNsense user permissions

Create a group (for example, monitoring) and grant the ACL units from the generated matrix for every collector you enable. The matrix covers every registered exporter endpoint, including non-collector health and log-shipping calls; status unknown is an explicit result and must not be replaced with a guessed narrower permission.

ACL units are not read-only

OPNsense authorises API keys by page-level URI patterns. A wildcard; may include writes row grants the whole API prefix, including the controller's write actions. This is a limitation of OPNsense ACL granularity, not evidence that the exporter sends writes. A dedicated monitoring user limits the blast radius, but does not make those available privileges harmless.

Generated collector-to-ACL matrix

Generated from the endpoint ACL map, OPNsense core 26.7.1 and 26.1.11, and github.com/opnsense/plugins @ b59cf8e (2026-07-12) (re-derived 2026-07-25).

Status is known, plugin-dependent, or unknown. Unknown is an audited result, not an omitted recommendation. plugin-gated means this endpoint is treated as absent when its plugin route returns 404.

CollectorCollection modePlugin gateEndpointACL statusLikely privilege (any one)ScopeEvidence / caveat
ACME Clientdefault-on (--exporter.disable-acme disables)plugin-gatedacmeCertificates
GET api/acmeclient/certificates/search
plugin-dependentServices: ACME Client (page-services-acmeclient)wildcard; may include writes--
Firewall Aliasesdefault-on (--exporter.disable-alias disables)--aliasTableSize
GET api/firewall/alias/get_table_size
knownFirewall: Alias: Edit (page-firewall-alias-edit); Firewall: Aliases (page-firewall-aliases)wildcard; may include writes--
APC UPS (apcupsd)default-on (--exporter.disable-apcupsd disables)plugin-gatedapcupsdServiceStatus
GET api/apcupsd/service/status
plugin-dependentServices: Apcupsd System Monitoring page (page-services-apcupsd)wildcard; may include writes--
APC UPS (apcupsd)default-on (--exporter.disable-apcupsd disables)plugin-gatedapcupsdUpsStatus
GET api/apcupsd/service/getUpsStatus
plugin-dependentServices: Apcupsd System Monitoring page (page-services-apcupsd)wildcard; may include writes--
ARP Tabledefault-on (--exporter.disable-arp-table disables); high-cardinality opt-in (--exporter.enable-arp-details)--arp
POST api/diagnostics/interface/search_arp
knownDiagnostics: ARP Table (page-diagnostics-arptable)wildcard; may include writes--
Local Authdefault-on (--exporter.disable-auth disables)--authAPIKeys
GET api/auth/user/search_api_key
knownSystem: Access: Management (page-system-usermanager)wildcard; may include writes--
Local Authdefault-on (--exporter.disable-auth disables)--authGroups
GET api/auth/group/search
plugin-dependentSystem: Access: Management (page-system-usermanager)wildcard; may include writesgranted by page-system-groupmanager on 26.1.11 and page-system-usermanager on 26.7.1
Local Authdefault-on (--exporter.disable-auth disables)--authUsers
GET api/auth/user/search
knownSystem: Access: Management (page-system-usermanager)wildcard; may include writes--
Config Backupdefault-on (--exporter.disable-backup disables)--backupHistory
GET api/core/backup/backups/this
knownDiagnostics: Configuration History (page-diagnostics-configurationhistory)wildcard; may include writes--
BPF Statisticsdefault-on (--exporter.disable-bpf disables)plugin-gatedbpfStatistics
GET api/diagnostics/interface/get_bpf_statistics
knownDiagnostics: Netstat (page-diagnostics-netstat)wildcard; may include writes--
Certificatesdefault-on (--exporter.disable-certificates disables)--caCertificates
GET api/trust/ca/search
knownSystem: CA Manager (page-system-camanager)wildcard; may include writes--
Captive Portaldefault-on (--exporter.disable-captiveportal disables)plugin-gatedcaptivePortalServiceStatus
GET api/captiveportal/service/status
knownServices: Captive Portal (page-services-captiveportal)wildcard; may include writes--
Captive Portaldefault-on (--exporter.disable-captiveportal disables)plugin-gatedcaptivePortalSessions
POST api/captiveportal/session/search
knownServices: Captive Portal (page-services-captiveportal)wildcard; may include writes--
Captive Portaldefault-on (--exporter.disable-captiveportal disables)--captivePortalVoucherGroups
GET api/captiveportal/voucher/list_voucher_groups
knownServices: Captive Portal (page-services-captiveportal)wildcard; may include writes--
Captive Portaldefault-on (--exporter.disable-captiveportal disables)--captivePortalVoucherProviders
GET api/captiveportal/voucher/list_providers
knownServices: Captive Portal (page-services-captiveportal)wildcard; may include writes--
Captive Portaldefault-on (--exporter.disable-captiveportal disables)--captivePortalVouchers
GET api/captiveportal/voucher/list_vouchers
knownServices: Captive Portal (page-services-captiveportal)wildcard; may include writes--
Captive Portaldefault-on (--exporter.disable-captiveportal disables)plugin-gatedcaptivePortalZones
GET api/captiveportal/session/zones
knownServices: Captive Portal (page-services-captiveportal)wildcard; may include writes--
CARPdefault-on (--exporter.disable-carp disables)--carpStatus
GET api/diagnostics/interface/get_vip_status
knownInterfaces: Virtual IPs: Status (page-status-carp)wildcard; may include writes--
Certificatesdefault-on (--exporter.disable-certificates disables)--certificates
GET api/trust/cert/search
knownSystem: Certificate Manager (page-system-certmanager)wildcard; may include writes--
Chronydefault-on (--exporter.disable-chrony disables)plugin-gatedchronyServiceStatus
GET api/chrony/service/status
plugin-dependentServices: Chrony (page-services-chrony)wildcard; may include writes--
Chronydefault-on (--exporter.disable-chrony disables)plugin-gatedchronySourceStats
GET api/chrony/service/chronysourcestats
plugin-dependentServices: Chrony (page-services-chrony)wildcard; may include writes--
Chronydefault-on (--exporter.disable-chrony disables)plugin-gatedchronySources
GET api/chrony/service/chronysources
plugin-dependentServices: Chrony (page-services-chrony)wildcard; may include writes--
Chronydefault-on (--exporter.disable-chrony disables)plugin-gatedchronyTracking
GET api/chrony/service/chronytracking
plugin-dependentServices: Chrony (page-services-chrony)wildcard; may include writes--
ClamAVdefault-on (--exporter.disable-clamav disables)plugin-gatedclamavVersion
GET api/clamav/service/version
plugin-dependentServices: ClamAV (page-services-clamav)wildcard; may include writes--
Systemdefault-on (--exporter.disable-system disables)--cpuType
GET api/diagnostics/cpu_usage/getCPUType
knownLobby: Dashboard (page-system-login-logout)wildcard; may include writes--
CPUdefault-on (--exporter.disable-cpu disables)--cpuUsageStream
GET api/diagnostics/cpu_usage/stream
knownLobby: Dashboard (page-system-login-logout)wildcard; may include writes--
Crondefault-on (--exporter.disable-cron-table disables)--cronJobs
POST api/cron/settings/searchJobs
knownSystem: Settings: Cron (page-system-cron)wildcard; may include writes--
CrowdSecdefault-on (--exporter.disable-crowdsec disables)plugin-gatedcrowdsecAlerts
POST api/crowdsec/alerts/search
plugin-dependentCrowdSec (page-user-crowdsec)wildcard; may include writes--
CrowdSecdefault-on (--exporter.disable-crowdsec disables)plugin-gatedcrowdsecAppsecConfigs
POST api/crowdsec/appsecconfigs/search
plugin-dependentCrowdSec (page-user-crowdsec)wildcard; may include writes--
CrowdSecdefault-on (--exporter.disable-crowdsec disables)plugin-gatedcrowdsecAppsecRules
POST api/crowdsec/appsecrules/search
plugin-dependentCrowdSec (page-user-crowdsec)wildcard; may include writes--
CrowdSecdefault-on (--exporter.disable-crowdsec disables)plugin-gatedcrowdsecBouncers
POST api/crowdsec/bouncers/search
plugin-dependentCrowdSec (page-user-crowdsec)wildcard; may include writes--
CrowdSecdefault-on (--exporter.disable-crowdsec disables)plugin-gatedcrowdsecCollections
POST api/crowdsec/collections/search
plugin-dependentCrowdSec (page-user-crowdsec)wildcard; may include writes--
CrowdSecdefault-on (--exporter.disable-crowdsec disables)plugin-gatedcrowdsecDecisions
POST api/crowdsec/decisions/search
plugin-dependentCrowdSec (page-user-crowdsec)wildcard; may include writes--
CrowdSecdefault-on (--exporter.disable-crowdsec disables)plugin-gatedcrowdsecMachines
POST api/crowdsec/machines/search
plugin-dependentCrowdSec (page-user-crowdsec)wildcard; may include writes--
CrowdSecdefault-on (--exporter.disable-crowdsec disables)plugin-gatedcrowdsecParsers
POST api/crowdsec/parsers/search
plugin-dependentCrowdSec (page-user-crowdsec)wildcard; may include writes--
CrowdSecdefault-on (--exporter.disable-crowdsec disables)plugin-gatedcrowdsecPostoverflows
POST api/crowdsec/postoverflows/search
plugin-dependentCrowdSec (page-user-crowdsec)wildcard; may include writes--
CrowdSecdefault-on (--exporter.disable-crowdsec disables)plugin-gatedcrowdsecScenarios
POST api/crowdsec/scenarios/search
plugin-dependentCrowdSec (page-user-crowdsec)wildcard; may include writes--
CrowdSecdefault-on (--exporter.disable-crowdsec disables)plugin-gatedcrowdsecServiceStatus
GET api/crowdsec/service/status
plugin-dependentCrowdSec (page-user-crowdsec)wildcard; may include writes--
CrowdSecdefault-on (--exporter.disable-crowdsec disables)plugin-gatedcrowdsecVersion
GET api/crowdsec/version/get
plugin-dependentCrowdSec (page-user-crowdsec)wildcard; may include writes--
Hardwaredefault-on (--exporter.disable-hardware disables)plugin-gateddechwPowerStatus
GET api/dechw/info/power_status
unknownNo matched ACL; only page-allexactthe dec-hw plugin grants api/dechw/info/powerstatus; the exporter registers the underscored spelling power_status, which routes to the same action but matches no privilege except page-all.
ISC DHCPv4default-on (--exporter.disable-dhcpv4 disables); high-cardinality opt-in (--exporter.enable-dhcpv4-details)plugin-gateddhcpv4
GET api/dhcpv4/leases/searchLease
plugin-dependentServices: ISC DHCPv4: Leases (page-status-dhcpleases)wildcard; may include writes--
ISC DHCPv6default-on (--exporter.disable-dhcpv6 disables); high-cardinality opt-in (--exporter.enable-dhcpv6-details)plugin-gateddhcpv6Leases
GET api/dhcpv6/leases/searchLease
plugin-dependentStatus: ISC DHCPv6: Leases (page-status-dhcpv6leases)wildcard; may include writes--
ISC DHCPv6default-on (--exporter.disable-dhcpv6 disables); high-cardinality opt-in (--exporter.enable-dhcpv6-details)plugin-gateddhcpv6Prefixes
GET api/dhcpv6/leases/searchPrefix
plugin-dependentStatus: ISC DHCPv6: Leases (page-status-dhcpv6leases)wildcard; may include writes--
Hardwaredefault-on (--exporter.disable-hardware disables)plugin-gateddmidecodeInfo
GET api/dmidecode/service/get
plugin-dependentService: DMI Data Widget (page-service-dmidecode)exact--
Dnsmasq DHCPdefault-on (--exporter.disable-dnsmasq disables); high-cardinality opt-in (--exporter.enable-dnsmasq-details)--dnsmasqLeases
GET api/dnsmasq/leases/search
knownServices: Dnsmasq DNS/DHCP: Settings (page-services-dnsforwarder)wildcard; may include writes--
Dnsmasq DHCPdefault-on (--exporter.disable-dnsmasq disables); high-cardinality opt-in (--exporter.enable-dnsmasq-details)--dnsmasqRanges
GET api/dnsmasq/settings/searchRange
knownServices: Dnsmasq DNS/DHCP: Settings (page-services-dnsforwarder)wildcard; may include writes--
Dnsmasq DHCPdefault-on (--exporter.disable-dnsmasq disables); high-cardinality opt-in (--exporter.enable-dnsmasq-details)plugin-gateddnsmasqServiceStatus
GET api/dnsmasq/service/status
knownServices: Dnsmasq DNS/DHCP: Settings (page-services-dnsforwarder)wildcard; may include writes--
DynDNSdefault-on (--exporter.disable-dyndns disables)plugin-gateddyndnsAccounts
GET api/dyndns/accounts/searchItem
plugin-dependentServices: Dynamic DNS (page-services-dyndns)wildcard; may include writes--
DynDNSdefault-on (--exporter.disable-dyndns disables)plugin-gateddyndnsServiceStatus
GET api/dyndns/service/status
plugin-dependentServices: Dynamic DNS (page-services-dyndns)wildcard; may include writes--
Firewalldefault-on (--exporter.disable-firewall disables)--firewallGeoIP
GET api/firewall/alias/get_geo_i_p
knownFirewall: Alias: Edit (page-firewall-alias-edit); Firewall: Aliases (page-firewall-aliases)wildcard; may include writes--
(log shipping)non-collector endpoint--firewallRuleIDs
GET api/diagnostics/firewall/list_rule_ids
knownDiagnostics: Firewall sessions (page-diagnostics-system-pftop)exact--
Firewall Rulesdefault-on (--exporter.disable-firewall-rules disables); high-cardinality opt-in (--exporter.enable-firewall-rules-details)--firewallRuleStats
GET api/firewall/filter_util/rule_stats
knownFirewall: Rules (page-firewall-rules)wildcard; may include writes--
Firewall Rulesdefault-on (--exporter.disable-firewall-rules disables); high-cardinality opt-in (--exporter.enable-firewall-rules-details)--firewallRules
POST api/firewall/filter/search_rule
knownFirewall: Rules [new] (page-filter-api)wildcard; may include writes--
Flow Volumedefault-on (--exporter.disable-flow disables)--firewallStates
POST api/diagnostics/firewall/query_states
knownDiagnostics: Show States (page-diagnostics-showstates)wildcard; may include writes--
Firewalldefault-on (--exporter.disable-firewall disables)--firewallStats
GET api/diagnostics/firewall/stats
knownDiagnostics: Logs: Firewall: Summary View (page-diagnostics-logs-firewall-summary)wildcard; may include writes--
Firmwaredefault-on (--exporter.disable-firmware disables)--firmware
GET api/core/firmware/status
knownSystem: Firmware (page-system-firmware-manualupdate)wildcard; may include writes--
Firmwaredefault-on (--exporter.disable-firmware disables)--firmwareInfo
GET api/core/firmware/info
knownSystem: Firmware (page-system-firmware-manualupdate)wildcard; may include writes--
Gatewaysdefault-on (--exporter.disable-gateways disables)--gatewaysStatus
GET api/routing/settings/searchGateway
knownSystem: Gateways (page-system-gateways)wildcard; may include writes--
HAProxydefault-on (--exporter.disable-haproxy disables)plugin-gatedhaproxyCounters
GET api/haproxy/statistics/counters
plugin-dependentServices: HAProxy (page-services-haproxy)wildcard; may include writes--
HAProxydefault-on (--exporter.disable-haproxy disables)plugin-gatedhaproxyInfo
GET api/haproxy/statistics/info
plugin-dependentServices: HAProxy (page-services-haproxy)wildcard; may include writes--
HAProxydefault-on (--exporter.disable-haproxy disables)plugin-gatedhaproxyServiceStatus
GET api/haproxy/service/status
plugin-dependentServices: HAProxy (page-services-haproxy)wildcard; may include writes--
HAProxydefault-on (--exporter.disable-haproxy disables)plugin-gatedhaproxyTables
GET api/haproxy/statistics/tables
plugin-dependentServices: HAProxy (page-services-haproxy)wildcard; may include writes--
HA Sync Statusopt-in (--exporter.enable-hasync)--hasyncServices
POST api/core/hasync_status/services
knownStatus: HA backup (page-status-habackup)wildcard; may include writes--
HA Sync Statusopt-in (--exporter.enable-hasync)--hasyncVersion
GET api/core/hasync_status/version
knownStatus: HA backup (page-status-habackup)wildcard; may include writes--
(health probe)non-collector endpoint--healthCheck
GET api/core/system/status
knownSystem: Status (page-system-status)wildcard; may include writes--
Host Discoverydefault-on (--exporter.disable-hostdiscovery disables)--hostdiscoverySearch
GET api/hostdiscovery/service/search
knownInterfaces: Neighbors: Automatic discovery (page-hostdiscovery)wildcard; may include writes--
IDS/IPS (Suricata)default-on (--exporter.disable-ids disables)--idsAlertLogs
GET api/ids/service/get_alert_logs
knownServices: Intrusion Detection (page-services-ids)wildcard; may include writes--
IDS/IPS (Suricata)default-on (--exporter.disable-ids disables)--idsQueryAlerts
POST api/ids/service/query_alerts
knownServices: Intrusion Detection (page-services-ids)wildcard; may include writes--
IDS/IPS (Suricata)default-on (--exporter.disable-ids disables)--idsRulesets
GET api/ids/settings/list_rulesets
knownServices: Intrusion Detection (page-services-ids)wildcard; may include writes--
IDS/IPS (Suricata)default-on (--exporter.disable-ids disables)--idsSearchInstalledRules
POST api/ids/settings/searchInstalledRules
knownServices: Intrusion Detection (page-services-ids)wildcard; may include writes--
IDS/IPS (Suricata)default-on (--exporter.disable-ids disables)--idsSettings
GET api/ids/settings/get
knownServices: Intrusion Detection (page-services-ids)wildcard; may include writes--
IDS/IPS (Suricata)default-on (--exporter.disable-ids disables)--idsStatus
GET api/ids/service/status
knownServices: Intrusion Detection (page-services-ids)wildcard; may include writes--
(log shipping)non-collector endpoint--interfaceConfig
GET api/diagnostics/interface/get_interface_config
unknownNo matched ACL; only page-allexactno core ACL pattern covers api/diagnostics/interface/get_interface_config at all in either supported release; only page-all reaches it.
(log shipping)non-collector endpoint--interfaceStatistics
GET api/diagnostics/interface/get_interface_statistics
knownDiagnostics: Netstat (page-diagnostics-netstat)wildcard; may include writes--
Interfacesdefault-on (--exporter.disable-interfaces disables)--interfaces
GET api/diagnostics/traffic/interface
knownReporting: Traffic (page-status-trafficgraph)wildcard; may include writes--
Interfacesdefault-on (--exporter.disable-interfaces disables)--interfacesOverview
GET api/interfaces/overview/interfaces_info
knownStatus: Interfaces (page-status-interfaces)wildcard; may include writes--
IPsecdefault-on (--exporter.disable-ipsec disables)--ipsecLegacyStatus
GET api/ipsec/legacy_subsystem/status
plugin-dependentVPN: IPsec: Tunnels [legacy] (page-vpn-ipsec)wildcard; may include writes--
IPsecdefault-on (--exporter.disable-ipsec disables)plugin-gatedipsecPhase1
GET api/ipsec/sessions/search_phase1
knownStatus: IPsec (page-status-ipsec)wildcard; may include writes--
IPsecdefault-on (--exporter.disable-ipsec disables)plugin-gatedipsecPhase2
POST api/ipsec/sessions/search_phase2
knownStatus: IPsec (page-status-ipsec)wildcard; may include writes--
IPsecdefault-on (--exporter.disable-ipsec disables)plugin-gatedipsecPools
GET api/ipsec/leases/pools
knownStatus: IPsec: Leasespage (page-status-ipsec-leases)wildcard; may include writes--
IPsecdefault-on (--exporter.disable-ipsec disables)--ipsecSad
GET api/ipsec/sad/search
knownStatus: IPsec: SAD (page-status-ipsec-sad)wildcard; may include writes--
IPsecdefault-on (--exporter.disable-ipsec disables)plugin-gatedipsecServiceStatus
GET api/ipsec/service/status
knownStatus: IPsec: SPD (page-status-ipsec-spd); VPN: IPsec: Connections (page-vpn-ipsec-connections); VPN: IPsec: Edit Pre-Shared Keys (page-vpn-ipsec-editkeys); VPN: IPsec: Key Pairs (page-vpn-ipsec-keypairs)wildcard; may include writes--
IPsecdefault-on (--exporter.disable-ipsec disables)--ipsecSpd
GET api/ipsec/spd/search
knownStatus: IPsec: SPD (page-status-ipsec-spd)wildcard; may include writes--
Kea DHCPdefault-on (--exporter.disable-kea disables); high-cardinality opt-in (--exporter.enable-kea-details)--keaLeases4
GET api/kea/leases4/search
knownServices: DHCP: Kea(v4) (page-dhcp-kea-v4)wildcard; may include writes--
Kea DHCPdefault-on (--exporter.disable-kea disables); high-cardinality opt-in (--exporter.enable-kea-details)--keaLeases6
GET api/kea/leases6/search
knownServices: DHCP: Kea(v6) (page-dhcp-kea-v6)wildcard; may include writes--
Kea DHCPdefault-on (--exporter.disable-kea disables); high-cardinality opt-in (--exporter.enable-kea-details)--keaPdPools6
GET api/kea/dhcpv6/searchPdPool
knownServices: DHCP: Kea(v6) (page-dhcp-kea-v6)wildcard; may include writes--
Kea DHCPdefault-on (--exporter.disable-kea disables); high-cardinality opt-in (--exporter.enable-kea-details)plugin-gatedkeaServiceStatus
GET api/kea/service/status
knownServices: DHCP: Kea Ctrl Agent (page-dhcp-kea-ctrl-agent); Services: DHCP: Kea DDNS Agent (page-dhcp-kea-ddns); Services: DHCP: Kea(v4) (page-dhcp-kea-v4); Services: DHCP: Kea(v6) (page-dhcp-kea-v6)wildcard; may include writes--
Kea DHCPdefault-on (--exporter.disable-kea disables); high-cardinality opt-in (--exporter.enable-kea-details)--keaSubnets4
GET api/kea/dhcpv4/searchSubnet
knownServices: DHCP: Kea(v4) (page-dhcp-kea-v4)wildcard; may include writes--
Kea DHCPdefault-on (--exporter.disable-kea disables); high-cardinality opt-in (--exporter.enable-kea-details)--keaSubnets6
GET api/kea/dhcpv6/searchSubnet
knownServices: DHCP: Kea(v6) (page-dhcp-kea-v6)wildcard; may include writes--
LLDP Neighborsdefault-on (--exporter.disable-lldpd disables)plugin-gatedlldpdNeighbors
GET api/lldpd/service/neighbor
plugin-dependentServices: Lldpd (page-services-lldpd)wildcard; may include writes--
Mbufdefault-on (--exporter.disable-mbuf disables)--memoryStatistics
GET api/diagnostics/interface/get_memory_statistics
knownDiagnostics: Netstat (page-diagnostics-netstat)wildcard; may include writes--
Monitdefault-on (--exporter.disable-monit disables)plugin-gatedmonitServiceStatus
GET api/monit/service/status
knownWebCfg - Services: Monit System Monitoring page (page-services-monit)wildcard; may include writes--
Monitdefault-on (--exporter.disable-monit disables)plugin-gatedmonitStatus
GET api/monit/status/get/xml
knownWebCfg - Services: Monit System Monitoring page (page-services-monit)wildcard; may include writes--
Firewalldefault-on (--exporter.disable-firewall disables)--natDNATRules
GET api/firewall/d_nat/search_rule
knownFirewall: NAT: Destination NAT (page-firewall-nat-portforward-edit)wildcard; may include writes--
Firewalldefault-on (--exporter.disable-firewall disables)--natNPTRules
GET api/firewall/npt/search_rule
knownFirewall: NAT: NPTv6 (page-firewall-nat-npt)wildcard; may include writes--
Firewalldefault-on (--exporter.disable-firewall disables)--natOneToOneRules
GET api/firewall/one_to_one/search_rule
knownFirewall: NAT: 1:1 (page-firewall-nat-1-1-edit)wildcard; may include writes--
Firewalldefault-on (--exporter.disable-firewall disables)--natSourceNATRules
GET api/firewall/source_nat/search_rule
knownFirewall: NAT: Source NAT (page-filter-snat-api)wildcard; may include writes--
NDPdefault-on (--exporter.disable-ndp disables); high-cardinality opt-in (--exporter.enable-ndp-details)--ndpTable
GET api/diagnostics/interface/get_ndp
knownDiagnostics: NDP Table (page-diagnostics-ndptable)wildcard; may include writes--
NetBirddefault-on (--exporter.disable-netbird disables); high-cardinality opt-in (--exporter.enable-netbird-details)plugin-gatednetbirdServiceStatus
GET api/netbird/service/status
plugin-dependentVPN: NetBird (page-vpn-netbird)wildcard; may include writes--
NetBirddefault-on (--exporter.disable-netbird disables); high-cardinality opt-in (--exporter.enable-netbird-details)plugin-gatednetbirdStatus
GET api/netbird/status/status
plugin-dependentVPN: NetBird (page-vpn-netbird)wildcard; may include writes--
NetFlowopt-in (--exporter.enable-netflow)--netflowCacheStats
GET api/diagnostics/netflow/cacheStats
knownDiagnostics: Netflow configuration (page-diagnostics-netflow)wildcard; may include writes--
NetFlowopt-in (--exporter.enable-netflow)--netflowGetConfig
GET api/diagnostics/netflow/getconfig
knownDiagnostics: Netflow configuration (page-diagnostics-netflow)wildcard; may include writes--
NetFlowopt-in (--exporter.enable-netflow)--netflowIsEnabled
GET api/diagnostics/netflow/isEnabled
knownDiagnostics: Netflow configuration (page-diagnostics-netflow)wildcard; may include writes--
NetFlowopt-in (--exporter.enable-netflow)--netflowStatus
GET api/diagnostics/netflow/status
knownDiagnostics: Netflow configuration (page-diagnostics-netflow)wildcard; may include writes--
Network Diagnosticsopt-in (--exporter.enable-network-diagnostics)--netisrStatistics
GET api/diagnostics/interface/get_netisr_statistics
knownDiagnostics: Netstat (page-diagnostics-netstat)wildcard; may include writes--
Nginxdefault-on (--exporter.disable-nginx disables)plugin-gatednginxBans
GET api/nginx/bans/searchban
plugin-dependentnginx (page-Nginx)wildcard; may include writes--
Nginxdefault-on (--exporter.disable-nginx disables)plugin-gatednginxServiceStatus
GET api/nginx/service/status
plugin-dependentnginx (page-Nginx)wildcard; may include writes--
Nginxdefault-on (--exporter.disable-nginx disables)plugin-gatednginxVts
GET api/nginx/service/vts
plugin-dependentnginx (page-Nginx)wildcard; may include writes--
NTPdefault-on (--exporter.disable-ntp disables)--ntpGPS
GET api/ntpd/service/gps
unknownNo matched ACL; only page-allexactStatus: NTP grants only the exact route api/ntpd/service/status; nothing grants api/ntpd/service/gps except page-all.
NTPdefault-on (--exporter.disable-ntp disables)--ntpStatus
GET api/ntpd/service/status
knownStatus: NTP (page-status-ntp)exact--
NUT UPSdefault-on (--exporter.disable-nut disables)plugin-gatednutServiceStatus
GET api/nut/service/status
plugin-dependentNut (page-nut)wildcard; may include writes--
NUT UPSdefault-on (--exporter.disable-nut disables)plugin-gatednutUpsStatus
GET api/nut/diagnostics/upsstatus
plugin-dependentNut (page-nut)wildcard; may include writes--
OpenVPNdefault-on (--exporter.disable-openvpn disables)--openVPNInstances
POST api/openvpn/instances/search
knownVPN: OpenVPN: Instances (page-openvpn-instances)wildcard; may include writes--
OpenVPNdefault-on (--exporter.disable-openvpn disables)--openVPNSessions
GET api/openvpn/service/search_sessions
knownStatus: OpenVPN (page-status-openvpn)wildcard; may include writes--
Firewalldefault-on (--exporter.disable-firewall disables)--pfStates
GET api/diagnostics/firewall/pf_states/1
unknownNo matched ACL; only page-allexactLobby: Dashboard grants the exact route api/diagnostics/firewall/pf_states with no trailing wildcard; the exporter appends the /1 parameter, so the request URI matches no privilege except page-all.
Firewalldefault-on (--exporter.disable-firewall disables)--pfStatisticsByInterface
GET api/diagnostics/firewall/pf_statistics/interfaces
knownDiagnostics: Firewall statistics (page-diagnostics-pf-info)wildcard; may include writes--
PF Statisticsdefault-on (--exporter.disable-pf-stats disables)--pfStatsInfo
GET api/diagnostics/firewall/pf_statistics/info
knownDiagnostics: Firewall statistics (page-diagnostics-pf-info)wildcard; may include writes--
PF Statisticsdefault-on (--exporter.disable-pf-stats disables)--pfStatsMemory
GET api/diagnostics/firewall/pf_statistics/memory
knownDiagnostics: Firewall statistics (page-diagnostics-pf-info)wildcard; may include writes--
PF Statisticsdefault-on (--exporter.disable-pf-stats disables)--pfStatsTimeouts
GET api/diagnostics/firewall/pf_statistics/timeouts
knownDiagnostics: Firewall statistics (page-diagnostics-pf-info)wildcard; may include writes--
Network Diagnosticsopt-in (--exporter.enable-network-diagnostics)--pfsyncNodes
GET api/diagnostics/interface/get_pfsync_nodes
knownInterfaces: Virtual IPs: Status (page-status-carp)wildcard; may include writes--
Protocol Statisticsdefault-on (--exporter.disable-protocol disables)--protocolStatistics
GET api/diagnostics/interface/get_protocol_statistics
knownDiagnostics: Netstat (page-diagnostics-netstat)wildcard; may include writes--
Q-Feedsdefault-on (--exporter.disable-qfeeds disables)plugin-gatedqfeedsStats
GET api/qfeeds/settings/stats
unknownNo matched ACL; only page-allexactthe q-feeds-connector plugin grants api/q_feeds/*; the exporter registers api/qfeeds/..., which routes to the same controller but matches no privilege except page-all.
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaBfdCounters
GET api/quagga/diagnostics/bfdcounters
plugin-dependentRouting (page-routing)wildcard; may include writes--
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaBfdNeighbors
GET api/quagga/diagnostics/bfdneighbors
plugin-dependentRouting (page-routing)wildcard; may include writes--
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaBgpNeighbors
GET api/quagga/diagnostics/bgpneighbors
plugin-dependentRouting (page-routing)wildcard; may include writes--
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaBgpSummary
GET api/quagga/diagnostics/bgpsummary
plugin-dependentRouting (page-routing)wildcard; may include writes--
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaGeneralRoute4
GET api/quagga/diagnostics/search_generalroute4
plugin-dependentRouting (page-routing)wildcard; may include writes--
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaGeneralRoute6
GET api/quagga/diagnostics/search_generalroute6
plugin-dependentRouting (page-routing)wildcard; may include writes--
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaOspfDatabase
GET api/quagga/diagnostics/ospfdatabase
plugin-dependentRouting (page-routing)wildcard; may include writes--
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaOspfInterface
GET api/quagga/diagnostics/ospfinterface
plugin-dependentRouting (page-routing)wildcard; may include writes--
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaOspfNeighbors
POST api/quagga/diagnostics/searchOspfneighbor
plugin-dependentRouting (page-routing)wildcard; may include writes--
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaOspfOverview
GET api/quagga/diagnostics/ospfoverview
plugin-dependentRouting (page-routing)wildcard; may include writes--
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaOspfRoute
GET api/quagga/diagnostics/search_ospfroute
plugin-dependentRouting (page-routing)wildcard; may include writes--
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaOspfv3Database
GET api/quagga/diagnostics/search_ospfv3database
plugin-dependentRouting (page-routing)wildcard; may include writes--
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaOspfv3Interface
GET api/quagga/diagnostics/ospfv3interface
plugin-dependentRouting (page-routing)wildcard; may include writes--
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaOspfv3Overview
GET api/quagga/diagnostics/ospfv3overview
plugin-dependentRouting (page-routing)wildcard; may include writes--
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaOspfv3Route
GET api/quagga/diagnostics/search_ospfv3route
plugin-dependentRouting (page-routing)wildcard; may include writes--
FRR Routing (BGP/OSPF/BFD)default-on (--exporter.disable-frr disables)plugin-gatedquaggaServiceStatus
GET api/quagga/service/status
plugin-dependentRouting (page-routing)wildcard; may include writes--
Relayd Load Balancerdefault-on (--exporter.disable-relayd disables)plugin-gatedrelaydStatusSum
GET api/relayd/status/sum
plugin-dependentServices: Relayd (page-services-relayd)wildcard; may include writes--
Network Diagnosticsopt-in (--exporter.enable-network-diagnostics)--routingTable
GET api/diagnostics/interface/get_routes
knownDiagnostics: Routing tables (page-diagnostics-routingtables)wildcard; may include writes--
Servicesdefault-on (--exporter.disable-services disables)--services
GET api/core/service/search
knownStatus: Services (page-status-services)wildcard; may include writes--
Siproxddefault-on (--exporter.disable-siproxd disables)plugin-gatedsiproxdRegistrations
GET api/siproxd/service/showregistrations
plugin-dependentServices: Siproxd (page-services-siproxd)wildcard; may include writes--
SMART Disk Healthopt-in (--exporter.enable-smart)plugin-gatedsmartInfo
POST api/smart/service/info
plugin-dependentServices: SMART (page-services-smart)wildcard; may include writes--
SMART Disk Healthopt-in (--exporter.enable-smart)plugin-gatedsmartList
POST api/smart/service/list
plugin-dependentServices: SMART (page-services-smart)wildcard; may include writes--
ZFS Boot Environmentsdefault-on (--exporter.disable-snapshots disables)--snapshotsIsSupported
GET api/core/snapshots/is_supported
knownSystem: Snapshots (page-snapshots)wildcard; may include writes--
ZFS Boot Environmentsdefault-on (--exporter.disable-snapshots disables)--snapshotsSearch
GET api/core/snapshots/search
knownSystem: Snapshots (page-snapshots)wildcard; may include writes--
Network Diagnosticsopt-in (--exporter.enable-network-diagnostics)--socketStatistics
GET api/diagnostics/interface/get_socket_statistics
knownDiagnostics: Netstat (page-diagnostics-netstat)wildcard; may include writes--
Syslogdefault-on (--exporter.disable-syslog disables)plugin-gatedsyslogServiceStatus
GET api/syslog/service/status
knownSystem: Settings: Logging (page-diagnostics-logs-settings-targets)wildcard; may include writes--
Syslogdefault-on (--exporter.disable-syslog disables)--syslogStats
GET api/syslog/service/stats
knownSystem: Settings: Logging (page-diagnostics-logs-settings-targets)wildcard; may include writes--
Activitydefault-on (--exporter.disable-activity disables)--systemActivity
GET api/diagnostics/activity/get_activity
knownDiagnostics: System Activity (page-diagnostics-system-activity)wildcard; may include writes--
Systemdefault-on (--exporter.disable-system disables)--systemDisk
GET api/diagnostics/system/systemDisk
unknownNo matched ACL; only page-allexactthe Core ACL grants the snake_case spelling api/diagnostics/system/system_disk (Lobby: Dashboard). OPNsense routes both spellings to the same action but matches the ACL against the raw request URI, so the camelCase URL the exporter registers is covered by no privilege except page-all.
Systemdefault-on (--exporter.disable-system disables)--systemInformation
GET api/diagnostics/system/system_information
knownLobby: Dashboard (page-system-login-logout)wildcard; may include writes--
Mbufdefault-on (--exporter.disable-mbuf disables)--systemMbuf
GET api/diagnostics/system/systemMbuf
unknownNo matched ACL; only page-allexactthe Core ACL grants api/diagnostics/system/system_mbuf (Lobby: Dashboard); the camelCase URL the exporter registers matches no privilege except page-all.
Kernel Memory (UMA zones and malloc types)default-on (--exporter.disable-kernel-memory disables)--systemMemory
GET api/diagnostics/system/memory
unknownNo matched ACL; only page-allexactthe Core ACL's Lobby: Dashboard privilege lists the seven api/diagnostics/system/system_* URLs individually and carries no wildcard; api/diagnostics/system/memory (SystemController::memoryAction) appears in no pattern in either audited core release, so it is covered by no privilege except page-all. Re-checked against core stable/26.7 and master on 2026-07-30.
Systemdefault-on (--exporter.disable-system disables)--systemResources
GET api/diagnostics/system/systemResources
unknownNo matched ACL; only page-allexactthe Core ACL grants api/diagnostics/system/system_resources (Lobby: Dashboard); the camelCase URL the exporter registers matches no privilege except page-all.
Systemdefault-on (--exporter.disable-system disables)--systemSwap
GET api/diagnostics/system/systemSwap
unknownNo matched ACL; only page-allexactthe Core ACL grants api/diagnostics/system/system_swap (Lobby: Dashboard); the camelCase URL the exporter registers matches no privilege except page-all.
Temperaturedefault-on (--exporter.disable-temperature disables)--systemTemperature
GET api/diagnostics/system/systemTemperature
unknownNo matched ACL; only page-allexactthe Core ACL grants api/diagnostics/system/system_temperature (Lobby: Dashboard); the camelCase URL the exporter registers matches no privilege except page-all.
Systemdefault-on (--exporter.disable-system disables)--systemTime
GET api/diagnostics/system/systemTime
unknownNo matched ACL; only page-allexactthe Core ACL grants api/diagnostics/system/system_time (Lobby: Dashboard); the camelCase URL the exporter registers matches no privilege except page-all.
Tailscaledefault-on (--exporter.disable-tailscale disables); high-cardinality opt-in (--exporter.enable-tailscale-peer-details)plugin-gatedtailscaleServiceStatus
GET api/tailscale/service/status
plugin-dependentTailscale (page-tailscale-config)wildcard; may include writes--
Tailscaledefault-on (--exporter.disable-tailscale disables); high-cardinality opt-in (--exporter.enable-tailscale-peer-details)plugin-gatedtailscaleStatus
GET api/tailscale/status/status
plugin-dependentTailscale (page-tailscale-config)wildcard; may include writes--
Toropt-in (--exporter.enable-tor)plugin-gatedtorCircuits
GET api/tor/service/circuits
plugin-dependenttor (page-tor)wildcard; may include writes--
Toropt-in (--exporter.enable-tor)plugin-gatedtorHiddenServices
GET api/tor/service/get_hidden_services
plugin-dependenttor (page-tor)wildcard; may include writes--
Toropt-in (--exporter.enable-tor)plugin-gatedtorStreams
GET api/tor/service/streams
plugin-dependenttor (page-tor)wildcard; may include writes--
Traffic Shaperdefault-on (--exporter.disable-trafficshaper disables)plugin-gatedtrafficShaperStatistics
GET api/trafficshaper/service/statistics
knownDiagnostics: Shaper status (page-diagnostics-limiter-info); Firewall: Shaper (page-firewall-trafficshaper)wildcard; may include writes--
Unbound DNSdefault-on (--exporter.disable-unbound disables); high-cardinality opt-in (--exporter.enable-unbound-infra)--unboundBlocklistPolicies
GET api/unbound/overview/get_policies
knownServices: Unbound (page-services-unbound); Status: DNS Overview (page-status-dnsoverview)wildcard; may include writes--
Unbound DNSdefault-on (--exporter.disable-unbound disables); high-cardinality opt-in (--exporter.enable-unbound-infra)--unboundDNSStatus
GET api/unbound/diagnostics/stats
knownServices: Unbound (page-services-unbound)wildcard; may include writes--
Unbound DNSdefault-on (--exporter.disable-unbound disables); high-cardinality opt-in (--exporter.enable-unbound-infra)--unboundInfra
GET api/unbound/diagnostics/dumpinfra
knownServices: Unbound (page-services-unbound)wildcard; may include writes--
Unbound DNSdefault-on (--exporter.disable-unbound disables); high-cardinality opt-in (--exporter.enable-unbound-infra)--unboundInsecureDomains
GET api/unbound/diagnostics/listinsecure
knownServices: Unbound (page-services-unbound)wildcard; may include writes--
Unbound DNSdefault-on (--exporter.disable-unbound disables); high-cardinality opt-in (--exporter.enable-unbound-infra)--unboundLocalData
GET api/unbound/diagnostics/listlocaldata
knownServices: Unbound (page-services-unbound)wildcard; may include writes--
Unbound DNSdefault-on (--exporter.disable-unbound disables); high-cardinality opt-in (--exporter.enable-unbound-infra)--unboundLocalZones
GET api/unbound/diagnostics/listlocalzones
knownServices: Unbound (page-services-unbound)wildcard; may include writes--
Unbound DNSdefault-on (--exporter.disable-unbound disables); high-cardinality opt-in (--exporter.enable-unbound-infra)--unboundQueryStatsEnabled
GET api/unbound/overview/is_enabled
knownServices: Unbound (page-services-unbound); Status: DNS Overview (page-status-dnsoverview)wildcard; may include writes--
Unbound DNSdefault-on (--exporter.disable-unbound disables); high-cardinality opt-in (--exporter.enable-unbound-infra)--unboundQueryStatsTotals
GET api/unbound/overview/totals/512
knownServices: Unbound (page-services-unbound); Status: DNS Overview (page-status-dnsoverview)wildcard; may include writes--
(log shipping)non-collector endpoint--unboundSearchQueries
POST api/unbound/overview/search_queries
knownServices: Unbound (page-services-unbound); Status: DNS Overview (page-status-dnsoverview)wildcard; may include writes--
Unbound DNSdefault-on (--exporter.disable-unbound disables); high-cardinality opt-in (--exporter.enable-unbound-infra)plugin-gatedunboundServiceStatus
GET api/unbound/service/status
knownServices: Unbound (page-services-unbound)wildcard; may include writes--
Vnstat Traffic Accountingopt-in (--exporter.enable-vnstat)plugin-gatedvnstatGetJsonData
GET api/vnstat/service/get_json_data
plugin-dependentServices: Vnstat (page-services-vnstat)wildcard; may include writes--
Vnstat Traffic Accountingopt-in (--exporter.enable-vnstat)plugin-gatedvnstatInterfaceList
GET api/vnstat/service/interface_list
plugin-dependentServices: Vnstat (page-services-vnstat)wildcard; may include writes--
Wireguarddefault-on (--exporter.disable-wireguard disables)--wireguardClients
GET api/wireguard/service/show
knownVPN: WireGuard: Configuration (page-wireguard-config); VPN: WireGuard: Status (page-wireguard-diagnostics)wildcard; may include writes--
Wireguarddefault-on (--exporter.disable-wireguard disables)plugin-gatedwireguardServiceStatus
GET api/wireguard/service/status
knownVPN: WireGuard: Configuration (page-wireguard-config); VPN: WireGuard: Status (page-wireguard-diagnostics)wildcard; may include writes--

401 and 403 remediation

For a 401 or 403, the exporter log and operator console identify the collector, endpoint, and likely privilege from this matrix. Grant the indicated privilege to the API key's user, then check System > Access > Users > Effective Privileges. The guidance never includes an API key, secret, authorization header, or response body.

TLS configuration

Using OPNsense with HTTPS

The exporter connects to OPNsense via HTTPS by default when --opnsense.protocol=https is set. For OPNsense instances using a certificate signed by a public CA, no additional configuration is needed.

Self-signed or private-CA certificates

If your OPNsense uses a self-signed certificate or one issued by a private CA, trust the CA where the exporter can see it. The recommended approach depends on how the exporter runs.

Host / bare binary (recommended for non-container installs)

On a normal Linux host the exporter uses the OS trust store. Add the OPNsense CA to it and refresh the bundle:

sudo cp opnsense-ca.crt /usr/local/share/ca-certificates/opnsense-ca.crt
sudo update-ca-certificates

This works only where update-ca-certificates (or your distro's equivalent) merges that directory into the system bundle. It does not apply to the official container image.

Container (official distroless image)

The official runtime image is distroless: it has no update-ca-certificates and does not merge /usr/local/share/ca-certificates into Go's trust roots, so mounting a certificate there leaves it untrusted. Instead mount the CA bundle at any path and point Go's TLS stack at it with SSL_CERT_FILE:

services:
  opnsense2otel:
    image: ghcr.io/rknightion/opnsense2otel:latest
    environment:
      SSL_CERT_FILE: /certs/opnsense-ca.pem
    volumes:
      - ./opnsense-ca.pem:/certs/opnsense-ca.pem:ro

See Custom CA certificates in the Docker deployment guide for the full example.

Disable TLS verification (not recommended)

--opnsense.insecure

Or via environment variable:

OPN2OTEL_OPS_INSECURE=true

Warning

Disabling TLS verification exposes the API key and secret to man-in-the-middle attacks. Only use this for testing or on trusted networks. When enabled, the exporter logs a startup warning: TLS certificate verification disabled (opnsense.insecure); API credentials and data are exposed to MITM risk.

Exporter TLS (web config)

The exporter itself can serve metrics over HTTPS using the Prometheus exporter toolkit's web configuration:

--web.config.file=/path/to/web-config.yml

Example web config:

web-config.yml
tls_server_config:
  cert_file: /path/to/cert.pem
  key_file: /path/to/key.pem

Avoid enabling the exporter toolkit's rate_limit option in the web config on listeners reachable by untrusted peers: it is a single pre-authentication global bucket, so any one client can exhaust it and starve legitimate Prometheus scrapes.

File-based secrets

For production deployments, avoid passing API credentials as command-line flags or plain environment variables. Instead, use file-based secrets:

Env VarDescription
OPS_API_KEY_FILEPath to a file containing the API key
OPS_API_SECRET_FILEPath to a file containing the API secret

The exporter reads the first line of each file. File-based secrets take precedence over flag/env var values when set.

Docker secrets example

services:
  opnsense2otel:
    image: ghcr.io/rknightion/opnsense2otel:latest
    environment:
      OPS_API_KEY_FILE: /run/secrets/opnsense-api-key
      OPS_API_SECRET_FILE: /run/secrets/opnsense-api-secret
    secrets:
      - opnsense-api-key
      - opnsense-api-secret

Kubernetes secrets example

env:
  - name: OPS_API_KEY_FILE
    value: /etc/opnsense2otel/creds/api-key
  - name: OPS_API_SECRET_FILE
    value: /etc/opnsense2otel/creds/api-secret
volumeMounts:
  - name: api-key-vol
    mountPath: /etc/opnsense2otel/creds
    readOnly: true

Systemd with file permissions

# Create credential files
# The exporter service user needs read access; unrelated users do not.
sudo install -d -o root -g opnsense2otel -m 0710 /etc/opnsense2otel
printf '%s\n' 'your-api-key' | sudo install -o root -g opnsense2otel -m 0640 /dev/stdin /etc/opnsense2otel/api-key
printf '%s\n' 'your-api-secret' | sudo install -o root -g opnsense2otel -m 0640 /dev/stdin /etc/opnsense2otel/api-secret

The directory's 0710 mode lets the service group traverse directly to the named files without listing the directory. Each 0640 file is readable only by root and the opnsense2otel group; unrelated users cannot traverse the directory.

OPNsense settings

One collector needs an extra OPNsense setting enabled:

  • Unbound DNS collector: Enable Unbound DNS > Advanced > Extended Statistics in the OPNsense web UI for full DNS metrics.

Container security

The official container image is hardened:

  • Distroless base image - minimal attack surface with no shell, package manager, or unnecessary binaries
  • Non-root execution - runs as UID 65532 (nonroot)
  • Read-only root filesystem - supported in Kubernetes and Docker
  • No capabilities - all Linux capabilities are dropped in the Kubernetes deployment manifest
  • Static binary - no runtime dependencies, CGO disabled

The /metrics endpoint requires no authentication by default, so restrict who can reach it at the network layer. On Kubernetes, a sample NetworkPolicy limiting ingress on the metrics port to Prometheus is provided at deploy/k8s/networkpolicy.yaml.