Виправити WordPress «exceeds upload_max_filesize»: правильно збільшуємо ліміти (PHP, Nginx/Apache, хостинг)

Було корисно?

Нічого так не надихає, як маркетингова команда, що намагається завантажити 120 MB головного відео за п’ять хвилин до запуску — і отримує «exceeds the maximum upload size for this site» або класичне «exceeds upload_max_filesize».

Ця помилка ніколи не про один перемикач. Це ланцюжок. PHP має ліміти. Веб‑сервер має ліміти. Проксі та CDN мають ліміти. WordPress має свої припущення. Панель хостингу має «корисні» значення за замовчуванням. Виправити правильно означає знайти найслабше ланка, свідомо підвищити його та перевірити, що фактично змінилося.

Швидкий план діагностики

Якщо не робити нічого іншого — зробіть це. Це перетворює «я змінив php.ini і нічого не змінилося» на короткий, нудний тикет. Нудно — добре.

1) Визначте реальну поверхню помилки: повідомлення WordPress, HTTP‑статус чи лог сервера

  • Якщо в браузері видно HTTP 413 або просту сторінку Nginx/Cloudflare: вас блокують перед PHP. Спочатку виправляйте проксі/веб‑сервер.
  • Якщо WordPress показує «exceeds upload_max_filesize» або «exceeds the maximum upload size»: ймовірно, ви натрапили на обмеження PHP (або WordPress читає значення PHP і показує їх).
  • Якщо процес крутиться і падає з «link expired» / «failed to write file to disk» / «missing a temporary folder»: це не про розмір; це система файлів, тимчасова папка або права доступу.

2) Знайдіть найменший ліміт у ланцюжку

Збої відбуваються на мінімумі з наступних:

  • Клієнтські обмеження браузера (рідко, але мобільні можуть таймаути)
  • Ліміт тіла запиту CDN/WAF/проксі
  • Ліміт тіла запиту веб‑сервера (Nginx/Apache)
  • Ліміти PHP SAPI: upload_max_filesize, post_max_size, memory_limit, таймаути
  • Обмеження диска: вільне місце, тимчасовий розділ, виснаження інодів
  • WordPress + плагіни (рідше, але буває)

3) Перевірте, які значення PHP фактично використовує (не гадати)

PHP може підвантажувати різні ini‑файли залежно від SAPI (FPM vs CLI), пулу та пакування дистрибутива. Підтвердіть завантажений конфіг та ефективні значення.

4) Змінюйте по одному шару і перезапускайте потрібний сервіс

Перезапуск неправильного демона — це посвята. І даремна трата часу. Міняйте потрібний конфіг, перевіряйте синтаксис, перезавантажуйте/рестартуйте, а потім тестуйте.

5) Повторно тестуйте з файлом, який має зломитися, а потім з тим, що має пройти

Тестувати 2 MB після того, як ви «підняли до 512 MB», нічого не каже. Оберіть файл 50–80% від нового ліміту і спробуйте знову.

Цитата для вашого ранбуку: Hope is not a strategy. (генерал Г. Норман Шварцкопф)

Що насправді означає помилка (і чого вона не означає)

«exceeds upload_max_filesize» — це PHP, який говорить — конкретно підсистема завантажень файлів. Вона викидається, коли PHP відмовляється прийняти файл, бо він більший за upload_max_filesize. WordPress зазвичай показує це як дружнє повідомлення у завантажувачі медіа.

Але у продакшні все заплутано. Ви можете бачити це повідомлення навіть якщо:

  • Ваш проксі блокує тіло запиту, а WordPress вгадує ліміт на основі налаштувань PHP (ви підняли PHP, WordPress показує більше число, але завантаження все одно гине на краю).
  • Ви відредагували неправильний php.ini (часто на хостингах з кількома PHP, у контейнерах або коли CLI != FPM).
  • post_max_size все ще менше за upload_max_filesize (файл у межах upload_max_filesize, але весь POST‑тіло перевищує).
  • Ви натрапляєте на таймаути (великі завантаження по повільному каналу), а не на обмеження розміру.

Також: помилка нічого не каже про диск. Ви можете підняти ліміти до 2 GB і все одно провалитися, бо /tmp маленький або том заповнений. Завантаження не магія; файли кудись записуються.

Ланцюжок обмежень завантаження: де блокують запити

Уявіть завантаження WordPress як посилку, що проходить через пункти контролю. Будь‑який пункт може відхилити її. Ваше завдання — знайти, який охоронець зупиняє.

Контрольний пункт A: CDN/WAF/реверс‑проксі

Якщо у вас Cloudflare, керований WAF, ALB/ELB, API‑шлюз або контролер ingress, скоріш за все існує обмеження розміру запиту і іноді поведінка буферизації, яка змінює, як працюють великі завантаження.

Контрольний пункт B: Веб‑сервер

