Observability

NetBird services emit runtime metrics via OpenTelemetry and expose them in Prometheus exposition format (with OpenMetrics 1.0.0 support). You can scrape these endpoints to monitor traffic, latency, peer activity, and the internal health of each service, and to render the Grafana dashboards NetBird ships.

This section documents what each service records, the default listening endpoint, and how to change it.

Service endpoints

Every server-side component exposes a /metrics HTTP endpoint. By default, Management, Signal, Relay, and Combined listen on port 9090; Proxy listens on port 8080.

ServiceDefault endpointHow to change
Managementhttp://0.0.0.0:9090/metrics--metrics-port flag
Signalhttp://0.0.0.0:9090/metrics--metrics-port flag
Relayhttp://0.0.0.0:9090/metrics--metrics-port flag
Proxyhttp://localhost:8080/metrics--health-addr flag / NB_PROXY_HEALTH_ADDRESS
Combinedhttp://0.0.0.0:9090/metricsserver.metricsPort in config.yaml

Combined deployments

In the combined container (the default for new installations via getting-started.sh), Management, Signal, and Relay all share one metrics server and one /metrics endpoint. The port is set with server.metricsPort in config.yaml (default 9090) — see Combined.

Multi-container deployments

In the older multi-container setup, each service runs its own metrics server. To avoid port collisions when colocating services on a single host, override --metrics-port per container, for example:

netbird-mgmt --metrics-port 9090
netbird-signal --metrics-port 9091
netbird-relay --metrics-port 9092

Exposition format

All endpoints return Prometheus text format with OpenMetrics support enabled:

curl http://localhost:9090/metrics

Naming conventions

NetBird services register metrics with OpenTelemetry instrument names (using dots as separators, e.g. management.grpc.sync.request.counter). The Prometheus exporter rewrites them on the way out:

  • Dots become underscores: management.grpc.sync.request.countermanagement_grpc_sync_request_counter.
  • Counters get a _total suffix unless the instrument name already ends in _total. So management.grpc.sync.request.countermanagement_grpc_sync_request_counter_total, while registrations_total stays registrations_total.
  • UpDownCounters and ObservableGauges are emitted as Prometheus gauge types. The name is unchanged (e.g. proxy_domains_count, relay_peers_active).
  • Histograms expand to three series — <name>_bucket, <name>_sum, <name>_count. When the instrument was registered with a unit (milliseconds, microseconds, bytes, …), that unit is appended to the base name unless the name already ends in it. So proxy.peer.add.duration.ms with unit milliseconds becomes proxy_peer_add_duration_ms_milliseconds_bucket, but relay_peer_authentication_time_milliseconds (no unit registered) stays relay_peer_authentication_time_milliseconds_bucket.

Service prefixes are baked into the OTel instrument names themselves:

  • Management metrics start with management_*.
  • Relay metrics start with relay_*.
  • Proxy metrics start with proxy_*.
  • Signal metrics are unprefixed when Signal runs standalone (active_peers, messages_forwarded_total, …). In the combined container they are emitted with a signal_ prefix (signal_active_peers, signal_messages_forwarded_total, …) so they don't collide with the other services on the shared /metrics endpoint.

The metric tables on the per-service pages show the on-the-wire Prometheus names, so you can copy them straight into a PromQL query.

You can scrape them with a standard Prometheus scrape_config:

scrape_configs:
  - job_name: 'netbird-management'
    static_configs:
      - targets: ['management.example.com:9090']
  - job_name: 'netbird-signal'
    static_configs:
      - targets: ['signal.example.com:9090']
  - job_name: 'netbird-relay'
    static_configs:
      - targets: ['relay.example.com:9090']
  - job_name: 'netbird-proxy'
    static_configs:
      - targets: ['proxy.example.com:8080']

Network exposure

Most metrics endpoints listen on all interfaces (0.0.0.0) and have no authentication; the Proxy endpoint listens on localhost by default. Restrict access at the firewall, reverse proxy, or service-mesh layer so that only your Prometheus scraper and operators can reach them.

Grafana dashboards

NetBird ships ready-to-use Grafana dashboards for Management, Signal, and Relay. See Dashboards for download links and required dashboard variables.