MAATRIX / Блог / WordPress на сервере: частые ошибки и решения

WordPress на сервере: частые ошибки и решения

WordPress на сервере: частые ошибки и решения

MAATRIX

На своём VPS WordPress ломается не так, как на шаред-хостинге: сайт просит FTP-доступ для обновления, все страницы кроме главной отдают 404, медиатека отвечает 413 Request Entity Too Large, браузер уходит в ERR_TOO_MANY_REDIRECTS. Почти все ошибки WordPress на сервере — не баги движка, а стык между PHP-FPM, веб-сервером, правами на файлы и памятью. Ниже — как понять, какой слой сломался, и что в нём чинить.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

С чего начинать разбор ошибок WordPress

Запрос проходит четыре слоя: Nginx (или Apache) → PHP-FPM → WordPress → MariaDB. Ошибка каждого выглядит по-своему — это и есть способ не гадать по симптому.

СимптомКуда смотреть
404 везде, кроме главнойправила rewrite веб-сервера
413 Request Entity Too Largeclient_max_body_size в Nginx
502 / 504, «зависает»pm.max_children, таймауты FPM
Пустая белая страницаdebug.log, лимит памяти PHP
Просит FTP-доступ при обновлениивладелец файлов
«Ошибка соединения с базой данных»MariaDB, следы OOM

Сначала — кто ответил:

curl -sI https://example.com | head -5
tail -f /var/log/nginx/error.log
journalctl -u php8.3-fpm -n 50 --no-pager

Заголовок Server: nginx без X-Powered-By — до PHP запрос не дошёл. Дошёл, но пусто — включайте WP_DEBUG и WP_DEBUG_LOG в wp-config.php, задав свой путь вроде /var/log/wp/debug.log: по умолчанию файл ложится в wp-content и открыт по прямой ссылке любому. Каталог создайте заранее и отдайте www-data.

Два сообщения сбивают с толку. Письмо «Ваш сайт столкнулся с технической ошибкой» — не спам, а режим восстановления: по ссылке ?action=enter_recovery_mode админка открывается с отключённым сбойным плагином. А Briefly unavailable for scheduled maintenance значит, что оборвавшееся обновление оставило файл-флаг: rm -f /var/www/example.com/.maintenance.

Права и владелец: запрос FTP и «не удалось создать директорию»

Самая частая серверная ошибка выглядит так: при установке плагина открывается форма «Для обновления WordPress необходим доступ к вашему серверу по FTP» или приходит Installation failed: Could not create directory.

Механика простая: перед записью WordPress создаёт временный файл от имени процесса PHP. Не вышло — движок считает прямой доступ закрытым и переключается на ftpext. Значит, владелец файлов не тот, что у PHP-FPM.

ps -o user= -C php-fpm8.3 | sort -u
stat -c '%U:%G %a %n' /var/www/example.com/wp-content

Вывод root:root при пользователе www-data — диагноз поставлен.

chown -R www-data:www-data /var/www/example.com
find /var/www/example.com -type d -exec chmod 755 {} \;
find /var/www/example.com -type f -exec chmod 644 {} \;
chmod 640 /var/www/example.com/wp-config.php

Честно про два обхода. chmod -R 777 проблему «чинит» и делает сайт мишенью: любой процесс на машине, включая чужой скрипт с соседнего сайта, допишет код в wp-includes. define('FS_METHOD', 'direct'); убирает форму FTP, но прав не даёт: при чужом владельце придёт Не удалось создать директорию. — честнее, но не легче.

Если файлы выкатывает отдельный пользователь (deploy, Git, CI), chown слетает после каждого деплоя: тогда владельцем оставляют deploy, а запись для PHP выдают точечно через setfacl -R -d -m u:www-data:rwX .../wp-content/uploads. А на AlmaLinux и Rocky при верных 755 в логе бывает (13)Permission denied — это SELinux: chcon -R -t httpd_sys_rw_content_t wp-content/uploads; на Ubuntu и Debian такого слоя нет.

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть WordPress

404 на всех страницах, кроме главной

Классика переезда. Проверяется за десять секунд — постучитесь по «некрасивой» ссылке:

curl -s -o /dev/null -w '%{http_code}\n' 'https://example.com/?p=1'          # 200
curl -s -o /dev/null -w '%{http_code}\n' 'https://example.com/hello-world/'  # 404

?p=1 работает, ЧПУ — нет: дело в правилах перезаписи. В Nginx файла .htaccess не существует вообще, советы «проверьте .htaccess» тут бесполезны. Нужен один блок:

index index.php index.html;

location / {
    try_files $uri $uri/ /index.php?$args;
}

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

