Nginx client max body size

It is common to use Nginx coupled with PHP-FPM to run PHP websites: WordPress, Magento, etc.

Nginx is a great web server, but what makes it so tricky to configure is lack of information how a particular directive is applied in each location.

Let’s say you want to increase the limit for max size of uploaded files in a PHP website. One would expect that placing client_max_body_size into the ~ .php$ location block will suffice.

Suppose that we want to allow uploads up to 64MB. And someone is uploading a file that is 32MB.

This is our configuration:

server {   location / {  try_files $uri $uri/ /index.php$is_args$args;  }  location ~ .php$ {  client_max_body_size 64M;  fastcgi_pass ...  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;  } } 

Uploading to /upload.php will succeed. But uploading to /user/upload will result in the file being rejected with 413 Request Entity Too Large


Why wouldn’t client_max_body_size work? It appears that client_max_body_size is not exactly inherited. There are 2 cases which I have identified.

Case 1. If your PHP file is accessed directly

If your request URL matches to the PHP regex location directly, e.g. /test.php, then the client_max_body_size directive that is defined there applies cleanly and as stated. It disregards whichever limit was set in outer scopes.

Case 2. If your location is the result of internal rewrites

Things get very interesting when your location match happened as the result of internal rewrites (try_files). That is, you are uploading to a URL that requires rewriting of request to match with the PHP file to process the upload.

The client_max_body_size directive will not apply unless it’s more restricting than the default 1MB or the one that is set in outer scopes. In other words, client_max_body_size cannot be increased in a rewritten location. You have to define it at server context if you want to increase the limit for rewritten URLs.

So the following will work:

server {   client_max_body_size 64M;  location / {  try_files $uri $uri/ /index.php$is_args$args;  }  location ~ .php$ {  fastcgi_pass ...  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;  } }   

Why do we have to care?

One would be just fine putting the large client_max_body_size in server {} context and be happy that things work. However, this exposes some risk to the DDoS. Many large file uploads will consume disk space on your server. They will consume network bandwidth as well as TCP sockets.

So what is the rule of thumb here? It depends on your use case.

First, if you are certain that your website will not accept large file uploads exceeding the default 1MB, do not specify any extra configuration. Let the default value apply.

If you only accept large uploads directly at PHP URLs which don’t involve any internal rewriting by nginx, you can put the client_max_body_size in the ~ .php$ location only and this would be most safe.

Finally, if you accept uploads exceeding 1MB at SEO friendly URLs (e.g. /user/upload), then you can put client_max_body_size 64M; in server {} context. But to address security concerns you might want to take a different approach, which we are going to detail next.

Increase file upload limit in nginx for SEO-friendly upload endpoints.

So your upload must be taken at a SEO friendly location, e.g. /user/upload

and you want to increase the upload limit just there. This would be quite better in terms of security, since other locations will be less prone to large uploads DDoS.

You can achieve this by specifying a separate location for your “pretty upload handler”, like the following:

server {   location / {  try_files $uri $uri/ /index.php$is_args$args;  }  location = /user/upload {  client_max_body_size 64M;  fastcgi_pass ...  fastcgi_param SCRIPT_FILENAME $document_root/index.php;  include fastcgi_params;  fastcgi_param SCRIPT_NAME /index.php;  }  location ~ .php$ {  fastcgi_pass ...  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;   } } 

What we did there is relaxed the upload limit just for our upload handler. Note that we have to adjust fastcgi_param SCRIPT_FILENAME and point it directly to /index.php script as there is no longer any rewrite to it. We have essentially converted an indirect match (our initial configuration) into direct match to our upload handler with the pretty URL.

Note how we put fastcgi_param SCRIPT_NAME /index.php at the end of /user/upload location. This is so it overrides the one which is set in fastcgi_params file.

NGINX large uploads are successfully working on hosted WordPress sites, finally (as per suggestions from nembleton & rjha94)

I thought it might be helpful for someone, if I added a little clarification to their suggestions. For starters, please be certain you have included your increased upload directive in ALL THREE separate definition blocks (server, location & http). Each should have a separate line entry. The result will like something like this (where the … reflects other lines in the definition block):

http {  ...  client_max_body_size 200M; }  

