Миграция WordPress на новый VDS без простоя — это не магия, а дисциплина: план, staging, правильная синхронизация файлов и базы, финальный свитч DNS с минимальным «окном» записи. Ниже — подробный, проверенный на проектах чеклист с готовыми командами и пояснениями для админов, девопсов и вебмастеров.
План без простоя: что именно мы делаем
Чтобы перенести WordPress на новый VDS без потери трафика и заявок, нужны четыре шага: подготовка сервера, staging-копия сайта, синхронизация (rsync + дамп БД), и переключение DNS с возможностью отката. Важно учитывать динамическую природу WordPress: пользователи оставляют комментарии, оформляют заказы, меняют контент. По этой причине финальный шаг должен быть быстрым, а кеш страниц — готовым.
Золотое правило: снизьте TTL DNS заранее. Тогда «свитч» пройдёт за минуты, а не за часы.
Если нужен обзор методик «нулевого простоя» шире WordPress, посмотрите разбор подходов и рисков в статье Zero‑downtime миграции сайтов.
Предварительный чеклист
- Аудит текущего хоста: версии PHP/MySQL, модули, cron-задачи, объёмы
wp-content
. - Снижение TTL у A/AAAA/CNAME записей домена (например, до 300–600 секунд) за 24–72 часа до миграции. Изменить TTL можно в панели вашего регистратора или через регистрацию доменов.
- Доступ по SSH и ключи, список пользователей и прав, параметры файрвола.
- План совместимости: целевая версия PHP-FPM, доступные расширения, ограничения
memory_limit
,upload_max_filesize
,client_max_body_size
. - Резервные копии всего: дамп БД, полный архив файлов, экспорт задач cron.
Подготовка VDS: ОС, пакеты, пользователи, безопасность
Ниже пример для Ubuntu 22.04 LTS, но логика одинакова для большинства дистрибутивов.
apt update && apt upgrade -y
apt install -y nginx php-fpm php-mysql php-xml php-curl php-gd php-zip php-mbstring php-intl php-imagick
apt install -y mariadb-server redis-server unzip rsync git curl
Создаём выделенного пользователя и директории проекта:
adduser --disabled-password --gecos "" wpuser
usermod -aG www-data wpuser
mkdir -p /var/www/example.com/{public,logs}
chown -R wpuser:www-data /var/www/example.com
Базовая защита SSH и файрвол:
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl reload ssh
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

