0

I have a nginx config with about 10 vhosts, and I want to have them all share custom 404 and 50x and maintenance error pages. The nginx is a reverse proxy serving angular index.html and I'm a bit confused on how to get the error_page 404 /oops/root directive to pick up the font and image assets in a different directory than the website itself (can't point to the website dir if the site root is returning a 404).

If for any reason the root of the app results in a 404, I'd like to show a custom index.html inside the /usr/share/nginx/html/oops directory, and be able to point to oops/fonts/* and oops/image.svg and pngs.

Everything is working fine except the assets. The 404 page shows up, but the images and fonts do not have the proper path. Can't seem to see in nginx debug level logs how to get them to show up.

upstream notbrain-api {
  server 192.168.1.2:3000;
}

server {

  access_log /var/log/nginx/access.log human_json;
  error_log /var/log/nginx/error.log debug;

  listen       443 ssl;
  server_name  notbrain.com;
  include /etc/nginx/ssl/shared_ssl.nginx;

  # font cache fix
  location ~* \.(?:woff|eot|ttf|otf) {
    root "/usr/local/apps/notbrain.com/dist";
    proxy_cache            STATIC;
    proxy_cache_valid      200  7d;
    add_header Vary Accept-Encoding;
    add_header Cache-Control public;
  }

  # proxy to upstream api host
  location /api {
    proxy_connect_timeout        60;
    proxy_send_timeout          300;
    proxy_read_timeout          300;
    send_timeout                300;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    expires -1;
    add_header Cache-Control "no-store";
    proxy_pass http://notbrain-api;
  }

  location / {
    root "/usr/local/apps/notbrain.com/dist";
    index index.html;
    try_files $uri $uri/ /index.html =404;
    expires -1;
    add_header Cache-Control "no-store";
  }

  location ~ \.(aspx|php|jsp|cgi|do|rb)$ {
    return 410;
  }

  # currently working for 404.html, but can't figure out how to point assets to snafu/
  # would like to avoid having to explicitly rewrite all images and fonts
  # 
  error_page 404 /snafu/404.html;
  location /snafu/ {
    # index and assets are inside /usr/share/nginx/html/snafu/[fonts/, images/]
    root "/usr/share/nginx/html/";
  }

 }
notbrain
  • 209
  • 3
  • 16

1 Answers1

0

Figured out it was a couple of workarounds that were interfering with the new error_page stanza.

First, I used alias instead of root in the error_page location match:

...
error_page 404 /snafu.html/404.html;
location /snafu.html/ {
  alias "/usr/share/nginx/html/snafu.html/";
}
...

Then, in the HTML of all the error pages, I prefixed all assets with /snafu.html/ (fonts and images).

The remaining issue was missing fonts, since we had a workaround for a web font caching issue that unnecessarily declared a root:

location ~* \.(?:woff|eot|ttf|otf) {
  root "/usr/local/apps/notbrain.com/dist";
  proxy_cache            STATIC;
  proxy_cache_valid      200  7d;
  add_header Vary Accept-Encoding;
  add_header Cache-Control public;
}

The above was now too aggressive, and was intercepting all font requests and setting the root to the main site (which is in 404 state). This needed to work for both the error pages and the site itself. Removing the root and expanding the regex to match both fixed it up:

location ~* ^(.+/)?fonts/(.+)\.(?:woff|woff2|eot|ttf|otf)$ {
  proxy_cache            STATIC;
  proxy_cache_valid      200  7d;
  add_header Vary Accept-Encoding;
  add_header Cache-Control public;
}

I'm sure there's a more elegant way to express the ^(.+/)?fonts/(.+) but this seemed to work.

I'm unsure why a cleaner ^(.+)?/fonts/(.+)\.(?:woff|woff2|eot|ttf|otf)$ regex doesn't work - my intent there is to always have a leading slash but an optional directory in front of it. Is it because .+ never matches a slash?

notbrain
  • 209
  • 3
  • 16