I have a site where the standard Drupal maintenance page is the simplest way to communicate short periods of down time with. our users.
The problem is that when Drupal emits a maintenance page, it attaches a status of 503. AFAICT, this is the same error status a lot of nginx configurations use to indicate that your PHP-FPM instances have passed away and ceased to pine for the fyords :-)
What's best practice here? Right now, we're in a configuration where a 503 causes our elastic load balancers to effectively shut down the site (not my idea). Which means once we go into maint mode, the site goes down entirely.
Due to the way we deploy, using an nginx maint page (detected with a -f arg, for example) is not a good option. Is there a reasonable way to configure nginx so we can distinguish a maint page from a dead FPM?

Comments
This is indeed a problem
you could detour the 503 status code, but then the real 503 would be confounded with a maintenance page.
IMHO this is a bug, the status code should be
307and not503. I think an issue with a patch is appropriate.To be correct this
needs to be a real redirect. Right now the default maintenance page is the index which is practical but bad for this purpose.
Giving it some thought I
found a solution that involves Lua and returns a special
X-Maintenance: YESheader for the Drupal maintenance page. Or you could just check for the presence of the Etag in the case of the Drupal maintenance page as opposed to the "regular" 503.Here's my take: https://gist.github.com/3778833
If you're doing something automated check directly for the presence of the Etag or use the above code.
Look Ma no Lua
in your server/vhost do:
error_page 503 = @503;
location @503 {
if ($upstream_http_etag) {
return 503 "Site down for maintenance. We'll be back shortly";
}
}
You can addapt the retun string, maybe using an hash of the hostname so that you can automate as much as possible. Note that the default drupal page gets
replaced by a string.
Limitations of the AWS health checks and status = 503
Perusio,
Much thanks. At least it's possible to distuguish a Drupal generated 503 from any other kind of 503 that nginx might emit.
Our core problem was that the web server emitted 503 at all, however. The key insight as we investigated this was that the AWS load balancers (ELBs) do a health check on the connected web servers. If they detect any flavor of 4xx or 5xx, they declare the instance "unhealthy", and refuse to pass its output through.
While some folks deal with this by having the web server pass on a 200 in this case, this is pretty risky, especially if you are reindexed a lot by search engines: you can end up (as Disney did in 2010) up on Google as "Down for Maintenance", sometimes for days.
There is, however, a work around. I did this directly in Drupal using hook_menu_site_status_alter:
<?php/**
* Change the menu site status for our custom health check
*/
function vfa_core_menu_site_status_alter(&$page_callback_result, $read_only_path) {
if ($page_callback_result == MENU_SITE_OFFLINE and $read_only_path == 'aws-heartbeat') {
$page_callback_result = MENU_SITE_ONLINE;
}
}
?>
This causes the link /aws-heartbeat to return a "200 OK" even when the site as a whole returns 503. Since the AWS health check (and apparently, other HTTP based health-checkers) look at a specific URL, if you set the URL to point to the heart beat, it lets your site display your desired 503 UI without causing the health check alarms to go off.
I'm not sure if there's some down side to this tactic I'm seeing, but so far, it appears to work.
It's even simpler
if just want to return a 200:
Do:
location @503 {if ($upstream_http_etag) {
return 200;
}
}
No need for PHP code. You'll leave the default behaviour in place.
Maintainance page not working on Drupal 7, nginx 1.8.0
Hello,
On an https site my maintenance page not working on Drupal 7, nginx 1.8.0 .
it shows error 404.
error is:
[error] 32015#0: *63 open() "/usr/share/nginx/html/50x.html" failed (2: No such file or directory), client: xx.xx.xxx.xxx, server: www.mysite.com, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/var/run/php5-fpm.sock", host: "www.mysite.com"
also changed fastcgi to 127.0.0.1:9000 on my vhost file and www.conf with no luck still below error:
.... "/usr/share/nginx/html/50x.html" failed (2: No such file or directory), client: xx.xx.xxx.xxx, server: www.mysite.com, request: "GET /admin/reports/dblog HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", ...
Any ideas?
Thanks
George