У багатьох конфігураціях Nginx за замовчуванням має досить малий ліміт тіла запиту (client_max_body_size). Apache теж може застосовувати обмеження через директиви на кшталт LimitRequestBody (хоча не завжди поставлене за замовчуванням).

Контрольний пункт C: PHP SAPI (FPM/mod_php)

Класичне трио:

  • upload_max_filesize: ліміт на окремий файл.
  • post_max_size: ліміт на весь POST‑тіло (має бути більшим за upload_max_filesize; давайте запас).
  • memory_limit: впливає на опрацювання і деякі плагіни; не завжди має бути більшим за розмір файлу, але практично потрібен запас.

Також звертайте увагу на:

  • max_execution_time, max_input_time: таймаути для повільних завантажень і обробки в PHP.
  • max_file_uploads: кількість файлів в одному запиті (рідко для медіа WordPress, але при масовому завантаженні плагіни можуть його перевищити).
  • upload_tmp_dir: куди PHP зберігає тимчасові файли завантаження; якщо вказує на маленьку файлову систему — програш.

Контрольний пункт D: Файлова система та ОС

Завантаження пишуться у тимчасовий простір, потім у wp-content/uploads (або в інше місце за налаштуванням). Можливі помилки:

  • Заповнений диск або виснаження інодів
  • Неправильні права/власник
  • Прапори монтування noexec зазвичай не впливають на медіа, але політики SELinux/AppArmor можуть
  • Накопичувач контейнера overlay може заповнюватися, хоча прикріплений том має місце

Контрольний пункт E: WordPress та плагіни

WordPress показує «Maximum upload file size» на основі того, що йому каже PHP. Плагіни можуть додавати власну валідацію, а деякі плагіни безпеки блокують певні MIME‑типи або розширення, що користувачі іноді сприймають як помилку розміру.

Цікаві факти та коротка історія лімітів завантаження

  1. За замовчуванням PHP мав дуже маленький ліміт. Значення на кшталт 2 MB були поширені, бо у часи шаред‑хостингу 2000‑х ресурси строго обмежувалися.
  2. post_max_size важливий навіть для одиночних файлів. Файл передається в multipart‑формі; повне тіло включає межі і поля, тому потрібен запас.
  3. Nginx відхиляє перевели розміри раніше. Коли перевищено client_max_body_size, Nginx може повернути 413, не дотикаючись до PHP‑FPM. Це добре для захисту бекендів, але плутає людей.
  4. «413 Request Entity Too Large» старший за більшість WordPress-сайтів. Це HTTP‑статус із часів, коли термін «entity» був звичним у специфікації для тіла запиту.
  5. WordPress не «ставить» PHP‑ліміти. Він їх читає. Будь‑яка панель, що стверджує, що «змінює PHP», або записує конфіги, або чемно брешуть.
  6. PHP‑FPM і PHP CLI — різні SAPI. CLI може показати вам адекватні значення, тоді як FPM використовує інші ini‑файли. Багато інцидентів починаються з того, що хтось виконав php -i і повірив йому.
  7. Завантаження зазвичай пишуться в тимчасове сховище спочатку. PHP пише у тимчасовий файл перед переміщенням. Якщо /tmp на маленькому розділі, великі завантаження провалюються, навіть якщо кінцевий том має місце.
  8. CDN часто обмежують розмір запиту на нижчих тарифах. Ви можете підняти Nginx і PHP, але програти на краю. Edge не веде переговорів.
  9. Великі медіа‑завантаження стали звичними лише нещодавно. Сучасні телефони знімають 4K за замовчуванням; 200 MB «швидкі кліпи» тепер стандарт і знищать 2 MB за замовчуванням з ентузіазмом.

Практичні завдання: команди, виводи, рішення (12+)

Це ходи, які я очікую від SRE на реальному хості. Кожне завдання включає: команду, що означає вивід, та рішення, яке приймаєте.

Завдання 1: Підтвердити ефективні PHP‑ліміти (перевірка CLI)

cr0x@server:~$ php -r 'echo "upload_max_filesize=",ini_get("upload_max_filesize"),"\npost_max_size=",ini_get("post_max_size"),"\nmemory_limit=",ini_get("memory_limit"),"\n";'
upload_max_filesize=2M
post_max_size=8M
memory_limit=128M

Що це значить: Це погляд PHP CLI. Він може не збігатися з PHP‑FPM або mod_php.

Рішення: Якщо CLI вже високий, але WordPress все ще падає — припиніть редагувати випадкові ini і перевірте веб‑SAPI далі.

Завдання 2: Визначити, який PHP SAPI працює (FPM чи модуль Apache)

cr0x@server:~$ ps -ef | egrep 'php-fpm|apache2|httpd' | head
root        1012       1  0 09:00 ?        00:00:02 php-fpm: master process (/etc/php/8.2/fpm/php-fpm.conf)
www-data    1044    1012  0 09:00 ?        00:00:00 php-fpm: pool www
root        1200       1  0 09:00 ?        00:00:01 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;

