When setting up Nginx as a reverse proxy, you might encounter situations where the backend service becomes temporarily unavailable. In such cases, instead of showing generic error messages or blank pages, it's better to display a custom maintenance page to your users.
Here's what's happening with the current setup:
server {
listen 80;
server_name "";
location / {
proxy_pass http://127.0.0.1:9080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 1;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504 http_404;
proxy_intercept_errors on;
}
error_page 501 502 503 @maintenance;
location @maintenance {
root /locust/www/fallback/htdocs;
index index.html index.htm;
}
}
The configuration has several problems preventing the fallback from working:
- The
error_page
directive only handles 501, 502, and 503 status codes - Nginx might be returning different error codes when the backend is down
- The root path needs proper verification
Here's a corrected configuration that properly handles backend unavailability:
server {
listen 80;
server_name example.com;
# Maintenance page location
location /maintenance.html {
root /var/www/html;
internal;
}
location / {
proxy_pass http://127.0.0.1:9080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Timeout settings
proxy_connect_timeout 1s;
proxy_read_timeout 1s;
proxy_send_timeout 1s;
# Error handling
proxy_intercept_errors on;
error_page 500 502 503 504 /maintenance.html;
}
}
The working solution includes several important changes:
- Added proper timeout settings for all proxy operations
- Expanded the error codes to include common proxy failures (500, 502, 503, 504)
- Simplified the maintenance page handling using a direct file reference
- Made the maintenance page accessible only internally
To verify it works:
# Test configuration
sudo nginx -t
# Simulate backend failure
sudo service your-backend-service stop
# Check response
curl -I http://your-domain.com
For more complex scenarios, consider:
# Using regex to match multiple error codes
error_page 5xx /maintenance.html;
# Custom error page for different status codes
error_page 502 /502.html;
error_page 503 /503.html;
# Serving different maintenance pages based on URI
location ~ ^/(api|admin) {
proxy_pass http://127.0.0.1:9080;
error_page 502 /api-maintenance.html;
}
- Ensure your maintenance page doesn't exceed Nginx buffer limits
- Verify file permissions on your maintenance HTML files
- Don't forget to include proper MIME types for your error pages
- Test with different error scenarios (timeout, connection refused, etc.)
When implementing error handling:
- Keep maintenance pages small (under 10KB recommended)
- Consider caching maintenance pages in memory
- Avoid external resources in maintenance pages (CSS, JS, images)
- Use browser cache headers for static maintenance pages
When setting up Nginx as a reverse proxy, it's common to encounter situations where the backend service becomes temporarily unavailable. While Nginx provides robust proxy features, properly handling these failure scenarios requires specific configuration.
The original configuration attempts to handle this with:
error_page 501 502 503 @maintenance;
location @maintenance {
root /locust/www/fallback/htdocs;
index index.html index.htm;
}
The key issue lies in the HTTP status codes being intercepted. When a backend service is unavailable, Nginx typically returns a 502 (Bad Gateway) or 504 (Gateway Timeout) error. However, the configuration only handles 501, 502, and 503.
Here's a working configuration that properly handles all common proxy failure scenarios:
server {
listen 80;
server_name "";
location / {
proxy_pass http://127.0.0.1:9080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Timeout settings
proxy_connect_timeout 1s;
proxy_read_timeout 2s;
proxy_send_timeout 2s;
# Error handling
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_intercept_errors on;
}
# Handle all possible proxy failure codes
error_page 500 502 503 504 /maintenance.html;
location = /maintenance.html {
root /locust/www/fallback/htdocs;
internal;
}
}
The improved solution includes:
- More comprehensive timeout settings
- Broader range of handled error codes (500-504)
- Simplified error page handling using a direct path
internal
directive to prevent direct access
To verify it works:
- Start Nginx with the new configuration
- Make sure your backend service is running
- Stop the backend service
- Access your Nginx server - you should see the maintenance page
For production environments, you might want to add:
# Cache control for maintenance page
location = /maintenance.html {
add_header Cache-Control "no-store";
expires 0;
# ... rest of config ...
}
This ensures browsers won't cache the maintenance page when the service comes back online.