How to Disable Nginx Request Body Buffering Completely for Direct Upload Streaming


2 views

When working with media streaming applications like Madsonic behind Nginx, buffered uploads can cause significant problems:

  • Progress bars fail to update in real-time
  • Temporary files create unnecessary disk I/O
  • Memory usage spikes with large uploads
  • 31115#0 client request body warnings appear in logs

Here's the optimized configuration that completely disables all request buffering:

location / {
    proxy_pass https://madsonic-server/;
    
    # Critical buffering directives
    proxy_buffering off;
    proxy_request_buffering off;
    client_body_in_file_only off;
    
    # Buffer size adjustments
    client_body_buffer_size 0;
    client_max_body_size 0;
    proxy_max_temp_file_size 0;
    
    # Timeout extensions for large uploads
    proxy_read_timeout 18000;
    proxy_send_timeout 18000;
    client_body_timeout 18000;
    
    # HTTP protocol optimizations
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    
    # Standard proxy headers
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

Understand these critical aspects of the solution:

Directive Purpose Impact
proxy_request_buffering Disables initial request buffering Eliminates 31115 warnings
client_body_buffer_size 0 Prevents memory buffering Forces direct streaming
proxy_max_temp_file_size 0 Blocks disk buffering Reduces I/O overhead

Verify the solution works with these methods:

  1. Progress monitoring: Upload a large file (1GB+) and check if progress updates smoothly
  2. Log verification: Search Nginx error logs for "a client request body is buffered" messages
  3. Real-time testing: Use ngrep to monitor packet flow during uploads:
    ngrep -d any port 443 and host your-madsonic-server

For production environments handling heavy upload traffic:

# Kernel-level optimizations
net.ipv4.tcp_tw_reuse = 1
net.core.somaxconn = 1024
net.ipv4.tcp_fin_timeout = 30

# Nginx worker adjustments
worker_processes auto;
worker_rlimit_nofile 100000;
events {
    worker_connections 4000;
    multi_accept on;
    use epoll;
}

Watch out for these issues:

  • Firewalls interrupting long-running connections
  • Corporate proxies injecting buffering
  • SSL termination points adding their own buffering
  • Client-side JavaScript upload libraries with their own chunking

When setting up reverse proxies with Nginx, many developers encounter the frustrating a client request body is buffered to a temporary file warning. This occurs particularly during file uploads through web interfaces like Madsonic, where progress indicators fail due to buffering behavior.

By default, Nginx buffers client request bodies when:

  • The body size exceeds client_body_buffer_size
  • The request needs to be passed to a backend server
  • The client connection speed is slower than backend processing

This buffer-and-forward approach helps with performance in most cases but becomes problematic for real-time upload scenarios.

Here's the definitive configuration to eliminate all request buffering:

location / {
    proxy_pass https://madsonic-server/;
    proxy_redirect off;
    
    # Critical buffering controls
    proxy_buffering off;
    proxy_request_buffering off;
    client_body_in_file_only clean;
    client_body_buffer_size 0;
    
    # Connection tuning
    proxy_http_version 1.1;
    proxy_read_timeout 18000;
    proxy_send_timeout 18000;
    
    # Headers for proper backend handling
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

1. proxy_request_buffering off
This is the primary directive that disables buffering of client request bodies. When off, Nginx immediately begins sending data to the backend.

2. client_body_in_file_only clean
Forces Nginx to write request bodies directly to disk without buffering, then immediately deletes the files after processing.

3. client_body_buffer_size 0
Eliminates memory buffering completely by setting the buffer size to zero.

While this configuration solves the upload progress issue, be aware that:

  • Backend servers must handle slow clients directly
  • No protection against slow client attacks
  • May increase backend server load

For production environments with untrusted clients, consider implementing rate limiting separately:

limit_req_zone $binary_remote_addr zone=upload:10m rate=1r/s;

location /upload {
    limit_req zone=upload burst=5;
    # Include the bufferless config above
}

If you still see buffering occurring:

  1. Check for multiple location blocks matching your URL
  2. Verify Nginx version supports these directives (1.7.11+)
  3. Inspect both HTTP and server-level configuration
  4. Test with curl -v -T largefile.ext http://yourserver

Remember that some modules (like upload modules) may implement their own buffering regardless of these settings.