PHP configuration: Customizing NGINX’s error page handling
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
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/;
# }
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);
But organic application errors, like HTTP 500’s, will be surfaced like this as well:
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>
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