Настройка Nginx и PHP-FPM под WordPress
Минимальный сервер-блок с отдачей статики и проксированием в php-fpm:
cat > /etc/nginx/sites-available/example.com <<'NGINX'
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/public;
access_log /var/www/example.com/logs/access.log;
error_log /var/www/example.com/logs/error.log;
client_max_body_size 64m;
index index.php index.html;
location ~* \.(?:jpg|jpeg|gif|png|webp|svg|css|js|ico|woff2?)$ {
expires 7d;
add_header Cache-Control "public, no-transform";
try_files $uri =404;
}
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
location ~ /\.(ht|git) {
deny all;
}
}
NGINX
ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
Проверьте пул PHP-FPM, чтобы не упираться в процессы при пиковой нагрузке:
sed -n '1,160p' /etc/php/8.2/fpm/pool.d/www.conf | sed -n '1,160p'
# Важно для высоконагруженных:
# pm = dynamic
# pm.max_children = 16
# pm.start_servers = 4
# pm.min_spare_servers = 4
# pm.max_spare_servers = 8
systemctl reload php8.2-fpm
Staging: готовим клон сайта для проверки
Создайте поддомен для staging (например, staging.example.com
) с отдельной корневой папкой. На первом шаге перенесём текущую PROD-копию в staging, чтобы оттестировать окружение.
- Скопируйте файлы сайта (первичный перенос можно сделать tar/rsync).
- Сделайте дамп БД и разверните на новом сервере в отдельной базе.
- Скорректируйте
wp-config.php
под новую БД и домен staging.
# На старом сервере
cd /path/to/old/docroot
wp db export /tmp/wp.sql --add-drop-table
# Перенос файлов (кроме кэшей и бэкапов)
rsync -az --delete \
--exclude='.git' --exclude='cache/' --exclude='wp-content/cache/' \
--exclude='*.log' --exclude='updraft/' \
./ wpuser@new-vds:/var/www/example.com/public/
# Перенос БД
scp /tmp/wp.sql wpuser@new-vds:/tmp/
# На новом сервере (создать БД/пользователя)
mysql -e "CREATE DATABASE wpstaging CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -e "CREATE USER 'wpstg'@'localhost' IDENTIFIED BY 'StrongPass';"
mysql -e "GRANT ALL PRIVILEGES ON wpstaging.* TO 'wpstg'@'localhost'; FLUSH PRIVILEGES;"
mysql wpstaging < /tmp/wp.sql
Правим wp-config.php
и меняем URL сайта на staging через WP-CLI, чтобы корректно обновить сериализованные строки:
wp config set DB_NAME wpstaging --type=constant --path=/var/www/example.com/public
wp config set DB_USER wpstg --type=constant --path=/var/www/example.com/public
wp config set DB_PASSWORD StrongPass --type=constant --path=/var/www/example.com/public
# Корректный search-replace для смены домена
wp search-replace 'https://example.com' 'https://staging.example.com' --all-tables --precise --report-changed-only
Если WP-CLI не установлен, поставьте его в систему и добавьте в PATH. Это сильно уменьшает риски порчи сериализованных данных при замене URL.
Первая синхронизация rsync: быстро и безопасно
На этапе staging мы перенесли файлы один раз. Для финальной миграции нам понадобится двухфазный rsync: первичный (полный) и дельта перед свитчем DNS. Исключаем кэш и временные каталоги, чтобы не тратить трафик и время.
# Полная синхронизация файловой части PROD -> VDS
rsync -az --delete \
--exclude='.git' \
--exclude='wp-content/cache/' \
--exclude='wp-content/uploads/cache/' \
--exclude='wp-content/upgrade/' \
--exclude='*.log' \
user@old-host:/var/www/example.com/public/ \
/var/www/example.com/public/
После первичного прогона rsync уже будет знать, какие блоки изменились, и дельта-перекопирование перед свитчем займёт секунды.
Перенос базы данных и «заморозка» записи
БД — самый чувствительный компонент при безостановочной миграции. Полностью без «окна записи» в классическом LAMP/LEMP добиться сложно без репликации. На практике используют короткую «заморозку» записи, пока делается финальный дамп и импорт.
- Включите режим технического обслуживания только для авторизованных (или запретите логин) — сайт при этом продолжает отдавать кешированные страницы гостям.
- Остановите wp-cron и задачи, которые пишут в БД.
- Сделайте финальный дамп и импортируйте его на VDS.
# На старом сервере
wp maintenance-mode activate
wp cron event list | wc -l # оценить объём
# Финальный дамп с блокировкой таблиц на момент снимка
wp db export /tmp/final.sql --add-drop-table --single-transaction
# Быстрая передача и импорт на новом сервере
scp /tmp/final.sql wpuser@new-vds:/tmp/
mysql -e "DROP DATABASE IF EXISTS wpprod; CREATE DATABASE wpprod CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql wpprod < /tmp/final.sql
# На новом сервере: обновить конфиг PROD
wp config set DB_NAME wpprod --type=constant --path=/var/www/example.com/public
Если домены отличаются, повторите wp search-replace
для прод-домена на новом сервере. Для одинаковых доменов ничего менять не нужно.
Тест окружения до свитча: /etc/hosts
Перед тем как менять DNS, проверьте сайт на новом VDS, подменив домен на локальной машине через /etc/hosts
(или аналоги в вашей ОС). Так инспектируете будущий PROD в «боевом» доменном имени, но трафик пользователей остаётся на старом сервере.
# На локальном компьютере
sudo sh -c 'echo "203.0.113.10 example.com www.example.com" >> /etc/hosts'
# Откройте сайт в браузере и проверьте логи /var/www/example.com/logs
Проверьте вход в админку, формы, загрузку файлов, интеграции с платёжными и внешними сервисами. Просмотрите error_log
Nginx и php-fpm
, убедитесь, что нет фатальных ошибок или предупреждений.
Оптимизация nginx и php-fpm под WordPress
Чтобы свитч DNS прошёл без просадки, подайте кешированную статику и не допустите исчерпания процессов PHP-FPM. Пара полезных твиков:
client_max_body_size
— на уровне сервера, чтобы загрузка медиа не падала.- Включите OPcache и проверьте
opcache.memory_consumption
,opcache.max_accelerated_files
. - Сведите к минимуму «тяжёлые» плагины, прогрейте кеш страниц до свитча.
# OPcache (пример для php.ini)
sed -i 's/^;\?opcache.enable=.*/opcache.enable=1/' /etc/php/8.2/fpm/php.ini
sed -i 's/^;\?opcache.memory_consumption=.*/opcache.memory_consumption=256/' /etc/php/8.2/fpm/php.ini
sed -i 's/^;\?opcache.max_accelerated_files=.*/opcache.max_accelerated_files=20000/' /etc/php/8.2/fpm/php.ini
systemctl reload php8.2-fpm
Финальная дельта rsync и переключение DNS
Когда всё готово и проверено через hosts, выполняем короткую финальную синхронизацию и меняем записи DNS. Благодаря заниженному TTL пользователи быстро «переедут» на VDS.
# Дельта файлов прямо перед переключением
rsync -az --delete \
--exclude='wp-content/cache/' \
user@old-host:/var/www/example.com/public/ \
/var/www/example.com/public/
# Опционально: финальный небольшой дамп, если был активный трафик
wp db export /tmp/final2.sql --add-drop-table --single-transaction
scp /tmp/final2.sql wpuser@new-vds:/tmp/
mysql wpprod < /tmp/final2.sql
Далее обновите A/AAAA записи домена на IP VDS. Когда основная масса трафика перейдёт (обычно 5–30 минут с TTL=300), можно выключать режим обслуживания:
wp maintenance-mode deactivate