(in my ISPconfig 3 setup, this block is in the /etc/nginx/nginx.conf file)

server {  ...  client_max_body_size 200M; }  location / {  ...  client_max_body_size 200M; }  

(in my ISPconfig 3 setup, these blocks are in the /etc/nginx/conf.d/default.conf file)

Also, make certain that your server’s php.ini file is consistent with these NGINX settings. In my case, I changed the setting in php.ini’s File_Uploads section to read:

upload_max_filesize = 200M 

Note: if you are managing an ISPconfig 3 setup (my setup is on CentOS 6.3, as per The Perfect Server), you will need to manage these entries in several separate files. If your configuration is similar to one in the step-by-step setup, the NGINX conf files you need to modify are located here:

/etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf    

My php.ini file was located here:


I continued to overlook the http {} block in the nginx.conf file. Apparently, overlooking this had the effect of limiting uploading to the 1M default limit. After making the associated changes, you will also want to be sure to restart your NGINX and PHP FastCGI Process Manager (PHP-FPM) services. On the above configuration, I use the following commands:

/etc/init.d/nginx restart /etc/init.d/php-fpm restart

Буферы Nginx задают возможность использования оперативной памяти для сохранения представляющей ценность информации. Их размер задается в конфигурационном файле и определяет будет ли использоваться оперативная память или все будет записываться на диск.

Размер буферов задается в зависимости от количества доступных серверу ресурсов. Если их много значения можно можно увеличивать.




Размер буферов определяется четырьмя директивами в конфигурационном файле, в секции server либо в http:







Первая директива определяет размер буфера под основное содержимое поступившего от клиента запроса, вторая — размер буфера под заголовок запроса. client_max_body_size — максимальный размер основного содержимого клиентского запроса.


large_client_header_buffers принимает два значения, разделенных пробелами: максимальное числом и размер буферов для чтения большого заголовка запроса клиента.

Значение размера буфера всегда должно быть меньше client_body_buffer_size, иначе возникнет ошибка 414 (Request-URI Too Large).

Также оно должно быть меньше client_header_buffer_size. В противном случае вернется ошибка 400 (Bad Request).

По умолчанию размер одного буфера равен 8K байт.



В конфигурационном файле для не самого мощного сервера значения буферов могут быть такими:

client_body_buffer_size 20K;
client_header_buffer_size 4k;
client_max_body_size 12m;
large_client_header_buffers 2 12k;


Менять их стоит если имеют место проблемы с производительностью или возникает одна из упомянутых выше ошибок.

Задать их можно для каждого виртуального хоста — для каждого сайта (в секции server) или для всего сервера (в секции http).


Читайте про настройку Nginx для работы при высоких нагрузках.

Советы по настройке и оптимизации Nginx

Совет №1 — Организация файлов конфигурации Nginx

Обычно файлы конфигурации Nginx хранятся в /etc/nginx


Один из удобных способов организации файлов конфигурации в стиле Debian/Ubuntu Apache:

Файлы виртуальных хостов разделены на две директории. Директория sites-available может содержать любые файлы: тестовые, старые конфиги, копии конфигов и прочие. А директория sites-enabled содержит только реально работающие конфигурации, в действительности являющиеся только символическими ссылками на файлы в директории sites-available.

Не забудьте добавить следующие строки в файл nginx.conf:

Совет №2 — Определить Nginx worker_processes и worker_connections

Настройки по умолчанию  хороши, но их стоит немного оптимизировать: max_clients = worker_processes * worker_connections.

Базовые настройки Nginx могут обрабатывать сотни одновременных соединений:

Обычно 1000 одновременных соединений на один сервер это хорошо, но порою другие части, например жесткий диск могут оказаться медленными и это приведет к тому, что Nginx будет заблокирован на операции ввода-вывода (I/O). Чтобы избежать блокировки используйте, например, следующие настройки: одни worker_process на ядро процессора


Worker Processes

Чтобы определить сколько ядер имеет ваш процессор, введите:

В данном случае у меня четыре ядра, поэтому окончательный парамерт worker_processes устанавливаем как 4:

Worker Connections

Лично я придерживаюсь 1024 соединений на один воркер, потому что у меня нет никаких оснований для повышения этого значения. Но если например 4096 соединений в секунду не хватает, то можно попробовать удвоить 2048 соединений на процесс.