Що це значить: У вас Nginx + PHP‑FPM. Зміни треба робити в конфігах FPM/pool, а не в Apache.

Рішення: Продовжуйте з шляхами конфігурації FPM і перезавантажте PHP‑FPM та Nginx.

Завдання 3: Знайти завантажений php.ini для PHP‑FPM (не CLI)

cr0x@server:~$ php-fpm8.2 -i | egrep 'Loaded Configuration File|Scan this dir for additional .ini files'
Loaded Configuration File => /etc/php/8.2/fpm/php.ini
Scan this dir for additional .ini files => /etc/php/8.2/fpm/conf.d

Що це значить: Це ini‑файл і директорія для сканування для SAPI FPM.

Рішення: Редагуйте /etc/php/8.2/fpm/php.ini або створіть перевизначення в conf.d, потім перезавантажте PHP‑FPM.

Завдання 4: Перевірити ефективні значення в FPM ini

cr0x@server:~$ sudo egrep -n '^(upload_max_filesize|post_max_size|memory_limit|max_execution_time|max_input_time)' /etc/php/8.2/fpm/php.ini
861:upload_max_filesize = 2M
701:post_max_size = 8M
436:memory_limit = 128M
409:max_execution_time = 30
415:max_input_time = 60

Що це значить: Це поточні налаштовані значення для FPM.

Рішення: Підніміть їх до значень, що відповідають очікуваним завантаженням, потім перезавантажте PHP‑FPM. Переконайтесь, що post_max_size більше за upload_max_filesize.

Завдання 5: Перевірити обмеження тіла запиту Nginx по всьому конфігу

cr0x@server:~$ sudo nginx -T 2>/dev/null | egrep -n 'client_max_body_size'
45:    client_max_body_size 1m;
212:        client_max_body_size 16m;

Що це значить: У вас кілька областей. Переможе найбільш специфічний блок location/server.

Рішення: Встановіть client_max_body_size там, де фактично співпадає ваш WordPress vhost (зазвичай у блоці server). Видаліть суперечливі значення, якщо можна.

Завдання 6: Перевірити синтаксис Nginx перед перезавантаженням

cr0x@server:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Що це значить: Безпечно перезавантажувати. Якщо синтаксис не пройшов — не перезавантажуйте; виправте файл.

Рішення: Перезавантажуйте Nginx тільки після чистого -t.

Завдання 7: Правильно перезавантажити сервіси (і перевірити, що вони справді перезавантажилися)

cr0x@server:~$ sudo systemctl reload nginx
cr0x@server:~$ sudo systemctl reload php8.2-fpm
cr0x@server:~$ systemctl is-active nginx php8.2-fpm
active
active

Що це значить: Перезавантаження пройшло і сервіси активні.

Рішення: Якщо перезавантаження не вдалося або сервіс неактивний — зупиніться; виправте сервіс перш ніж тестувати завантаження.

Завдання 8: Перевірити перекриття в пулі PHP‑FPM (вони можуть тихо обмежувати значення)

cr0x@server:~$ sudo egrep -n 'php_admin_value\[(upload_max_filesize|post_max_size|memory_limit)\]|request_terminate_timeout' /etc/php/8.2/fpm/pool.d/www.conf
;php_admin_value[upload_max_filesize] = 10M
;php_admin_value[post_max_size] = 12M
;request_terminate_timeout = 0

Що це значить: Тут закоментовано, але на деяких системах це активно і перевизначає php.ini.

Рішення: Якщо існують перевизначення в пулі — свідомо встановіть значення там, задокументуйте і припиніть вважати php.ini єдиним джерелом істини.

Завдання 9: Перевірити директиви розміру тіла в Apache (якщо ви використовуєте Apache)

cr0x@server:~$ sudo apachectl -M | head -n 5
Loaded Modules:
 core_module (static)
 so_module (static)
 watchdog_module (static)
 http_module (static)

Що це значить: Apache присутній; якщо він фронтенд — перевірте його ліміти і інтеграцію PHP (mod_php або proxy_fcgi).

Рішення: Якщо у вас Apache — шукайте LimitRequestBody і перевірте конфіг віртуального хоста.

Завдання 10: Знайти в конфігах Apache обмеження розміру запиту

cr0x@server:~$ sudo grep -R --line-number -E 'LimitRequestBody' /etc/apache2/sites-enabled /etc/apache2/apache2.conf 2>/dev/null
/etc/apache2/sites-enabled/000-default.conf:27:LimitRequestBody 10485760

Що це значить: Apache жорстко обмежений до 10 MB на цьому vhost. Зміни в PHP не матимуть значення.

Рішення: Підніміть LimitRequestBody (або видаліть його, якщо контролюєте ліміти в іншому місці), потім перезавантажте Apache.

