# Fix Apache mod_status Page Not Accessible From Remote Hosts
You enable Apache's mod_status module to monitor server performance, but when you try to access https://example.com/server-status from your workstation, you get a 403 Forbidden error. The module is loaded, the configuration is present, but access is denied.
The Default Configuration
The default mod_status configuration restricts access to localhost only:
<Location "/server-status">
SetHandler server-status
Require local
</Location>Require local allows access only from 127.0.0.1, ::1, and localhost. Any request from a remote IP address is denied.
Allowing Access From Specific IPs
To monitor Apache from a remote workstation, add your IP address:
<Location "/server-status">
SetHandler server-status
Require local
Require ip 203.0.113.50
Require ip 10.0.0.0/8
</Listing>Or more concisely:
<Location "/server-status">
SetHandler server-status
Require ip 203.0.113.50 10.0.0.0/8 127.0.0.1
</Location>Important: Never use Require all granted for server-status. It exposes detailed information about every active connection, including client IP addresses, request URLs, and server load. This is sensitive operational data.
Enabling Extended Status
To get detailed information about each request (URL, client IP, processing time), enable extended status:
ExtendedStatus OnThis must be set in the main server configuration (not in a VirtualHost or .htaccess). Without it, server-status shows only basic worker information without request details.
Verifying mod_status Is Loaded
apache2ctl -M | grep statusIf not listed:
sudo a2enmod status
sudo systemctl reload apache2The server-status Query Parameters
The server-status page supports several query parameters:
```bash # Auto format (machine-readable) curl -s http://localhost/server-status?auto
# Show all workers including idle ones curl -s http://localhost/server-status?refresh=5
# JSON format (Apache 2.4.43+) curl -s http://localhost/server-status?json ```
The ?auto format is ideal for monitoring scripts:
Total Accesses: 145234
Total kBytes: 892341
Uptime: 86400
ReqPerSec: 1.68
BytesPerSec: 10560
BytesPerReq: 6284
BusyWorkers: 12
IdleWorkers: 38
ConnsTotal: 45
ConnsAsyncWriting: 3
ConnsAsyncKeepAlive: 28
ConnsAsyncClosing: 2Monitoring Script Using server-status
```bash #!/bin/bash # apache-monitor.sh
URL="http://localhost/server-status?auto" busy=$(curl -s "$URL" | grep "BusyWorkers" | awk '{print $2}') idle=$(curl -s "$URL" | grep "IdleWorkers" | awk '{print $2}') total=$((busy + idle)) pct=$((busy * 100 / total))
echo "$(date): Workers $busy/$total (${pct}% busy)"
if [ $pct -gt 80 ]; then echo "ALERT: Apache worker utilization above 80%" fi
# Log to file echo "$(date +%Y-%m-%dT%H:%M:%S) busy=$busy idle=$idle pct=$pct" >> /var/log/apache-monitor.log ```
Run this every minute via cron:
* * * * * /usr/local/bin/apache-monitor.shSecurity Considerations
The server-status page reveals:
- Client IP addresses of all active connections
- Full request URLs being processed
- Virtual server handling each request
- Response sizes and processing times
- Server uptime and total request count
Restrict access to trusted monitoring IPs only. If using a monitoring service (Datadog, New Relic, etc.), add their IP ranges to the Require ip list.
For automated monitoring from the same server, use Require local with a cron script that posts metrics to your monitoring system, rather than allowing remote access to server-status.