I've finally worked most of it out. Thanks everyone for your tips and putting the time in to write answer.
The issue is that our error404.php
was returning our error page with an 404 Not Found header too (using header('HTTP/1.0 404 Not Found');
) and Nginx was then intercepting this error as recursive_error_pages
is off (default) and it was showing its own 404 page. Switching off fastcgi_intercept_errors
is the solution. If we remove the header('HTTP/1.0 404 Not Found');
from the error file then we'd get the error but with a 200
which is obviously not what we want.
This does not, however, solve the problem of accessing a missing page which ends with .php
(so it matches the location block as we are now getting back the standard PHP-FPM response to those of a 404 header with the body File not found.
. I could use Nate's answer to get around this, but I'd rather not need to specify all the file names there. I'll look for another solution for this and post it here when I get one.
EDIT: A more full solution:
You need to intercept errors in your main php location block (fastcgi_intercept_errors
is on
) and then have another block for your error pages where you don't intercept them. See this config example:
server {
listen 80;
listen 443 ssl;
server_name mydomain.co.uk;
ssl_certificate /xxxxxxx.crt;
ssl_certificate_key /xxxxxxx.key;
# Custom error pages
recursive_error_pages off;
error_page 404 = /http_errors/404.php;
# error_page 500 501 502 503 504 = /error5xx.php; # Not sure about this yet!
# Any simple .php page
location ~ \.php$ {
root /var/www/xxxxx;
include /etc/nginx/fastcgi.conf;
fastcgi_pass phpfastcgiservers;
include fastcgi_params;
fastcgi_intercept_errors on;
}
# Handling error pages
location ^~ /http_errors/ {
internal;
root /var/www/xxxxx;
include /etc/nginx/fastcgi.conf;
fastcgi_pass phpfastcgiservers;
include fastcgi_params;
fastcgi_intercept_errors off;
}
}
This will mean that any of your PHP pages which return an HTTP status code of 404 will have their own content (if any) ignored and the content of your /http_errors/404.php
file will be used instead.