Завдання 11: Переконатися в наявності місця на диску та інодів (для завантажень потрібні обидва)

cr0x@server:~$ df -h /var/www/html /tmp
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        80G   62G   15G  81% /
tmpfs           1.0G  120M  904M  12% /tmp
cr0x@server:~$ df -i /var/www/html /tmp
Filesystem      Inodes  IUsed   IFree IUse% Mounted on
/dev/vda1      5242880 910000 4332880   18% /
tmpfs           262144    980 261164    1% /tmp

Що це значить: Маєте 15 GB вільних і іноди в нормі. /tmp — 1 GB, що може бути мало для великих завантажень.

Рішення: Якщо плануєте дозволяти 2 GB завантаження — збільште тимчасове сховище або вкажіть upload_tmp_dir на більший файловий простір.

Завдання 12: Перевірити повідомлення WordPress про максимальний розмір завантаження (що бачить адміністратор)

cr0x@server:~$ sudo -u www-data php /var/www/html/wp-admin/includes/file.php 2>/dev/null || true

Що це значить: Це не дуже хороший спосіб опитати WordPress, але нагадує: WordPress — це PHP‑код. Значення в адмінці походять із налаштувань PHP, а не навпаки.

Рішення: Використовуйте правильну перевірку phpinfo() у веб‑контексті, якщо потрібно (див. наступне завдання), а потім видаліть її.

Завдання 13: Створити тимчасову сторінку phpinfo для підтвердження значень FPM (потім видалити)

cr0x@server:~$ sudo tee /var/www/html/phpinfo.php >/dev/null <<'EOF'
/etc/php/8.2/fpm/php.ini 

Що це значить: Тепер ви інспектуєте PHP у контексті сервера, що й має значення.

Рішення: Підтвердіть значення; потім видаліть phpinfo.php. Залишати її — запрошення до проблем.

Завдання 14: Переглянути логи на наявність 413 або помилок завантаження PHP

cr0x@server:~$ sudo tail -n 50 /var/log/nginx/error.log
2025/12/27 09:22:18 [error] 1432#1432: *991 client intended to send too large body: 24681231 bytes, client: 203.0.113.9, server: example.com, request: "POST /wp-admin/async-upload.php HTTP/1.1", host: "example.com", referrer: "https://example.com/wp-admin/media-new.php"

Що це значить: Це не PHP. Nginx відхиляє тіло запиту (тут ~24.6 MB).

Рішення: Підніміть client_max_body_size у правильній області. Не чіпайте PHP доти, поки Nginx не перестане бути бар’єром.

Завдання 15: Перевірити лог PHP на помилки, пов’язані з завантаженням

cr0x@server:~$ sudo tail -n 50 /var/log/php8.2-fpm.log
[27-Dec-2025 09:25:10] WARNING: [pool www] child 2123 said into stderr: "PHP message: PHP Warning:  POST Content-Length of 52459012 bytes exceeds the limit of 8388608 bytes in Unknown on line 0"

Що це значить: post_max_size — 8 MB (8388608 байт). Користувач намагався ~52 MB. PHP відхилив ще до того, як WordPress зміг щось зробити.

Рішення: Збільшіть post_max_size понад бажаний макс завантаження, з запасом.

Завдання 16: Підтвердити, що проксі/CDN не накладає менший ліміт (приклад: Cloudflare через заголовки відповіді)

cr0x@server:~$ curl -I -sS https://example.com/wp-admin/media-new.php | egrep -i 'server:|cf-ray|via:|x-cache'
server: cloudflare
cf-ray: 88f0c1d2ab123456-LHR

Що це значить: Cloudflare у шляху. Ліміти розміру можуть залежати від тарифу і проявлятися як 413/520 помилки.

Рішення: Якщо є участь краю — відтворіть, обійшовши його (прямий test до origin) або перевірте налаштування тіла запиту на edge. Не припускайте, що проблема — на origin.

Жарт 1: Ліміти завантаження — як політика витрат у корпорації: про неї дізнаються тільки тоді, коли намагаються зробити щось нормальне.

Виправлення по стеку: Apache, Nginx, PHP-FPM, проксі, панелі, контейнери

Обрати розумні цільові ліміти (і припинити казати «просто поставте 2G» як план)

Почніть з реальної потреби: «Нам потрібно завантажувати до 200 MB відео» або «Нам достатньо 64 MB для PDF». Потім встановіть:

  • upload_max_filesize = вимога (наприклад, 256M)
  • post_max_size = upload_max_filesize + накладні витрати (наприклад, 300M)
  • memory_limit = залежить від плагінів та обробки зображень; для медіа‑насичених WP зазвичай 256M–512M
  • Ліміт тіла веб‑сервера/проксі ≥ post_max_size

