When dealing with static HTML sites on Nginx, a common pitfall is encountering infinite redirect cycles when trying to handle missing files. The configuration you've shared reveals several potential issues that could lead to this behavior.
server {
listen 127.0.0.1:8080;
server_name .somedomain.com;
root /var/www/somedomain.com;
location ~* \\.php.$ {
include /etc/nginx/fastcgi.conf;
}
location / {
root /var/www/somedomain.com;
try_files $uri $uri/ ;
}
error_page 404 /errors/404.html;
location /errors/ {
alias /var/www/errors/;
}
}
The infinite redirect cycle occurs because of how Nginx processes the try_files
directive combined with the error page handling. Here's what's happening:
- When a non-existent file is requested, Nginx checks
$uri
then$uri/
- When both fail, it triggers the 404 error page
- The 404 error page path gets processed through the same
try_files
logic - This creates an endless loop
Here's the fixed configuration:
server {
listen 127.0.0.1:8080;
server_name .somedomain.com;
root /var/www/somedomain.com;
location ~* \\.php$ {
include /etc/nginx/fastcgi.conf;
fastcgi_intercept_errors on;
}
location / {
try_files $uri $uri/ =404;
}
location = /errors/404.html {
internal;
alias /var/www/errors/404.html;
}
error_page 404 /errors/404.html;
}
- Added
=404
totry_files
to properly terminate the search - Made the 404.html location block internal-only
- Fixed the PHP regex pattern (removed trailing dot)
- Added
fastcgi_intercept_errors on
for PHP files
To verify the fix works:
curl -I http://somedomain.com/nonexistent-page.html
Should return HTTP 404 with your custom error page, without any redirect loops.
Consider these additional improvements:
# Cache error pages
location /errors/ {
alias /var/www/errors/;
expires 30d;
access_log off;
}
# Handle common static files more efficiently
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
add_header Cache-Control "public";
}
When testing a static HTML site with Nginx, you might encounter an infinite redirect loop when accessing non-existent PHP files, despite having proper error_page directives configured. The error log typically shows:
2023/03/15 10:00:00 [error] 1234#0: *1 rewrite or internal redirection cycle while internally redirecting to "/errors/404.html"
The core issue stems from how Nginx processes try_files
and error_page
directives. Let's examine the problematic config:
server {
listen 127.0.0.1:8080;
server_name .somedomain.com;
root /var/www/somedomain.com;
location ~* \.php.$ {
include /etc/nginx/fastcgi.conf;
}
location / {
root /var/www/somedomain.com;
try_files $uri $uri/ ;
}
error_page 404 /errors/404.html;
location /errors/ {
alias /var/www/errors/;
}
}
The redirect cycle occurs because:
- Nginx first tries to serve the PHP file via the location block
- When not found, it falls back to the
/
location withtry_files
- The 404 error then redirects to
/errors/404.html
- This new request gets caught in the same cycle
Here's the corrected configuration that prevents the loop:
server {
listen 127.0.0.1:8080;
server_name .somedomain.com;
root /var/www/somedomain.com;
# Handle PHP files explicitly
location ~ \.php$ {
try_files $uri =404;
include /etc/nginx/fastcgi.conf;
fastcgi_pass unix:/var/run/php-fpm.sock;
}
# Static files
location / {
try_files $uri $uri/ =404;
}
# Custom error page outside root
location = /404.html {
root /var/www/errors;
internal;
}
error_page 404 /404.html;
}
- Added explicit
=404
fallback intry_files
- Separated error document handling with
internal
directive - More specific PHP file matching with
\.php$
- Explicit fastcgi_pass directive for PHP processing
Verify the fix by:
curl -I http://somedomain.com/nonexistent.php
# Should return 404 with your custom page
Check your error logs to confirm the redirect loop is resolved:
tail -f /var/log/nginx/somedomain.com-error.nginx.log