You try to upload a theme, a video or a database backup and the browser shows 413 Request Entity Too Large, or the upload just fails with a vague error. Nginx caps request bodies at 1 MB by default, and anything bigger is rejected before it reaches PHP or your app. This guide raises the limit in the right place, lines it up with PHP's own limits, and confirms the fix.
Before you start
- A Linux VPS running Nginx.
- SSH access with sudo.
- The size you actually need. Pick a sensible number such as 64 MB rather than an unlimited value.
Confirm it is Nginx
A 413 from Nginx shows a plain page with 413 Request Entity Too Large and nginx at the bottom. The error log confirms it:
sudo grep "client intended to send too large body" /var/log/nginx/error.log | tail -5A line like this means Nginx rejected the upload:
client intended to send too large body: 52428800 bytes, client: 198.51.100.20, server: example.com, request: "POST /wp-admin/async-upload.php HTTP/2.0"The number is the size of the upload in bytes. If you see nothing here but uploads still fail, the limit is in PHP or your app; skip to Match PHP's limits.
Where the setting goes
client_max_body_size can be set in three places. A lower level overrides a higher one:
http: every site on the server.server: one site.location: one path, such as an upload endpoint.
Setting it per site is usually best. Each site gets only what it needs.
Raise the limit for one site
Open the site's config, for example /etc/nginx/sites-available/example.com on Ubuntu/Debian or /etc/nginx/conf.d/example.com.conf on AlmaLinux/Rocky. Add the line inside the server block:
server {
server_name example.com;
client_max_body_size 64M;
}Keep your existing lines; only add client_max_body_size. If the site has separate blocks for port 80 and 443, put it in the 443 block that serves the site.
To raise it only for one path, such as an admin upload URL:
location /wp-admin/ {
client_max_body_size 256M;
try_files $uri $uri/ /index.php?$args;
}Remember the PHP request is often handled in a separate location ~ \.php$ block. A limit set in /wp-admin/ does not apply to it, because the upload is a POST to a .php file. Setting the value at server level avoids this trap.
Raise the limit for every site
Create a small file in conf.d, which is loaded in the http context:
echo "client_max_body_size 64M;" | sudo tee /etc/nginx/conf.d/upload-size.confCheck it is not already set in nginx.conf first, or the test will report a duplicate:
sudo grep -rn client_max_body_size /etc/nginx/0 disables the check entirely. Avoid it on public sites, since it lets anyone send unlimited data to your server.
Apply the change
sudo nginx -t && sudo systemctl reload nginxMatch PHP's limits
PHP has its own limits. The smallest limit in the chain wins. Set these in your PHP-FPM php.ini:
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 120upload_max_filesizeis the largest single file.post_max_sizeis the whole request and must be at least as large asupload_max_filesize.
Find the right php.ini file:
- Ubuntu/Debian:
/etc/php/8.3/fpm/php.ini(replace8.3with your version; list them withls /etc/php). - AlmaLinux/Rocky:
/etc/php.ini.
Then restart PHP-FPM:
sudo systemctl restart php8.3-fpmOn AlmaLinux and Rocky, the service is php-fpm. Full details are in Raise PHP upload limits.
Other places a limit can hide
- Cloudflare: the free plan rejects request bodies over 100 MB at the edge, regardless of your server settings. Upload large files through a hostname that is not proxied, or split them.
- A second proxy: if another Nginx or a load balancer sits in front, raise the limit there too.
- The app itself: WordPress, Laravel and others may enforce their own maximum. WordPress shows its current limit under Media → Add New.
Check it works
Create a test file slightly smaller than the new limit and post it:
head -c 50M /dev/urandom > /tmp/test-upload.bin
curl -s -o /dev/null -w '%{http_code}\n' -F "file=@/tmp/test-upload.bin" https://example.com/
rm /tmp/test-upload.binAny status except 413 means Nginx accepted the body. A 405 or 404 is normal here, because the test posts to a page that does not accept uploads. Then try a real upload in your app's admin area.
Troubleshooting
- Still 413 after the change: the reload did not happen, or the setting is in a block that does not handle the request. Run
sudo nginx -T | grep client_max_body_sizeand check which block each line is in. - No 413, but the upload fails or the file is empty: PHP's
post_max_sizeorupload_max_filesizeis lower. Raise both and restart PHP-FPM. - Large uploads time out instead: the upload takes longer than PHP or proxy timeouts. See Fix 504 Gateway Timeout in Nginx.
- phpMyAdmin imports still fail: it has its own limits. See phpMyAdmin import size limit.
Next steps
- WordPress-specific upload limits: Increase the WordPress upload size.
- Make sure the server has room for big files: Free disk space on Linux.
