Nginx custom internal error page when upstream is down

I am new to Nginx and have a reverse proxy to an upstream glassfish server. I am trying to set up a custom 503 page for when the app is down for maintenance. I have been failing to do so for several hours now. The maintenance.html page contains a css and jpg link. These are showing up when I am forwarded to the maintenance page. All I get is the text of the page and a broken image.

CentOS 6.5 nginx 1.4.4 (from nginx repo)

upstream glassfish {
server <upstream IP>:8181 max_fails=1;
}

server {
 listen       80;
 server_name  localhost;

#charset koi8-r;
#access_log  /var/log/nginx/log/host.access.log  main;

error_page  404 502   /static/error.html;
error_page  503      /static/maintenance.html;

location ~ ^/static/ {
    internal;
}

 location / {
 proxy_set_header X-Real-IP  $remote_addr;
 proxy_set_header X-Forwarded-For $remote_addr;
 proxy_set_header Host $host;
 proxy_pass https://glassfish;
 port_in_redirect off;
 }
}

The error that shows up in the access.log is

[19/Dec/2013:17:49:17 -0500] "GET /static/main.css HTTP/1.1" 404 1136 "http:/// [19/Dec/2013:17:49:18 -0500] "GET /static/header-logo.jpg HTTP/1.1" 404 1136 "http:///

I have checked that /etc/nginx/html/static/header-logo.jpg exists

I'm sure it's simple enough, but I just cannot figure it out!


I recently wanted to do the same thing (show a nicer maintenance/error-page with images, CSS and custom fonts).

What I ended up doing was using an internal location block like this:

server {
  …

  error_page 502 = @maintenance;

  location @maintenance {
    root /path/to/maintenance-site;

    if (!-f $request_filename) {
      rewrite ^ /index.html break;
    }
  }
}

I wrote a blog post about it, if you need more detail (has been down because I was rebuilding my infrastructure but is back up again).


You say you're doing this:

location ~ ^/static/ {
    internal;
}

The internal keyword means that this location is only visible for internal requests, which your error_page requests are.

If you want to be able to access /static/ directly from the web-browser, which would seem necessary in order to serve images referenced from the error pages, then you'd have to remove the internal directive from the said location.


I think the best approach is to do the following things:

  • Use inline CSS
  • Convert your images to Base64

After doing this, you can embed the generated Base64 string into the background-image CSS rule as follows:

background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEADI.....==)

You can use the string with the <img> tags as well, just pass it to the src attribute as follows:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEADI.....==" />

This way you can keep the internal nginx rule.

Cheers!