title: Nginx Error Pages - One Location Rule to Fit Them All?
body: <p>Having the following nginx vhost config:</p>
  
  <pre><code>server {
      listen 80;
      listen 443 ssl;
      server_name default;
      root /var/www/default/html;
      error_log /var/www/default/log/error.log;
      access_log /var/www/default/log/access.log;
      ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
      ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
  
      autoindex on;
      index index.html index.php;
  
      location / {
          try_files $uri $uri/ @php;
      }
  
      location @php {
          rewrite ^/(.*)/?$ /index.php/$1 last;
      }
  
      location ~* /(?:[.]|.*[.](?:bak|fla|inc|ini|log|psd|sh|sql|swp)|(?:file|upload)s?/.*[.](?:php)) {
          deny all;
      }
  
      location ~* [.](?:php) {
          fastcgi_buffer_size             128k;
          fastcgi_buffers                 4 256k;
          fastcgi_busy_buffers_size       256k;
          fastcgi_connect_timeout         30;
          fastcgi_ignore_client_abort     off;
          fastcgi_index                   index.php;
          fastcgi_intercept_errors        on;
          fastcgi_pass                    unix:/var/run/php5-fpm.sock;
          fastcgi_read_timeout            60;
          fastcgi_send_timeout            60;
          fastcgi_split_path_info         ^(.+[.]php)(/.*)$;
          fastcgi_temp_file_write_size    256k;
  
          include /etc/nginx/fastcgi_params;
      }
  
      error_page 403 /403.html; location = /403.html {
          root /var/www/default/error;
      }
  
      error_page 404 /404.html; location = /404.html {
          root /var/www/default/error;
      }
  
      error_page 405 /405.html; location = /405.html {
          root /var/www/default/error;
      }
  
      error_page 500 501 502 503 504 /5xx.html; location = /5xx.html {
          root /var/www/default/error;
      }
  }
  </code></pre>
  
  <p>Is it possible to have the 40x and 50x errors served by a single location rule? Something like:</p>
  
  <pre><code>error_page 403 /403.html;
  error_page 404 /404.html;
  error_page 405 /405.html;
  error_page 500 501 502 503 504 /5xx.html;
  
  location ~ /(?:40[345]|5xx)[.]html$ {
      root /var/www/default/error;
  }
  </code></pre>
  
  <p>If the I the above, I always get the nginx default 404 errors. String matches (no operator) and exact matches (<code>=</code> operator) work, but with the the case-[in]sensitive regex operator (<code>~[*]</code>) it doesn't.</p>
  
  <p>I guess the problem is the order in which the location blocks are processed.</p>
  
  <p>Is there anyway to overcome that to reduce the unneeded <code>root</code> redundancy?</p>