How to correctly configure Nginx's client_max_body_size | Troubleshooting upload limits
When implementing file uploads in Nginx, the issue of "small files upload fine but large files result in a 413 error" is encountered very frequently. The cause is almost always insufficient <code>client_max_body_size</code> configuration. However, simply fixing the Nginx configuration often doesn't resolve the issue, and you need a comprehensive understanding including PHP's <code>upload_max_filesize</code> and <code>post_max_size</code>, as well as timeout settings. This article systematically explains all configuration items related to upload limits.
Default Value and Role of client_max_body_size
Nginx has a <code>client_max_body_size</code> directive that limits the maximum size of request bodies from clients. The default value is <code>1m</code> (1 MiB). Requests exceeding this limit are immediately rejected with a <code>413 Request Entity Too Large</code> error.
Since the default is as small as 1m, you'll quickly hit the limit even when uploading a single image or PDF. In actual production environments, you need to raise this value appropriately according to your use case.
Configuration location: differences between http / server / location
<code>client_max_body_size</code> can be set at any configuration level in Nginx (http / server / location). More specific scope settings take precedence.
# http ブロック(全サーバー共通)
http {
client_max_body_size 10m;
server {
listen 80;
server_name example.com;
# server ブロック(このバーチャルホスト全体)
client_max_body_size 50m;
location /upload {
# location ブロック(このパスのみ)
# より大きなファイルを許可したい場合
client_max_body_size 200m;
proxy_pass http://app;
}
location /api {
# APIエンドポイントはデフォルト(1m)のままにする例
client_max_body_size 1m;
}
}
}
Setting a larger value only for upload-specific endpoints while keeping others small is the security best practice. You can specify <code>0</code> for unlimited, but this increases DoS attack risk and is not recommended.
413 Request Entity Too Large error: causes and solutions
We will organize the causes and countermeasures for 413 errors.
| Cause | Points to Check | Countermeasure |
|---|---|---|
| Nginx Limit Exceeded | <code>client_max_body_size</code> in nginx.conf | Increase the value |
| PHP limit exceeded | <code>upload_max_filesize</code> in php.ini | Increase the value |
| Exceeded limit for entire POST body | <code>post_max_size</code> in php.ini | Make it larger than upload_max_filesize |
| Reverse Proxy Limits | Upstream Nginx or load balancer configuration | Check proxies at each stage |
After changing Nginx configuration, you must always reload.
# 設定の文法チェック
nginx -t
# 設定のリロード(サービス停止なし)
nginx -s reload
# または systemd 経由
systemctl reload nginx
Relationship with PHP's upload_max_filesize / post_max_size
Simply raising Nginx's <code>client_max_body_size</code> is not enough. If the backend is PHP, there are independent limits at the PHP level as well. Upload succeeds only when all three of these settings are set to appropriate values.
; php.ini の設定
; 1ファイルあたりの上限
upload_max_filesize = 100M
; POSTリクエスト全体の上限(upload_max_filesize より大きくする)
; multipart/form-data のオーバーヘッド分を見込んで多めに設定
post_max_size = 110M
; メモリ上限(post_max_size より大きくする)
memory_limit = 256M
; アップロード処理の実行時間(大容量ファイル用に延ばす)
max_execution_time = 300
max_input_time = 300
The relationships between important configuration values are as follows.
- client_max_body_size(Nginx) ≥ post_max_size(PHP) ≥ upload_max_filesize(PHP)
- If Nginx rejects a request, the processing never reaches PHP
- <code>post_max_size</code> is the size limit for the entire POST body, including multiple file uploads and non-file form fields
Importance of proxy_read_timeout / proxy_send_timeout
When uploading large files, timeout settings are also important. The default <code>proxy_read_timeout</code> is 60 seconds, and if the upload takes time, the process will be interrupted.
location /upload {
client_max_body_size 500m;
proxy_pass http://app_backend;
# バックエンドからのレスポンス待機時間
# 大容量ファイルの処理には長めに設定
proxy_read_timeout 600s;
# クライアントへのデータ送信待機時間
proxy_send_timeout 600s;
# バックエンドへの接続タイムアウト
proxy_connect_timeout 60s;
# クライアントのリクエストボディ受信タイムアウト
# 2回の連続した読み取り操作の間の時間
client_body_timeout 120s;
}
It is recommended to set different timeout values for upload endpoints and regular API endpoints.
Configuration in Docker (nginx.conf Mounting)
In Docker environments, custom nginx.conf or conf.d files are mounted into containers to apply configuration.
# Dockerfile でのカスタム設定追加
FROM nginx:alpine
# カスタム設定ファイルをコピー
COPY ./nginx/conf.d/upload.conf /etc/nginx/conf.d/upload.conf
# デフォルト設定を完全に置き換える場合
# COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
# docker-compose.yml でのボリュームマウント
version: '3.8'
services:
nginx:
image: nginx:alpine
volumes:
# ディレクトリごとマウント(変更が即反映される)
- ./nginx/conf.d:/etc/nginx/conf.d
# または特定ファイルだけマウント
# - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
ports:
- "80:80"
# nginx/conf.d/upload.conf
server {
listen 80;
server_name localhost;
# グローバルのアップロード上限
client_max_body_size 100m;
location / {
proxy_pass http://app:9000;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
location /upload {
client_max_body_size 500m;
proxy_pass http://app:9000;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
}
}
Configuration Verification Command
To check what value <code>client_max_body_size</code> is set to in your current Nginx configuration, it's convenient to expand all settings with <code>nginx -T</code> and then grep the result.
# 全設定を展開して client_max_body_size を検索
nginx -T | grep -i body_size
# 出力例:
# client_max_body_size 1m; ← デフォルト(http ブロック)
# client_max_body_size 100m; ← カスタム設定(server ブロック)
# 設定ファイルのパスも確認
nginx -T | grep "# configuration"
# 特定の設定ファイルだけチェック
nginx -t -c /etc/nginx/nginx.conf
# 現在読み込まれている設定のダンプ
nginx -T 2>/dev/null | grep -A1 "client_max"
Common configuration errors and how to fix them
- <strong>Unit error</strong>: <code>client_max_body_size 100</code> defaults to bytes. Always specify a unit like <code>100m</code>
- <strong>Hierarchy oversight</strong>: You think you're overriding within a location block, but a higher-level server block or http block is taking effect
- <strong>Forgetting to reload</strong>: Configuration changes won't take effect unless you run <code>nginx -s reload</code>
- <strong>Multiple server blocks</strong>: Another conf.d file loaded via include is conflicting
- <strong>Mismatch with PHP</strong>: Even after increasing Nginx limits, if PHP's <code>upload_max_filesize</code> remains low, errors other than 413 may occur
Test files for this article (free)
- → <a href="/ja/files/threshold/" class="text-primary-600 dark:text-primary-400 hover:underline">Boundary Value Test Files</a> — Reproduce errors at the client_max_body_size configuration threshold
- → <a href="/ja/files/images/png/" class="text-primary-600 dark:text-primary-400 hover:underline">PNG Test Images List</a> — Verify Nginx limits with PNG images of various sizes
Related articles
- → <a href="/ja/blog/how-to-test-upload-limit/" class="text-primary-600 dark:text-primary-400 hover:underline">How to Properly Test File Upload Limits</a>
- → <a href="/ja/blog/multipart-form-data-overhead/" class="text-primary-600 dark:text-primary-400 hover:underline">Calculating multipart/form-data Overhead Accurately</a>
- → <a href="/ja/blog/mb-vs-mib-file-size/" class="text-primary-600 dark:text-primary-400 hover:underline">Difference Between MB and MiB | Correct Understanding of File Size Units</a>