Журнал Tenku

Как перенести сайт с обычного хостинга на VPS без простоя

Переезд с shared на VPS ломается не на rsync, а на спешке: забыли TTL, сертификат не выпустился, PHP другой версии, сайт открылся «как архив». Ниже — порядок, которым можно перевезти WordPress, Laravel и большинство PHP-сайтов за один вечер и откатиться за пять минут, если что-то пошло не так.

Предполагается: VPS Ubuntu уже есть, первый вход и файрвол сделаны по гайду SSH. Если сервера нет — тарифы. Какой план брать под сайт — выбор тарифа.

За сутки до переезда, не в час X

  1. В DNS домена поставьте TTL 300 секунд на A-записи. Если было 86400, часть мира будет ходить на старый IP до суток после смены.
  2. Запишите текущие версии: PHP, MySQL/MariaDB, путь к сайту, cron. На shared это панель. Сфотографируйте.
  3. Проверьте, что домен уже резолвится и вы владеете DNS. Переезд «а DNS у программиста, который в отпуске» — не переезд.
  4. Снимите бэкап на стороне shared: файлы + дамп базы. Скачайте себе. Это ваш откат, даже если VPS сгорит в ночь переноса.
  5. Откройте на 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.logClass 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, формы логинятся, админка пускает, картинки на месте:

  1. A-запись на новый IP. AAAA — либо корректный IPv6 Tenku, либо удалите старый AAAA, иначе клиенты IPv6 уйдут в никуда.
  2. Подождите 5–15 минут, проверяйте с LTE dig ваш-домен A.
  3. Выпустите или подключите сертификат, принудительный редирект на HTTPS.
  4. Пройдите чеклист: главная, внутренняя, POST формы, оплата test, админка, wp-cron/очередь, почта с сайта (это SMTP-сервис, не sendmail с VPS).

Не удаляйте аккаунт на shared две недели. Это горячий откат: вернули A-запись — мир снова на старом месте.

Откат

Если через час после переключения «ничего не работает»:

  1. A-запись обратно на IP shared. TTL у вас 300 — быстро.
  2. Не чините пять вещей сразу на VPS под продом. Чините на VPS, пока DNS снова на shared.
  3. Типичные причины: не импортировалась база, не тот DocumentRoot, SELinux нет но open_basedir, права на wp-content/uploads, забытый .htaccess rewrite, который на 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, а тормоза приложения или не та локация.

Нужен сервер под задачу?

Выберите тариф и локацию — VPS появится в кабинете.

Смотреть тарифы