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/".
When using the
Rflag 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.htmlin this case you should set an appropriateErrorDocumentand simply use theR=503flag in theRewriteRuledirective to trigger this via an internal subrequest.For example
The
Lflag is also unnecessary when specifying a non-3xx status, since it is implied.If the rule is inside a
<Directory>block that targets themy_projectsubdirectory then you don't need the condition that checks the request is not already/maintenance.html. TheErrorDocumentshould probably be defined outside of the<Directory>container.UPDATE:
The
ErrorDocumentdirective 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 themy_project"subdirectory" is in fact its own vHost, not a subdirectory off the "parent" (as I assumed).If you want to use an
ErrorDocumentthat is located elsewhere on the filesystem (ie. outside of the vHost) then you could use anAliasto point to this other location.For example, in your existing vHost for
my_project.de:Alternatively you could configure
/var/www/my_project.de/public/maintenance.htmlas a symlink to/var/www/maintenance.html.This condition will need to be modified to include the
/errordocsprefix. Alternatively, remove this condition altogether and modify theRewriteRulepattern. For example:A minor issue with your existing mod_rewrite implementation is that direct requests to the
ErrorDocumentitself 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:The check against the
REDIRECT_STATUSenvironment variable ensures that only direct requests from the client are processed, not internal subrequests.