Переезд с виртуального хостинга на VDS — это не только про «больше ресурсов», но и про контроль: версии PHP, тонкие настройки Nginx/Apache, собственные лимиты MySQL, гибкие бэкапы. Главный страх — простой. В этой инструкции разложим миграцию на шаги, чтобы добиться zero downtime или свести окно недоступности к секундам.
Архитектура переезда и принципы zero downtime
Стратегия простая: готовим VDS в стороне, синхронизируем данные в два подхода (initial + delta), тестируем сайт через /etc/hosts
, затем быстро переключаем DNS. При возможности — включаем проксирование со старого хостинга на новый, чтобы даже при старых DNS‑кешах трафик ушёл на VDS. Дополнительно про техники безостановочных релизов — в материале миграции без простоя.
Zero downtime на чистом DNS бывает сложно: у клиентов и провайдеров есть кеши. Минимизируйте риск: заранее снижайте TTL, держите старую площадку доступной и, если возможно, временно проксируйте трафик на новый IP.
Шаг 1. Аудит текущей площадки
Перед стартом зафиксируйте состояние проекта и окружения. Это сэкономит часы при отладке:
- Домен(а) и их DNS‑записи: A/AAAA, CNAME, MX, TXT (SPF/DMARC), записи для поддоменов.
- Версии и конфигурации: PHP (
phpinfo()
), список расширений (php -m
),php.ini
(лимиты:memory_limit
,upload_max_filesize
,post_max_size
,max_execution_time
), Apache/Nginx директивы (.htaccess
или конфиг vhost). - База данных: движок (MySQL/MariaDB), кодировка/сортировка, размер, специфические режимы (
sql_mode
,innodb_strict_mode
,lower_case_table_names
),max_allowed_packet
. - Фоновые задачи:
crontab -l
текущего пользователя, периодические PHP‑скрипты, очереди. - Хранилища сессий/кеша: файлы, Redis/Memcached, БД.
- Отправка почты: локальный MTA или внешнее SMTP, данные авторизации.
Шаг 2. Подготовка VDS: база безопасности и доступов
Берём свежую Debian/Ubuntu. Обновляем систему, создаём пользователя с ключами SSH, закрываем лишнее, настраиваем время и swap:
apt update && apt -y upgrade
adduser deploy
usermod -aG sudo deploy
mkdir -p /home/deploy/.ssh && chmod 700 /home/deploy/.ssh
# вставьте публичный ключ
nano /home/deploy/.ssh/authorized_keys
chmod 600 /home/deploy/.ssh/authorized_keys && chown -R deploy:deploy /home/deploy/.ssh
# базовый фаервол UFW
apt -y install ufw
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
# время и таймзона
timedatectl set-timezone Europe/Moscow
# опциональный swap (если RAM ограничен)
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
Затем ужесточите SSH: порт, запрет паролей, PermitRootLogin no
.

