Nested if workaround for Nginx to allow a specific ip address access to a disabled site
When doing maintenance on a web application, you probably have a custom 503
site, showing your customers that the servers are currently lying on the operating table.
At the dynamic ridesharing service flinc, we touch a certain file on our reverse proxies (e.g. using capistrano deploy:web:disable
) when maintenance begins. Nginx then serves a static “we’ve disabled the site for maintenance” site, instead of the actual content.
But wouldn’t it be nice to test your web application before going live for your customers? It sure would. Unfortunately, this is not as simple as a task as you might think, because you cannot nest if
directives in an Nginx location and if is evil.
Because of hose limitations, we need another creative approach.
As try_files
is also forbidden in if
directives and only return
and rewrite
are safe commands to use let’s abuse the unused HTTP status code 418
to work around this.
Basically, as long as the maintenance.html
is not present or we are sitting in our office, we return the 418
status code. For customers, we’re serving 503
in case the site is disabled.
So let’s define the locations for normal operation (try serving the static files directly, and redirect all other requests to our upstream)
And finally, our maintenance site. We’re serving maintenance.html
instead of the requested site.
As POST
requests to static websites are not allowed and therefore all our disabled forms will return a 405
instead of the wanted 503
, let’s correct those as well.
The last location
directive makes sure that the static assets required for the maintenance page (images, stylesheets, etc) stored in /maintenance
are served normally.