Якщо дозволяєте дуже великі завантаження — плануйте пропускну спроможність, таймаути та зростання сховища. «Завантаження працюють» — не те саме, що «завантаження не розвалять сервер наступного місяця».

Nginx + PHP‑FPM (найпоширеніша сучасна конфігурація)

1) Підвищити Nginx client_max_body_size

Встановіть його у правильному блоці server (або в http для глобального застосування). Приклад snippet vhost:

cr0x@server:~$ sudo tee /etc/nginx/sites-available/example.com.conf >/dev/null <<'EOF'
server {
    listen 80;
    server_name example.com;
    root /var/www/html;

    client_max_body_size 300m;

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }
}
EOF

Рішення: Встановіть Nginx принаймні на post_max_size. Якщо Nginx менше за PHP — користувачі отримають 413; якщо PHP менше за Nginx — користувачі отримають PHP/WordPress помилки. В будь‑якому випадку — тикет.

2) Підвищити ліміти PHP‑FPM у правильному ini

Редагуйте FPM ini або киньте окремий override файл у conf.d (чистіше для управління конфігом).

cr0x@server:~$ sudo tee /etc/php/8.2/fpm/conf.d/99-wordpress-uploads.ini >/dev/null <<'EOF'
upload_max_filesize = 256M
post_max_size = 300M
memory_limit = 512M
max_execution_time = 120
max_input_time = 120
EOF

Рішення: Використовуйте зрозуміле ім’я для override. Це пришвидшує аудит і інцидент‑відповідь краще, ніж шпигування в vendor‑php.ini.

3) Перезавантажити, потім верифікувати через phpinfo у веб‑контексті

Перезавантажте FPM і Nginx. Підтвердіть у відданому phpinfo, що нові значення активні. Потім видаліть phpinfo.

Налаштування Apache

Apache може запускати PHP через mod_php (старий підхід) або через PHP‑FPM (proxy_fcgi). Ліміти різняться залежно від інтеграції.

Обмеження тіла запиту в Apache

Якщо у вас LimitRequestBody у vhost або директиві directory — це жорстка межа. Підніміть її (байти) або видаліть, якщо контролюєте ліміти інакше.

cr0x@server:~$ sudo sed -i 's/LimitRequestBody 10485760/LimitRequestBody 314572800/' /etc/apache2/sites-enabled/000-default.conf
cr0x@server:~$ sudo apachectl configtest
Syntax OK
cr0x@server:~$ sudo systemctl reload apache2

Рішення: Якщо використовуєте Apache як зворотний проксі перед FPM — узгодьте тіла Apache з post_max_size PHP.

Ліміти PHP (mod_php vs FPM)

Якщо ви використовуєте mod_php — шлях ini зазвичай /etc/php/X.Y/apache2/php.ini. Якщо FPM — /etc/php/X.Y/fpm/php.ini. Не «виправляйте» Apache ini, якщо Apache не подає PHP напряму.

Реверс‑проксі та балансувальники навантаження

Звичайні винуватці:

  • Nginx перед Nginx (так, буває). Кожен шар може мати власний client_max_body_size.
  • Контролери ingress у Kubernetes зі своїми налаштуваннями тіла запиту.
  • Правила WAF, що блокують великі тіла або певні multipart шаблони.

Метод той самий: знайдіть шар, що викидає 413 (або обриває з’єднання), потім піднімайте той шар. Якщо можете тимчасово обійти проксі (прямий доступ до origin) — зробіть це, щоб звузити діапазон.

cPanel / Plesk / керовані панелі хостингу

Панелі часто дають «збільшити розмір завантаження» у UI. Під капотом вони правлять ini або per‑site конфіги. Пастка — розбіжність конфігів:

  • Панель пише в один ini, а ваш сайт використовує іншу версію PHP або обробник.
  • Панель піднімає PHP, але Nginx/Apache все ще обмежує тіло.
  • Зміни панелі перезаписуються оновленнями або конфіг‑менеджментом.

Користуйтеся панеллю, якщо це ваша модель управління, але завжди верифікуйте через phpinfo і логи. Панель — UI, не джерело істини.

Docker і контейнеризований WordPress

Контейнери дають дві класичні проблеми:

  • Ви можете редагувати конфіг на хості, який контейнер не використовує.
  • Фронтенд‑проксі (Traefik/Nginx/Ingress) часто має реальний ліміт, а не PHP контейнера.

Якщо ви запускаєте офіційний образ WordPress з Apache — зазвичай налаштовуєте PHP через ini‑сніпети, змонтовані в контейнер.

cr0x@server:~$ docker exec -it wordpress php -i | egrep 'Loaded Configuration File|upload_max_filesize|post_max_size' | head
Loaded Configuration File => /usr/local/etc/php/php.ini
upload_max_filesize => 2M => 2M
post_max_size => 8M => 8M