Типичная ошибка — конфиг из инструкции по статическому сайту с try_files $uri $uri/ =404;. Вариант той же беды: пропущен index index.php, в error.log появляется directory index of "/var/www/example.com/" is forbidden, браузер видит 403.

На Apache нужны a2enmod rewrite и AllowOverride All вместо None: при None файл .htaccess игнорируется молча — ошибок в логе нет, просто 404. После правки пересохраните структуру ссылок или выполните wp rewrite flush --hard.

Загрузка файлов и таймауты: 413, 504 и молча обрезанные настройки

413 Request Entity Too Large — ответ Nginx, PHP запрос даже не увидел; в error.log строка client intended to send too large body: 27262976 bytes. Лечит client_max_body_size 64m; в http или server.

«Файл превышает upload_max_filesize, указанный в php.ini» — уже ответ WordPress: лимит в PHP. Правьте /etc/php/8.3/fpm/php.ini, затем systemctl reload php8.3-fpm:

upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 300
max_input_vars = 5000

Три подводных камня:

  • php -i показывает не то — у CLI отдельный php.ini в /etc/php/8.3/cli/. Значения FPM смотрите в админке: «Здоровье сайта → Информация → Сервер».
  • Пул перебивает php.ini — строка php_admin_value[upload_max_filesize] = 8M в /etc/php/8.3/fpm/pool.d/www.conf приоритетнее: grep -r php_admin_value /etc/php/8.3/fpm/pool.d/.
  • .user.ini в корне сайта кэшируется 300 секунд (user_ini.cache_ttl) — правка «не применяется» ещё пять минут.

504 Gateway Time-out при импорте или бэкапе — это upstream timed out (110: Connection timed out) while reading response header в логе Nginx. Нужны три согласованных значения: fastcgi_read_timeout 300s; у Nginx, request_terminated_timeout = 300s в пуле PHP-FPM и max_execution_time = 300 в PHP; поднимете одно — упрётесь в остальные.

Отдельно стоит max_input_vars: по умолчанию 1000, превышение не выдаёт ошибки вообще — меню на 200 пунктов сохраняется наполовину, настройки темы теряют поля, в debug.log тишина.

HTTPS и редиректы: ERR_TOO_MANY_REDIRECTS и смешанный контент

Браузер показывает ERR_TOO_MANY_REDIRECTS, curl считает круги:

curl -sIL -o /dev/null -w '%{num_redirects}\n' https://example.com
sudo -u www-data wp --path=/var/www/example.com option get siteurl

Адрес в базе не совпадает с фактическим. В wp_options осталось http://example.com или вариант с www, а веб-сервер редиректит на https:// без www. Лечится константами:

define('WP_HOME', 'https://example.com');
define('WP_SITEURL', 'https://example.com');

Минус честный: поля в админке станут неактивными, а ссылки внутри статей останутся старыми — константы их не переписывают.

Сайт за обратным прокси или Cloudflare. TLS до WordPress не доходит, $_SERVER['HTTPS'] пуст, движок отдаёт http://-ссылки, прокси снова гонит на https://. Лечится в wp-config.php до строки require_once ABSPATH:

if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
    $_SERVER['HTTPS'] = 'on';
}

Со стороны прокси нужен proxy_set_header X-Forwarded-Proto $scheme;. Риск, о котором молчат мануалы: заголовку вы теперь верите на слово, а прислать его может кто угодно — держите бэкенд на 127.0.0.1, наружу только ufw allow 22/tcp и ufw allow 80,443/tcp.

Смешанный контент после переезда на HTTPS — замок перечёркнут, картинки не грузятся. Массовая замена — через WP-CLI, сначала с --dry-run и свежим дампом:

sudo -u www-data wp --path=/var/www/example.com search-replace \
  'http://example.com' 'https://example.com' --all-tables --dry-run

Прямой UPDATE ... REPLACE() делать нельзя: настройки тем и виджетов хранятся сериализованными, рядом со строкой записана её длина. После httphttps длина меняется, а число нет — блоки исчезают. WP-CLI пересобирает сериализацию.

Память, воркеры и база: OOM, max_children и «gone away»

Сайт падал ночью без нагрузки, а утром работает — почти наверняка отработал OOM killer: dmesg -T | grep -i 'killed process'.

[Tue Aug 25 03:11:44 2026] Out of memory: Killed process 8123 (php-fpm8.3)
total-vm:512864kB, anon-rss:196404kB, file-rss:0kB

Если жертвой стал mariadbd, симптом другой — «Ошибка установки соединения с базой данных», хотя виновата память; её разбор — в отдельной статье.