Шаг 3. Установка стека: Nginx/Apache, PHP-FPM, MySQL/MariaDB
Выбор веб‑сервера зависит от приложения. Часто используется Nginx + PHP‑FPM. Для проектов, завязанных на .htaccess
, может быть проще стартовать с Apache. Главное — начать с тех же версий, что и на виртуальном хостинге (или совместимых).
apt -y install nginx
apt -y install apache2 # если нужен Apache
apt -y install php-fpm php-cli php-mysql php-xml php-mbstring php-zip php-curl php-gd php-intl
apt -y install mariadb-server # или mysql-server
Создаём пользователя/группу проекта, директории, базовую структуру:
useradd --system --home /var/www/project --shell /usr/sbin/nologin project
mkdir -p /var/www/project/public
chown -R project:project /var/www/project
Пример server block для Nginx:
server {
listen 80;
server_name example.com www.example.com;
root /var/www/project/public;
access_log /var/www/project/logs/access.log;
error_log /var/www/project/logs/error.log;
index index.php index.html;
client_max_body_size 64m;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock; # проверьте версию
fastcgi_read_timeout 120s;
}
location ~* \.(?:css|js|jpg|jpeg|png|gif|webp|svg|ico)$ {
expires 7d;
add_header Cache-Control "public, max-age=604800";
}
}
Apache vhost (если требуется):
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/project/public
ErrorLog /var/www/project/logs/error.log
CustomLog /var/www/project/logs/access.log combined
<Directory /var/www/project/public>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Для PHP‑FPM проверьте пул: пользователь project
, режим pm
, лимиты. Для MySQL задайте корректную кодировку, буферы и пакет:
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
max_allowed_packet = 64M
sql_mode = STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
Шаг 4. Первый бэкап и начальная синхронизация rsync
Делаем бэкап у источника и только потом копируем. Минимум: дамп БД и снапшот файлового дерева. Исключаем кеши и временные файлы, чтобы не тянуть лишнее.
# дамп базы без блокировки таблиц
mysqldump --single-transaction --routines --triggers --events \
-h old-mysql-host -u dbuser -p dbname > dbname.initial.sql
# начальная синхронизация файлов по SSH
rsync -aHAXz --numeric-ids --delete \
--exclude '.git' --exclude 'node_modules' --exclude 'vendor' \
--exclude 'storage/cache' --exclude 'storage/logs' \
-e 'ssh -p 22' olduser@old-host:/home/olduser/www/ /var/www/project/
chown -R project:project /var/www/project
Импортируйте БД на VDS:
mysql -u root -p -e "CREATE DATABASE dbname CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -u root -p dbname < dbname.initial.sql
Проверьте конфиг приложения (.env
, wp-config.php
и т.п.): URL, доступы к БД, кэш, сессии, SMTP. На VDS часто меняются DB_HOST
, DB_PASSWORD
, пути к сокетам.
Шаг 5. Зависимости, сборка и права
На виртуальном хостинге многое предустановлено. На VDS ставите сами: Composer, Node.js, расширения PHP.
apt -y install git unzip curl
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
cd /var/www/project && sudo -u project composer install --no-dev --optimize-autoloader
# если есть фронтенд
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt -y install nodejs
sudo -u project npm ci && sudo -u project npm run build
Проверьте права: веб‑серверу нужен доступ на чтение к коду и на запись к каталогам storage
/uploads/cache. Задайте минимально необходимые разрешения.
Шаг 6. Просмотр и тест на новом IP через /etc/hosts
До DNS‑переключения удобно проверить сайт, подставив IP VDS локально:
# на своей рабочей станции
sudo nano /etc/hosts
# добавьте строку
203.0.113.10 example.com www.example.com
Очистите кеш браузера/запустите приватное окно и прогоните сценарии: формы, загрузку файлов, личные кабинеты, оплату (в тестовом режиме), авторизацию. Параллельно мониторьте логи:
tail -f /var/www/project/logs/error.log
journalctl -fu nginx
Шаг 7. Двухфазная синхронизация: delta без остановки
Пока вы тестировали, сайт на старом хостинге жил своей жизнью. Сделайте вторую, «дельтовую», синхронизацию перед переключением трафика.
- Отключите фоновые задания на исходном хостинге:
crontab -r
или закомментируйте задания. Поставьте приложение в режим обслуживания, при этом страницы с кэшем могут продолжить отдавать контент. - Сделайте финальный дамп БД и синхронизацию файлов:
mysqldump --single-transaction --routines --triggers --events \
-h old-mysql-host -u dbuser -p dbname > dbname.final.sql
mysql -u root -p dbname < dbname.final.sql
rsync -aHAXz --numeric-ids --delete \
--exclude '.git' --exclude 'node_modules' --exclude 'vendor' \
--exclude 'storage/cache' --exclude 'storage/logs' \
-e 'ssh -p 22' olduser@old-host:/home/olduser/www/ /var/www/project/
Если запуск фризить нельзя вообще, рассмотрите альтернативы:
- Временное проксирование трафика со старого хоста на новый (Apache
mod_proxy
или Nginxproxy_pass
, если доступно) — тогда даже при неактуальном DNS все запросы уйдут на VDS. - Read‑only режим и повторная запись операций в очередь (подходит для некоторых CMS/фреймворков). Сложнее в реализации.
Шаг 8. SSL/TLS и редиректы
Выпустите сертификат уже на VDS. Для автоматизации подойдёт ACME‑клиент. После получения включите HTTPS и редирект с HTTP на HTTPS. При необходимости про 301, HSTS и нюансы миграции на HTTPS — подробный разбор в статье про редиректы и HSTS. Если нужен выпуск без ручной рутины — используйте SSL-сертификаты.
# для Nginx проверьте блоки server для :80 и :443, настройте сертификаты
# редирект на HTTPS
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
Если изначально был только HTTP, готовьте миграцию на HTTPS отдельно: проверьте абсолютные URL, mixed content, заголовки HSTS.

