Releases
v2.0.0
Compare
Sorry, something went wrong.
No results found
2.0.0 (2026-07-04)
⚠ BREAKING CHANGES
smart: the SMART collector is now off by default. Set --exporter.enable-smart (env OPNSENSE_EXPORTER_ENABLE_SMART=true) to restore the opnsense_smart_* metrics.
arp,ndp: opnsense_arp_table_entries and opnsense_ndp_entries per-entry series are no longer emitted by default. Set --exporter.enable-arp-details / --exporter.enable-ndp-details to restore them; otherwise use the new opnsense_arp_table_entries_total / opnsense_ndp_entries_total aggregates.
interfaces: distinguish unknown link state from down so PPPoE WANs aren't reported down
when --exporter.instance-label is unset, the instance label now defaults to the configured OPNsense address rather than the API hostname. Set --exporter.instance-use-hostname to keep hostname-derived labels, or set --exporter.instance-label explicitly.
firewall: opnsense_firewall_interface_hits_total is renamed to opnsense_firewall_interface_log_entries_recent and changed from counter to gauge. Any user dashboards/alerts using rate()/increase() on the old name must switch to plotting the new gauge directly. The shipped dashboard is updated.
grafana: grafana/alerts/opnsense.rules.yaml is removed. Users loading that file into Prometheus/Mimir/the Grafana Cloud ruler should migrate to the Grafana-managed manifests under grafana/alerts/grafana-managed/ (gcx resources push).
Features
apicapture: resolve OPS_API_KEY_FILE/OPS_API_SECRET_FILE like the exporter (428353b ), closes #157
arp,ndp: gate per-entry metrics behind opt-in details flags (2ac1221 ), closes #125
collector: add disable switches for interfaces, protocol, services (ef94751 ), closes #143
config: make OPNsense API timeout and retry count configurable (045571f ), closes #140
docs: align docs site with m7kni.io brand + server-side SEO/LLM metadata (9bca073 ), closes #70
grafana: drop portable Prometheus rules format, ship Grafana-managed alerting only (2af458a ), closes #76 #95
metrics: add per-endpoint API request count and duration self-metrics (802c53a ), closes #126
security: warn at startup when --opnsense.insecure disables TLS verification (2d3914d ), closes #159
smart: make SMART collector opt-in (--exporter.enable-smart, default-off) (4c8af5c ), closes #139
Bug Fixes
activity: parse thread states independently so zombie/stopped states don't zero metrics (73ba3f8 ), closes #82
alerts: make OPNsenseEndpointErrors for:15m require sustained errors (586563a ), closes #94
apicontract: filter abstract-controller phantom endpoints from the manifest (9ab2ee9 ), closes #146
apicontract: isolate per-controller parse failures in extract.py (fca0054 ), closes #111
captiveportal: decode zones map serialized as a JSON array (27fef5b ), closes #73
carp: source VIP label from the subnet field and dedupe multi-address vhids (30641c1 ), closes #166
certificates: omit valid_from/valid_to for pending CSRs instead of epoch 0 (b80a1da ), closes #167
chrony: skip sources metrics on sub-fetch failure instead of false zero (4aed2cf ), closes #163
ci: match drift issue by label+title, not the broken bot-login filter (5944a81 ), closes #83
ci: surface api-contract verb-drift warnings instead of burying them (e8cfff8 ), closes #93
collector: bound no-deadline collections to stop a stalled box blackout (4baabb8 ), closes #128
collector: dedupe services/wireguard/ntp label tuples to prevent scrape-wide 500s (45e3403 ), closes #85
collector: distinguish deadline-expired skipped scrapes from completed ones (6664350 ), closes #122
collector: emit cumulative counters as CounterValue in firewall/ipsec/protocol (5621823 ), closes #106
collector: keep dhcpv4/acme/smart/dyndns silent when their plugin is absent (52a72d8 ), closes #87
collector: skip scalar metrics whose backing sub-call failed in pf-stats/system (47145c2 ), closes #91
collector: surface interfaces-overview fetch failures via success/errors (14d9190 ), closes #123
collector: use panic: sentinel on endpoint-errors label, not subsystem slug (86326fc ), closes #120
config: consistent env-var surface — telemetry-path envar + prefixed *_FILE aliases (6a4d64e ), closes #141
config: empty OPS_API_KEY_FILE/OPS_API_SECRET_FILE falls back to flag (9e56123 ), closes #109
config: reject empty/invalid --web.telemetry-path instead of panicking (945cfb4 ), closes #108
config: validate Pyroscope server-address scheme at startup (e328a7c ), closes #142
crowdsec: mark bouncers/machines absent on row decode failure instead of false zero (75c758f ), closes #104
dashboard: add $device variable so pf-traffic/netflow panels stop blanking (b8506a5 ), closes #98
dashboard: gate DHCP backend rows on presence, not lease count (2d16b13 ), closes #114
dashboard: key multi-query table renames/units on Value #A..N, not metric names (4800d96 ), closes #97
dashboard: match Exporter Runtime panels on job=~"opnsense.*", not hardcoded job (479560e ), closes #113
dashboard: scale epoch-seconds timestamps to ms for dateTimeAsIso panels (baacea2 ), closes #78
dashboard: show lease-expiry column in dnsmasq/Kea lease-detail tables (0dbfe5c ), closes #112
deps: update module github.com/grafana/pyroscope-go to v1.4.0 (#69 ) (fb582e6 )
deps: update module github.com/prometheus/exporter-toolkit to v0.17.0 (#62 ) (0783001 )
deps: update module github.com/prometheus/exporter-toolkit to v0.17.1 (#65 ) (77f9eb2 )
deps: update module google.golang.org/grpc to v1.82.0 (#63 ) (637e901 )
docgen: cover top-level Collector metrics + fatal on unparsed constructors (02a90a2 ), closes #119
docgen: derive metric Type from emission ValueType, not _total suffix (3dc7c1c ), closes #100
docgen: make doclint flag/env extraction shape-based and lint grafana tabs (f6fbbde ), closes #151
docker: rename build ARG Version→VERSION so published images embed the version (c92830e ), closes #79
docs: correct container UID to 65532 (distroless nonroot), not 65534 (44fa537 ), closes #115
docs: pin grafana/README tab list + alert/recording counts to generated data (53061bb ), closes #116
docs: pin sub-collector count (47) in CLAUDE.md + 3 docs pages, close drift gap (1774373 ), closes #117
docs: replace oversized gradient hero with a compact docs-friendly intro (fca3dc6 ), closes #70
firewall: filter pfctl pseudo-entries and strip mutable (skip) suffix from interface label (9009e04 ), closes #105
firewall: re-type interface hit count as a sliding-window gauge, not a counter (8b3fdfa ), closes #74
frr: make frrAFLabel lossless per SAFI to avoid duplicate BGP series (3fda9d2 ), closes #162
gateways: emit status for enabled monitor-disabled gateways (GatewayDown blind spot) (85a95ec ), closes #77
haproxy: omit HTTP response-code counters for tcp-mode proxies (4b6cc40 ), closes #164
interfaces: distinguish unknown link state from down so PPPoE WANs aren't reported down (cfd1d63 ), closes #86
interfaces: parse counter fields tolerantly so one bad field doesn't drop all interface metrics (b0f9ee0 ), closes #102
k8s: pin image tag and add seccomp/SA-token hardening to example manifest (7f5df45 ), closes #147
k8s: raise example scrapeTimeout to 30s and use resolvable Service DNS (393f998 ), closes #99
main: gracefully drain HTTP server on SIGTERM/SIGINT instead of os.Exit(0) (123b774 ), closes #161
make: pass API creds to local-run/capture via env, not world-readable argv (8729693 ), closes #160
ntp: parse unit-suffixed ntpq when/poll intervals instead of coercing to 0 (f9001f0 ), closes #89
openvpn: count only real client rows as sessions (a0b9c70 ), closes #88
opnsense: widen byte/packet counter fields to int64 for 32-bit source builds (4ef3662 ), closes #103
otlp: close three config-validation gaps that silently break export (dcd76f3 ), closes #92
otlp: isolate gatherers so one bad collector can't black out export (ab0fdcc ), closes #101
otlp: post to the /v1/metrics signal path for base-URL endpoints (22d841e ), closes #80
profiling: flush final Pyroscope window on shutdown instead of dropping it (962bead ), closes #121
protocol: expose IPv6/ICMPv6 stats instead of silently dropping them (579a2b2 ), closes #165
resilience: short-circuit when firewall unreachable + backoff/jitter retries (d228260 ), closes #127
resolve instance label deterministically instead of via a startup race (3ec7122 ), closes #75
server,collectors: stop duplicate label tuples from 500-ing the whole scrape (6980c93 ), closes #81
server: reject NaN/Inf/absurd scrape-timeout header values (c8e574b ), closes #124
system: correct DST-transition skew in uptime and config_last_change (f49edc2 ), closes #107
unbound: capture all RR query types, not a fixed 16-field whitelist (6b955fd ), closes #138
unbound: skip stats series when unbound-control is unavailable (c6b652e ), closes #90
unbound: stop clamp_min(denom,1) collapsing cache hit ratio below 1 qps (0381b26 ), closes #96
Performance
mbuf: read extended fields from systemMbuf, skip redundant API call (3712561 ), closes #137
opnsense: parallelize independent multi-endpoint Fetch functions (baa4964 ), closes #129
Miscellaneous
deps: update anthropics/claude-code-action action to v1.0.160 (#61 ) (4966911 )
deps: update anthropics/claude-code-action action to v1.0.161 (#64 ) (511cee1 )
deps: update anthropics/claude-code-action action to v1.0.162 (#66 ) (a442589 )
deps: update anthropics/claude-code-action action to v1.0.163 (#71 ) (5196a33 )
deps: update docker/build-push-action action to v7.3.0 (#67 ) (54eba0e )
deps: update docker/setup-buildx-action action to v4.2.0 (#68 ) (4b6eb3e )
deps: update module github.com/anchore/syft to v1.46.0 (#169 ) (0960135 )
deps: update module github.com/anchore/syft/cmd/syft to v1.46.0 (#170 ) (7a86913 )
deps: update module github.com/google/go-licenses to v2 (#171 ) (c10f69e )
docs: remove committed zensical site/ build output and gitignore it (224998e ), closes #152
remove Snyk from CI (0c80fcf )
Documentation
apicontract: correct false "live-box stage (P3)" exemption claim (7b777a1 ), closes #110
drop false promhttp_* claim from --web.disable-exporter-metrics help (360e12d ), closes #149
firmware: correct misleading needs_reboot help text (1d66d54 ), closes #168
geo: content-shape pass for LLM/search retrievability (eb025ae )
mark shipped collectors COMPLETED in stale todos.txt (7fe6e8b ), closes #158
troubleshooting: flag the activity collector as the top scrape-latency cost (6be042e ), closes #150
Build & Infrastructure
docker: digest-pin the golang builder image + Renovate pinDigests (b6069f8 ), closes #148
Tests
contract: derive postEndpoints from POST call sites to catch drift (2e54b96 ), closes #145
contract: extend response-shape contracts beyond healthCheck (dabe778 ), closes #144
main: gate that every collector disable switch is wired in main.go (4f99761 ), closes #153
opnsense: drop duplicated testEndpoints(), build test clients from defaultEndpoints() (386aa39 ), closes #154
opnsense: pin hasync single-node {"response": false} shape (ed8dec9 ), closes #156
opnsense: use raw JSON fixtures for services/arp/ntp/carp instead of mustMarshal(struct) (10b1831 ), closes #155
CI/CD
add OpenSSF Scorecard via shared reusable workflow (3759427 )
bump shared rknightion reusables v1.0.0 -> v1.3.1 (f8c2fa0 )
drop CodeQL pull_request trigger to trim Actions fan-out (3bb206c )
grafana: enforce dashboard coverage, regen freshness & manifest validity (311267e ), closes #84
lint: pin golangci-lint version and enforce gofmt in CI (ee2e1c2 ), closes #132
release: fall back to github.token when RELEASE_PLEASE_TOKEN is absent (7aa5d42 ), closes #131
remove claude issue-triage workflow (b70aa01 )
remove dead build-telemetry OTEL config referencing non-existent secrets (03a748d ), closes #133
remove notify-maintainer-on-new-issue workflow (91e343f )
renovate: track pinned syft / go-licenses versions via custom managers (65b3e38 ), closes #135
run extract_test.py parser-contract tests in the api-contract job (457802b ), closes #136
security: narrow api-contract-enrich agent gh allowlist + document ingress (e34e288 ), closes #134
security: pin opnsense/docs SHA and parser pip deps in api-contract (b2cf72e ), closes #130
You can’t perform that action at this time.