Install a maintenance page without restarting apache
2009 mai 8 4 Commentaires
These days we are working with fabric to remove some hazard in maintenance.
Recently someone gzip a Data.fs file in production and our customer loose 2 days of work. We choose to use fabric (http://www.nongnu.org/fab/) to limit command line working to the strict minimum.
Now, almost all procedures were added in a fabric factory, from the installation of a development environment to the upgrade of the production server. In this last part, we search a solution to put a maintenance page without have to gain root privileges to restart the apache used in frontend. For static or CGI sites you can use a .htaccess file to override the global rules. For a stopped Zope server it doesn’t help much.
The goal is to use RewriteCond and RewriteRule in a such way that a static HTML file would be displayed when it exists. We can call it ‘maintenance.html‘ and rename it ‘maintenance.html-disabled‘ to let the site be displayed normally.
We start with a virtual host generated by iw.recipe.squid:
<VirtualHost *:80>
ServerName www.gosseyn.fr
RewriteEngine On
RewriteLog /my/path/to/squid/parts/squid/log/rewrite_www.gosseyn.fr.log
RewriteLogLevel 0
CustomLog /my/path/to/squid//parts/squid/log/access_www.gosseyn.fr.log common
ErrorLog /my/path/to/squid//parts/squid/log/error_www.gosseyn.fr.log
## common rules for squid rewrite rules
RewriteRule ^(.*)$ - [E=BACKEND_LOCATION:127.0.0.1]
RewriteRule ^(.*)$ - [E=BACKEND_PORT:8081]
RewriteRule ^(.*)$ - [E=BACKEND_PATH:site]
RewriteRule ^/(.*)/$ http://127.0.0.1:3128/%{ENV:BACKEND_LOCATION}/%{ENV:BACKEND_PORT}/http/%{SERVER_NAME}/80/%{ENV:BACKEND_PATH}/__original_url__/$1 [L,P]
RewriteRule ^/(.*)$ http://127.0.0.1:3128/%{ENV:BACKEND_LOCATION}/%{ENV:BACKEND_PORT}/http/%{SERVER_NAME}/80/%{ENV:BACKEND_PATH}/__original_url__/$1 [L,P]
## specific rules base on cookie
</VirtualHost>
First we need to declare a document root and to bypass all security rules. We create a new path in the root of our buildout folder called ‘maintenances_pages’.
DocumentRoot /my/path/to/buildout/prod/maintenance_pages
<Directory "/my/path/to/buildout/prod/maintenance_pages">
Options None
AllowOverride None
Order allow,deny
allow from all
<LimitExcept GET>
Order allow,deny
allow from all
</LimitExcept>
</Directory>
These declaration should satisfy all paranoid BOFH.
Now create a file called maintenance.html within the folder. All code (javascript, CSS and images) must be embeded, this is a limitation of this approach.
Well, how to detect that a file exist on the filesystem from apache. You can do this with the flag ‘-f’ from the rewrite module:
RewriteCond /my/path/to/buildout/prod/maintenance_pages/maintenance.html -f
Then redirect all pages to our maintenance page:
RewriteCond %{REQUEST_URI} !/maintenance.html
RewriteRule $ /maintenance.html [R=302,L]
We also need to disable the standard rewrite rules. The easier way to do it is to use ‘!-f‘.
RewriteCond /my/path/to/buildout/prod/maintenance_pages/maintenance.html !-f
RewriteRule ^/(.*)/$ http://127.0.0.1:3128/%{ENV:BACKEND_LOCATION}/%{ENV:BACKEND_PORT}/http/%{SERVER_NAME}/80/%{ENV:BACKEND_PATH}/__original_url__/$1 [L,P]
RewriteCond /my/path/to/buildout/prod/maintenance_pages/maintenance.html !-f
RewriteRule ^/(.*)$ http://127.0.0.1:3128/%{ENV:BACKEND_LOCATION}/%{ENV:BACKEND_PORT}/http/%{SERVER_NAME}/80/%{ENV:BACKEND_PATH}/__original_url__/$1 [L,P]
These rules will not be applied anymore when our maintenance file will be name ‘maintenance.html’. Our goal is reached.
The whole virtualhost file look like this:
<VirtualHost *:80>
ServerName www.gosseyn.fr
RewriteEngine On
RewriteLog /my/path/to/squid/parts/squid/log/rewrite_www.gosseyn.fr.log
RewriteLogLevel 0
CustomLog /my/path/to/squid//parts/squid/log/access_www.gosseyn.fr.log common
ErrorLog /my/path/to/squid//parts/squid/log/error_www.gosseyn.fr.log
DocumentRoot /my/path/to/buildout/prod/maintenance_pages
<Directory "/my/path/to/buildout/prod/maintenance_pages">
Options None
AllowOverride None
Order allow,deny
allow from all
<LimitExcept GET>
Order allow,deny
allow from all
</LimitExcept>
</Directory>
## our maintenance page
RewriteCond /my/path/to/buildout/prod/maintenance_pages/maintenance.html -f
RewriteCond %{REQUEST_URI} !/maintenance.html
RewriteRule $ /maintenance.html [R=302,L]
## common rules for squid rewrite rules
RewriteRule ^(.*)$ - [E=BACKEND_LOCATION:127.0.0.1]
RewriteRule ^(.*)$ - [E=BACKEND_PORT:8081]
RewriteRule ^(.*)$ - [E=BACKEND_PATH:site]
RewriteCond /my/path/to/buildout/prod/maintenance_pages/maintenance.html !-f
RewriteRule ^/(.*)/$ http://127.0.0.1:3128/%{ENV:BACKEND_LOCATION}/%{ENV:BACKEND_PORT}/http/%{SERVER_NAME}/80/%{ENV:BACKEND_PATH}/__original_url__/$1 [L,P]
RewriteCond /my/path/to/buildout/prod/maintenance_pages/maintenance.html !-f
RewriteRule ^/(.*)$ http://127.0.0.1:3128/%{ENV:BACKEND_LOCATION}/%{ENV:BACKEND_PORT}/http/%{SERVER_NAME}/80/%{ENV:BACKEND_PATH}/__original_url__/$1 [L,P]
## specific rules base on cookie
</VirtualHost>
It will be difficult to include this in a recipe as we modify an existing virtualhost in a very specific way.
As usual, all feedbacks are appreciated.
Commentaires récents