Architecture#

Nginx :8080/nginx_status
    ↓  scrape
nginx-prometheus-exporter :9113/metrics   [systemd]
    ↓  scrape
vmagent :8429                             [systemd, already running]
    ↓  remote_write
vminsert :8480  →  vmstorage :8400        [systemd, already running]

Grafana :3000  →  vmselect :8481          [already running]

Prerequisites: VictoriaMetrics cluster (vmstorage, vminsert, vmselect, vmagent) and Grafana are already running. See VictoriaMetrics Cluster Setup.


Step 1 — Enable nginx stub_status#

Add a dedicated server block that only exposes the status endpoint on localhost:

# /etc/nginx/conf.d/stub_status.conf
server {
    listen 8080;
    server_name localhost;

    location /nginx_status {
        stub_status;
        allow 127.0.0.1;
        deny all;
    }
}
sudo nginx -t && systemctl reload nginx

Verify:

curl http://localhost:8080/nginx_status
# Active connections: 3
# server accepts handled requests
#  10 10 15
# Reading: 0 Writing: 1 Waiting: 2
Field Meaning
Active connections currently open client connections
accepts total accepted connections (lifetime counter)
handled total handled connections — drops = accepts − handled
requests total HTTP requests (lifetime counter)
Reading workers reading request headers
Writing workers writing response to client
Waiting keep-alive idle connections

Step 2 — Install nginx-prometheus-exporter#

The exporter translates the stub_status plaintext into Prometheus-format metrics at :9113/metrics.

Download binary:

wget https://github.com/nginxinc/nginx-prometheus-exporter/releases/latest/download/nginx-prometheus-exporter_linux_amd64.tar.gz
tar xzf nginx-prometheus-exporter_linux_amd64.tar.gz
sudo install -m 755 nginx-prometheus-exporter /usr/local/bin/nginx-prometheus-exporter

Create systemd service:

# /etc/systemd/system/nginx-prometheus-exporter.service
[Unit]
Description=Nginx Prometheus Exporter
After=network.target

[Service]
Type=simple
User=victoriametrics
Group=victoriametrics
ExecStart=/usr/local/bin/nginx-prometheus-exporter \
    --nginx.scrape-uri=http://localhost:8080/nginx_status \
    --web.listen-address=:9113
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now nginx-prometheus-exporter

Verify metrics:

curl -s http://localhost:9113/metrics | grep nginx
# nginx_connections_active 3
# nginx_connections_reading 0
# nginx_connections_waiting 2
# nginx_connections_writing 1
# nginx_http_requests_total 15
# nginx_up 1

Metrics exposed:

Metric Type Description
nginx_up Gauge 1 if nginx is reachable
nginx_connections_active Gauge currently active connections
nginx_connections_accepted_total Counter total accepted connections
nginx_connections_handled_total Counter total handled connections
nginx_connections_reading Gauge reading request headers
nginx_connections_writing Gauge writing response
nginx_connections_waiting Gauge keep-alive idle
nginx_http_requests_total Counter total HTTP requests

Step 3 — Add nginx job to vmagent scrape config#

Add the nginx exporter as a scrape target in /etc/vmagent/scrape.yml:

scrape_configs:
  # ... existing jobs (vmstorage, vminsert, vmselect, vmagent) ...

  - job_name: nginx
    static_configs:
      - targets: ['localhost:9113']

Reload vmagent to pick up the new config (sends SIGHUP):

sudo systemctl reload vmagent

Verify vmagent is scraping nginx:

# Check target status
curl -s http://localhost:8429/targets | grep nginx

Or open http://localhost:8429/targets in a browser — the nginx job should show state: up.


References#