Ограничение размера загружаемых файлов в 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

Безопасный порядок настройки

  1. Определить фактический необходимый размер.
  2. Проверить лимит приложения.
  3. Создать резервную копию.
  4. Добавить client_max_body_size.
  5. Выполнить nginx -t.
  6. Выполнить reload.
  7. Создать файл меньше лимита.
  8. Создать файл больше лимита.
  9. Проверить HTTP-коды.
  10. Проверить error log.
  11. Проверить свободное место.
  12. Удалить тестовые файлы.

Быстрый набор команд

Добавить в 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 и дисковая нагрузка.

Лимит загрузки должен соответствовать реальной задаче и не должен отключаться без необходимости.

← Предыдущая статья Настройка заголовков безопасности в Nginx Следующая статья → Настройка rate limiting в Nginx