We wanted to add a maintenance page to our rails app running on nginx. Capistrano provides a simple task to show your maintenance page cap deploy:web:disable
. It includes basic instructions for how to configure nginx, although I found these didn’t quite work for us as documented.
One thing the configuration suggests it to return a 503 status code so that crawlers know the site is temporarily down and will retry the crawl later. This made sense, but when we did this in front of the load balancer it automatically sent it’s own 503 to the browser because it detected that the app server was returning 503 (which is what it should do, or roll over to another server). What we needed was the ability to have our load balancer run it’s health check on the app server without getting the 503.
While I have read that that “If is evil” in nginx configurations, I found that I could check whether the request was the load balancer and return a 200 code within the maintenance handler:
if ($request_filename ~ '/health_check') { return 200; }
I also learned a lot from this older post (like how to allow inclusion of graphic assets such as our logo). But the key trick was to put a bare ‘=’ on the error_pages line so that Nginx would return the handler’s response code, rather than 503 for all pages.
error_page 503 = @maintenance;
Here is the entire configuration that we used (put this at the server
level).
recursive_error_pages on; if (-f $document_root/system/maintenance.html) { return 503; } error_page 503 = @maintenance; location @maintenance { error_page 405 /system/maintenance.html; if ($request_filename ~ '/health_check') { return 200; } if (-f $request_filename) { break; } rewrite ^(.*)$ /system/maintenance.html break; }