Nginx, PHP + FPM Custom Error Pages

Ken picture Ken · Mar 18, 2014 · Viewed 8k times · Source

I am trying to create some custom error pages but can't seem to get the 500 one working.

I have the following config:

server {
    listen 80;

    root /var/www/devsite;
    index index.php;
    server_name devsite;

    error_page 403 = /error.php?code=403;   
    error_page 404 = /error.php?code=404;
    error_page 500 = /error.php?code=500;

    location / {
        try_files $uri =404;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }

}

At first, I thought it might be because it's a PHP file so I changed:

error_page 500 = /error.php?code=500;

To a static page:

error_page 500 /500.html

But it still just shows a blank page with a 500 response code when I break some PHP code to trigger it.

I then tried to make it the last rule inside location ~ \.php$ but the same happens. Any ideas why the custom 500 page won't work?

I also notice that if you try to access an "access denied" file that has the .php extension, it will not show the custom 403 page and show the built-in page instead. Is there a way to make the rule cover .php files too?

Answer

Stecman picture Stecman · Mar 20, 2014

The piece you're missing is the fastcgi_intercept_errors directive. Without this directive, Nginx won't touch responses from CGI backends, so long as they are valid:

Determines whether FastCGI server responses with codes greater than or equal to 300 should be passed to a client or be redirected to nginx for processing with the error_page directive.

You need to put the following in your PHP handling location:

fastcgi_intercept_errors on;

As an aside, you may not need the = in your error_page lines (depending on your intended use). This syntax instructs Nginx to use the response code returned from the PHP script you're pointing to instead of the original response code:

If an error response is processed by a proxied server or a FastCGI server, and the server may return different response codes (e.g., 200, 302, 401 or 404) ... respond with the code it returns.