Переезд с shared на VPS ломается не на rsync, а на спешке: забыли TTL, сертификат не выпустился, PHP другой версии, сайт открылся «как архив». Ниже — порядок, которым можно перевезти WordPress, Laravel и большинство PHP-сайтов за один вечер и откатиться за пять минут, если что-то пошло не так.
Предполагается: VPS Ubuntu уже есть, первый вход и файрвол сделаны по гайду SSH. Если сервера нет — тарифы. Какой план брать под сайт — выбор тарифа.
За сутки до переезда, не в час X
- В DNS домена поставьте TTL 300 секунд на A-записи. Если было 86400, часть мира будет ходить на старый IP до суток после смены.
- Запишите текущие версии: PHP, MySQL/MariaDB, путь к сайту, cron. На shared это панель. Сфотографируйте.
- Проверьте, что домен уже резолвится и вы владеете DNS. Переезд «а DNS у программиста, который в отпуске» — не переезд.
- Снимите бэкап на стороне shared: файлы + дамп базы. Скачайте себе. Это ваш откат, даже если VPS сгорит в ночь переноса.
- Откройте на VPS порты 80 и 443 (
ufw allow 80,443/tcp) — Let's Encrypt не умеет в закрытый 80.
Согласуйте окно. Для магазина лучше будний поздний вечер, не чёрная пятница.
Поднимите стек на VPS до переключения DNS
Пока A-запись смотрит на старый хостинг, новый сервер никто из клиентов не видит. Это ваше безопасное окно.
Nginx, PHP-FPM, MariaDB, Certbot — рабочий каркас в статье про Nginx и SSL и, если это WP, в WordPress на VPS. Здесь — только то, что специфично для переноса.
Создайте пользователя БД и пустую базу той же кодировки, что на исходнике (обычно utf8mb4):
sudo mysql
CREATE DATABASE site CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'site'@'localhost' IDENTIFIED BY 'СИЛЬНЫЙ_ПАРОЛЬ';
GRANT ALL ON site.* TO 'site'@'localhost';
FLUSH PRIVILEGES;
Каталог сайта, например /var/www/site, владелец — пользователь php-fpm (www-data или отдельный пул).
Временный Nginx-хост на IP или на домене с server_name уже вашим, но DNS ещё старый: выпускать сертификат по HTTP-01 можно, если вы готовы на минуту направить домен или использовать DNS-challenge. Практичный путь:
- Подключите локально
hosts:IP_VPS ваш-домен.ruи отладьте сайт по HTTPS с самоподписанным, либо - Выпустите сертификат после переключения DNS, а до этого проверьте сайт по
http://IPс временнымserver_name _.
Для магазина лучше отладить по IP/hosts, чем показать клиентам «Not Secure» на час. Let's Encrypt после переключения DNS выпускается за минуту, если 80 порт открыт и A-запись уже новая. План Б: сертификат Cloudflare/DNS-challenge без даунтайма HTTP.
Перенос файлов
С shared, если есть SSH:
rsync -aH --info=progress2 user@shared:/path/to/site/ /var/www/site/
Если только FTP — FileZilla один раз, либо lftp. Архив tar.gz тоже живой вариант: главное не потерять права и .htaccess / скрытые файлы. .env Laravel и wp-config.php перенесите сознательно, не «как получится».
Проверьте размер: du -sh /var/www/site ≈ то, что было на shared. Если на VPS втрое меньше — не докачались uploads.
Права для WordPress:
sudo chown -R www-data:www-data /var/www/site
sudo find /var/www/site -type d -exec chmod 755 {} \;
sudo find /var/www/site -type f -exec chmod 644 {} \;
Не ставьте 777. Если плагин просит — чините владельца, не вселенную.
Перенос базы
На старом хостинге:
mysqldump -u USER -p --single-transaction --quick --routines --triggers ИМЯ_БД > dump.sql
Через phpMyAdmin — тот же дамп, только не обрывайте вкладку на 800 МБ. Для больших баз используйте SSH и gzip.
На VPS:
gunzip -c dump.sql.gz | sudo mysql site
Если дамп в utf8, а вы создали utf8mb4 — обычно ок. Если в дампе явные TYPE=MyISAM и древний charset — не «оптимизируйте» по дороге. Сначала чтобы завелось, потом индексы.
В конфиге сайта пропишите новый сокет/хост localhost, пользователя site, новый пароль. Старые логин-пароль shared в проде на VPS оставлять нельзя: они утекут вместе с копией конфига.
Для WordPress после смены домена (www / non-www, http→https) сериализованные URL чинят wp search-replace, не слепым sed по SQL. Для Laravel — APP_URL и php artisan config:cache.
PHP: совпадение версии важнее «самой новой»
Если на shared был PHP 8.1, не включайте 8.3 в ночь переезда «заодно». Поднимите 8.1, переключите, через неделю обновляйте. Иначе фатал в плагине спишут на хостинг.
Расширения, которые обычно забывают: php-xml, php-curl, php-mbstring, php-zip, php-gd или imagick, php-mysql. Симптом: белый экран, в php-fpm.log — Class mysqli not found.
Cron и очереди
Скопируйте crontab с панели shared. На VPS он живёт у пользователя:
sudo crontab -u www-data -e
Проверьте пути: /usr/bin/php vs /usr/local/bin/php. Запустите задачу руками один раз. Для Laravel — schedule:run каждую минуту и отдельный supervisor на queue, не php artisan queue:work в screen.
Переключение DNS
Когда сайт на VPS открывается по hosts, формы логинятся, админка пускает, картинки на месте:
- A-запись на новый IP. AAAA — либо корректный IPv6 Tenku, либо удалите старый AAAA, иначе клиенты IPv6 уйдут в никуда.
- Подождите 5–15 минут, проверяйте с LTE
dig ваш-домен A. - Выпустите или подключите сертификат, принудительный редирект на HTTPS.
- Пройдите чеклист: главная, внутренняя, POST формы, оплата test, админка, wp-cron/очередь, почта с сайта (это SMTP-сервис, не sendmail с VPS).
Не удаляйте аккаунт на shared две недели. Это горячий откат: вернули A-запись — мир снова на старом месте.
Откат
Если через час после переключения «ничего не работает»:
- A-запись обратно на IP shared. TTL у вас 300 — быстро.
- Не чините пять вещей сразу на VPS под продом. Чините на VPS, пока DNS снова на shared.
- Типичные причины: не импортировалась база, не тот
DocumentRoot, SELinux нет ноopen_basedir, права наwp-content/uploads, забытый.htaccessrewrite, который на Nginx не работает.
Apache-.htaccess на Nginx молча игнорируется. Правила RewriteRule нужно перенести в try_files и отдельные location. Для WordPress стандарт:
location / {
try_files $uri $uri/ /index.php?$args;
}
Без этого «внутренние страницы 404, главная есть».
После переезда
- Поставьте бэкапы, не надейтесь на «мы только что скопировали».
- Включите мониторинг места и
uptime. - Через 48 часов поднимите TTL обратно до 3600, когда убедитесь, что откат не нужен.
- Закройте FTP, если он больше не нужен. На VPS его и не было — так и оставьте.
Переезд сделан, когда не вы в hosts, а случайный человек с телефона открывает сайт, логинится и не пишет в поддержку. Если после переключения TTFB вырос — это уже не DNS, а тормоза приложения или не та локация.