Окончательные настройки выглядят седующим образом:

Совет №3 — Скрыть токены Nginx / Скрыть номер версии Nginx

Это хорошо из соображений безопасности — скрыть токены Nginx и скрыть номер версии Nginx, тем более если вы используете устаревшую версию Nginx. Это очень легко сделать — достаточно добавить в секцию http/server/location файла конфигурации следующую строку:

Совет №4 — Ограничение на размер передаваемых данных сервером Nginx

Если вы хотите разрешить пользователям загружать файлы, то вы должны увеличить размер сообщения. Это может быть сделано с помощью значения client_max_body_size, которое находится в секции http/server/location файла конфигурации. По умолчанию он равен 1 Мб, но его можно увеличить, например, до 20 Мб, а также увеличить размер буфера:

Если вы получаете сообщение об ошибке, то вы знаете, что client_max_body_size

слишком мало:

«Request Entity Too Large» (413)

Совет №5 — Управление кешем для статических файлов

Кэш браузера сохранит ресурсы и пропускную способность вашего сервера. Это несложная настройка Nginx позволит выключить ведение логов (access log и not found log), и установить срок истечения заголовка в 360 дней.

Если вы хотите более сложный заголовки или другие типы файлов, то вы можете настроить их отдельно.

Совет №6 — Проксируйте PHP запросы к PHP-FPM

Вы можете использовать по умолчанию стек tcp/ip или соединение через Unix-сокет. Также необходимо установить PHP-FPM слушать точно такой же ip:port или Unix-сокет. Вот очень простой пример конфигурации (вариант с Unix-сокетом  закоментирован):

Это дает возможность запуска PHP-FPM другим сервером.

Совет №7 — Предотвращение (запрет) доступа к скрытым файлам

Это очень распространено, когда корень сервера или другие публичные каталоги имеют скрытые файлы, которые начинаются с точки (.) И, как правило, они не предназначены для пользователей сайта. Публичный каталог может содержать файлы системы контроля версий: .git

, .svn; файлы IDE: .idea; .htaccess файлы. Настройки запещают доступ к скрытым файлам и отключают ведение логов:

 Советы по настройке и оптимизации PHP-FPM

Совет №1 — Файлы конфигурации PHP-FPM

Обычно конфигурации PHP-FPM расположенны в файле /etc/php-fpm.conf и в каталоге /etc/php-fpm.d/. Весь пулл конфигов расопложен в дикертории /etc/php-fpm.d/. Чтобы это работало, вы должны добавить следующую строку в php-fpm.conf:

Совет №2 — Глобальная конфигурация PHP-FPM

Настройки emergency_restart_thresholdemergency_restart_interval и process_control_timeout по умолчанию выключены, но я считаю что их стоит влючить, например, со следующими значениями:

Что это значит? Если 10 дочерних процессов PHP-FPM завершатся с помощью SIGSEGV или SIGBUS в течении 1 минуты, то PHP-FPM перезагрузится автоматически. А также дочерним процессам  установлен лимит времени реакции в 10 секунд на сигнал от мастера.

Совет №3 — Конфигурация пулов PHP-FPM

В PHP-FPM возможно использовать отденьные пулы для каждого сайта и точно распределять ресурсы, а также использовать разных пользователей и разные группы для каждого пула. Приведем примеры конфигураци трех различнх сайтов (или фактически три части одного сайта):


Примеры конфигурации каждого пула:



Это просто примеры как настроить несколько различных пулов.

Совет №4 — Конфигурация менеджера процессов (Pool Process Manager) PHP-FPM

Лучший способ использовать менеджер процессов PHP-FPM — это донамическое управление процессами, поэтому PHP-FPM запускает процессы только при необходимости. Это почти такой же подход как в Nginx с параметрами worker_processes и worker_connections. Таким образом большие значения не обеспечивают хорошего результата. Каждый процесс ест определнное количество памяти и, конечно, если у сайта очень большой трафик  и много оперативной памяти на сервере, то высокие значения — это правильный выбор. Но такие серверы как VPS обычно имеют ограниченное количество памяти: 256 Мб, 512 Мб, 1024 Мб. Такого небольшого объема ОЗУ достаточно даже для очень большого трафика (даже десятки запросов в секунду), если эту память использовать с умом.

