How to monitor Nginx

Monitor Nginx from outside and inside. Outside, an HTTP check per site catches downtime, slow responses and expiring certificates. Inside, watch the 5xx rate and upstream errors in the access and error logs, active connections against worker_connections, and the nginx service itself. Vigil's agent parses the access log automatically and alerts on error rate.

Updated · by PuzariCloud · commands checked against current releases

What can go wrong with Nginx

  • 502 Bad Gateway. The upstream (your app) refused the connection or died mid-response. The error log says connect() failed (111: Connection refused) while connecting to upstream.
  • 504 Gateway Timeout. The upstream accepted the request but did not answer within proxy_read_timeout (60 s by default): upstream timed out (110: Connection timed out).
  • Out of worker connections. Each worker handles worker_connections (often 512 or 1024) connections, including those to upstreams. When they run out the error log says worker_connections are not enough and clients see resets.
  • A bad reload. A config error makes nginx -s reload fail and the old config keeps running, so nothing looks wrong until the next full restart fails to start at all.
  • Certificate not reloaded. Certbot renewed the file but Nginx still serves the old certificate from memory until it is reloaded.

The signals that matter, with alert thresholds

SignalAlert whenWhy it matters
HTTP status and latency per sitenon-2xx/3xx, or p95 > 1 sWhat users see.
5xx share of requests> 5% over at least 20 requestsUpstream trouble even when the home page is fine.
502/504 lines in the error log> 10 per minuteWhich upstream is failing.
Active connections> 80% of workers × worker_connectionsHeadroom before resets.
Certificate days left≤ 14Renewal or reload is broken.
nginx servicenot activeDown on this host.

Thresholds are starting points. Tune them after a week of data: an alert nobody acts on should be raised or removed.

How to check Nginx by hand

Test the config before reloading, and dump what is loaded
sudo nginx -t
sudo nginx -T | less
Service state
systemctl status nginx
Upstream errors in the last hour
sudo grep -E 'upstream timed out|Connection refused|worker_connections are not enough' /var/log/nginx/error.log | tail -20
5xx count in the current access log
awk '$9 ~ /^5/' /var/log/nginx/access.log | wc -l
Connections via stub_status (needs the location below)
curl -s http://127.0.0.1/nginx_status

Enable the status page with location = /nginx_status { stub_status; allow 127.0.0.1; deny all; }. The awk one-liner assumes the default combined log format, where the status is field 9.

How to watch Nginx with Vigil

  1. In New monitor create an Uptime monitor for every site Nginx serves. SSL expiry is included (alert at 14 days by default), and a weekly security scan grades HSTS, CSP, cookies and TLS versions.
  2. Add the host under Servers and run the one-line installer it shows (curl -fsSL https://puzaricloud.in/install-server-agent.sh | sh -s -- --token <token>). The agent is one Python file with no dependencies; CPU, memory, disk, inode and load rules start working with the first report. The agent reads /var/log/nginx/access.log automatically.
  3. The server's APIs & traffic tab shows each endpoint's request rate, 5xx share and p95. The default rule alerts when more than 5% of at least 20 requests fail; set a p95 limit too if latency matters.
  4. Add nginx to the systemd services to watch, and the error-log watches below. Counts become log:<name> metrics you can limit (log:nginx_upstream_errors = 10).
  5. Running the nginx-prometheus-exporter? Add it under Prometheus exporters to scrape; an automatic NGINX dashboard appears.
/etc/vigil-agent.json (add to the existing keys)
{
  "log_watch": [
    {"name": "nginx_upstream_errors", "path": "/var/log/nginx/error.log", "pattern": "upstream timed out|Connection refused"},
    {"name": "nginx_worker_limit", "path": "/var/log/nginx/error.log", "pattern": "worker_connections are not enough"}
  ],
  "commands": {
    "nginx_active": "curl -s http://127.0.0.1/nginx_status | awk '/Active connections/ {print $3}'"
  }
}

Every alert goes to the channels you pick: email, Slack, Telegram, Discord, Microsoft Teams, Pushover, webhooks or on-call paging. Failures are confirmed by a second check before anyone is woken up.

Nginx monitoring FAQ

Why does my uptime check pass while users get 502s?

The home page may be static or cached while an API location proxies to a dead upstream. Monitor one URL per upstream (an API check on /api/health), and let the access-log 5xx rule catch the rest.

Do I need the Nginx Plus API?

No. Open-source Nginx gives you stub_status for connections and the access log for status codes and timings, which is what the agent uses.

Why does the old certificate still show after renewal?

Nginx loads certificates at start and reload. Add a deploy hook to certbot (--deploy-hook 'systemctl reload nginx') and keep the SSL expiry alert as the safety net.

Vigil by PuzariCloud

Watch Nginx without stitching five tools together

Uptime and API checks, heartbeats, server and database metrics, traces, errors and logs in one place, with one incident and one alert when something breaks. Every feature is on every plan, including Free.