Handling large file uploads (100MB+) with Nginx requires configuration changes at multiple levels — Nginx, your application framework, and potentially PHP-FPM. Misconfigurations cause frustrating "413 Request Entity Too Large" errors or timeouts during uploads. This guide covers configuring Nginx for reliable large file uploads.
Nginx Configuration
# /etc/nginx/nginx.conf or site config
http {
# Maximum upload size (default: 1M)
client_max_body_size 500M;
# Buffer settings for large uploads
client_body_buffer_size 128k;
client_body_temp_path /var/cache/nginx/uploads 1 2;
# Timeout settings (large files take time)
client_body_timeout 300s;
send_timeout 300s;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
proxy_connect_timeout 60s;
server {
listen 443 ssl http2;
# Per-location override
location /upload {
client_max_body_size 2G; # 2GB limit for this endpoint
client_body_buffer_size 256k;
client_body_timeout 600s;
proxy_pass http://127.0.0.1:8080;
proxy_request_buffering off; # Stream directly to backend
proxy_http_version 1.1;
proxy_set_header Connection "";
}
# Regular locations use the default 500M limit
location / {
proxy_pass http://127.0.0.1:8080;
}
}
}
Streaming Uploads (Proxy Buffering Off)
# For very large files, disable request buffering
# Nginx will stream the body directly to the backend
# instead of buffering it to disk first
location /upload {
proxy_pass http://127.0.0.1:8080;
proxy_request_buffering off; # Don't buffer to disk
# The backend receives data as it arrives
# Reduces disk I/O and latency for large uploads
# Still need adequate timeouts
proxy_read_timeout 600s;
client_body_timeout 600s;
}
PHP-FPM Configuration
# php.ini settings for large uploads
upload_max_filesize = 500M
post_max_size = 512M # Must be slightly larger than upload_max_filesize
memory_limit = 768M # Must be larger than post_max_size
max_execution_time = 300
max_input_time = 300
# PHP-FPM pool settings
request_terminate_timeout = 300
# Restart PHP-FPM
sudo systemctl restart php8.3-fpm
Chunked Upload for Very Large Files
# For files over 1GB, implement chunked uploads in your application
# Frontend sends file in chunks; backend reassembles
# Nginx config for chunked uploads
location /upload/chunk {
client_max_body_size 50M; # Each chunk is small
client_body_buffer_size 50M;
proxy_pass http://127.0.0.1:8080;
proxy_set_header Content-Range $http_content_range;
proxy_set_header X-Upload-ID $arg_upload_id;
}
# JavaScript example (using tus or custom chunking):
# const CHUNK_SIZE = 10 * 1024 * 1024; // 10MB chunks
# for (let offset = 0; offset < file.size; offset += CHUNK_SIZE) {
# const chunk = file.slice(offset, offset + CHUNK_SIZE);
# await fetch('/upload/chunk?upload_id=' + uploadId, {
# method: 'POST',
# headers: { 'Content-Range': `bytes ${offset}-${offset+chunk.size-1}/${file.size}` },
# body: chunk
# });
# }
Upload Progress Tracking
# Nginx upload progress module (nginx-upload-progress-module)
# Or use the Nginx Upload Module for direct file handling
# Alternative: Use application-level progress
# The backend can track upload progress and expose it via API
# WebSocket-based progress
location /upload/progress {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Disk Space and Temp Files
# Nginx buffers uploads to disk in client_body_temp_path
# Ensure adequate disk space and permissions
# Check temp directory
ls -la /var/cache/nginx/uploads/
# Create with correct permissions
sudo mkdir -p /var/cache/nginx/uploads
sudo chown www-data:www-data /var/cache/nginx/uploads
# Monitor disk during uploads
df -h /var/cache/nginx/
# Clean up stale temp files
find /var/cache/nginx/uploads -type f -mtime +1 -delete
Best Practices
- Set
client_max_body_sizeat the location level for upload endpoints — don't set it globally to 2G - Use
proxy_request_buffering offfor large files to avoid disk buffering - Implement chunked uploads for files over 1GB for reliability and resumability
- Match timeouts: Nginx, PHP-FPM, and your app framework all need adequate timeout values
- Monitor temp disk usage during high-volume upload periods
- Set PHP
post_max_sizeslightly larger thanupload_max_filesize