Проверим сколько процессов PHP-FPM позволит легко справляться серверу с нагрузкой. Сначала запустим Nginx и PHP-FPM и загрузим несколько страниц PHP, желательно самые тяжелые. Затем проверим сколько использует памяти процесс PHP-FPM — в Linux можно воспользоваться утилитами top или htop. Предположим что наш сервер имеет 512 Мб оперативной памяти и 220 Мб может быть использованно PHP-FPM, каждый процесс использует 24 Мб оператичной памяти (некоторые CMS с плагинами могут легко кушать 20-40 Мб на один запрос или даже больше). Затем просто вычислим значние max_children для сервера:

220 / 24 = 9.17

Приемлемым значнием pm.max_children будет 9. Это значние основанно на среднем значении и возможно далее его необходимо будет изменить, когда вы заметите длительное время использования памяти процессом. После быстрого тестирования несложно выбрать значния pm.start_servers value, pm.min_spare_servers и pm.max_spare_servers.

Окончательная конфигурация нашего примера может выглядеть следующим образом:

Максималоное количество запросов на процесс по умолчанию не ограничено, но хорошо бы установить какое-нибудь небольшое значение, например 200, и избежать проблем с памятью. Такого вида настрока может обрабарывать большое количество запросов, даже если значение параметра невелико.

У вас проблемы с натройкой Nginx или PHP-FPM или есть еще советы?

Не стесняйтеся писать замечания, вопросы и советы в комментариях.

Оригинальный пост на английском языке

nginx не пропускает больше одного мегабайта файлы, при этом везде в php.ini установил параметры размера, в апаче нет ограничения. Так как nginx проксирует на апач на 8080 порт, то в качестве проверки открывал сайт по айпи с указанным портом — файлы успешно загружаются, что показывает отсутствие проблем со стороны php — apache. Когда как через nginx файлы не проходят — 413 Request Entity Too Large. Ошибок в логах апача и нжинкса нет. Вот пример файла нжинкса, подскажите, куда ещё можно смотреть.

user nginx; worker_processes 1; worker_rlimit_nofile 100000;  error_log /var/log/nginx/error.log; #error_log /var/log/nginx/error.log notice; #error_log /var/log/nginx/error.log info;  pid /var/run/;   events {  worker_connections 1024;  use epoll; }   http {  include /etc/nginx/mime.types;  default_type application/octet-stream;   log_format main '$remote_addr - $remote_user [$time_local] "$request" '  '$status $body_bytes_sent "$http_referer" '  '"$http_user_agent" "$http_x_forwarded_for"';   access_log /var/log/nginx/access.log main;   sendfile on;  client_max_body_size 12m;  tcp_nopush on;  tcp_nodelay on;  server_tokens off;  gzip on;  gzip_static on;  gzip_comp_level 5;  gzip_min_length 1024;  keepalive_timeout 65;  limit_zone myzone $binary_remote_addr 10m;    # Load config files from the /etc/nginx/conf.d directory  #include /etc/nginx/conf.d/*.conf;    log_format isp '$bytes_sent $request_length';      server {  listen 80;  server_name ______;  client_max_body_size 12m;   rewrite ^(/manager/.*)$ https://$host$1 permanent;  error_page 404 = @fallback;   location ~* ^.+.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar)$ {  root /var/www/mastermind/data/www/;  access_log /var/www/httpd-logs/;  access_log /var/www/nginx-logs/mastermind isp;  }    location / {   client_max_body_size 12m;  client_body_buffer_size 128k;  proxy_connect_timeout 90;  proxy_send_timeout 6000;  proxy_read_timeout 6000;  proxy_buffer_size 4k;  proxy_buffers 4 32k;  proxy_busy_buffers_size 64k;  proxy_temp_file_write_size 12m;    proxy_pass http://IP:8080/;  proxy_redirect off;  proxy_buffering off;  proxy_set_header Host $host;  proxy_set_header X-Real-IP $remote_addr;  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;   }   location @fallback {  proxy_pass http://IP:8080;  proxy_set_header Host $host;  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  proxy_set_header X-Real-IP $remote_addr;  }   }  }

You May Also Like

About the Author: admind

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.