Monitor nginx performance with Prometheus and Grafana using nginx-prometheus-exporter

Intermediate 25 min Apr 25, 2026 19 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up comprehensive nginx monitoring with Prometheus and Grafana dashboards. Configure nginx stub_status, deploy nginx-prometheus-exporter, and create production-ready alerts for web server performance metrics.

Prerequisites

  • Root access to server
  • Basic nginx knowledge
  • Understanding of web server metrics

What this solves

This tutorial sets up comprehensive nginx monitoring using Prometheus and Grafana. You'll configure nginx to expose performance metrics, deploy nginx-prometheus-exporter to collect them, and create dashboards that track requests, response times, active connections, and server health in real time.

Step-by-step configuration

Update system packages

Start by updating your package manager to ensure you have the latest versions available.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install nginx if not already present

Install nginx web server if you don't have it running already.

sudo apt install -y nginx
sudo dnf install -y nginx

Configure nginx stub_status module

Enable nginx's built-in stub_status module to expose basic performance metrics. This creates an endpoint that shows active connections, requests, and server statistics.

server {
    listen 8080;
    server_name localhost;
    
    location /nginx_status {
        stub_status on;
        access_log off;
        allow 127.0.0.1;
        allow 10.0.0.0/8;
        allow 172.16.0.0/12;
        allow 192.168.0.0/16;
        deny all;
    }
}

Enable the status configuration

Link the status configuration to sites-enabled and test the nginx configuration for syntax errors.

sudo ln -s /etc/nginx/sites-available/nginx-status /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Test nginx status endpoint

Verify that nginx is exposing metrics correctly by testing the status endpoint.

curl http://localhost:8080/nginx_status

You should see output similar to:

Active connections: 1 
server accepts handled requests
 1 1 1 
Reading: 0 Writing: 1 Waiting: 0

Install nginx-prometheus-exporter

Download and install the nginx-prometheus-exporter binary. This tool scrapes nginx metrics and converts them to Prometheus format.

cd /tmp
wget https://github.com/nginxinc/nginx-prometheus-exporter/releases/download/v1.1.0/nginx-prometheus-exporter_1.1.0_linux_amd64.tar.gz
tar -xzf nginx-prometheus-exporter_1.1.0_linux_amd64.tar.gz
sudo mv nginx-prometheus-exporter /usr/local/bin/
sudo chmod +x /usr/local/bin/nginx-prometheus-exporter

Create nginx exporter user

Create a dedicated system user for the nginx exporter service for security isolation.

sudo useradd --no-create-home --shell /bin/false nginx-exporter

Create systemd service file

Create a systemd service file to manage the nginx-prometheus-exporter as a system service.

[Unit]
Description=NGINX Prometheus Exporter
After=network.target
Wants=network.target

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

[Install]
WantedBy=multi-user.target

Start and enable nginx exporter

Start the nginx exporter service and enable it to start automatically on boot.

sudo systemctl daemon-reload
sudo systemctl enable --now nginx-exporter
sudo systemctl status nginx-exporter

Test nginx exporter metrics

Verify that the exporter is working by checking the Prometheus metrics endpoint.

curl http://localhost:9113/metrics | grep nginx

You should see metrics like nginx_connections_active, nginx_http_requests_total, and nginx_connections_handled.

Install Prometheus

Download and install Prometheus to collect metrics from the nginx exporter.

cd /tmp
wget https://github.com/prometheus/prometheus/releases/download/v2.48.0/prometheus-2.48.0.linux-amd64.tar.gz
tar -xzf prometheus-2.48.0.linux-amd64.tar.gz
sudo mv prometheus-2.48.0.linux-amd64 /opt/prometheus
sudo ln -s /opt/prometheus/prometheus /usr/local/bin/prometheus

Create Prometheus user and directories

Set up the Prometheus user and required directories with correct permissions.

sudo useradd --no-create-home --shell /bin/false prometheus
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo chown prometheus:prometheus /var/lib/prometheus
sudo chown prometheus:prometheus /etc/prometheus

Configure Prometheus

Create Prometheus configuration to scrape metrics from the nginx exporter and Prometheus itself.

global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "nginx_rules.yml"

alerting:
  alertmanagers:
    - static_configs:
        - targets: []

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']
  
  - job_name: 'nginx'
    static_configs:
      - targets: ['localhost:9113']
    scrape_interval: 5s
    metrics_path: /metrics

Create nginx alerting rules

Define alerting rules for nginx performance monitoring and availability checks.