Не спешите отключать старый сервер. Держите его в онлайне несколько часов как «горячий» бэкап для отката.
Как проверить, что уже на новом VDS
Проверьте заголовки сервера, логи и IP, который резолвит ваш домен:
dig +short example.com
curl -I https://example.com | grep -Ei 'server|x-.+'
tail -f /var/www/example.com/logs/access.log
Сравните метрики загрузки CPU/RAM на старом и новом хостах, убедитесь, что php-fpm не выбирает лимит pm.max_children
, а Nginx не отдаёт 502/504.
Откат: на всякий случай
Если что-то пошло не так — верните A/AAAA записи на старый сервер. Поскольку TTL низкий, откат пройдёт так же быстро. Держите инструкцию отката под рукой, включая команды возврата DNS и rsync обратно (если понадобилось внести срочные правки в контент).
Частые проблемы и их решения
- Хардкод домена и путей. Используйте
wp search-replace
с ключом--precise
для сериализованных данных. - Права на файлы. Проверьте владельца (
wpuser:www-data
) и разрешения (755
для папок,644
для файлов). Избегайте 777. - Лимиты PHP-FPM. Увеличьте
pm.max_children
, если наблюдаете очереди. Следите за RAM. - Размер загрузки. Совместите
client_max_body_size
в Nginx иupload_max_filesize/post_max_size
в PHP. - Смешанный контент (HTTP/HTTPS). Проверьте
siteurl/home
и принудительный HTTPS в Nginx, установите SSL-сертификаты. Про 301, HSTS и тонкости миграции HTTPS — в материале Миграция домена, 301 и HSTS. - Кэш после переезда. Очистите кэши плагинов и CDN. Прогрейте популярные страницы.
Мониторинг и обслуживание после миграции
Включите статус страницы PHP-FPM и метрики Nginx для базового наблюдения. Проверьте cron и бэкапы.
# Пример: включить статусный путь php-fpm (www.conf)
# pm.status_path = /status
# ping.path = /ping
systemctl reload php8.2-fpm
# Легкий healthcheck nginx
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/
Соберите алерты по 502/504, росту времени ответа и объёму 5xx. Проверьте резервное копирование БД и wp-content/uploads
.
Мини-чеклист перед переключением DNS
- TTL снижен и выдержан 24+ часа.
- Staging проверен: авторизация, формы, загрузка файлов, почта.
- Полный rsync пройден, дельта готова.
- Дамп БД восстанавливается без ошибок, домен не «хардкодится».
- Nginx и php-fpm настроены, логи чистые от критических ошибок.
- Готов план отката и контакты ответственных.
Вывод
Безостановочная миграция WordPress на VDS — это последовательность аккуратных действий: staging для проверки окружения, rsync для быстрой синхронизации файлов, корректная работа с базой через WP-CLI и чёткий момент переключения DNS. Заранее снижайте TTL, прогревайте кеш, держите старый сервер как горячий бэкап и не забывайте о мониторинге. Такой подход позволяет переносить даже загруженные проекты без ощутимых простоев и потерь конверсии.