Перенести WordPress или WooCommerce на VDS недостаточно. Можно получить мощный сервер и при этом медленный магазин, 502 ошибки во время импорта, зависшие фоновые задачи или ситуацию, когда один тяжёлый запрос съедает ресурсы всего проекта.
Нормальная настройка VDS строится не вокруг принципа «поставим побольше памяти и увеличим все тайм-ауты», а вокруг баланса ресурсов: PHP-FPM, базы данных, Redis, Nginx, фоновых задач WordPress и реальной нагрузки интернет-магазина.
Актуальность: сентябрь 2026 года.
Рассматриваемая архитектура: Linux, Nginx, PHP-FPM, MySQL или MariaDB, Redis, WordPress и WooCommerce.
Важно: приведённые значения — стартовые ориентиры, а не универсальные настройки для любого сервера. Финальные параметры определяются по объёму RAM, количеству CPU, базе данных, посещаемости и фактическому потреблению ресурсов PHP-процессами.
1. Перед настройкой VDS зафиксируйте исходное состояние
Сделайте полноценную резервную копию
Перед миграцией или изменением серверных параметров необходимо сохранить:
При наличии WP-CLI полезно сохранить состояние проекта:
cd /var/www/site.ru/public_html
wp core version
wp plugin list --status=active
wp theme list --status=active
wp option get home
wp option get siteurl
wp db size --human-readable
wp db export ../backup-before-vds.sql
Архив сайта можно создать отдельно:
tar -czf /backup/site-files.tar.gz /var/www/site.ru/public_html
2. Используйте staging перед изменением production
Переключать PHP, Redis, структуру хранения заказов WooCommerce или систему кэширования непосредственно на рабочем магазине — плохая практика.
Создайте staging-копию проекта и сначала проверяйте изменения там.
Например, в уже существующий HTTPS-конфиг тестового сайта можно добавить Basic Auth:
auth_basic "Staging";
auth_basic_user_file /etc/nginx/.htpasswd-staging;
После изменения конфигурации:
sudo nginx -t
sudo systemctl reload nginx
server {}. Не заменяйте им существующий виртуальный хост.
Что обязательно проверить на staging
| Функция | Что проверяем |
|---|---|
| Каталог | Фильтры, сортировка, поиск, пагинация |
| Карточка товара | Цена, вариации, остатки, галерея |
| Корзина | Добавление, удаление, изменение количества |
| Checkout | Оформление заказа и валидация полей |
| Оплата | Тестовая транзакция и возврат пользователя |
| Доставка | Расчёт стоимости и API перевозчиков |
| WooCommerce | Фоновые задачи и Action Scheduler |
| 1С | Импорт товаров, цен, остатков и заказов |
3. Выбор версии PHP
Для современного WooCommerce следует использовать поддерживаемую версию PHP.
Для production-проектов разумным консервативным вариантом в 2026 году остаётся PHP 8.4. PHP 8.5 можно использовать после проверки совместимости конкретного проекта.
Перед обновлением проверьте:
- WooCommerce;
- активную тему;
- Elementor и его дополнения;
- платёжные плагины;
- интеграцию доставки;
- обмен с 1С;
- самописный код;
- Redis Object Cache;
- cron-задачи.
4. Не путайте PHP в консоли и PHP сайта
На одном сервере могут одновременно работать PHP 8.2, PHP 8.3, PHP 8.4 и разные PHP-FPM-пулы.
Команда:
php -v
показывает версию CLI PHP. Она не гарантирует, что сайт обслуживает та же версия.
Проверяем CLI
php -v
php --ini
php -m
Проверяем PHP-FPM
systemctl status php8.4-fpm
Затем необходимо посмотреть, какой сокет PHP использует конкретный виртуальный хост Nginx.
Ищите параметр:
fastcgi_pass
Например:
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
phpinfo(), удалите его сразу после диагностики. Публично оставлять такой файл не нужно.
5. Базовая конфигурация PHP для WooCommerce
Для среднего WooCommerce-магазина можно начать примерно с таких значений:
memory_limit = 512M
max_execution_time = 120
max_input_time = 120
max_input_vars = 10000
upload_max_filesize = 128M
post_max_size = 160M
realpath_cache_size = 4096K
realpath_cache_ttl = 600
expose_php = Off
Значения необходимо корректировать под конкретный проект.
memory_limit.
memory_limit — это лимит, а не ускоритель PHP.
То же самое касается:
max_execution_time;max_input_time;post_max_size.
Увеличенный тайм-аут разрешает медленному процессу работать дольше. Быстрее от этого он не становится.
6. Какие расширения PHP нужны WordPress и WooCommerce
| Расширение | Назначение |
|---|---|
| mysqli | Работа WordPress с MySQL/MariaDB |
| curl | HTTP API, оплаты, доставка, внешние сервисы |
| mbstring | Корректная работа со строками UTF-8 |
| intl | Интернационализация и локализация |
| xml | XML и CommerceML |
| soap | SOAP-интеграции, если они используются |
| zip | Архивы, обновления и импорт |
| imagick | Работа с изображениями |
| gd | Дополнительная библиотека обработки изображений |
| redis | Подключение PHP к Redis |
| opcache | Кэширование скомпилированного PHP-кода |
7. Настройка OPcache
OPcache — один из базовых компонентов производительности PHP. Он хранит уже скомпилированный PHP-код в памяти и избавляет PHP от повторной компиляции файлов при каждом запросе.
Пример:
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=2
opcache.save_comments=1
opcache.jit=off
opcache.jit_buffer_size=0
После изменения:
sudo php-fpm8.4 -t
sudo systemctl reload php8.4-fpm
8. PHP-FPM: не угадываем количество процессов
Один из самых распространённых способов «оптимизировать» WooCommerce — поставить огромное значение pm.max_children.
Результатом часто становится не ускорение сайта, а нехватка RAM, swap, рост нагрузки MySQL и 502/504 ошибки.
Как считать pm.max_children
Сначала определите, сколько памяти реально можно выделить PHP.
Например:
| RAM сервера | 8 GB |
|---|---|
| MySQL/MariaDB | 3 GB |
| Redis | 512 MB |
| ОС + Nginx + запас | 1.5 GB |
| Остаётся PHP | около 3 GB |
Если тяжёлый PHP-процесс потребляет около 250 MB:
Это ограничение по памяти. Реальное значение может оказаться ещё ниже из-за CPU или производительности базы данных.
Пример PHP-FPM пула
pm = dynamic
pm.max_children = 12
pm.start_servers = 3
pm.min_spare_servers = 3
pm.max_spare_servers = 6
pm.max_requests = 500
request_terminate_timeout = 180s
request_slowlog_timeout = 5s
slowlog = /var/log/php8.4-fpm/site-slow.log
pm.max_requests периодически перезапускает PHP-процесс и помогает ограничивать последствия утечек памяти в плагинах или стороннем коде.
Проверяем реальное потребление процессов
ps -ylC php-fpm8.4 --sort:rss
free -h
top
После изменения PHP-FPM необходимо контролировать:
- достижение
pm.max_children; - очередь запросов;
- 502 и 504 ошибки;
- RSS PHP-процессов;
- CPU;
- swap;
- время выполнения тяжёлых запросов.
9. Nginx: кэширование статики
CSS, JavaScript, изображения и шрифты не должны каждый раз заново загружаться без необходимости.
Но кэшировать все файлы на год с директивой immutable — тоже плохая идея.
CSS, JavaScript и шрифты
location ~* \.(?:css|js|woff|woff2|ttf|otf)$ {
expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable";
access_log off;
}
Для WordPress CSS и JS обычно имеют версию в URL, например:
style.css?ver=6.4.1
После изменения файла версия URL меняется, поэтому длительное кэширование безопаснее.
Изображения
location ~* \.(?:jpg|jpeg|png|gif|webp|avif|svg|ico)$ {
expires 30d;
add_header Cache-Control "public, max-age=2592000";
access_log off;
}
immutable использовать стоит осторожнее: изображение иногда заменяют, сохраняя прежний URL.
10. Запрещаем исполнение PHP внутри uploads
PHP-файлы в каталоге загрузок WordPress обычно не должны выполняться.
Соответствующее правило должно располагаться раньше общего PHP-location:
location ~* ^/wp-content/uploads/.*\.php$ {
deny all;
}
Ниже уже находится стандартная обработка PHP:
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
}
location. Поэтому недостаточно просто добавить правило куда-нибудь в конфиг и увидеть успешный nginx -t.
Проверка
После изменения:
sudo nginx -t
sudo systemctl reload nginx
Затем нужно проверить фактическое поведение сайта: обычные файлы uploads должны открываться, а PHP-файл из этого каталога не должен исполняться.
11. Защита чувствительных файлов
Минимально можно закрыть доступ к скрытым файлам, wp-config.php и служебным конфигурациям.
location ~ /\.(?!well-known).* {
deny all;
}
location = /wp-config.php {
deny all;
}
location ~* /(?:\.env|composer\.json|composer\.lock)$ {
deny all;
}
12. XML-RPC: не блокируйте автоматически
xmlrpc.php действительно часто становится целью автоматических атак.
Но некоторые внешние сервисы и интеграции могут его использовать.
Если XML-RPC вашему проекту точно не нужен:
location = /xmlrpc.php {
deny all;
}
13. Заголовки безопасности
Можно начать с относительно безопасного базового набора:
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
HSTS включайте только после того, как убедились, что основной домен и необходимые поддомены полностью работают через HTTPS.
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
default-src * 'unsafe-inline' 'unsafe-eval' только ради красивой галочки «у нас есть CSP». Такая политика почти теряет смысл как средство защиты.
Полноценный Content-Security-Policy строится после анализа используемых скриптов, iframe, систем аналитики, платёжных форм и внешних сервисов.
14. Redis Object Cache для WordPress и WooCommerce
Redis object cache хранит результаты частых запросов WordPress в оперативной памяти и уменьшает количество обращений к базе данных.
Особенно заметен эффект на:
- тяжёлых каталогах;
- фильтрах;
- административной части;
- личном кабинете;
- WooCommerce;
- проектах с большим количеством опций и метаданных.
Для WordPress можно использовать Redis Object Cache.
wp-config.php
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
define('WP_REDIS_DATABASE', 0);
define('WP_REDIS_PREFIX', 'site.ru:production:');
WP_CACHE_KEY_SALT для Redis Object Cache лучше заменить на актуальный WP_REDIS_PREFIX.
Если несколько сайтов используют Redis
Для каждого сайта используйте отдельный уникальный префикс:
shop1.ru:production:
shop2.ru:production:
shop1.ru:staging:
Для независимых клиентских проектов ещё лучше использовать отдельные экземпляры Redis или продуманное серверное разделение.
15. Ограничиваем память Redis
Redis не должен бесконтрольно занимать всю RAM.
Для экземпляра, используемого исключительно как восстанавливаемый объектный кэш, можно установить лимит:
maxmemory 512mb
maxmemory-policy allkeys-lfu
Размер зависит от конкретного сайта и объёма оперативной памяти сервера.
16. Page Cache для WooCommerce
Объектный кэш Redis и page cache — разные уровни кэширования.
Page cache может полностью отдать уже подготовленный HTML без запуска WordPress, PHP и большого количества SQL-запросов.
Для публичных страниц это даёт серьёзный прирост производительности.
Но WooCommerce содержит персонализированные данные.
Нельзя отдавать общий HTML-кэш для:
- корзины;
- checkout;
- личного кабинета;
- страницы оплаты;
- авторизованных пользователей;
- пользователей с индивидуальными ценами;
- AJAX-запросов;
- REST API;
- CommerceML;
- webhook;
- динамических сессий WooCommerce.
WooCommerce cookies, которые необходимо учитывать
wordpress_logged_in_
woocommerce_items_in_cart
woocommerce_cart_hash
wp_woocommerce_session_
/cart/ и /checkout/ недостаточно. Необходимо учитывать пользовательскую сессию и cookies.
Если используется FastCGI Cache Nginx, необходимо отдельно учитывать:
fastcgi_cache_bypass
fastcgi_no_cache
Первая директива запрещает использовать существующий кэш для запроса, вторая — сохранять результат запроса в кэш.
17. Реальный cron вместо запуска WP-Cron посетителями
По умолчанию WordPress запускает WP-Cron при посещениях сайта.
У такого подхода есть два недостатка:
- при низкой посещаемости задачи выполняются с задержкой;
- при высокой посещаемости механизм создаёт лишние проверки.
Для production-магазина разумно использовать системный cron.
wp-config.php
define('DISABLE_WP_CRON', true);
Создаём cron от пользователя сайта
sudo -u siteuser crontab -e
Например, запуск каждые пять минут:
*/5 * * * * cd /var/www/site.ru/public_html && /usr/local/bin/wp cron event run --due-now --quiet
which wp.
Проверяем задачи
wp cron event list
18. WooCommerce Action Scheduler
WooCommerce и многие плагины используют Action Scheduler для выполнения фоновых операций.
Проблемы с очередью могут приводить к задержкам:
- писем;
- webhook;
- синхронизации;
- обновления индексов;
- подписок;
- фоновых импортов;
- служебных задач WooCommerce.
Проверяем очередь
wp action-scheduler status
wp action-scheduler action list --status=pending
wp action-scheduler action list --status=failed
19. Интеграция WooCommerce с 1С
Обмен с 1С — отдельный тип нагрузки. Импорт нескольких тысяч товаров нельзя рассматривать как обычное открытие страницы WordPress.
Плохая практика:
max_execution_time = 600
request_terminate_timeout = 600s
fastcgi_read_timeout = 600s
и затем применять эти значения ко всему сайту только потому, что один импорт работает долго.
Что контролировать во время обмена
| Показатель | Зачем |
|---|---|
| CPU | Понимаем, не упирается ли импорт в процессор |
| RAM | Ищем PHP-процессы с аномальным потреблением |
| MySQL CPU | Определяем нагрузку на базу |
| PHP-FPM queue | Проверяем, остаются ли ресурсы для покупателей |
| Slow Query Log | Находим тяжёлые SQL-запросы |
| Время импорта | Сравниваем результат оптимизации |
20. MySQL и MariaDB нельзя настраивать одним универсальным конфигом
Настройки InnoDB зависят от:
- версии СУБД;
- объёма RAM;
- размера базы;
- характера нагрузки;
- числа PHP-процессов;
- наличия других сайтов на сервере.
Первым делом определите используемую СУБД:
mysql --version
21. InnoDB Buffer Pool
innodb_buffer_pool_size — один из наиболее важных параметров производительности InnoDB.
Но правило «отдать MySQL 70–80% RAM» подходит в первую очередь отдельному серверу базы данных.
Если на одном VDS одновременно работают:
- Nginx;
- PHP-FPM;
- MySQL/MariaDB;
- Redis;
- системные сервисы;
необходимо распределять память между всеми компонентами.
Пример для VDS с 8 GB RAM
В качестве стартовой точки для среднего WooCommerce можно выделить InnoDB примерно 2.5–3.5 GB, а затем корректировать значение по фактической нагрузке.
Например:
[mysqld]
max_connections = 120
max_allowed_packet = 128M
innodb_buffer_pool_size = 3G
innodb_flush_log_at_trx_commit = 1
skip_name_resolve = ON
slow_query_log = ON
long_query_time = 1
22. Redo Log: MySQL и MariaDB
Не используйте старые параметры MySQL из статей десятилетней давности без проверки версии.
MySQL 8.4
Для современных MySQL используется общий размер redo:
innodb_redo_log_capacity = 1G
MariaDB
У MariaDB набор параметров отличается, поэтому конфигурацию необходимо сверять именно с используемой версией.
Например, может использоваться:
innodb_log_file_size = 512M
23. Надёжность транзакций WooCommerce
WooCommerce хранит заказы, оплаты и изменения статусов в базе данных.
Поэтому для интернет-магазина сохранность транзакций обычно важнее нескольких процентов производительности.
Для MySQL стандартным безопасным вариантом является:
innodb_flush_log_at_trx_commit = 1
Если используются binlog:
sync_binlog = 1
innodb_flush_log_at_trx_commit = 2 иногда используют ради производительности, но при аварии ОС или оборудования появляется риск потерять последние транзакции. Для магазина это необходимо осознавать, а не включать как «оптимизацию».
24. Binlog лучше контролировать, а не просто отключать
Бинарный журнал MySQL используется для:
- репликации;
- восстановления на конкретный момент времени;
- восстановления изменений после последней полной резервной копии.
На WooCommerce-сайте возможность восстановить заказы после последнего ночного бэкапа может оказаться намного ценнее нескольких гигабайт диска.
Поэтому вместо автоматического отключения binlog лучше настроить срок хранения.
Например:
binlog_expire_logs_seconds = 604800
max_binlog_size = 100M
604800 секунд — семь суток.
25. Slow Query Log
Если WooCommerce медленный, проблема очень часто находится не в PHP, а в SQL-запросах.
Для диагностики включите журнал медленных запросов:
slow_query_log = ON
long_query_time = 1
На production журнал нужно контролировать, чтобы он не рос бесконечно.
join_buffer_size или sort_buffer_size. Сначала найдите проблему, затем лечите её.
26. Autoload-опции WordPress
WordPress автоматически загружает часть записей из таблицы options практически при каждом запросе.
Если в autoload попали мегабайты ненужных данных, Redis и мощный процессор не исправят архитектурную проблему полностью.
Проверяем общий объём
wp option list --autoload=on --format=total_bytes
Ищем крупные записи
wp option list --autoload=on --fields=option_name,size_bytes
27. HPOS в WooCommerce
High-Performance Order Storage переносит данные заказов WooCommerce из универсальных WordPress-таблиц posts/postmeta в специализированные таблицы заказов.
Для современных магазинов HPOS является нормальной архитектурой хранения заказов.
На существующем проекте перед переключением необходимо проверить:
28. Права файлов WordPress
Для большинства проектов базовой схемой остаются:
find /var/www/site.ru/public_html -type d -exec chmod 755 {} \;
find /var/www/site.ru/public_html -type f -exec chmod 644 {} \;
Для wp-config.php можно использовать более строгие права:
chmod 640 /var/www/site.ru/public_html/wp-config.php
Владелец должен соответствовать архитектуре конкретного сервера и PHP-FPM-пула.
chown -R www-data:www-data только потому, что он встретился в инструкции. На сервере с отдельными пользователями сайтов вы таким образом можете разрушить нормальную модель изоляции.
29. Базовая безопасность самого VDS
Оптимизация WordPress бессмысленна, если сам сервер оставлен практически без защиты.
Обновления
sudo apt update
sudo apt upgrade
Firewall
Перед включением firewall обязательно разрешите SSH.
sudo ufw allow OpenSSH
sudo ufw allow "Nginx Full"
sudo ufw enable
SSH
Для production разумно:
- использовать SSH-ключи;
- не работать постоянно под root;
- отключить парольный вход после проверки ключей;
- ограничить доступ административных сервисов.
30. Nginx rate limit — не полноценная DDoS-защита
Nginx умеет ограничивать число запросов с одного IP. Это полезно против:
- агрессивных ботов;
- brute-force;
- парсеров;
- аномального количества запросов к API.
Но это не заменяет защиту от серьёзной DDoS-атаки.
Для объёмных атак защита должна находиться выше по сети — у хостинг-провайдера, reverse proxy или CDN.
31. Миграция WooCommerce без потери заказов
У обычного информационного WordPress между созданием дампа и переключением DNS обычно ничего критичного не происходит.
У WooCommerce за это время могут появиться:
- новые заказы;
- оплаты;
- изменения статусов;
- регистрации клиентов;
- новые остатки;
- webhook.
Правильная последовательность
1. Подготовка
Развернуть новый сервер и полностью проверить сайт до переключения.
2. Снижение TTL
Заранее уменьшить DNS TTL, если это необходимо для миграции.
3. Финальная синхронизация
Перед переключением перенести последние изменения базы и необходимые файлы.
4. Переключение
Направить трафик на новый сервер.
5. Контроль
Проверить заказы, оплаты, cron, вебхуки, почту, 1С и логи.
6. Старый сервер
Не отключать его мгновенно, пока не подтверждена стабильность новой площадки.
32. Почему обычного бэкапа недостаточно
Резервная копия считается рабочей только после успешного восстановления.
Для WooCommerce также важно понимать Recovery Point Objective — сколько последних данных бизнес готов потерять.
Если бэкап создаётся раз в сутки, теоретически можно потерять почти сутки заказов.
Именно здесь становятся полезны:
- частые database backup;
- binlog;
- внешнее хранилище;
- point-in-time recovery.
33. Что мониторить после миграции
| Компонент | Что контролировать |
|---|---|
| CPU | Средняя и пиковая загрузка |
| RAM | Использование памяти и swap |
| Диск | Свободное место и I/O |
| PHP-FPM | Активные процессы, очередь, max_children |
| MySQL | CPU, соединения и slow query |
| Redis | Память, hit ratio и eviction |
| Nginx | 4xx, 5xx и время ответа |
| WordPress | PHP errors и cron |
| WooCommerce | Action Scheduler и ошибки заказов |
| 1С | Продолжительность и ошибки обмена |
Базовые команды
free -h
df -h
top
systemctl status nginx
systemctl status php8.4-fpm
systemctl status redis-server
systemctl status mysql
34. Измеряем производительность правильно
Главная страница из браузера администратора — плохой benchmark.
Для WooCommerce необходимо отдельно тестировать:
Публичный каталог
Страница без авторизации с прогретым page cache.
Холодный запрос
Страница без готового HTML-кэша.
Авторизованный клиент
Проверка сайта без общего page cache.
Фильтрация
Категории, фильтры и AJAX.
Checkout
Полный сценарий оформления заказа.
Импорт 1С
Работа магазина одновременно с тяжёлым обменом.
Полезно фиксировать не только среднее время ответа, но и p95.
35. Core Web Vitals после серверной оптимизации
Быстрый сервер ещё не гарантирует хорошие показатели Core Web Vitals.
После серверной части необходимо отдельно проверить:
- LCP;
- INP;
- CLS;
- TTFB;
- размер изображений;
- блокирующие CSS;
- JavaScript;
- шрифты;
- сторонние аналитические скрипты.
36. Итоговый чек-лист настройки VDS для WooCommerce
Заключение
Хорошо настроенный VDS для WordPress и WooCommerce — это не сервер с максимальными значениями memory_limit, pm.max_children и тайм-аутами по десять минут.
Производительная конфигурация строится из нескольких уровней:
- Nginx быстро отдаёт статические файлы;
- PHP-FPM имеет достаточно процессов, но не уничтожает RAM;
- OPcache исключает ненужную повторную компиляцию PHP;
- Redis уменьшает количество повторных запросов к базе;
- MySQL или MariaDB получают достаточно памяти для InnoDB;
- page cache ускоряет публичные страницы, не затрагивая персональные данные;
- cron и Action Scheduler стабильно выполняют фоновые задачи;
- обмен с 1С не блокирует покупателей;
- резервные копии позволяют реально восстановить магазин;
- мониторинг показывает проблему до того, как её заметят клиенты.
Именно поэтому оптимальная конфигурация VDS всегда определяется измерениями. Два магазина WooCommerce с одинаковым количеством товаров могут создавать совершенно разную нагрузку из-за фильтров, темы, плагинов, интеграций, персональных цен и фоновых процессов.
Настройка сервера заканчивается не тогда, когда сайт открылся после перезагрузки Nginx, а тогда, когда под реальной нагрузкой стабильно работают каталог, корзина, оплата, фоновые задачи, 1С и восстановление данных.