09 February 2012
Today I was having a real problem. Every minute on my linux box I call
apache2ctl status 
via a cronjob and this gives me various stats on how many servers are used/free. Useful. But upon moving some old websites off the server the above call began to fail - I'd get the error message
Forbidden
You don't have permission to access /server-status on this server.

There are lots of solutions around the web (some about SELinux, some about setting allow/deny in an apache config file under the location /server-status namespace), none of which actually solved my problem. They did give enough hints for me to work out what was going on! You see when you make the above call to apache2ctl it then (through mod_status) requests /server-status on the default website on your webserver. Now if you only have one site then that should be pretty easy to work out which one it is going to, but if you're hosting multiple sites then its not quite as obvious. For me it was the first site in the /etc/apache2/sites-enabled directory, (or you can find which one it is by visiting the webserver via its IP address rather than through a domain name as it is the domain name that is used to direct the browser call to a specific site that you host - if you visit your webserver via its IP address it doesn't really know what to serve you so you're sent to the default site).

So my default site was refusing to serve /server-status. I couldn't think why this was until I visited my .htaccess file and realised that I was using mod_rewrite to rewrite any www.mysite.com calls to mysite.com like so:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^mysite\.com$
RewriteRule (.*) http://mysite.com/$1 [R=301,L]
The answer then was to pop in an exclusion for /server-status so that it would be unaffected by mod_rewrite:
RewriteEngine On
RewriteCond %{HTTP_HOST} !^mysite\.com$
RewriteCond %{REQUEST_URI}  !^/server-status
RewriteRule (.*) http://mysite.com/$1 [R=301,L]

And hey presto it works! Hurrah!

UPDATE: I've found a better version. I host the site on a virtual server (amazon's ec2 stuff) and that means I often need to test a new instance of the server using either the IP address or a funny amazon made up name like ec2-99-98-97-96.compute-7.amazonaws.com, but if I stick that in the address bar of a browser the .htaccess reroutes it to mysite.com (the one that is live), so really I just need to slice off the www from any HTTP_HOST that is found and keep an exception in there for /server-status so that apache2ctl status doesn't complain. Here's what it looks like now:

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteCond %{REQUEST_URI} !^/server-status
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
If you wanted to be ultra portable you could put an if around it:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteCond %{REQUEST_URI} !^/server-status
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
</IfModule>


blog comments powered by Disqus