Apache server-status and server-info: enable, secure, read, monitor

Updated November 2026

mod_status shows what every Apache worker is doing right now: how many are busy, which requests are slow, and which clients are behind them. mod_info shows the loaded modules and configuration. Both are very useful and both leak information, so the first job is to make sure only you can see them.

Enable server-status

Debian and Ubuntu enable mod_status by default. /etc/apache2/mods-available/status.conf already maps /server-status with Require local and turns on ExtendedStatus, so on the server itself this works straight away:

curl http://localhost/server-status?auto

RHEL, AlmaLinux, Rocky and Fedora load the module (in /etc/httpd/conf.modules.d/00-base.conf) but map no URL. Create /etc/httpd/conf.d/status.conf:

<Location "/server-status">
    SetHandler server-status
    Require local
    # Add your monitoring server or office address:
    Require ip 192.0.2.10
</Location>

ExtendedStatus On
sudo apachectl configtest
sudo systemctl reload httpd       # Debian/Ubuntu: sudo systemctl reload apache2

Several Require lines in a row mean "any of these". Require local allows 127.0.0.0/8, ::1, and connections where client and server address are the same. On Debian, add your Require ip line to status.conf rather than writing a second <Location>.

Keep it private

Behind a proxy, "local" means everybody. If nginx, HAProxy, Varnish or a tunnel on the same machine forwards public traffic to Apache, every request arrives from 127.0.0.1 and Require local lets the whole internet in. Restrict by real client address with mod_remoteip, or serve the status page only on a separate port or address that the proxy does not forward.

See access control for more on Require.

ExtendedStatus

Without ExtendedStatus you only get counts and the scoreboard. With it you also get per-request details: client, virtual host, request line, CPU and traffic totals. Loading mod_status switches it on by default since httpd 2.3.6. It is a server-wide setting (not per virtual host), cannot change on a graceful restart, and the documentation notes it can slow the server a little. On a normal server, leave it on.

Read the status page

Open /server-status in a browser (add ?refresh=5 to reload every 5 seconds). The top shows version, MPM, uptime, request rates and a line such as "1 requests currently being processed, 0 workers gracefully restarting, 24 idle workers". Below that comes the scoreboard: one character per worker slot.

Scoreboard key
CharacterMeaningWhat lots of them suggest
_Waiting for connection (idle)Spare capacity
WSending replySlow backends or slow clients; check the request list
RReading requestSlow or stalled clients; consider mod_reqtimeout
KKeepalive (read)Idle keep-alive connections holding workers (prefork/worker)
CClosing connectionUsually brief
LLoggingSlow log disk or piped logger
DDNS lookupHostnameLookups or Require host in use
GGracefully finishingNormal for a while after a reload
S, IStarting up; idle cleanup of workerUsually brief
.Open slot with no current processRoom to start more processes

With the event MPM, a table above the scoreboard also shows per-process connection counts, including connections waiting in keep-alive or being written asynchronously; those do not hold a worker thread.

Below the scoreboard, the per-worker table shows SS (seconds since the current request began), Req (milliseconds the last request took), Client, VHost and Request. Sort out a busy server by looking for workers in W with a large SS: those are your slow URLs. The documentation suggests matching PIDs from top (sorted by CPU or memory) with this table to find the request behind a runaway process. Only the first 63 characters of each request are shown; SeeRequestTail On shows the last 63 instead.

Machine-readable output

Add ?auto for plain key: value lines. Fields vary a little by version and MPM. From an httpd 2.4.69 test server with the event MPM (trimmed):

curl -s http://localhost/server-status?auto
ServerVersion: Apache/2.4.69 (Debian)
ServerMPM: event
ServerUptimeSeconds: 1
Total Accesses: 3
Total kBytes: 76
CPULoad: 1
ReqPerSec: 3
BytesPerSec: 77824
BusyWorkers: 1
IdleWorkers: 24
Processes: 1
Stopping: 0
ConnsTotal: 0
ConnsAsyncKeepAlive: 0
Scoreboard: ____W____________________.....................

Count the scoreboard states with a one-liner:

curl -s http://localhost/server-status?auto | awk -F': ' '/^Scoreboard/ {print $2}' | fold -w1 | sort | uniq -c
    375 .
     24 _
      1 W

If BusyWorkers regularly approaches your MaxRequestWorkers value, see performance tuning before raising it.

mod_info: the configuration viewer

mod_info shows every loaded module, the directives it understands, the hooks it uses, and the directives in your configuration with file names and line numbers. The documentation warns that it can leak sensitive data such as paths, user names and passwords from other modules' directives, so enable it only while you need it.

# Debian/Ubuntu: info.conf maps /server-info with Require local
sudo a2enmod info
sudo systemctl reload apache2

# RHEL/Fedora: the module is loaded; add /etc/httpd/conf.d/info.conf
<Location "/server-info">
    SetHandler server-info
    Require local
</Location>

Useful views: /server-info?list (enabled modules), ?config (all directives, unsorted), ?server (basic server settings), ?mod_rewrite.c (one module), ?hooks and ?providers. mod_info reads the parsed configuration, so comments, Include lines, LoadModule and anything in .htaccess files do not appear. For a quick check without a web page, apachectl -M lists loaded modules and apachectl -S shows virtual hosts. Disable it again with sudo a2dismod info or by removing the file.

Monitoring tools

All the common tools read ?auto, so the access rules above apply to them too: allow the monitoring host's IP, or run the agent on the web server itself.

Prometheus

apache_exporter (version 1.1.1 as of November 2026) polls http://localhost/server-status?auto by default and serves metrics on port 9117. Run it on the web server and scrape it from Prometheus:

./apache_exporter --scrape_uri="http://localhost/server-status?auto"

# prometheus.yml
scrape_configs:
  - job_name: 'apache'
    static_configs:
      - targets: ['web1.example.com:9117']

Metrics include apache_up, apache_accesses_total, apache_sent_kilobytes_total, apache_workers{state="busy"} and {state="idle"}, and apache_scoreboard. The counters marked as extended need ExtendedStatus On. Port 9117 should be firewalled to your Prometheus server only.

Netdata and Zabbix

Netdata's Apache collector (go.d/apache.conf) looks for http://127.0.0.1/server-status?auto and charts connections, workers, requests and traffic. Zabbix ships an "Apache by HTTP" template that polls the same page with an HTTP agent item. In both cases the setup is mostly making sure the status URL answers for the collector's address.

Sources