Как перенести сервер на новый VPS без простоя
Пошаговое руководство по миграции Linux сервера с использованием метода запланированного переключения. Узнайте, как правильно настроить DNS TTL, перенести БД и данные.
Миграция сервера на новый VPS методом запланированного переключения
Для миграции сервера на новый VPS рассматривайте перенос как запланированное переключение, а не простое копирование. Разверните новый сервер с нуля, синхронизируйте данные дважды, убедитесь в работоспособности нового сервера по его собственному IP-адресу до внесения изменений в DNS, затем переключите записи и оставьте старый сервер включенным, пока не будете уверены в результате. Копирование байтов — самая простая часть. Порядок операций определяет, пройдет ли перенос без инцидентов или с большими затратами.
Это руководство охватывает один Linux-сервер, на котором работают веб-приложение, база данных и TLS (transport layer security) сертификат. Это типично для большинства конфигураций на одном сервере. Задействованы два хоста, поэтому в каждом примере в комментарии указано, на каком хосте выполняется команда. Адреса взяты из диапазонов документации: 198.51.100.10 — старый сервер, 203.0.113.20 — новый.
Прочитайте весь план действий перед началом. Первый шаг, снижение TTL для DNS, должен быть выполнен за несколько дней до того этапа, который вас действительно интересует.
Проведите инвентаризацию перед началом работ
Вы не сможете пересобрать сервер, если не описали его текущее состояние. Потратьте час на то, чтобы записать, какие функции выполняет старая машина. После миграции чаще всего ломается то, о чем никто не вспомнил: cron-задача, исключение в firewall или файл окружения, лежащий вне директории приложения.
Выполните эти команды на старом сервере и сохраните вывод там, где он будет доступен при работе с новым.
# old server: packages you asked for, not the dependencies they pulled in
apt-mark showmanual > ~/inv-packages.txt
# old server: what runs now, and what starts at boot
systemctl list-units --type=service --state=running --no-pager > ~/inv-services.txt
systemctl list-unit-files --state=enabled --no-pager >> ~/inv-services.txt
systemctl list-timers --all --no-pager > ~/inv-timers.txt
# old server: what is listening, on which address and port
sudo ss -tulpn > ~/inv-ports.txt
# old server: human accounts, skipping the system ones
awk -F: '$3 >= 1000 && $3 < 65534 {print $1, $3, $6, $7}' /etc/passwdapt-mark showmanual — это список, который действительно стоит иметь, так как он отсеивает все зависимости. Полный dpkg --get-selections на сервере пятилетней давности выдаст две тысячи строк и не даст никакой информации о целях установки пакетов.
Запланированные задачи скрываются в двух местах, поэтому проверьте оба. Задачу, которая запускается раз в месяц, вы обнаружите только через шесть недель после миграции.
# old server: per-user crontabs, then the system drop-ins
for u in $(cut -d: -f1 /etc/passwd); do sudo crontab -lu "$u" 2>/dev/null | sed "s/^/$u: /"; done
sudo ls -la /etc/cron.d /etc/cron.daily /etc/cron.hourlyЗатем проверьте компоненты, которые не являются обычными файлами: правила firewall, сертификаты, базы данных и объем данных, который вы планируете переносить.
# old server
sudo ufw status verbose # or: sudo nft list ruleset
sudo certbot certificates
sudo -u postgres psql -c '\l' # or: sudo mysql -e 'SHOW DATABASES;'
sudo du -xh --max-depth=1 / | sort -hcertbot certificates выводит имя каждого сертификата, домены, которые он покрывает, дату истечения срока действия и пути к файлам на диске. Этот вывод — ваш чек-лист для TLS. du -x работает в пределах одной файловой системы, поэтому он не перейдет на примонтированный том с резервными копиями и не покажет завышенный в десять раз объем данных.
Два элемента находятся вне сервера, и о них забывают каждый раз. Во-первых, любые сторонние сервисы, которые используют IP-адрес вашего сервера в списках разрешенных (allowlist): платежные шлюзы, управляемые базы данных, SMTP-реле или партнерские API. У новой машины будет новый адрес, поэтому в эти списки нужно добавить новый IP до переключения, а не после. Во-вторых, DNS-записи, которые создавали не вы, например, MX-запись или SPF-запись, содержащая старый IP-адрес в текстовом виде.
Почему стоит пересобирать систему, а не клонировать старую корневую файловую систему
Клонирование всей корневой файловой системы на новый VPS кажется более быстрым способом, и это так, пока не возникают проблемы. Корневая файловая система, которая годами находилась в эксплуатации, содержит вручную измененные конфигурации, которые никто не документировал, пакеты из репозиториев, которые больше не существуют, и настройки загрузки, созданные под виртуальное оборудование старой платформы. Вы переносите всё это, включая причины, по которым вы решили мигрировать.
Пересборка требует больше времени в первый день, но экономит ресурсы в дальнейшем. Вы устанавливаете текущий релиз, применяете базовые настройки безопасности, а затем копируете только данные: директорию приложения, конфигурации сайта, дамп базы данных, сертификаты и пользовательские загрузки. Всё, что вы не можете объяснить, не должно переноситься. Начинайте настройку нового сервера так же, как и любого другого, с первых десяти минут на новом VPS, затем добавляйте сервисы из инвентаря по одному и проверяйте каждый из них перед добавлением следующего.
Когда восстановление из образа или снимка является верным решением
Существует одно оправданное исключение для отказа от пересборки сервера. Если старый сервер не загружается или приложение невозможно пересобрать из исходного кода, восстановление из образа или снимка провайдера является прагматичным ответом. У этого метода есть существенные ограничения: он работает только в рамках одного провайдера и часто только внутри одного семейства тарифных планов, так как восстановленный диск ожидает наличия виртуальных устройств и сетевых имен конкретной платформы.
Снимок работающего сервера также несет в себе ту же проблему согласованности данных, что и любая другая пофайловая копия работающей базы данных. Рассматривайте восстановление из образа как способ аварийного восстановления, а не как план миграции, и ознакомьтесь с материалом почему снимок не является полноценной резервной копией перед тем, как строить на этом свой план.
Как перемещаются файлы: rsync через SSH
Запустите rsync со старого сервера, отправляя данные на новый. Отправка (push) обычно проще, так как старый сервер уже содержит данные и может прочитать их все под учетной записью sudo.
# old server: dry run first, and read what it says it will do
sudo rsync -aHAX --dry-run --itemize-changes \
-e 'ssh -i /root/.ssh/id_ed25519' \
/srv/app/ deploy@203.0.113.20:/srv/app/
# old server: the real bulk pass
sudo rsync -aHAX --info=progress2 \
-e 'ssh -i /root/.ssh/id_ed25519' \
/srv/app/ deploy@203.0.113.20:/srv/app/Флаги имеют значение. -a сохраняет права доступа, временные метки, символические ссылки и владельцев. -H сохраняет жесткие ссылки как жесткие ссылки, а не разворачивает их в отдельные копии. -A копирует POSIX ACL (списки контроля доступа), а -X копирует расширенные атрибуты. Без этих двух последних флагов файл, который выглядит идентично, может вести себя иначе, так как метки SELinux и ACL хранятся в расширенных атрибутах, и ничто другое их не фиксирует.
Две детали являются причиной большинства сбоев в этом процессе.
Завершающий слэш определяет, куда попадут данные. /srv/app/ означает содержимое этого каталога. /srv/app означает сам каталог. Ошибитесь, и вы получите /srv/app/app на новом сервере, а приложение запустится и сообщит об отсутствии файлов, так как пути, с которыми оно было настроено, теперь находятся на один уровень выше ожидаемого.
Под sudo тильда — это домашний каталог root. Указание -e 'ssh -i ~/.ssh/id_ed25519' внутри sudo rsync заставляет искать ключ в /root/.ssh, а не в вашем собственном домашнем каталоге. Если ключа там нет, SSH выведет Permission denied (publickey), rsync выведет rsync: connection unexpectedly closed и завершится с ненулевым кодом. Указывайте путь к ключу полностью. Если сообщение об аутентификации продолжает появляться после исправления пути, у сбоя publickey есть короткий список причин, и права доступа к каталогам на новом сервере — это следующее, что нужно проверить.
Владение файлами требует одного решения. При запуске от имени root rsync по умолчанию сопоставляет владельца и группу по имени, поэтому файл, принадлежащий www-data на старом сервере, станет принадлежать www-data на новом, даже если числовой UID (идентификатор пользователя) отличается. Это именно то, что нужно для пересборки. Добавляйте --numeric-ids только при копировании файловой системы, учетные записи которой не существуют на целевом сервере, а затем проверяйте результат с помощью ls -ln, так как файл, принадлежащий UID без соответствующей учетной записи, отображается как простое число, и доступ к нему будет запрещен для любого сервиса.
Выполняйте основной перенос за несколько дней до события, пока старый сервер всё ещё обслуживает трафик. Повторяйте его столько раз, сколько нужно: rsync передает только измененные данные, поэтому второй проход займет минуты вместо часов. Финальный проход, выполняемый в окне переключения, добавляет --delete, чтобы файлы, удаленные на старом сервере, также исчезли на новом.
# old server: final pass, inside the window, after the app has stopped writing
sudo rsync -aHAX --delete --info=progress2 \
-e 'ssh -i /root/.ssh/id_ed25519' \
/srv/app/ deploy@203.0.113.20:/srv/app/--delete удаляет файлы в месте назначения, которых больше нет в источнике, поэтому неверный путь к источнику вместе с --delete очистит целевой каталог. Каждый раз запускайте команду с --dry-run для предварительной проверки. Длительные передачи также прерываются при разрыве SSH-сессии на вашем ноутбуке, поэтому запускайте их внутри tmux или screen на старом сервере. Добавьте --bwlimit=20M, если копирование перегружает канал, пока старый сервер всё ещё обслуживает пользователей.
Как переносить базу данных: нативный дамп
База данных — это не просто каталог с файлами, хотя она так выглядит. Это набор файлов, состояние в оперативной памяти и журнал предзаписи (write-ahead log), согласованность которых гарантируется только в моменты, определяемые самой СУБД. Используйте штатные инструменты.
PostgreSQL требует два дампа, так как роли являются общими для всего кластера, а pg_dump их не включает:
# old server
sudo -u postgres pg_dumpall --globals-only -f /var/backups/globals.sql
sudo -u postgres pg_dump -Fc -f /var/backups/appdb.dump appdb# new server: restore in this order
sudo -u postgres psql -f /var/backups/globals.sql
sudo -u postgres createdb -O appuser appdb
sudo -u postgres pg_restore -d appdb --no-owner /var/backups/appdb.dumpЕсли пропустить globals.sql, вы восстановите все таблицы, но ни одна роль приложения не сможет их прочитать, так как инструкции GRANT ссылаются на несуществующего пользователя. -Fc создает дамп в пользовательском формате архива, который читается только через pg_restore и позволяет выборочно восстанавливать таблицы позже. Восстанавливайте данные в ту же или более новую мажорную версию. Откат к старой версии, например с 17 на 16, не поддерживается: pg_restore отклонит архив с ошибкой о неподдерживаемой версии в заголовке файла до начала записи.
MySQL и MariaDB используют одну команду с четырьмя параметрами, которые не включены по умолчанию:
# old server
sudo mysqldump --single-transaction --routines --triggers --events \
--databases appdb > /var/backups/appdb.sql# new server
sudo mysql < /var/backups/appdb.sql--single-transaction создает согласованный снимок без блокировки записи, но только для таблиц InnoDB. Таблицы MyISAM в той же базе копируются без таких гарантий, поэтому проверьте движки хранения перед тем, как доверять дампу. Параметры --routines, --triggers и --events по умолчанию выключены, поэтому обычный дамп восстановит данные, но проигнорирует хранимые процедуры и запланированные события. Пользователи базы данных и их права хранятся в системной базе mysql, которую дамп --databases appdb не затрагивает, поэтому воссоздайте их на новом сервере с помощью CREATE USER и GRANT. MariaDB 11 поставляется с тем же инструментом, что и mariadb-dump, и сохраняет mysqldump в качестве символической ссылки, поэтому по состоянию на август 2026 года работают оба названия.
SQLite представляет собой один файл, и его копирование во время записи приложением приведет к повреждению файла. Для него существует свой безопасный путь:
# old server
sqlite3 /var/lib/app/app.db ".backup '/var/backups/app.db'"Независимо от движка, проверяйте дамп перед использованием. Дамп, который прервался из-за нехватки места на диске, восстановится без ошибок, но данные будут обрезаны в точке остановки.
# old server: a complete mysqldump ends with a line reading "-- Dump completed on ..."
tail -n 3 /var/backups/appdb.sql
# new server: after restore, count rows in a table whose size you know
sudo mysql -e 'SELECT COUNT(*) FROM appdb.orders;'Почему нельзя использовать rsync для работающей базы данных
rsync копирует файлы по очереди. Работающая база данных записывает данные в несколько файлов одновременно, поэтому к моменту, когда rsync доходит до последнего файла, первый уже устаревает. Копия содержит страницы из разных моментов времени — состояния, в котором база данных никогда не находилась. Результатом станет либо сервер, который отказывается запускаться, либо, что еще хуже, сервер, который запустится, будет неделю выдавать корректные ответы, а затем выйдет из строя, когда запрос дойдет до поврежденной страницы. Никаких предупреждений в процессе не будет.
Существует два безопасных способа переноса файлов. Остановите базу данных, скопируйте файлы и запустите её снова: это корректный и простой метод, цена которого — время простоя, равное длительности копирования. Либо используйте инструмент, предназначенный для физического копирования работающего сервера. Для PostgreSQL это pg_basebackup, который взаимодействует с сервером для обеспечения согласованности копии:
# new server: pull a physical copy from the old one
pg_basebackup -h 198.51.100.10 -U replicator -D /var/lib/postgresql/16/main -X stream -PДля этого требуется роль с атрибутом REPLICATION и соответствующая запись pg_hba.conf на старом сервере, поэтому настройки здесь сложнее, чем при обычном дампе. Этот метод оправдан, если база данных настолько велика, что дамп и восстановление не укладываются в допустимое окно обслуживания. Для обычной миграции на одном сервере дамп остается лучшим решением.
Перевыпуск сертификатов до переключения, а не после
TLS-сертификат привязан к доменному имени, а не к IP-адресу, поэтому сам файл сертификата переносится без проблем. Сложности возникают с его обновлением. Стандартная проверка HTTP-01 в Certbot запрашивает у центра сертификации файл через 80 порт по доменному имени. Пока DNS указывает на старый сервер, запрос попадает на него, и обновление на новом сервере завершается ошибкой.
Первый вариант — скопировать существующие сертификаты и состояние их обновления. Они остаются действительными до истечения срока независимо от того, на каком сервере находятся.
# old server
sudo rsync -aHAX -e 'ssh -i /root/.ssh/id_ed25519' \
/etc/letsencrypt/ root@203.0.113.20:/etc/letsencrypt/Каждый файл в /etc/letsencrypt/renewal/ содержит название плагина аутентификации, который выпустил сертификат. Установите тот же плагин на новый сервер (например, python3-certbot-nginx), иначе первое обновление завершится ошибкой из-за неизвестного аутентификатора. Проверьте работоспособность обновления до того, как оно станет критически важным:
# new server, after DNS has moved
sudo certbot renew --dry-runВторой вариант — выпустить новый сертификат на новом сервере с использованием проверки DNS-01. Она подтверждает владение доменом через TXT-запись и не использует 80 порт. Этот метод работает до миграции, пока имя всё ещё указывает на старый сервер, что делает его более предпочтительным при возможности автоматизации работы с DNS-провайдером. В разделе Выпуск сертификатов с использованием проверки DNS-01 описана настройка плагинов и учетных данных.
В любом случае проверьте, какой сертификат фактически предъявляет новый сервер, не меняя настройки DNS:
# your laptop
echo | openssl s_client -connect 203.0.113.20:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -subject -dates -issuer-servername отправляет SNI (server name indication), благодаря чему веб-сервер выбирает нужный виртуальный хост. Если не использовать этот параметр, вы получите сертификат по умолчанию для данного IP-адреса и ошибку несоответствия, которая выглядит как реальная проблема, хотя таковой не является.
Уменьшите DNS TTL за несколько дней до перехода
DNS — это этап, на котором даже тщательная миграция может пойти не по плану, так как задержка в обновлении записей заложена в протокол, и её невозможно сократить в день переключения. Резолвер, который закэшировал вашу A-запись, продолжает отдавать её в течение всего времени жизни (TTL — time to live), полученного при запросе. Уменьшение TTL сейчас никак не повлияет на резолвер, который закэшировал запись десять минут назад со старым значением: он будет хранить старое значение до истечения старого TTL и только потом узнает о новом, более коротком. Поэтому уменьшайте TTL как минимум за один полный период старого TTL до момента перехода. Запас в один день — это комфортный вариант. Если эти механизмы для вас в новинку, пошаговое руководство по записям, резолверам и кэшированию даст необходимую теоретическую базу.
Приведенные ниже числа — это арифметический расчет на основе самого TTL, а не результат измерений.
The data behind this chart
[
{
"label": "TTL 3600 s (common default)",
"ttl_seconds": 3600,
"worst_case_stale_minutes": 60
},
{
"label": "TTL 900 s",
"ttl_seconds": 900,
"worst_case_stale_minutes": 15
},
{
"label": "TTL 300 s (lowered for cutover)",
"ttl_seconds": 300,
"worst_case_stale_minutes": 5
},
{
"label": "TTL 60 s (short window)",
"ttl_seconds": 60,
"worst_case_stale_minutes": 1
}
]A-запись, опубликованная с TTL 3600 секунд, может продолжать направлять пользователей на старый IP в течение 60 минут после внесения изменений. Уменьшите его до 300 секунд, и этот худший сценарий сократится до 5 минут. Воспринимайте эти цифры как нижний предел, а не как гарантию. Некоторые резолверы применяют собственный минимальный TTL и игнорируют любые меньшие значения, а некоторые среды выполнения приложений кэшируют разрешенный адрес на всё время жизни процесса. Поэтому клиент, запущенный до ваших изменений, может никогда не выполнить повторный запрос до перезапуска.
При проверке того, что новый TTL вступил в силу, запрашивайте авторитетный ответ, а не собственный кэш:
# your laptop: ask the zone's own nameserver, so no cache is involved
dig +short NS example.com
dig +noall +answer @$(dig +short NS example.com | head -n1) example.com AВторое поле в строке ответа — это TTL в секундах. Затем проверьте записи, о которых часто забывают: AAAA-запись, если старый сервер имел IPv6, www имя, когда оно является отдельной A-записью, а не CNAME, любую MX-запись, указывающую на сам сервер, SPF-запись, содержащую старый IP, и запись обратного DNS (PTR) для нового адреса. Настройте PTR через панель управления вашего провайдера до перехода, если сервер отправляет почту, так как принимающие почтовые серверы проверяют её, и отсутствие PTR приведет к отклонению почты через несколько часов после того, как всё остальное уже заработало.
Проверка нового сервера по IP до изменения DNS
Вы можете протестировать работу приложения на новом сервере, пока DNS всё ещё указывает на старый. Переопределите разрешение имени для одного запроса:
# your laptop: force one name to the new IP, for this request only
curl -sS --resolve example.com:443:203.0.113.20 \
-o /dev/null -w '%{http_code} %{ssl_verify_result}\n' https://example.com/--resolve меняет только направление соединения. TLS-сертификат по-прежнему проверяется по реальному имени, поэтому данный метод подтверждает как корректность сертификата, так и работу сервиса. %{ssl_verify_result} выводит 0, если цепочка сертификатов прошла проверку.
Чтобы просматривать сайт в браузере, переопределите имя для всей вашей машины, добавив одну строку в /etc/hosts на вашем ноутбуке или в C:\Windows\System32\drivers\etc\hosts в Windows:
203.0.113.20 example.com www.example.comЗатем пройдите по приложению так, как это сделал бы пользователь. Войдите в систему. Загрузите страницу, которая считывает данные из базы. Отправьте форму, которая записывает данные в базу. Загрузите файл и убедитесь, что он появился на диске. Инициируйте отправку почты и проверьте, доходит ли она, так как исходящий SMTP с нового IP-адреса часто преподносит сюрпризы. Удалите строку из файла hosts сразу после завершения проверки. Если оставить её, можно потратить час на отладку сайта, который у всех остальных работает корректно.
Пошаговый план переноса
- За несколько дней: уменьшите TTL, выполните массовую синхронизацию через rsync, подготовьте новый сервер и протестируйте его, используя переопределение в файле hosts.
- В день переноса, до начала работ: добавьте новый IP-адрес во все списки разрешённых (allowlist) сторонних сервисов и убедитесь, что задача резервного копирования на новом сервере настроена и направлена в ваше хранилище.
- Начало работ: переведите приложение на старом сервере в режим обслуживания (maintenance mode), чтобы прекратить приём записей.
- Сделайте финальный дамп базы данных, затем выполните завершающий проход rsync с флагом
--delete. - Разверните дамп на новом сервере и запустите службы.
- Проведите повторное тестирование через
--resolveи переопределение в hosts, включая одну реальную операцию записи. - Измените записи A и AAAA на новый IP-адрес.
- Наблюдайте за обоими серверами. Access log старого сервера показывает, кто всё ещё обращается к нему; количество таких запросов должно стремиться к нулю по мере истечения TTL.
- Отключите страницу обслуживания.
- Оставьте старый сервер включённым и не вносите в него никаких изменений как минимум неделю.
Этап перевода в режим обслуживания — это то, что часто пропускают, хотя именно он обеспечивает вашу безопасность. Если новая база данных приняла запись, откат изменений будет означать либо потерю этой записи, либо необходимость выгружать данные из новой базы и загружать их обратно в старую. Несколько минут работы в режиме «только чтение» — это небольшая цена. Две базы данных, в которые одновременно вносились изменения, потребуют нескольких дней ручного сведения данных.
План отката
Откат выполняется одним действием: возвратом DNS-записей к значению 198.51.100.10. Это возможно только благодаря четырем условиям, выполненным ранее.
- Старый сервер продолжает работать, его службы запущены, данные сохранены. Вы лишь остановили запись, но не вывели сервер из эксплуатации.
- Значение TTL остается низким, поэтому путь назад будет таким же быстрым, как и путь вперед.
- Вы добавили новый IP-адрес в списки разрешенных (allowlists) сторонних сервисов, а не заменили старый. Если удалить старый адрес, путь для отката будет заблокирован на этапе шлюза оплаты.
- На новый сервер не записывались данные, которые вы не можете идентифицировать, так как единственными записями были ваши тестовые транзакции.
До начала окна обслуживания определите, что именно станет триггером для отката. Достаточно двух условий: любая ошибка, которую вы не можете диагностировать за фиксированное количество минут, и любая потеря данных. Заблаговременная фиксация этих условий предотвращает часы догадок, которые превращают десятиминутный простой в длительный сбой.
Подтверждение успешной миграции
Миграция не считается завершённой только потому, что сайт открывается. Проверьте аспекты, которые могут отказать позже.
# new server
systemctl --failed
journalctl -p err -b --no-pager | tail -n 40
sudo certbot certificates
sudo systemctl list-timers --all --no-pagerРезультатом должен быть отчет systemctl --failed 0 loaded units listed. Команда certbot certificates должна отображать ожидаемые даты истечения срока действия, а list-timers — все запланированные задания из вашего инвентаря с указанием реального времени следующего запуска, а не пустые значения.
Затем намеренно перезагрузите новый сервер, наблюдая за процессом. Сервис, запущенный вручную и не добавленный в автозагрузку, работает исправно ровно до первой незапланированной перезагрузки в три часа ночи.
# new server
sudo reboot
# your laptop, once it comes back
curl -sS -o /dev/null -w '%{http_code}\n' https://example.com/Если приложение работает в контейнерах, эта ловушка проявляется иначе, поскольку для стека compose требуется явная политика перезапуска, чтобы он поднялся после перезагрузки.
Последняя проверка — самая простая для откладывания, но при этом самая важная: задание резервного копирования. Миграция, закончившаяся получением сервера без бэкапов, просто меняет один риск на другой. Запустите резервное копирование на новом сервере вручную, а затем восстановите один файл из него во временную директорию. Репозиторий restic с проверенным восстановлением — это именно то, что поможет вам в критической ситуации. Если вы в течение недели используете старый и новый серверы параллельно, единый способ доступа и настройки каждого хоста предотвратит их рассинхронизацию, пока оба сервера находятся в работе.
После переключения: старый сервер и завершающие шаги
Оставьте старый сервер включенным на одну-две недели. Это стоит как один месяц тарифа, который вы всё равно собирались отменить, но это ваш единственный способ отката. Затем завершите все оставшиеся дела.
- Повторное использование того же имени хоста в вашем
~/.ssh/configдля новой машины вызоветWARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!при первом подключении, так как это имя теперь отвечает с другим ключом хоста. Очистите устаревшую запись с помощьюssh-keygen -R example.comтолько после того, как убедитесь в причине изменения, а не автоматически, так как это же предупреждение выдается при атаке типа «человек посередине». Миграция — подходящий момент, чтобы пересмотреть права доступа ключей, чему посвящена статья Управление SSH-ключами в небольшой инфраструктуре. - Сделайте финальный снимок или резервную копию старого сервера и сохраните их где-то за пределами площадки старого провайдера.
- Удалите старый IP-адрес из систем мониторинга, записей SPF и сторонних списков разрешенных IP (allowlists) — именно в таком порядке и в самую последнюю очередь.
- Отменяйте старый тариф только после того, как убедитесь, что финальная копия успешно читается в другом месте.
FAQ
Сколько времени занимает перенос сервера на новый VPS?
Видимый для пользователя простой обычно ограничивается финальным дампом базы данных, последним проходом rsync и запуском сервиса, что для небольшого приложения занимает от 10 до 30 минут. Календарное время больше, так как TTL DNS нужно снизить как минимум за один период старого TTL до переключения, а лучше — за день. Копирование основного объема данных также стоит запланировать за несколько дней. Процесс выполняется на работающем сервере, а повторный запуск передает только изменения, произошедшие с момента последнего прохода.
Можно ли использовать rsync для работающей базы данных MySQL или PostgreSQL вместо создания дампа?
Нет. rsync копирует файлы по отдельности, в то время как база данных пишет в несколько файлов одновременно. В результате копия содержит страницы из разных моментов времени и представляет состояние, которого у базы данных никогда не было. Она может отказаться запускаться или запуститься, но выдать ошибку позже, когда запрос обратится к поврежденной странице. Используйте pg_dump с pg_dumpall --globals-only, или mysqldump --single-transaction, либо сначала остановите базу данных, а затем скопируйте файлы. Для больших кластеров PostgreSQL pg_basebackup позволяет создать согласованную физическую копию работающего сервера.
Как протестировать новый VPS до изменения DNS?
Переопределите разрешение имен на своем компьютере. Для одиночного запроса curl --resolve example.com:443:203.0.113.20 https://example.com/ направит соединение на новый IP, при этом проверка сертификата будет выполняться по реальному имени. Для тестирования в браузере добавьте 203.0.113.20 example.com в файл /etc/hosts на своем ноутбуке, выполните вход, чтение из базы данных, отправку формы и загрузку файла, после чего удалите строку. Чтобы проверить только сертификат, выполните openssl s_client -connect 203.0.113.20:443 -servername example.com.
Какой TTL следует установить и когда его нужно снижать?
Снизьте значение для записей A и AAAA до 300 секунд как минимум за один полный период старого TTL до переключения. Резолвер, закешировавший запись до вашего изменения, сохранит старое значение до истечения старого TTL, поэтому снижение за час до переключения бесполезно, если старый TTL составлял 86400. Верните обычное значение через несколько дней после миграции, когда логи доступа на старом сервере перестанут фиксировать активность.
Стоит ли копировать TLS-сертификат или выпустить новый на новом сервере?
Возможны оба варианта. Копирование /etc/letsencrypt/ сохраняет сертификат действительным до истечения его срока, но вы должны установить тот же плагин аутентификации certbot на новом сервере, иначе первое обновление завершится ошибкой; после переключения DNS выполните certbot renew --dry-run для проверки. Выпуск нового сертификата — более чистый способ, если вы можете использовать DNS-01 challenge, так как он подтверждает владение через TXT-запись и работает до того, как DNS начнет указывать на новый сервер. HTTP-01 challenge нельзя использовать на новом сервере до переноса DNS, так как запрос на валидацию попадет на старый сервер.