Take the 2-minute tour ×

I've been setting up Nginx as a reverse proxy for an app on the server. Part of this includes a maintenance page that has external content (like images). I was able to find a method for setting up an error page with images returning 200, but it looks like a reverse proxy will change the whole environment. Here's the original solution from nginx maintenance page with content issue

error_page 503 @maintenance;

location @maintenance {
    root /path_to_static_root;
    if (!-f $request_filename) {
        rewrite ^(.*)$ /rest_of_path/maintenance.html break;
    return 200;

The Reverse Proxy is configured as:

location / {
            proxy_redirect     off;

The Problem is that when a file is found to exist in the "maintenance" root, something goes wrong and the server returns a 502. Anyone know what the cause could be?

Some speculation I'm wondering if server listens on port 80, it somehow passes any good file request back into the proxy. If that were true, how would that be avoided?


Here's the error in the nginx log. I am directly trying to access 50x.html. Not sure why this would occur?

2012/02/17 19:39:15 [error] 21394#0: *13 connect() failed (111: Connection refused) while connecting to upstream, client: (my ip address), server: _, request: "GET /50x.html HTTP/1.1", upstream: "", host: "domain.com"

It looks like it is indeed trying to GET from the app and not the root. How can I bypass this?

Edit 2

I originally thought I had found an answer where a change was made for nginx v1.0.12 but it did not solve the problem. It involved a similar situation but my guess is the fix was too specific.

share|improve this question
add comment

1 Answer

up vote 2 down vote accepted

You shouldn't need to involve the backend (I.E., shouldn't use proxy pass) since your maintenance page should be a static html file that Nginx can serve directly.

Assuming you have a setup configured as ...

server {
    listen 80;
    server_name example.com;
    root /path/to/webroot;

    # Regular locations etc

Create a folder called "503_status" and put your maintenance page in there as "503.html".

With that in place, create a file called "maintenance.default" under the Nginx directory with the following content ...

error_page 503 /503_status/503.html;

# Candidate for redirection if not ending with one of these extensions.
if ( $request_uri !~ \.(jpg|gif|png|css|js)$ ) {
     set $maint  "Tr";
# Candidate for redirection if not a request for the maintenance page 
if ( $request_uri !~ ^/maintenance/$ ) {
    set $maint  "${maint}ue";
# Redirect to a location where the status code will be issued 
if ( $maint = True ) {
    rewrite ^ /maintenance/ redirect;
# Due to Nginx quirk, issue the status code in a location context.
# Make "internal" to prevent direct browsing.
location /maintenance {
    return 503;
# 503_status folder as "internal" so no direct browsing 
location 503_status {
    alias /server/path/to/503_status/folder;

Whenever you put to put the site into maintenance, just include the file as follows ...

server {
    listen 80;
    server_name example.com;
    root /path/to/webroot;

    include /server/path/to/maintenance.default;        

    # Regular locations etc

This will serve your maintenance page as well as any resources it needs (just make sure extension is in the list). The backend server does not come into play at all.

share|improve this answer
I see, so you must set up a new server config for maintenance content? Apologies if it wasn't clear, the location / { proxy_pass } in the Q is actually the backend server (a java application), so it is still necessary to link to it. Does that change anything in the answer? Thx! –  crockpotveggies Feb 19 '12 at 0:38
You don't create a new server block. Just include the maintenance.default file into the existing server block(s) for the affected domain(s). Nginx serves the 503.html file all by itself so the java app is not, and should not be, called at all. BTW, all your regular server block elements stay intact and you just include the maintenance.default file which takes over the process. When you remove the "include" line, you return to the normal setup. The only thing you add to your normal server block (first code block above) is "include /server/path/to/maintenance.default;" (last code block above). –  Dayo Feb 19 '12 at 7:38
Perfect, thanks for the detailed answer and the clarification. –  crockpotveggies Feb 19 '12 at 8:25
You are welcome. Note that there was an error in the code in that the "use of "return 503" at the server level appears to always return the default Nginx 503 error page. I have amended the answer so that the custom page is used. Disadvantage with this is that the actual status code that will be sent will be "200". –  Dayo Feb 19 '12 at 10:04
Finally got a config that will issue the custom page along with the correct status code. Been an interesting journey of discovery for me!! –  Dayo Feb 19 '12 at 13:09
show 2 more comments

Your Answer


