Ограничение размера загружаемых файлов в Nginx
Пошаговая настройка client_max_body_size в Nginx для сайта, отдельного location и reverse proxy с проверкой ошибки 413 Request Entity Too Large.
Nginx ограничивает размер тела HTTP-запроса. Если пользователь отправляет файл или форму, превышающую допустимый лимит, сервер возвращает ошибку:
413 Request Entity Too Large
В этой инструкции рассматривается только настройка директивы client_max_body_size для сайта, отдельного location и reverse proxy.
Проверено на: Ubuntu Server 24.04 LTS
Уровень сложности: начальный
Время выполнения: около 10–15 минут
Требуемый доступ: пользователь с правамиsudo
Что будет настроено
После выполнения инструкции можно будет:
- проверить текущий лимит;
- задать максимальный размер загрузки для сайта;
- ограничить только отдельный URL;
- настроить лимит для reverse proxy;
- проверить ошибку
413; - согласовать лимит Nginx с приложением;
- безопасно применить и отменить изменение.
Что ограничивает client_max_body_size
Директива:
client_max_body_size
ограничивает размер тела HTTP-запроса.
Это относится не только к файлам, но и к:
- multipart/form-data;
- JSON;
- XML;
- POST-формам;
- API-запросам;
- загрузке архивов;
- импорту данных.
Пример значения
client_max_body_size 20m;
Означает максимальный размер тела запроса около 20 МБ.
Поддерживаемые суффиксы:
k — килобайты
m — мегабайты
g — гигабайты
Примеры:
client_max_body_size 512k;
client_max_body_size 10m;
client_max_body_size 1g;
Где можно задавать директиву
client_max_body_size можно указывать в контекстах:
http
server
location
В http
Лимит применяется ко всем сайтам Nginx.
В server
Лимит применяется к одному виртуальному хосту.
В location
Лимит применяется только к конкретному URL-префиксу.
Для большинства случаев безопаснее задавать лимит в конкретном server или location.
Проверка активной конфигурации
sudo nginx -T |
grep -n 'client_max_body_size'
Если команда ничего не вернула, используется значение по умолчанию.
Проверьте конкретный server block:
sudo nginx -T |
grep -n -A20 -B5 'server_name example.com'
Определение нужного лимита
Не задавайте заведомо слишком большое значение.
Ориентируйтесь на фактический сценарий:
Аватары: 2–5 МБ
Документы: 10–50 МБ
Архивы: 100–500 МБ
Видео: отдельный upload endpoint или object storage
Размер должен учитывать требования приложения и доступные ресурсы сервера.
Создание резервной копии
sudo cp /etc/nginx/sites-available/example.com /etc/nginx/sites-available/example.com.before-upload-limit
Проверьте:
ls -l /etc/nginx/sites-available/example.com*
Лимит для всего сайта
Откройте:
sudo nano /etc/nginx/sites-available/example.com
Добавьте внутри server:
server {
listen 443 ssl;
server_name example.com;
client_max_body_size 20m;
location / {
try_files $uri $uri/ =404;
}
}
Теперь все запросы к этому виртуальному хосту ограничены значением 20 МБ.
Лимит только для upload endpoint
Пример:
server {
server_name example.com;
location / {
try_files $uri $uri/ =404;
}
location /upload/ {
client_max_body_size 100m;
proxy_pass http://127.0.0.1:3000;
}
}
Остальная часть сайта будет использовать стандартное или родительское значение.
Разные лимиты для разных разделов
server {
server_name example.com;
client_max_body_size 10m;
location /profile/avatar/ {
client_max_body_size 5m;
proxy_pass http://127.0.0.1:3000;
}
location /documents/import/ {
client_max_body_size 100m;
proxy_pass http://127.0.0.1:3000;
}
location / {
proxy_pass http://127.0.0.1:3000;
}
}
Настройка для reverse proxy
Пример:
server {
listen 443 ssl;
server_name app.example.com;
client_max_body_size 50m;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $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;
}
}
Nginx проверяет размер запроса до передачи backend-приложению.
Настройка в отдельном snippet
Создайте:
sudo nano /etc/nginx/snippets/upload-limit.conf
Добавьте:
client_max_body_size 50m;
Подключите в server block:
include /etc/nginx/snippets/upload-limit.conf;
Такой подход удобен, если одинаковый лимит используется в нескольких сайтах.
Проверка конфигурации
sudo nginx -t
Ожидаемый результат:
syntax is ok
test is successful
Применение
sudo systemctl reload nginx
Проверьте:
systemctl status nginx --no-pager
Создание тестового файла
Файл размером 5 МБ:
dd if=/dev/zero of=/tmp/upload-5m.bin bs=1M count=5
Файл размером 25 МБ:
dd if=/dev/zero of=/tmp/upload-25m.bin bs=1M count=25
Проверьте:
ls -lh /tmp/upload-5m.bin /tmp/upload-25m.bin
Проверка через curl
Если приложение принимает multipart upload:
curl -v -F "file=@/tmp/upload-5m.bin" https://example.com/upload/
Для большого файла:
curl -v -F "file=@/tmp/upload-25m.bin" https://example.com/upload/
При лимите 20 МБ второй запрос должен вернуть:
413 Request Entity Too Large
Проверка кода ответа
curl -sS -o /dev/null -w '%{http_code}\n' -F "file=@/tmp/upload-25m.bin" https://example.com/upload/
Ожидаемый результат:
413
Проверка без рабочего приложения
Даже если backend не умеет обрабатывать файл, Nginx всё равно может вернуть 413 до передачи запроса.
Это позволяет проверить сам лимит.
Для файла меньше лимита backend может вернуть другой код, например:
404
405
500
Это уже ответ приложения, а не ошибка размера Nginx.
Проверка журнала ошибок
sudo tail -50 /var/log/nginx/example.com.error.log
Для превышенного лимита обычно появляется сообщение:
client intended to send too large body
Поиск:
sudo grep -i 'too large body' /var/log/nginx/example.com.error.log |
tail -20
Проверка общего error.log
Если у сайта нет отдельного журнала:
sudo grep -i 'too large body' /var/log/nginx/error.log |
tail -20
Пользовательская страница ошибки 413
Создайте файл:
sudo mkdir -p /var/www/example.com/errors
sudo tee /var/www/example.com/errors/413.html >/dev/null <<'EOF'
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Файл слишком большой</title>
</head>
<body>
<h1>Файл слишком большой</h1>
<p>Размер загружаемого файла превышает допустимый лимит.</p>
</body>
</html>
EOF
Добавьте в server block:
error_page 413 /413.html;
location = /413.html {
root /var/www/example.com/errors;
internal;
}
Проверьте:
sudo nginx -t &&
sudo systemctl reload nginx
Важность параметра internal
internal;
запрещает прямой внешний запрос к служебной странице.
Она будет показана только при внутренней обработке ошибки Nginx.
Согласование с приложением
У приложения может быть собственный лимит.
Примеры ограничений:
- PHP
upload_max_filesize; - PHP
post_max_size; - Node.js body parser limit;
- Django upload handlers;
- ASP.NET request body size;
- Java multipart limit;
- framework-specific upload setting.
Итоговый допустимый размер определяется самым маленьким лимитом в цепочке.
Пример цепочки лимитов
Nginx: 100 МБ
Приложение: 20 МБ
Пользователь сможет пройти проверку Nginx, но приложение отклонит файл больше 20 МБ.
Другой вариант:
Nginx: 20 МБ
Приложение: 100 МБ
Nginx отклонит запрос раньше приложения.
PHP-FPM
Для PHP проверьте:
php -i |
grep -E 'upload_max_filesize|post_max_size'
Или конфигурационные файлы:
grep -RniE 'upload_max_filesize|post_max_size' /etc/php/
Обычно:
post_max_size
должен быть не меньше:
upload_max_filesize
Node.js
В Node.js лимит может задаваться в middleware.
Пример для Express:
app.use(express.json({ limit: "20mb" }));
Загрузка файлов через multipart обычно настраивается отдельной библиотекой.
Nginx и приложение должны иметь согласованные значения.
Docker-приложение
Если backend работает в контейнере, настройка Nginx на хосте не изменяет лимит приложения в контейнере.
Проверьте:
- переменные окружения;
- конфигурацию приложения;
- reverse proxy внутри Docker;
- дополнительный Nginx в контейнере.
CDN и внешний reverse proxy
Если перед Nginx находится CDN, WAF или load balancer, у него также может быть лимит размера запроса.
Цепочка:
Клиент → CDN → Nginx → приложение
Даже высокий лимит Nginx не поможет, если CDN ограничивает загрузку меньшим значением.
Таймауты для больших загрузок
Большой файл может загружаться долго.
В отдельных сценариях могут потребоваться:
client_body_timeout 60s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
Не увеличивайте таймауты без необходимости.
Медленная загрузка может быть связана с сетью, а не с размером файла.
Временные файлы тела запроса
Nginx может записывать большие тела запросов во временный каталог.
Проверьте итоговую конфигурацию:
sudo nginx -T |
grep -n 'client_body_temp_path'
Проверьте свободное место:
df -h
Большие параллельные загрузки могут создать нагрузку на диск.
Память и диск
Увеличение client_max_body_size не означает, что Nginx хранит весь файл в RAM.
Но большие запросы могут:
- использовать временные файлы;
- увеличивать дисковую нагрузку;
- занимать место;
- создавать нагрузку на backend;
- увеличивать время соединений.
Значение 0
client_max_body_size 0;
отключает проверку размера тела запроса.
Не используйте это значение без веской причины.
Неограниченная загрузка повышает риск:
- заполнения диска;
- DoS;
- перегрузки приложения;
- злоупотребления upload endpoint.
Почему слишком большой лимит опасен
Значение:
client_max_body_size 10g;
для обычной формы загрузки почти всегда избыточно.
Лучше:
- ограничить размер по реальной задаче;
- использовать object storage;
- применять multipart upload;
- ограничить частоту запросов;
- контролировать свободное место.
Несколько server block для HTTP и HTTPS
Если HTTP-блок только перенаправляет на HTTPS:
server {
listen 80;
server_name example.com;
return 301 https://example.com$request_uri;
}
Лимит загрузки нужно задавать в HTTPS server block, где фактически обрабатывается запрос.
Проверка наследования
Если лимит задан в server:
client_max_body_size 20m;
а в location:
client_max_body_size 100m;
для этого location будет использоваться 100 МБ.
Проверьте итоговую конфигурацию:
sudo nginx -T |
grep -n -A5 -B5 'client_max_body_size'
Ошибка 413 остаётся после увеличения лимита
Проверьте:
- изменён ли правильный server block;
- включён ли файл в
sites-enabled; - выполнен ли reload;
- нет ли другого Nginx;
- нет ли CDN;
- нет ли reverse proxy;
- лимит приложения;
- активную конфигурацию.
Команда:
sudo nginx -T |
grep -n 'client_max_body_size'
Проверка процесса Nginx
ps aux |
grep '[n]ginx'
Убедитесь, что запрос попадает на тот сервер, где изменена конфигурация.
Ошибка 413 приходит от приложения
Проверьте заголовки и тело ответа.
Nginx обычно пишет в error log:
client intended to send too large body
Если записи нет, ограничение может находиться в приложении или внешнем proxy.
Ошибка 413 только для одного URL
Проверьте локальные директивы:
sudo nginx -T |
grep -n -A15 -B5 'location /upload'
Внутри location может быть меньший лимит.
Ошибка 500 после увеличения лимита
Nginx пропустил запрос, но приложение не смогло его обработать.
Проверьте:
sudo journalctl -u APP_SERVICE -n 100 --no-pager
Проверьте место:
df -h
Удаление тестовых файлов
rm -f /tmp/upload-5m.bin /tmp/upload-25m.bin
Откат настройки
Восстановите резервную копию:
sudo cp /etc/nginx/sites-available/example.com.before-upload-limit /etc/nginx/sites-available/example.com
Проверьте:
sudo nginx -t
Примените:
sudo systemctl reload nginx
Безопасный порядок настройки
- Определить фактический необходимый размер.
- Проверить лимит приложения.
- Создать резервную копию.
- Добавить
client_max_body_size. - Выполнить
nginx -t. - Выполнить reload.
- Создать файл меньше лимита.
- Создать файл больше лимита.
- Проверить HTTP-коды.
- Проверить error log.
- Проверить свободное место.
- Удалить тестовые файлы.
Быстрый набор команд
Добавить в server block:
client_max_body_size 20m;
Проверить:
sudo nginx -t
Применить:
sudo systemctl reload nginx
Создать тестовый файл:
dd if=/dev/zero of=/tmp/upload-test.bin bs=1M count=25
Проверить:
curl -sS -o /dev/null -w '%{http_code}\n' -F "file=@/tmp/upload-test.bin" https://example.com/upload/
Итог
После выполнения инструкции:
- определён необходимый лимит загрузки;
- настроен
client_max_body_size; - рассмотрены уровни
http,serverиlocation; - выполнена проверка ошибки
413; - добавлена пользовательская страница ошибки;
- согласован лимит Nginx и приложения;
- разобраны внешние proxy и дисковая нагрузка.
Лимит загрузки должен соответствовать реальной задаче и не должен отключаться без необходимости.