Как перенести сайт с хостинга на VPS
Сам перенос занимает пару часов, а ошибки обычно случаются вокруг него: забытое задание cron, правила .htaccess, которые nginx не читает, запись AAAA со старым адресом или почта, которая пропала вместе со сменой IP. Ниже — порядок действий с командами и проверками для сайта на PHP и MySQL.
Эта статья — о том, как переехать. Стоит ли переезжать вообще и какой сервер брать, разобрано в статье Когда переезжать с хостинга на VPS. Здесь считаем, что VPS уже куплен, а сайт сделан на WordPress, Битриксе, Laravel или другом движке на PHP с базой MySQL. Для других стеков порядок тот же, меняются только команды.
Сроки: переезд в четыре этапа
- За два дня: выписать всё, что работает на хостинге, и уменьшить TTL записей DNS.
- За день: подготовить сервер, скопировать файлы и базу, проверить сайт на новом адресе.
- День переезда: закрыть сайт на запись, перенести свежие данные, сменить DNS.
- Неделя-две после: держать хостинг включённым как запасной вариант.
Что выписать на хостинге
Почти все проблемы после переезда — это то, что работало на хостинге само и о чём забыли. Пройдитесь по панели хостинга и запишите:
- Версию PHP и расширения. Их видно в панели или через SSH командами
php -vиphp -m. На VPS поставьте ту же версию, а обновление PHP сделайте отдельно, позже. - Версию и размер базы данных, кодировку таблиц.
- Задания cron: что и как часто запускается. Пути к файлам на VPS будут другими.
- Правила в .htaccess: редиректы, ЧПУ, ограничения доступа к папкам.
- Почту: ящики, пересылки, где стоят записи MX.
- Поддомены и все записи DNS, в том числе TXT для подтверждения сервисов.
- Внешние сервисы, которые знают IP сайта. Платёжные системы, обмен с 1С, API партнёров и почтовые сервисы часто пускают запросы только с разрешённых адресов. Новый IP нужно добавить у них заранее.
За сутки-двое до переезда уменьшите TTL записей A и AAAA домена до 300 секунд. Тогда в день переключения новый адрес разойдётся за минуты, а не за сутки.
Подготовьте сервер
Начните с базовой защиты: обновления, вход по ключу, файрвол. Всё это собрано в статье Первые 10 шагов после покупки VPS. Дальше два пути.
С панелью управления. ISPmanager, FASTPANEL или aaPanel ставят веб-сервер, PHP нужной версии и базу за несколько кликов и дают привычный по хостингу интерфейс. Тарифы с ними: VPS с ISPmanager, VPS с FASTPANEL, VPS с aaPanel.
Без панели. Для Ubuntu и Debian минимальный набор ставится одной командой, пакеты без номера версии тянут PHP, который идёт с системой:
apt install nginx mariadb-server php-fpm php-mysql php-curl php-gd php-mbstring php-xml php-zip php-intl
Если на хостинге была более старая или новая версия PHP, чем в системе, её ставят из сторонних репозиториев с пакетами PHP для Ubuntu и Debian.
Учтите главное отличие от хостинга: nginx не читает .htaccess. Редиректы и ЧПУ нужно перенести в конфигурацию сайта. Для WordPress основное правило выглядит так: try_files $uri $uri/ /index.php?$args;. Если правил много, проще поставить Apache за nginx: так работает большинство панелей, и .htaccess продолжает действовать.
Перенесите файлы
Если на хостинге есть доступ по SSH, быстрее всего забрать файлы прямо с VPS через rsync:
rsync -avz user@old-host.example:~/public_html/ /var/www/example.com/
Повторный запуск той же команды докачает только изменившееся, это пригодится в день переезда. Если SSH нет, есть два варианта: собрать архив в файловом менеджере панели и скачать его на сервер через wget или забрать файлы по FTP утилитой lftp:
lftp -u user old-host.example -e "mirror --parallel=4 public_html /var/www/example.com; quit"
Обычный FTP передаёт пароль открытым текстом, поэтому если хостинг поддерживает SFTP или FTPS, используйте их. После копирования отдайте файлы пользователю веб-сервера и выставьте обычные права:
chown -R www-data:www-data /var/www/example.com
find /var/www/example.com -type d -exec chmod 755 {} +
find /var/www/example.com -type f -exec chmod 644 {} +
Перенесите базу данных
Сделайте дамп на хостинге. Через SSH:
mysqldump --single-transaction --default-character-set=utf8mb4 -u user -p dbname | gzip > db.sql.gz
Без SSH дамп выгружают через phpMyAdmin, но большие базы он может не осилить из-за ограничения времени на хостинге; тогда спросите дамп у поддержки или сделайте его по частям. На VPS создайте базу и пользователя и загрузите дамп:
mysql -e "CREATE DATABASE site CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'site'@'localhost' IDENTIFIED BY 'надёжный_пароль';
GRANT ALL PRIVILEGES ON site.* TO 'site'@'localhost';"
zcat db.sql.gz | mysql site
Частая ошибка при загрузке — Unknown collation: 'utf8mb4_0900_ai_ci'. Она значит, что дамп сделан в MySQL 8, а на VPS стоит MariaDB, которая такой сортировки не знает. Либо ставьте на VPS ту же СУБД, что на хостинге, либо замените в дампе сортировку на utf8mb4_unicode_ci.
Затем пропишите новые данные доступа к базе в настройках сайта: для WordPress — wp-config.php, для Битрикса — /bitrix/.settings.php и /bitrix/php_interface/dbconn.php, для Laravel — файл .env. Сервер базы теперь localhost.
Перенесите задания cron
Задания запускайте от пользователя сайта, а не от root: crontab -u www-data -e. Проверьте пути: на хостинге сайт лежал в чём-то вроде /home/user/public_html, на VPS — в /var/www/example.com, и путь к PHP тоже может отличаться (which php). Отдельно проверьте задачи, которые хостер выполнял сам: агенты Битрикса на cron, обмен с 1С, отправку писем из очереди.
Проверьте сайт до смены DNS
Посетители пока ходят на хостинг, а вы можете открыть новый сервер у себя. Пропишите домен с IP сервера в файл hosts своего компьютера (/etc/hosts в Linux и macOS, C:\Windows\System32\drivers\etc\hosts в Windows):
203.0.113.10 example.com www.example.com
Пройдитесь по главной, каталогу, карточке товара, поиску, формам, корзине и входу в админку, загрузите картинку. Параллельно смотрите журнал ошибок: tail -f /var/log/nginx/error.log. Быстро проверить ответ сервера без браузера можно так: curl -I --resolve example.com:80:203.0.113.10 http://example.com/.
Типичные проблемы на этом шаге:
- 502 Bad Gateway — nginx не видит PHP-FPM: путь к сокету в конфигурации сайта не совпадает с тем, что в настройках пула PHP.
- Белый экран или ошибка 500 — не хватает расширения PHP. Точное название будет в журнале ошибок.
- Не загружаются большие файлы — в nginx по умолчанию тело запроса ограничено 1 МБ (
client_max_body_size), в PHP — параметрамиupload_max_filesizeиpost_max_size. - Ссылки ведут на 404 — не перенесены правила из .htaccess.
Сертификат TLS
Обычная проверка домена для бесплатного сертификата идёт по HTTP на тот адрес, куда сейчас указывает DNS, то есть на хостинг. Поэтому до переключения есть три пути:
- Получить сертификат проверкой через DNS:
certbot certonly --manual --preferred-challenges dns -d example.com -d www.example.com. certbot попросит добавить запись TXT. Такой сертификат сам не продлевается, поэтому после переезда выпустите обычный. - Временно перенести текущий сертификат и ключ с хостинга, если панель позволяет их выгрузить.
- Сменить DNS и сразу выпустить сертификат командой
certbot --nginx -d example.com -d www.example.com. Несколько минут сайт по HTTPS будет выдавать ошибку, для небольшого сайта это приемлемо.
После выпуска проверьте автоматическое продление: certbot renew --dry-run.
День переезда
- Закройте сайт на запись: включите режим обслуживания или хотя бы остановите приём заказов и комментариев. Для магазина это несколько минут.
- Ещё раз запустите ту же команду rsync — она перенесёт только изменения.
- Сделайте свежий дамп базы и загрузите его на VPS поверх старого.
- Смените запись A домена и www на IP сервера. Если у домена есть запись AAAA с IPv6-адресом хостинга, замените её на IPv6 сервера или удалите, иначе часть посетителей продолжит попадать на старый сервер.
- Проверьте, что новые записи видны:
dig +short example.com A @8.8.8.8иdig +short example.com AAAA @8.8.8.8. - Откройте сайт для записи уже на VPS.
Не потеряйте почту
Самая частая неприятность переезда. Посмотрите, куда указывает MX: dig +short example.com MX. Если там example.com или mail.example.com, который ведёт на тот же IP, что и сайт, то смена записи A отправит почту на VPS, где почтового сервера нет. Перед переключением заведите для почты отдельную запись со старым IP хостинга и укажите её в MX, а лучше заранее перенесите почту домена в отдельный почтовый сервис.
Если сайт отправляет письма (заказы, восстановление пароля), проверьте их после переезда. Письма с нового IP без записи SPF попадут в спам: либо добавьте IP сервера в SPF, либо отправляйте письма через SMTP почтового сервиса. Свой почтовый сервер на VPS — отдельная задача, тарифы для неё в подборке VPS для почтового сервера.
После переезда и откат
Не отключайте хостинг одну-две недели. В первые часы проверьте старую базу: если между финальным дампом и сменой DNS кто-то успел оформить заказ на старом сервере, перенесите его вручную. Через пару дней загляните в журнал посещений хостинга: если туда всё ещё ходят люди, где-то остался старый адрес, чаще всего в записи AAAA или www.
Откат простой, пока хостинг работает: верните в DNS старый IP, и благодаря короткому TTL посетители вернутся на хостинг за минуты. Когда всё стабильно, верните TTL к обычным значениям, настройте резервные копии по статье Резервные копии VPS и внешний мониторинг. Тарифы под сайты: VPS для сайта, VPS для WordPress, VPS для интернет-магазина, VPS для Битрикса. Для первой пробной сборки удобна почасовая оплата.