Шаг 9. DNS‑переключение без нервов
За 24–72 часа до переезда снизьте TTL у A/AAAA‑записей до 300–600 секунд. В момент переключения поменяйте IP в A/AAAA на адрес VDS. Старую площадку держите доступной ещё 24–48 часов.
# проверяем актуальный ответ авторитативных NS
dig +short A example.com
# следим за распространением
watch -n 15 'dig +short A example.com @1.1.1.1; echo ---; dig +short A example.com @8.8.8.8'
Чтобы исключить split‑brain по сессиям/БД, на старом хостинге:
- Не включайте обратно cron и запись в БД.
- По возможности проксируйте все запросы на новый IP до полного схождения DNS.
Шаг 10. Пост‑чекапы, наблюдение и оптимизация
Сразу после переключения:
- Проверьте статус‑страницы:
/health
или аналоги, 200 OK. - Просмотрите логи ошибок Nginx/Apache и PHP в разрезе последних минут.
- Проверьте отправку почты, вебхуки, платежные нотификации, веб‑сокеты, загрузки крупных файлов (проверьте
client_max_body_size
иpost_max_size
). - Замерьте перформанс, включите/подкрутите OPcache (
opcache.enable
,opcache.memory_consumption
) и кэш статики.
Шаг 11. Типичные подводные камни
- Несовпадение версий PHP/расширений:
intl
,imagick
,gd
,zip
,bcmath
,redis
. - Иные режимы MySQL: другой
sql_mode
, кодировки,lower_case_table_names
(особенно при переходе Windows → Linux). Проверяйте сравнение и индексы. - Разные лимиты:
client_max_body_size
в Nginx,LimitRequestBody
в Apache,upload_max_filesize
/post_max_size
в PHP. - Пути к сокетам: PHP‑FPM, MySQL. Обновите
.env
и конфиги. - Права и владелец файлов: убедитесь, что процессы веб‑сервера и воркеры очередей имеют нужные права.
- SELinux/AppArmor/фаервол: проверьте, что порты 80/443/3306 доступны локально/снаружи по замыслу.
- Почта: исходящие 25/tcp могут быть ограничены — используйте SMTP‑ретрансляцию у почтового провайдера.
- IPv6: если включили AAAA, убедитесь, что сайт корректно слушает v6 и сертификат покрывает оба стека.
Шаг 12. Откат: как вернуться без паники
Держите план «Б» готовым заранее:
- Не удаляйте старые данные и доступы в течение минимум 48 часов.
- Сохраните финальные бэкапы файлов и БД перед переключением.
- Если после переключения обнаружились критические проблемы, верните A/AAAA‑записи на старый IP (учтите TTL). Чтобы ускорить, уменьшайте TTL заранее.
- При откате не забывайте о новых записях/данных на VDS — решите, что считать источником истины и синхронизируйте дельту обратно.
Мини‑чек‑лист команд
# безопасность
ufw status
ss -tulpn | grep -E ':22|:80|:443'
# веб‑сервер
nginx -t && systemctl reload nginx
apachectl configtest && systemctl reload apache2
# PHP‑FPM
systemctl status php8.2-fpm
# БД
mysql -e 'SHOW VARIABLES LIKE "sql_mode";'
# синхронизация
rsync -aHAXz --delete -e 'ssh -p 22' old:/src/ /dst/
# DNS
dig +short A example.com @1.1.1.1
FAQ
Сколько длится «окно»?
При двухфазной синхронизации и заранее сниженных TTL само переключение укладывается в 1–2 минуты. Если удаётся включить проксирование со старого хоста на новый, для пользователей окно отсутствует.
Что делать с сессиями?
Во время периода расхождения DNS часть пользователей может попасть на старый IP. Если нельзя включить прокси — смиритесь с возможной разлогинизацией или держите старую площадку в read‑only. Лучшее — проксировать весь HTTP на VDS до схождения кешей.
Нужен ли rsync или можно просто архивом?
Rsync даёт инкрементальную передачу и валидацию атрибутов. Архив подойдёт для очень небольших проектов, но лишит вас дельтовой синхронизации.
Как проверить, что всё «как было»?
Сравните версии PHP/расширений, режимы MySQL, дерните ключевые URL и API, прогоните smoke‑тесты, проверьте метрики ошибок и время отклика через наблюдение логов и системных счётчиков. Для WordPress можно развернуть staging и прогнать тесты — см. гайд про staging и DNS.
Итог
Переезд на VDS — это контролируемый процесс: план, бэкапы, двухфазная rsync‑синхронизация по SSH, тест через /etc/hosts
, аккуратное DNS‑переключение, пост‑проверки и готовность к откату. Сделав один такой релиз по шпаргалке, следующий вы проведёте ещё быстрее и спокойнее.