Replace Nginx’s plain default error pages with your own, while keeping the right HTTP status code.
server {
listen 80;
server_name example.com;
root /var/www/example.com;
# Map status codes to your pages.
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /404.html {
internal;
}
location = /50x.html {
internal;
}
}
Details:
error_page 404 /404.html;tells Nginx to serve/404.htmlwhen a 404 occurs. The browser still receives a 404 status (not 200), which is what crawlers and monitoring expect.internal;makes/404.htmlreachable only via an internal redirect (the error handler) — visitinghttps://example.com/404.htmldirectly returns 404. Without it the page is publicly fetchable.- The error page files live under your
rootlike any static file. Keep them self-contained (inline CSS, no broken asset links) so they render even when the rest of the site is down.
Show your own page for upstream errors too (when proxying):
location / {
proxy_pass http://127.0.0.1:3000;
proxy_intercept_errors on; # let Nginx replace upstream 5xx with your page
error_page 502 503 504 /50x.html;
}
Without proxy_intercept_errors on;, the backend’s own error body is passed through unchanged.
sudo nginx -t && sudo nginx -s reload