NG

NGINX Prometheus Exporter

Official Prometheus exporter for NGINX and NGINX Plus

Monitoring & Status ★ 2k stars Easy setup Apache-2.0

NGINX Prometheus Exporter is the official exporter that scrapes the NGINX stub status or the NGINX Plus API and exposes connection, request, and upstream metrics for Prometheus. It is widely used to monitor reverse proxy and web server health.

Key features

  • Stub status and Plus API support
  • Connection and request metrics
  • Upstream health for NGINX Plus
  • Single static binary

Pros & cons

Strengths

  • Maintained by NGINX team
  • Trivial to deploy

Trade-offs

  • Limited metrics from stub status
  • Best detail needs NGINX Plus

NGINX Prometheus Exporter replaces

Last reviewed Sep 13, 2026 · 774 words

Open-source NGINX exposes exactly 7 counters through stub_status, and NGINX Prometheus Exporter turns those 7 into Prometheus series and nothing more. Active connections, accepted, handled, reading, writing, waiting, and total requests. No per-virtual-host split, no status codes, no upstream health, no latency. If your question is "is nginx alive and is it saturating", this exporter answers it in 64 MB of RAM with no configuration beyond a URL. If your question is "which site is returning 502s", it cannot answer, and pretending otherwise is how people end up with a dashboard that looks fine during an outage.

Turn on stub_status first, and keep it private

The exporter scrapes an HTTP endpoint that nginx does not expose by default. Add a small server block bound to a port nobody outside can reach:

server {
    listen 127.0.0.1:8080;
    location /stub_status {
        stub_status;
        allow 127.0.0.1;
        allow 172.16.0.0/12;
        deny all;
    }
}

Confirm with curl http://127.0.0.1:8080/stub_status that you see the "Active connections" block, and confirm nginx -V 2>&1 | grep -o with-http_stub_status_module prints something; distribution and official Docker builds include the module, but some minimal builds do not. The allow list needs your Docker bridge range if the exporter runs as a container, which is the single most common reason the exporter reports nginx_up 0.

The exporter: one flag and one port

services:
  nginx-exporter:
    image: nginx/nginx-prometheus-exporter:latest
    command:
      - --nginx.scrape-uri=http://nginx:8080/stub_status
    ports:
      - "9113:9113"
    restart: unless-stopped

Metrics are on port 9113 at /metrics. The scrape target in Prometheus is the exporter, not nginx. There is nothing else to configure for open-source nginx; the remaining flags exist for NGINX Plus, TLS to the status endpoint, and the metrics listen address. The catalogue's "trivial to deploy" is accurate.

What the 7 numbers tell you

nginx_connections_active against worker_processes * worker_connections tells you how close to the connection ceiling you are, and a sustained figure above 70 percent is the alert worth keeping. nginx_connections_accepted minus nginx_connections_handled should be zero; a growing gap means nginx is refusing connections, usually because of that same ceiling or a file descriptor limit. rate(nginx_http_requests_total[5m]) is your request rate, and a sudden drop to zero with nginx_up 1 means the thing behind nginx died, not nginx. nginx_connections_waiting is keepalive connections idling; a high number is normal and not a problem. That is the useful vocabulary, and it fits on one dashboard row.

Three ways to get status codes and per-site metrics

The exporter's own answer is NGINX Plus, whose API exposes per-zone requests, response codes, upstream health checks and cache statistics, and the same binary reads it with --nginx.plus. That is a commercial licence and not where most self-hosters go.

The second route is the VTS module, a third-party nginx module that adds per-server and per-upstream counters with status codes and has its own exporter. It gives the richest data but requires compiling nginx with the module, which means maintaining your own build.

The third and most practical is a log-based exporter: point a tool such as prometheus-nginxlog-exporter at the access log with a format that includes $status, $request_time and $upstream_response_time, and you get status-code counts and latency histograms per virtual host with no change to the nginx binary. It costs a log parse per request and a few more series, and for a self-hoster it is the route I would take.

The proxies that make this moot

Caddy exposes a Prometheus endpoint natively with per-host request and status-code metrics. Traefik does the same with one line of config, including per-router and per-service latency histograms. If you have not committed to nginx and metrics matter to you, the reverse proxy comparison is worth reading before you build monitoring around a 7-counter endpoint. nginx remains the right choice for a lot of workloads; its observability is just an older design.

What I'd do

Run the exporter on every nginx you own, because it is free, and keep one alert on active connections against the ceiling and one on nginx_up. Pair it with Node Exporter on the same host so the connection numbers sit next to CPU and file descriptors. The day someone asks which site is throwing errors, add a log-based exporter rather than fighting the stub_status limits, and the day you rebuild the proxy layer, let Caddy or Traefik give you the numbers for nothing.

Similar monitoring & status apps