Рішення: Якщо контейнер все ще показує 2M/8M — потрібно змонтувати ini‑override у /usr/local/etc/php/conf.d (або пересобрати образ), потім перезапустити контейнер.

Обмеження на рівні WordPress: що важливо, а що — кулеметна магія

WordPress «Maximum upload file size» — це відображення симптома

У Media → Add New WordPress показує максимальний розмір. Це число зазвичай походить з upload_max_filesize і post_max_size, іноді з додатковою логікою. Це не гарантія, що весь шлях підтримує цей розмір.

«Хаки» у wp-config.php

Ви бачитимете поради додати константи або виклики ini_set у wp-config.php:

  • ini_set('upload_max_filesize','256M')
  • define('WP_MEMORY_LIMIT','256M')

Правда така: ini_set() не може змінити налаштування з PHP_INI_SYSTEM у багатьох конфігураціях, а pool‑php_admin_value у FPM може блокувати його повністю. Якщо працює — це крихке. Якщо не працює — люди витрачають дні, вірячи, що WordPress їх ігнорує із зла.

Надавайте перевагу нудному, контрольованому підходу: ставте PHP‑ліміти у ini/pool, ставте ліміти веб‑сервера у конфігу веб‑сервера, перевіряйте логи.

Memory limit — не ліміт на завантаження (але може вбити завантаження)

Само завантаження не вимагає, щоб PHP тримав весь файл у пам’яті; воно стрімииться у тимчасовий файл. Але плагіни можуть обробляти файли (зміна розмірів зображень, витяг метаданих відео, прев’ю PDF) і витрачати пам’ять. Якщо піднімаєте ліміти завантаження і раптом бачите білий екран або фатали після завантаження — часто це пам’ять або час виконання під час обробки, а не саме завантаження.

Блокування по MIME або розширеннях маскується під «помилку завантаження»

Деякі хости блокують певні розширення. WordPress також має обмеження MIME. Коли користувач чує «завантаження не вдалося», він припускає розмір. Перевіряйте фактичне повідомлення і логи. Блокований SVG, EXE чи екзотичний відеоконтейнер — це не проблема розміру.

Жарт 2: «Просто підніміть ліміт» — операційний еквівалент «вимкни і увімкни знову» — інколи правильний, але завжди підозрілий.

Поширені помилки (симптом → причина → виправлення)

1) Симптом: WordPress показує максимум 256MB, але завантаження падають з HTTP 413

Причина: Nginx/edge proxy має менший ліміт тіла запиту, ніж PHP.

Виправлення: Підніміть client_max_body_size (і будь‑який upstream proxy). Переконайтесь у логах Nginx, що більше не бачите «client intended to send too large body».

2) Симптом: Ви відредагували php.ini, перезапустили PHP, нічого не змінилося

Причина: Ви відредагували неправильний ini (CLI vs FPM vs Apache), або перевизначення пулу переважає.

Виправлення: Перевірте завантажений конфіг для веб‑SAPI через phpinfo; шукайте pool‑перевизначення php_admin_value.

3) Симптом: Завантаження падає приблизно у ~8MB або ~16MB рівно, незалежно від налаштувань

Причина: Upstream‑пристрій обмежує (WAF, ALB, контролер ingress) або Apache LimitRequestBody.

Виправлення: Ідентифікуйте шар, що повертає 413 через логи і заголовки; підніміть той ліміт. Не піднімайте PHP навмання перш за все.

4) Симптом: Завантаження починається, потім падає з «The link you followed has expired.»

Причина: Часто таймаути або прострочення nonce при повільних завантаженнях; іноді max_execution_time або таймаути проксі.

Виправлення: Підвищте PHP‑таймаути і proxy read timeouts; переконайтесь, що користувач не завантажує по надто повільному каналу відносно таймаутів сервера.

5) Симптом: Завантаження падає з «Missing a temporary folder» або «Failed to write file to disk»

Причина: upload_tmp_dir невірно налаштований, права неправильні, диск повний або /tmp замалий.

Виправлення: Перевірте df -h, df -i, права на /tmp та wp-content/uploads, вкажіть upload_tmp_dir в доступний шлях з місцем.

6) Симптом: Тільки великі зображення падають; маленькі проходять

Причина: Обробка зображень після завантаження перевищує memory_limit або max_execution_time; або плагін робить важку роботу.

Виправлення: Підвищте memory_limit, профілюйте поведение плагінів, розгляньте відвантаження ресайзу або обмеження автоматично створюваних розмірів.

7) Симптом: Працює при обході CDN, падає через CDN

Причина: Ліміт на краю або правило WAF блокує multipart/form-data.

Виправлення: Налаштуйте CDN/WAF або маршрутизовуйте адмін/медіа‑завантаження напряму на origin, якщо архітектура дозволяє.

Чеклісти / покроковий план

