Skip to main content

NGINX

This guide collects metrics, traces, and logs from NGINX using three approaches: the nginx-prometheus-exporter for stub_status metrics, nginx-module-otel for distributed traces, and the filelog receiver for access and error logs. All telemetry is shipped to base14 Scout through the OTel Collector.

Prerequisites

RequirementMinimumRecommended
NGINX1.191.24+
nginx-prometheus-exporter1.5.1latest
OTel Collector Contrib0.90.0latest
base14 ScoutAny-

Before starting:

What You'll Monitor

  • Metrics: active connections, accepted/handled connections, request rate, reading/writing/waiting states
  • Traces: distributed request traces with upstream propagation
  • Logs: access logs and error logs

Collecting metrics

Step 1: Expose stub_status metrics from nginx

Add the following server block inside the http block of your nginx.conf:

nginx.conf
http {
# ... your existing config ...

server {
listen 8080;
server_name localhost;

location /status {
stub_status;
allow 127.0.0.1;
deny all;
}
}
}
warning

The server block must be placed inside the http block. Placing it outside will result in: "server" directive is not allowed here

Test and reload nginx:

sudo nginx -t && sudo systemctl reload nginx

Verify the status endpoint is working:

curl http://127.0.0.1:8080/status

Step 2: Install and run the nginx prometheus exporter

Download the exporter from the nginx-prometheus-exporter releases page.

curl -LO https://github.com/nginx/nginx-prometheus-exporter/releases/download/v1.5.1/nginx-prometheus-exporter_1.5.1_linux_amd64.tar.gz
tar xzf nginx-prometheus-exporter_1.5.1_linux_amd64.tar.gz
sudo mv nginx-prometheus-exporter /usr/local/bin/

Create a systemd service to run the exporter:

/etc/systemd/system/nginx-prometheus-exporter.service
sudo tee /etc/systemd/system/nginx-prometheus-exporter.service > /dev/null <<'EOF'
[Unit]
Description=Nginx Prometheus Exporter
After=network.target nginx.service

[Service]
Type=simple
ExecStart=/usr/local/bin/nginx-prometheus-exporter --nginx.scrape-uri=http://127.0.0.1:8080/status
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

Start the exporter:

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

Verify metrics are being exported:

curl http://127.0.0.1:9113/metrics

Step 3: Add the following receiver in your Scout collector

config/otel-collector.yaml
prometheus/nginx:
config:
scrape_configs:
- job_name: nginx
scrape_interval: 5s
metrics_path: /metrics
static_configs:
- targets: ["0.0.0.0:9113"]

Note: Make sure you add prometheus/nginx to the receivers in your metrics pipeline as well.

Now the metrics are scraped from nginx.

Collecting traces

Step 1: Install the nginx OTel module

Download and install the pre-built .deb package from the nginx-otel-build releases.

curl -LO https://github.com/base-14/nginx-otel-build/releases/download/v0.1.1/ubuntu24.04-nginx1.24.0-amd64.deb
sudo apt install ./ubuntu24.04-nginx1.24.0-amd64.deb
warning

Take a backup of your nginx config before installing the module. It might be overwritten by the module installation.

Step 2: Configure nginx to send traces

Add the following configs in your nginx.conf file:

nginx.conf
load_module modules/ngx_otel_module.so;

http {
otel_exporter {
endpoint 0.0.0.0:4317;
}
otel_service_name nginx;
otel_resource_attr environment <deployment-environment>;
otel_trace on;
otel_trace_context inject;
}

Note: replace otel_service_name and otel_resource_attr with actual values.

Now the traces will be sent to the Scout Collector.

Collecting logs

Step 1: Add the filelog receiver to collect the logs

config/otel-collector.yaml
receivers:
filelog/nginx:
include:
- /var/log/nginx/*.log
start_at: beginning

Note: If you have configured log collection location to a custom directory, update the include block with the correct path.

note

The OTel Collector process needs read access to the NGINX log files. If you see permission errors, add the otelcol-contrib user to the group that owns the log files:

sudo usermod -aG <log-file-group> otelcol-contrib

Replace <log-file-group> with the group that owns your NGINX log directory (commonly adm or www-data). Restart the collector after making this change.

Verify the Setup

After configuring all three collection methods, verify each is working:

# Check metrics are being scraped from the exporter
curl -s http://127.0.0.1:9113/metrics | head -10

# Check Collector logs for nginx metrics
docker logs otel-collector 2>&1 | grep -i "nginx"

# Verify stub_status is responding
curl http://127.0.0.1:8080/status

Troubleshooting

stub_status returns 403 Forbidden

Cause: The allow directive in the status location block restricts access.

Fix:

  1. Add the Collector's IP to the allow list in the location /status block
  2. For Docker setups, add the container network CIDR (e.g., allow 172.16.0.0/12;)
  3. Reload NGINX: sudo nginx -t && sudo systemctl reload nginx

No metrics on port 9113

Cause: The nginx-prometheus-exporter is not running or cannot reach the stub_status endpoint.

Fix:

  1. Check exporter status: systemctl status nginx-prometheus-exporter or docker ps | grep exporter
  2. Verify stub_status is accessible: curl http://127.0.0.1:8080/status
  3. Check exporter logs for connection errors

Traces not appearing in Scout

Cause: The OTel module is not loaded or the exporter endpoint is wrong.

Fix:

  1. Verify the module is loaded: nginx -V 2>&1 | grep otel
  2. Confirm otel_exporter endpoint points to the Collector's gRPC port (4317)
  3. Check Collector logs for incoming trace data: docker logs otel-collector 2>&1 | grep traces

FAQ

Does this work with NGINX running in Kubernetes?

Yes. Deploy the nginx-prometheus-exporter as a sidecar container and point the Collector's Prometheus scrape config at the sidecar. For traces, include the OTel module in your NGINX container image.

Can I use NGINX Plus instead of open-source NGINX?

NGINX Plus provides a richer metrics API at /api/. Use the nginxplusreceiver in OTel Collector Contrib instead of the Prometheus exporter approach described here.

Why are there three separate collection methods?

NGINX does not expose all telemetry through a single interface. Metrics come from stub_status via the exporter, traces require the OTel module, and logs are read from files. Each requires its own receiver in the Collector pipeline.

What's Next?

  • Create Dashboards: Explore pre-built dashboards or build your own. See Create Your First Dashboard
  • Monitor More Components: Add monitoring for Apache HTTP Server, HAProxy, and other components
  • Fine-tune Collection: Adjust scrape intervals and log paths based on your deployment
Was this page helpful?