groups:
  - name: nginx_alerts
    rules:
      - alert: NginxDown
        expr: up{job="nginx"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Nginx exporter is down"
          description: "Nginx prometheus exporter has been down for more than 1 minute"
      
      - alert: NginxHighConnections
        expr: nginx_connections_active > 100
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "High nginx connections"
          description: "Nginx has {{ $value }} active connections"
      
      - alert: NginxHighRequestRate
        expr: rate(nginx_http_requests_total[5m]) > 100
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "High nginx request rate"
          description: "Nginx request rate is {{ $value }} requests per second"

Set configuration file permissions

Set correct ownership for Prometheus configuration files.

sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml
sudo chown prometheus:prometheus /etc/prometheus/nginx_rules.yml

Create Prometheus systemd service

Create systemd service file for Prometheus with security hardening options.

[Unit]
Description=Prometheus Server
Documentation=https://prometheus.io/docs/
After=network-online.target

[Service]
User=prometheus
Group=prometheus
Type=simple
Restart=on-failure
ExecStart=/usr/local/bin/prometheus \
  --config.file=/etc/prometheus/prometheus.yml \
  --storage.tsdb.path=/var/lib/prometheus \
  --web.console.templates=/opt/prometheus/consoles \
  --web.console.libraries=/opt/prometheus/console_libraries \
  --web.listen-address=0.0.0.0:9090 \
  --web.enable-lifecycle \
  --log.level=info

[Install]
WantedBy=multi-user.target

Start Prometheus service

Start Prometheus and enable it to run automatically on system boot.

sudo systemctl daemon-reload
sudo systemctl enable --now prometheus
sudo systemctl status prometheus

Install Grafana

Add Grafana repository and install Grafana for creating monitoring dashboards.

sudo apt install -y software-properties-common wget
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
sudo apt update
sudo apt install -y grafana
sudo tee /etc/yum.repos.d/grafana.repo << 'EOF'
[grafana]
name=grafana
baseurl=https://packages.grafana.com/oss/rpm
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://packages.grafana.com/gpg.key
EOF
sudo dnf install -y grafana

Start Grafana service

Enable and start Grafana service on port 3000.

sudo systemctl enable --now grafana-server
sudo systemctl status grafana-server

Configure firewall rules

Open firewall ports for Prometheus and Grafana web interfaces.

sudo ufw allow 3000/tcp
sudo ufw allow 9090/tcp
sudo ufw reload
sudo firewall-cmd --permanent --add-port=3000/tcp
sudo firewall-cmd --permanent --add-port=9090/tcp
sudo firewall-cmd --reload

Access Grafana and add Prometheus data source

Open Grafana in your browser and configure Prometheus as a data source. The default login is admin/admin.

Navigate to http://your-server-ip:3000 and log in. Go to Configuration > Data Sources > Add data source > Prometheus. Set the URL to http://localhost:9090 and click Save & Test.

Create nginx dashboard

Create a comprehensive dashboard with nginx performance panels. Go to Create > Dashboard > Add new panel and use these queries:

Panel NameQueryDescription
Active Connectionsnginx_connections_activeCurrent active connections
Request Raterate(nginx_http_requests_total[5m])Requests per second
Connection Statesnginx_connections_reading, nginx_connections_writing, nginx_connections_waitingConnection breakdown
Total Requestsnginx_http_requests_totalCumulative request count

Verify your setup

Check that all services are running correctly and metrics are being collected.

sudo systemctl status nginx nginx-exporter prometheus grafana-server
curl http://localhost:8080/nginx_status
curl http://localhost:9113/metrics | grep nginx_connections_active
curl http://localhost:9090/api/v1/query?query=up

Generate some traffic to test monitoring:

for i in {1..100}; do curl -s http://localhost/ > /dev/null; done

Common issues

SymptomCauseFix
nginx_status returns 403IP not allowed in allow listAdd your IP to nginx status config allow directives
nginx-exporter connection refusednginx status endpoint not accessibleCheck nginx status config and restart nginx
Prometheus targets downFirewall blocking ports or services not runningCheck service status and firewall rules
Grafana shows no dataPrometheus data source misconfiguredVerify Prometheus URL in Grafana data source settings
Permission denied errorsIncorrect file ownershipRun sudo chown prometheus:prometheus /etc/prometheus/*

Next steps

Running this in production?

Want this handled for you? Setting this up once is straightforward. Keeping it patched, monitored, backed up and performant across environments is the harder part. See how we run infrastructure like this for European teams.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle managed devops services for businesses that depend on uptime. From initial setup to ongoing operations.