Дальше — арифметика. Размер воркера покажет ps -ylC php-fpm8.3 --sort:rss | awk 'NR>1 {print int($8/1024)" MB"}' | tail -5. Ориентиры: блог с кэширующим плагином — 45–70 МБ на воркер, WooCommerce с конструктором страниц — 120–190 МБ. Формула (RAM − память MariaDB − 350 МБ на систему) / размер воркера для 2 ГБ и MariaDB на 600 МБ даёт (2048 − 600 − 350) / 90 ≈ 12. Прописываем в /etc/php/8.3/fpm/pool.d/www.conf:

pm = ondemand
pm.max_children = 12
pm.process_idle_timeout = 30s
pm.max_requests = 500

pm.max_requests перезапускает воркер каждые 500 запросов — страховка от утечек в плагинах. Строка WARNING: [pool www] server reached pm.max_children setting (5), consider raising it означает очередь: запросы ждут воркера и получают 502 или 504. Поднимать значение вслепую бессмысленно — падение переедет в OOM.

Со стороны базы регулярны две вещи: MySQL server has gone away при импорте большого дампа лечится max_allowed_packet = 64M в /etc/mysql/mariadb.conf.d/50-server.cnf, а буфер InnoDB по умолчанию 128 МБ — для базы в 1–2 ГБ разумно 256–512 МБ.

Swap на VPS часто отсутствует, а он снимает большую часть ночных падений: fallocate -l 2G /swapfile, mkswap, swapon, строка в /etc/fstab, vm.swappiness=10. Это подушка, а не решение — сайт в swap медленный даже на NVMe. Тормозит панель, а не сайт — медленная админка; страница пустая — белый экран смерти.

Какой сервер под WordPress брать в MAATRIX

Половина разобранного выше — следствие тесной машины: OOM ночью, очередь на max_children, 504 на импорте. Конфигурация и есть профилактика.

Минимум: 1 vCPU, 2 ГБ RAM, 25–30 ГБ NVMe плюс 2 ГБ swap. Хватает на блог или визитку с кэшированием страниц: MariaDB с буфером 256 МБ и 8–10 воркеров PHP-FPM. Ограничение честное — это конфигурация под кэш. Магазин на WooCommerce с визуальным конструктором сюда не влезет: воркер весит под 180 МБ, и третий запрос в корзину кончается OOM. Вариант с 1 ГБ рабочим не считаю.

Комфортный вариант: 2 vCPU, 4 ГБ RAM, 60–80 ГБ NVMe. Три-пять небольших сайтов или один магазин: Redis под объектный кэш, буфер InnoDB на 1 ГБ, 15–20 воркеров, место под медиа и бэкапы. Магазину с тысячами товаров нужны 4 vCPU и 8 ГБ: узкое место — процессор на некэшируемых корзине и оплате.

Локация — Лондон. Для европейской аудитории это минимальный пинг и соседство с GDPR-периметром, а из Москвы до площадки 45–60 мс — на TTFB кэшированной страницы разница неразличима. Если сайт собирает персональные данные россиян и вы работаете по 152-ФЗ, берите Россию: пинг 5–15 мс и никакой трансграничной передачи. Франция равноценна Лондону, США — под американскую аудиторию.

Как это выглядит при заказе. WordPress есть в каталоге приложений MAATRIX и устанавливается автоматически — команды из этой статьи вручную вводить не нужно. Автоустановка работает на Ubuntu и Debian, включая 24.04 LTS: приезжает связка Nginx + PHP-FPM + MariaDB с владельцем www-data, рабочим try_files и вменяемыми лимитами загрузки, то есть без трёх самых частых поломок выше. Доступы появляются в личном кабинете, раздел «Доступ». Оплата — картами российских банков, по СБП, криптой или токеном MAAT. Тариф помогут выбрать разборы лучшего VPS для WordPress в Великобритании и ускорения на слабом VPS, конфигурации — на странице аренды VPS.

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть WordPress

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

WordPress просит FTP-доступ при установке плагина. Что вписать?

Ничего: это признак того, что владелец файлов не совпадает с пользователем PHP-FPM. Выполните chown -R www-data:www-data /var/www/example.com — форма исчезнет. FS_METHOD без прав только сменит текст ошибки.

После включения ЧПУ все страницы отдают 404. Куда смотреть?

В конфиг Nginx: нужен try_files $uri $uri/ /index.php?$args;, а не =404; файла .htaccess в Nginx нет. На Apache проверьте a2enmod rewrite и AllowOverride All.

Сайт падает ночью и сам поднимается. Это атака?

Чаще нет: dmesg -T | grep -i 'killed process' покажет, что OOM killer убил php-fpm или mariadbd во время планового задания. Пересчитайте pm.max_children и добавьте swap.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.