While NGINX documentation states client_max_body_size
can be set within location
blocks, many administrators encounter situations where these overrides fail to take effect. The 413 "Request Entity Too Large" error persists despite proper configuration.
Here's a typical problematic configuration:
server {
client_max_body_size 10M;
location /uploads {
client_max_body_size 100M;
# This override frequently fails
}
}
The root cause often lies in request processing order. When PHP processing occurs (common for admin panels), the request body size check happens before reaching the location block.
Solution 1: Move the directive to server context with conditions
server {
set $upload_limit 10M;
if ($uri ~ ^/admin) {
set $upload_limit 256M;
}
client_max_body_size $upload_limit;
}
Solution 2: Ensure proper location matching
location ^~ /admin {
client_max_body_size 256M;
# Explicitly handle PHP processing
location ~ \.php$ {
fastcgi_param PHP_VALUE "upload_max_filesize=256M \n post_max_size=256M";
include fastcgi_params;
}
}
For an admin panel with PHP file uploads:
server {
listen 80;
server_name example.com;
# Default limit
client_max_body_size 16M;
location /admin {
# Override for admin area
client_max_body_size 256M;
# PHP handler with matching settings
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_param PHP_VALUE "upload_max_filesize=256M \n post_max_size=256M";
include fastcgi_params;
}
}
}
Check effective values using:
curl -I -X POST -H "Content-Length: 257000000" http://example.com/admin/test
Inspect NGINX debug logs for body size checks:
error_log /var/log/nginx/debug.log debug;
The client_max_body_size
directive in NGINX can indeed be placed in http
, server
, or location
blocks, with inner blocks overriding outer ones. However, there's a common pitfall when dealing with PHP processing.
When you're dealing with PHP file uploads, the request might be processed by a different location
block (typically location ~ \.php$
) before reaching your /admin
location. Here's what typically happens:
server {
# This applies to all requests
client_max_body_size 16M;
location /admin {
# This gets ignored for PHP files
client_max_body_size 256M;
}
location ~ \.php$ {
# PHP files end up here with the 16M limit
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
}
To properly handle this, you need to:
- Set the global default (16M in http block)
- Override for your admin area
- Ensure the PHP handler respects this override
Here's the working configuration:
http {
client_max_body_size 16M;
server {
server_name example.com;
root /var/www/example.com;
location /admin {
client_max_body_size 256M;
# Important: Pass to PHP handler with inherited size
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
}
}
If nested locations aren't feasible in your setup, consider these options:
# Option 1: Match admin PHP files separately
location ~ ^/admin/.+\.php$ {
client_max_body_size 256M;
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
# Option 2: Use a regex location
location ~ /admin {
client_max_body_size 256M;
try_files $uri $uri/ /index.php?$args;
}
After making changes, always:
sudo nginx -t
sudo systemctl reload nginx
Test with a large file upload using curl:
curl -X POST -H "Content-Type: multipart/form-data" \
-F "file=@large_file.zip" http://example.com/admin/upload.php