I have the following situation. I have for my webapp under /var/www the folder "my_project". Now I want to display a maintenance page using mod_rewrite.
For this I have placed under /var/www the file "maintenance.html". Additionally I added the following rewrite conditions including the following rewrite rule in the config file for the "my_project" folder under /etc/apache2/sites-available :
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName my_project.de
ServerAlias www.my_project.de
DocumentRoot /var/www/my_project.de/public
<Directory /var/www/my_project.de/public/>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Require all granted
</Directory>
RewriteEngine on
RewriteCond /var/www/maintenance.html -f
RewriteCond %{REQUEST_URI} !^/maintenance\.html$
RewriteCond %{REMOTE_ADDR} !^00\.00\.00\.000
RewriteRule ^ - [R=503]
ErrorDocument 503 /var/www/maintenance.html
LogLevel debug
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Now I get the message "Service Unavailble. The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later", if the file "maintenance.html" is located in the folder /var/www. However, I want the maintenance.html file to be displayed instead of the message described above.
Can anyone tell me what I may be doing wrong or understanding here?
UPDATE:
I adjusted the config file and the above config represents the current situation. However this seems to result in a redirect loop. Because in the error.log file of apache is the following written:
Error logs:
AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.
AH00122: redirected from r->uri = /var/www/maintenance.html
AH00122: redirected from r->uri = /var/www/maintenance.html
AH00122: redirected from r->uri = /var/www/maintenance.html
AH00122: redirected from r->uri = /var/www/maintenance.html
AH00122: redirected from r->uri = /var/www/maintenance.html
AH00122: redirected from r->uri = /var/www/maintenance.html
AH00122: redirected from r->uri = /var/www/maintenance.html
AH00122: redirected from r->uri = /var/www/maintenance.html
AH00122: redirected from r->uri = /var/www/maintenance.html
AH00122: redirected from r->uri = /login
Note: I already tried a relative path vor the maintenance.html file but that did not work as well (e.g. /maintenance.html)
FINAL SOLUTION:
Thanks to @MrWhite I got it working. The final vHost config looks like this:
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName my_project.de
ServerAlias www.my_project.de
Alias /errordocs /var/www
# Permit access to the Alias target
<Directory /var/www>
Require all granted
</Directory>
ErrorDocument 503 /errordocs/maintenance.html
DocumentRoot /var/www/my_project.de/public
<Directory /var/www/my_project.de/public/>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Require all granted
</Directory>
RewriteEngine on
RewriteCond /var/www/maintenance.html -f
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REMOTE_ADDR} !^00\.00\.00\.000
RewriteRule ^ - [R=503]
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
In order to "activate" the maintenance mode it is now only required to place a "maintenance.html" file in the directory "var/www/".
RewriteRule (.*) /maintenance.html [R=503,L]
When using the R
flag with a non-3xx status, the substitution string is ignored (you should ideally include a single hyphen as the substitution in this case).
To serve /maintenance.html
in this case you should set an appropriate ErrorDocument
and simply use the R=503
flag in the RewriteRule
directive to trigger this via an internal subrequest.
For example
ErrorDocument 503 /maintenance.html
:
RewriteRule ^ - [R=503]
The L
flag is also unnecessary when specifying a non-3xx status, since it is implied.
If the rule is inside a <Directory>
block that targets the my_project
subdirectory then you don't need the condition that checks the request is not already /maintenance.html
. The ErrorDocument
should probably be defined outside of the <Directory>
container.
UPDATE:
The ErrorDocument
directive requires a root-relative URL-path, not an absolute file-path. Consequently this error document needs to exist within the confines of the vHost. It would seem from your updated config that the my_project
"subdirectory" is in fact its own vHost, not a subdirectory off the "parent" (as I assumed).
If you want to use an ErrorDocument
that is located elsewhere on the filesystem (ie. outside of the vHost) then you could use an Alias
to point to this other location.
For example, in your existing vHost for my_project.de
:
Alias /errordocs /var/www
# Permit access to the Alias target
<Directory /var/www>
Require all granted
</Directory>
ErrorDocument 503 /errordocs/maintenance.html
Alternatively you could configure /var/www/my_project.de/public/maintenance.html
as a symlink to /var/www/maintenance.html
.
RewriteCond %{REQUEST_URI} !^/maintenance\.html$
This condition will need to be modified to include the /errordocs
prefix. Alternatively, remove this condition altogether and modify the RewriteRule
pattern. For example:
RewriteRule !^/errordocs/maintenance\.html$ - [R=503]
A minor issue with your existing mod_rewrite implementation is that direct requests to the ErrorDocument
itself will be served with a 200 OK status and potentially be indexed by search engines. (Not that this should be a serious issue since the location of this file is unknown to the user - better than when it is located in the document root). However, this can be resolved with the following instead:
# Trigger a 503 for all "user" requests
RewriteCond /var/www/maintenance.html -f
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REMOTE_ADDR} !^203\.0\.113\.111
RewriteRule ^ - [R=503]
The check against the REDIRECT_STATUS
environment variable ensures that only direct requests from the client are processed, not internal subrequests.