Покроково: безпечно підняти ліміти на Nginx + PHP‑FPM

  1. Визначте цільовий розмір завантаження. Приклад: 256M. Вирішіть post_max_size=300M.
  2. Перевірте поточні блокери: лог Nginx на 413; лог PHP‑FPM на «POST Content-Length exceeds».
  3. Встановіть ліміт Nginx у правильному vhost: client_max_body_size 300m;
  4. Встановіть override PHP‑FPM: upload_max_filesize, post_max_size, таймаути, і за потреби memory_limit.
  5. Перевірте і перезавантажте: nginx -t, перезавантажте Nginx і PHP‑FPM.
  6. Підтвердіть через phpinfo у веб‑контексті (тимчасово) і видаліть її.
  7. Протестуйте завантаження на 50–80% від ліміту і трохи вище, щоб переконатись у коректній поведінці при відмові.
  8. Спостерігайте за диском: Переконайтеся, що /tmp і ваш WordPress‑том витримають паралельні завантаження.
  9. Задокументуйте нові ліміти в ранбуку, включно з місцями конфігурації.

Чекліст: що узгодити між шарами (мінімальна коректність)

  • client_max_body_size (або еквівалент Apache) ≥ post_max_size
  • post_max_sizeupload_max_filesize + накладні витрати
  • Тимчасове сховище ≥ максимального завантаження (з урахуванням очікуваної конкуренції)
  • Таймаути PHP і проксі узгоджені з тривалістю завантажень
  • Налаштування origin, проксі і CDN узгоджені (без прихованих менших лімітів)

Чекліст: операційні запобіжники (щоб «підняття лімітів» не стало «ой»)

  • Вирішіть, чи дозволятимете великі завантаження лише в адмінці (деякі стеки дозволяють обмежувати по шляху).
  • Додайте моніторинг: використання диску, інодів і рівень помилок 413 та попереджень PHP про завантаження.
  • Майте план відкату: повернути ini‑сніпет, повернути директиву vhost, перезавантажити сервіси.
  • Якщо дозволяєте дуже великі файли — розгляньте відвантаження медіа в об’єктне сховище і використання multipart‑завантажень.

Три міні‑історії з корпоративного світу

Міні‑історія 1: Інцидент через хибне припущення

Рітейл‑компанія запускала WordPress за реверс‑проксі. Одного дня маркетинг додав лендинг із короткими відео. Завантаження почали падати переважно для віддалених співробітників. Інженер он‑колу побачив помилку WordPress про upload_max_filesize, відредагував /etc/php/8.1/fpm/php.ini, підняв ліміти, перезавантажив PHP‑FPM і оголосив перемогу.

Наступне завантаження все одно впало. Знову те саме повідомлення. Вони підняли ще, бо «якщо 256M не допомогло, 512M точно допоможе». Не допомогло. Тепер команда мала дві проблеми: завантаження й досі падали, і PHP вже дозволяв великі payload‑и без обговорення дискових, таймаутних чи захисних наслідків.

Корінь виявився прозаїчним: реверс‑проксі мав client_max_body_size = 20M. WordPress показував новий більший ліміт PHP, але проксі відсікало запити на 20M. Люди в HQ іноді проходили, бо їхні файли були менші; віддалені більше завантажували.

Виправлення зайняло десять хвилин: підняли проксі до відповідного post_max_size, перезавантажили і додали алерт на 413. Урок: не припускайте, що повідомлення вказує шар, де проблема — у багатошарових системах перша компонента, що відкидає запит, говорить істину; WordPress зазвичай не та компонента.

Міні‑історія 2: Оптимізація, що дала зворотний ефект

Медіа‑сайт вирішив «підвищити продуктивність», посиливши ліміти всюди. Вони зменшили Nginx client_max_body_size до 10M, бо «ніхто не має завантажувати більше», і це зменшило бот‑шум. Також скоротили PHP‑таймаути, бо довгі запити здавалися підозрілими.

Потім бізнес почав проводити вебінари. Маркетинг почав завантажувати легітимні 80M ескізи для відео і 150M аудіо. Співробітники обходили проблему, використовуючи FTP і вручну кидаючи файли в wp-content/uploads, що обходило метадані WordPress і ламало медіа‑бібліотеку. Добре для аптайму, погано для коректності.

Наслідок: робочі обходи створили «привидні медіа» — файли на диску без записів у БД, посилання, які не оновлюються при зміні домену тощо. Коли ліміти потім підняли, довелося розгрібати ці наслідки. Рішення: чітка політика завантажень (256M), узгодження лімітів edge/proxy/PHP і відвантаження медіа в об’єктне сховище.

Міні‑історія 3: Нудна, але правильна практика, що врятувала ніч

Великий корпоративний інтранет мав кілька WordPress‑інстансів на одній платформі. Платформа тримала невеликий набір хардендованих дефолтів, включно з лімітами завантажень. Але вони також мали правило: будь‑яка зміна ліміту робиться через один конфігураційний сніпет, розгорнутий автоматизацією, і перевіряється health‑чеком, що читає ефективні значення.

