PHP configuration: Customizing NGINX’s error page handling

5 minute read | By Anthony Salemo

This post will cover how to alter NGINX’s error page handling when using PHP 8.x “Blessed Images” on App Service Linux.

Overview

With PHP 8.x Blessed Images using NGINX (the current default), if the application returns a status code in the range of 5xx - this may surface as a response from NGINX as an HTTP 404

NGINX HTTP 404

While in application logging, you may see:

127.0.0.1 -  21/Jun/2023:15:56:54 +0000 "GET /index.php" 502

Or

127.0.0.1 -  21/Jun/2023:16:56:15 +0000 "GET /index.php" 500

This is because of the below directive and location block in /etc/nginx/sites-available/default:

# redirect server error pages to the static page /50x.html
#
error_page   500 502 503 504  /50x.html;
location = /50x.html {
   root   /html/;
}

Ultimately, the reason is that 50x.html does not exist on the file system. Therefor, a 404 is returned. This can be misleading if not aware. There is a few ways we can change the behavior here.

Override NGINX’s default behavior

To start, you need to override NGINX’s configuration by following this post - NGINX Rewrite Rules for Azure App Service Linux PHP 8.x - or if using frameworks that serve content out of a different directory, like Laravel (Laravel Deployment on App Service Linux) - this can be followed.

We can now change the behavior in a few different ways.

IMPORTANT: None of these methods will alter an applications debug mode. You still may need to enable debug mode, depending on the situation, which must be done from an application standpoint - eg., APP_DEBUG, WP_DEBUG, etc.

Return the error directly from the application

The easiest way to do this is to override /etc/nginx/sites-available/default by commenting out both the block and directive:

# redirect server error pages to the static page /50x.html
#
# error_page   500 502 503 504  /50x.html;
# location = /50x.html {
#   root   /html/;
# }

Laravel HTTP 500

We see here this HTTP 500 is now returned directly from Laravel - instead of seeing an HTTP 404 from NGINX.

Return the status code from NGINX

You can return the status code sent back by the application by updating only the error_page directive - delete or comment out the 50x.html location block from earlier:

error_page   500 502 503 504 /index.php;

The .php file must be relative to where root is set. For example, root may be set to/home/site/wwwroot/public - this index.php file must be under this directory.

For example, here we’re purposefully returning an HTTP 502:

return response('test', 502);

NGINX HTTP 502

But organic application errors, like HTTP 500’s, will be surfaced like this as well:

NGINX HTTP 500

Return a custom error page from NGINX

We can return a custom error page through NGINX using the directives and location block above. We’d need to first:

  • Create a 50x.html file on the file system. Put whatever desired content in here as needed.
  • Place this under an appropriate directory. For example, /home/site/wwwroot

Change our location and directives to something like the below:

# redirect server error pages to the static page /50x.html
#
error_page   500 502 503 504  /50x.html;
location = /50x.html {
   root   /home/site/wwroot;
}

With some HTML like the below, you should see the following on a route encountering a 5xx status code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Error</title>
</head>
<body>
    <h1>NGINX - Custom Error Page</h1>
</body>
</html>

NGINX Custom error page

Further troubleshooting

App Service Logs

If further troubleshooting is needed, ensure that App Service Logs are enabled. You can then view logging in a few different ways:

  • LogStream
  • logs directly from the Kudu site, or directly view/download via an FTP client
  • Diagnose and Solve Problems -> Application Logs detector, Container Crash detector, or Container Issues

If App Service Logs are not enabled, only docker.log files will be generated, which will not show application related stdout / stderr and will make troubleshooting issues more complicated. default_docker.log files are the files that show application stdout/err.

Application Debug logging

Do not solely rely on this configuration change for debugging - enabling App Service Logs plus the relevant environment variable or configuration for application debug mode, which will depend on the framework/library/application type use, while reproducing the issue can help uncover the issue faster.

NGINX errors - “Reloading nginx configuration: nginx failed!”

If you’re overriding NGINX via startup command or script, you may see this:

Reloading nginx configuration: nginx failed!

This most likely may be happening due to invalid syntax in one of the NGINX files.

You can use the nginx -t command for a syntax check. In this case, it may call out an issue like the below:

root@fb9fbe0e7314:/home# nginx -t
nginx: [emerg] directive "server" has no opening "{" in /etc/nginx/sites-enabled/default:1
nginx: configuration file /etc/nginx/nginx.conf test failed