The stub_status page shows live connection counts and request totals. That is harmless for you and useful to an attacker measuring your traffic. Serve it only on a local or internal listener, wrap it in allow and deny rules, and check from outside that it returns an error.
What the page contains
The nginx documentation lists the data: active connections, total accepted connections, total handled connections, total requests, and the Reading, Writing and Waiting counts. Handled usually equals accepted, unless a resource limit such as worker_connections was reached.
None of this is a secret in the sense of a password. But it tells an outsider how busy you are, how close you are to your connection limit, and whether an attack is landing, which is useful for timing one.
How it is enabled
The module is not built by default. It needs --with-http_stub_status_module, though many distribution builds include it. Since version 1.7.5 the directive takes no argument.
location = /basic_status {
stub_status;
}
Lock it down
The stub_status page does not document access control itself, but you can combine it with allow and deny from the separate access module. Rules are evaluated in order, so allow lines must come before deny all.
location = /basic_status {
stub_status;
allow 127.0.0.1;
allow 10.0.0.0/8;
deny all;
}
Two cautions.
First, behind a balancer, the address nginx checks may be the balancer's, which is inside your allowed range, and then everyone passes. Check which address the access module sees. The rewriting done by the realip module applies, so a broad trusted range there can undo your allow list. See nginx real_ip.
Second, a wide allow range such as the whole private space is not a boundary if your private network hosts other tenants or untrusted workloads. Narrow it to the monitoring host.
Better: separate listener
Put status on its own server block that listens on loopback or an internal interface only.
server {
listen 127.0.0.1:8081;
location = /basic_status { stub_status; }
}
An exporter on the same host reads it. Nothing on the public listener refers to it at all, so a typo in the public config cannot expose it.
Keep the monitor's own credentials and network path in mind too. If an exporter scrapes the page across the network, restrict the allow line to that exporter's single address, and review that list whenever the monitoring host changes.
Check from outside
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/basic_status
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/nginx_status
You want 403 or 404 on both. Also look for other management endpoints in your inventory, including ingress controller metrics ports and admin APIs. Asset discovery is how you find the ones nobody remembers.
Where Safeguard fits
Safeguard provides asset discovery and dependency scanning, which help you find forgotten services and the components they run. A free scan is available at https://gold.safeguard.sh/scan.
Quick check
Why put allow lines before deny all?
nginx evaluates access rules in order and stops at the first match, so deny all first would block everyone.
Sources
Last reviewed: 19 October 2026.