← Назад в блог

WordPress: ускоряем Nginx + PHP-FPM до TTFB меньше 300 мс

Пошаговая настройка OPcache и fastcgi_cache для WordPress 6.x на VPS (Nginx + PHP-FPM). Снижаем TTFB до 300 мс и нагрузку CPU. Конфиги, проверка, типичные ошибки.

WordPress: ускоряем Nginx + PHP-FPM до TTFB меньше 300 мс

Требования

  • WordPress 6.x
  • PHP 8.2
  • Доступ к VPS (root)

WordPress: ускоряем Nginx + PHP-FPM до TTFB меньше 300 мс

Если wordpress долго загружается nginx php-fpm, TTFB 2–5 секунд, CPU стабильно загружен, а плагинов немного — проблема почти всегда в конфигурации PHP-FPM, OPcache и отсутствии fastcgi_cache.

После настройки:

  • TTFB меньше 300 мс
  • CPU без перегруза
  • OPcache реально работает
  • Nginx кеширует анонимный трафик

Без Docker. Обычный VPS в prod.

Сниппеты по статье: OPcache для WordPress (php.ini) · PHP-FPM pool (pm dynamic) · Nginx fastcgi_cache для WordPress · Проверка TTFB (curl)


В чём проблема

Симптомы:

  • Страница открывается 2–5 секунд
  • curl -w "%{time_starttransfer}" показывает TTFB 1.8–3.5 сек
  • CPU 70–100%
  • top показывает php-fpm в топе процессов
  • Кеш-плагинов нет или они не решают проблему

Проверка TTFB (сниппет: curl TTFB):

curl -o /dev/null -s -w "TTFB: %{time_starttransfer}\n" https://example.com

Если видите:

TTFB: 2.341221

— PHP генерирует страницу каждый раз. Nginx не кеширует. OPcache либо отключён, либо настроен плохо.

Причины обычно такие:

  1. OPcache выключен или память 64MB.
  2. PHP-FPM работает с 5 процессами при 8 ядрах.
  3. Нет fastcgi_cache.
  4. Неправильно настроен bypass для админки.

Как отличить от других причин: если отключить все плагины (переименовать папку wp-content/plugins) и TTFB всё равно высокий — дело в стеке (Nginx/PHP-FPM/OPcache), а не в коде темы или плагинах. Если после отключения плагинов стало быстро — оптимизируйте тяжёлые плагины или кеш на уровне приложения. Здесь разбираем именно случай «плагинов немного, но стек не настроен».

WordPress сам по себе не медленный. Медленный — стек. Если после настройки появятся 502/504 — смотрите Nginx и PHP-FPM: ошибки 502, 504. Конфиг виртуальных хостов — в настройке server blocks для нескольких проектов.


Рабочее решение

1️⃣ Настраиваем OPcache (PHP 8.2)

Готовый блок с пояснениями: сниппет «OPcache для WordPress (php.ini)». Ниже — кратко.

Файл:

/etc/php/8.2/fpm/php.ini

Ищем блок OPcache и приводим к нормальному виду:

opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=256
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.fast_shutdown=1

Почему так:

  • 256MB — минимум для продакшена
  • validate_timestamps=0 — без постоянной проверки файлов
  • 20 000 файлов — WordPress + плагины легко съедают 10k+

Путь к php.ini может отличаться: на Debian/Ubuntu это обычно /etc/php/8.2/fpm/php.ini, на CentOS/Rocky — /etc/php.ini или отдельный файл в /etc/php.d/. Убедитесь, что правите именно конфиг FPM, а не CLI: php -i | grep "Loaded Configuration" покажет активный файл для CLI, для FPM смотрите конфиг пула.

Перезапуск:

systemctl restart php8.2-fpm

Проверка:

php -i | grep opcache.enable

Ожидаем:

opcache.enable => On => On

2️⃣ Настройка PHP-FPM (CPU не должен кипеть)

Полный вариант с проверкой памяти: сниппет «PHP-FPM pool (pm dynamic)». Ниже — ключевые параметры.

Файл:

/etc/php/8.2/fpm/pool.d/www.conf

Меняем pm режим:

pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 4
pm.max_spare_servers = 8
pm.max_requests = 500

pm.max_requests — после скольких запросов воркер перезапускается; снижает риск утечек памяти в долгоживущих процессах. 500–1000 нормально для WordPress.

Как считать:

  • max_children ≈ RAM / 60MB
  • Если 2GB RAM → ~30 процессов максимум

Проверка нагрузки:

ps --no-headers -o "rss,cmd" -C php-fpm8.2 | awk '{ sum+=$1 } END { print sum/1024 " MB" }'

3️⃣ Включаем fastcgi_cache в Nginx

Это ключевой момент. Готовый конфиг с bypass для админки: сниппет «Nginx fastcgi_cache для WordPress».

Файл:

/etc/nginx/nginx.conf

Добавляем в http:

fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=WORDPRESS:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

Создаём директорию:

mkdir -p /var/cache/nginx
chown -R www-data:www-data /var/cache/nginx

Размер зоны keys_zone=WORDPRESS:100m — это не место на диске, а объём ключей в памяти. 100m хватает на десятки тысяч URL. Реальный кеш лежит в /var/cache/nginx; убедитесь, что на разделе достаточно места (гигабайт и больше для активного сайта). Параметр inactive=60m — удалять ключ из кеша, если к нему не обращались 60 минут.


4️⃣ Настройка server для WordPress

Файл сайта:

/etc/nginx/sites-available/example.com

В location ~ .php$ добавляем:

set $skip_cache 0;

if ($request_method = POST) {
    set $skip_cache 1;
}

if ($query_string != "") {
    set $skip_cache 1;
}

if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-login.php") {
    set $skip_cache 1;
}

if ($http_cookie ~* "wordpress_logged_in") {
    set $skip_cache 1;
}

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

    fastcgi_cache WORDPRESS;
    fastcgi_cache_valid 200 60m;
    fastcgi_cache_bypass $skip_cache;
    fastcgi_no_cache $skip_cache;
    add_header X-FastCGI-Cache $upstream_cache_status;
}

Перезапуск:

systemctl restart nginx

Проверка результата

Проверка TTFB

curl -I https://example.com

В заголовках должно быть:

X-FastCGI-Cache: MISS

Повторный запрос:

X-FastCGI-Cache: HIT

Проверка времени:

curl -o /dev/null -s -w "TTFB: %{time_starttransfer}\n" https://example.com

Ожидаемый результат:

TTFB: 0.112341

CPU должен упасть минимум в 2–4 раза.

Краткий чеклист:

  • OPcache: php -i | grep opcache.enable → On
  • PHP-FPM: в pool.d/www.conf стоит pm = dynamic, pm.max_children по памяти
  • Nginx: в ответе есть заголовок X-FastCGI-Cache, при повторном запросе — HIT
  • TTFB: для закешированной главной — меньше 0,3 сек (лучше 0,05–0,15)

Если хотя бы один пункт не выполняется — возвращайтесь к соответствующему шагу выше. На проде после любых изменений конфига делайте nginx -t перед systemctl reload nginx.


Если не работает

1️⃣ Нет заголовка X-FastCGI-Cache → location блок не применяется.

Проверь:

nginx -T | grep fastcgi_cache

2️⃣ Всегда BYPASS → Cookie не даёт кешировать.

Проверь:

curl -I https://example.com | grep Set-Cookie

3️⃣ OPcache не даёт прироста → validate_timestamps включён.

Проверь:

php -i | grep validate_timestamps

Должно быть 0 в проде. После деплоя кода делайте systemctl reload php8.2-fpm, чтобы OPcache подхватил новые файлы.

4️⃣ Кеш не создаётся (всегда MISS) → путь к кешу неверный или нет прав.

Проверь:

ls -la /var/cache/nginx

Владелец должен быть www-data (или пользователь nginx). Если директории нет — создай и выдай права, как в шаге 3 выше, затем systemctl restart nginx.


Типичные ошибки

❌ OPcache 64MB Причина: дефолт Debian Решение: минимум 256MB


❌ pm = ondemand Причина: экономия памяти Проблема: запуск процессов под нагрузкой Решение: dynamic


❌ Кеширование админки Причина: нет bypass Решение: skip_cache условия


❌ Кеш не чистится при деплое Причина: validate_timestamps=0 Решение: после деплоя:

systemctl reload php8.2-fpm

Где применять

  • Production VPS
  • Nginx + PHP-FPM
  • Без Docker
  • CI/CD с деплоем через git pull
  • WordPress 6.x

Если используешь Docker — логика та же, но путь к сокету другой. Основы Nginx — в Nginx: основы веб-сервера. Дальнейшая оптимизация фронта (LCP, INP, кеш) — WordPress и Core Web Vitals.


После обновления кода или темы

При opcache.validate_timestamps=0 OPcache не перечитывает файлы сам. После деплоя (git pull, загрузка обновлённой темы или плагинов) выполните:

systemctl reload php8.2-fpm

Так PHP-FPM перезапустит воркеры и подхватит новый код. При необходимости сбросьте fastcgi_cache: удалите содержимое /var/cache/nginx или перезапустите Nginx. Для инвалидации только части кеша в Nginx нужна отдельная настройка (например, purge по ключу).


Итог

Если wordpress долго загружается nginx php-fpm, проблема почти никогда не в “тяжёлом WordPress”.

Проблема в:

  • выключенном OPcache
  • неправильном pm
  • отсутствии fastcgi_cache

После этих трёх шагов:

  • TTFB меньше 300 мс
  • CPU стабилен
  • Сайт ощущается быстрым

WordPress может работать быстро. Просто стек должен быть настроен как прод, а не как shared-хостинг 2012 года. Следуйте шагам по порядку и проверяйте результат после каждого этапа.

0 просмотров

Комментарии

Загрузка комментариев...
Пока нет комментариев. Будьте первым!