Коли новий сайт попросив більше для тренінгових відео, команда не чіпала php.ini вручну. Вони додали один ini‑файл у conf.d, оновили Nginx vhost, і додали canary‑перевірку, що завантажує файл трохи нижче ліміту на staging. Потім розгорнули поступово.

Через два тижні базовий образ оновив vendor php.ini. Сайти, що вручну редагували той файл, могли б повернутися до 2M і спричинити пожежу в helpdesk. Цей фліт встояв: override‑snippet вижив, canary‑перевірка була зеленою, і ніхто нічого не помітив.

Ось що купує «нудне»: стійкість до змін, що псують ніч.

FAQ

1) У чому різниця між upload_max_filesize і post_max_size?

upload_max_filesize обмежує окремий файл. post_max_size обмежує весь HTTP POST‑тіло. Для завантажень POST‑тіло завжди більше за файл через multipart‑накладні. Встановлюйте post_max_size вищим.

2) Я підняв upload_max_filesize, але WordPress все одно показує старий ліміт. Чому?

Або ви редагували неправильний ini (CLI vs FPM vs Apache), зміни не перезавантажили, або інша конфігурація (php_admin_value у пулі FPM) перевизначає. Підтвердіть через phpinfo у веб‑контексті.

3) Чому я бачу HTTP 413 замість WordPress‑помилки?

Тому що щось перед WordPress відхилило тіло запиту — часто Nginx client_max_body_size, Apache LimitRequestBody, балансувальник навантаження або CDN.

4) Чи потрібно піднімати memory_limit відповідно до розміру завантаження?

Не обов’язково для самого передавання, але часто для того, що відбувається після: ресайз зображень, витяг метаданих, прев’ю PDF, робота плагінів. Якщо завантаження успішні, а обробка падає — підозрюйте пам’ять.

5) Наскільки високо слід ставити ліміти для WordPress?

Встановлюйте найменше значення, що підтримує реальні потреби з запасом. Для багатьох сайтів практично 64M–256M. Якщо потрібно більше — розгляньте відвантаження медіа в об’єктне сховище і перевірте таймаути та дискову ємність.

6) Чи можна встановити ліміти в .htaccess?

Іноді, на Apache з mod_php, директиви типу php_value upload_max_filesize у .htaccess можуть працювати. У PHP‑FPM зазвичай ні. Розглядайте .htaccess як застарілий інструмент і перевіряйте результати.

7) Чому завантаження падають лише для деяких користувачів або мереж?

Повільні uplink‑канали можуть вичерпувати таймаути. Корпоративні проксі можуть заважати. Також різні користувачі завантажують різні файли. Перевірте таймаути, чи варіюються edge‑захисти по регіонах, і протестуйте з мережі origin.

8) Чи є підвищення лімітів ризиком для безпеки?

Може бути. Більші тіла — більше ресурсоємності: пропускна здатність, тимчасовий диск, CPU для обробки і довші запити. Встановлюйте ліміти свідомо, обмежуйте за можливості по шляху (адмін), і моніторте.

9) Як визначити, який шар блокує завантаження?

Шукайте 413 у браузері і в логах Nginx/Apache. Якщо Nginx логгить «client intended to send too large body» — це Nginx. Якщо PHP пише «POST Content-Length exceeds» — це PHP. Якщо ніде — підозрюйте CDN/WAF або проблеми з файловою системою.

10) Чому вчора працювало, а сьогодні впало без змін?

Поширені причини: оновлення пакета замінило конфіги, панель скинула налаштування, диск заповнився або змінилася політика проксі/WAF. Саме тому варто мати конфіг‑сніпети і перевірки верифікації.

Висновок: наступні кроки, що не підведуть

Виправлення «exceeds upload_max_filesize» — це не пошук чарівної рядки в php.ini. Це узгодження лімітів по всьому шляху запиту і доведення ефективної конфігурації у веб‑контексті.

Зробіть наступне:

  1. Пройдіть швидкий план діагностики і визначте, чи блок — на краю, веб‑сервері чи в PHP.
  2. Встановіть чітку цільову величину і узгодьте client_max_body_size/LimitRequestBody, post_max_size і upload_max_filesize.
  3. Перезавантажте потрібні сервіси, потім перевірте через served phpinfo (тимчасово) і логи.
  4. Перевірте диск і тимчасове сховище. Якщо дозволяєте великі файли — плануйте конкуренцію і зростання.
  5. Запишіть, де зберігаються налаштування. Майбутнє «ви» — чужинець; лишіть карту.
← Попередня
Втома від підписок: як індустрія здала в оренду ваші власні інструменти
Наступна →
Помилки входу Proxmox LDAP/AD: де ламається ланцюг автентифікації і як виправити

Залишити коментар