Migrating a live Linux server to a new VPS is one of the highest-risk operations a sysadmin performs. Done without a plan, it means hours of downtime, broken database connections, hard-coded IP addresses scattered across config files, and — worst case — data loss if the cutover happens before the transfer is complete. Done with the right process, the same migration can happen with under 60 seconds of actual service interruption.
This guide covers the full operational playbook: inventory and pre-migration prep, rsync-based live transfer, DNS TTL staging for near-zero downtime cutover, and post-migration validation.
Why Linux Server Migrations Fail (and How to Avoid the Common Traps)
Most migration failures fall into one of four categories:
- No pre-migration inventory: Services are missed because no one documented what was running. After cutover, a cron job or background service fails silently on the new server.
- DNS TTL not staged in advance: DNS TTL is still set at 86400 (24 hours) at the time of cutover, meaning clients are still resolving the old IP for up to 24 hours after the switch. This is the most common cause of prolonged "downtime" that is actually a propagation problem.
- Single rsync run: One rsync is run, then the server is switched. But files changed during the rsync are not synced. A second incremental rsync immediately before cutover catches these changes.
- Hard-coded IP references: Config files, application code, database connection strings, and firewall rules contain the old server's IP and break immediately after cutover.
💡 None of these worked? Skip the guesswork.
Get Expert Help →Pre-Migration Checklist: Inventory, Backups, and Staging
systemctl list-units --type=service --state=running
crontab -l
cat /etc/cron.d/*
ls /etc/cron.daily/ /etc/cron.weekly/
Note every service, its configuration file location, and any dependencies (databases, message queues, cache servers).
tar czf /root/premigration-backup-$(date +%Y%m%d).tar.gz /etc /home /var/www /var/lib/mysql
Upload this to S3 or a remote storage location. This is your rollback point — the moment things go wrong on the new server, you can restore to the old one.
On the new VPS, install the same OS version (or one version newer if upgrading). Install the same packages:
# On old server — export package list
dpkg --get-selections > /tmp/package-list.txt
# On new server — import and install
dpkg --set-selections < /tmp/package-list.txt
apt-get dselect-upgrade
Log into your DNS provider and change the TTL for all A records pointing to the old server IP to 300 seconds (5 minutes). Wait for the current TTL to expire (up to 24 hours if it was 86400) before proceeding. This is non-negotiable — skip this step and you will have hours of post-cutover DNS propagation.
Step-by-Step: Using Rsync for a Live, Incremental Server Transfer
Rsync is the right tool for this job because it copies only changed files and can be run multiple times incrementally, with each run getting faster as the delta shrinks.
First rsync run — bulk transfer (run while old server is live)
rsync -avz --progress --delete -e "ssh -p 22 -i /root/.ssh/migration_key" /home/ root@NEW_SERVER_IP:/home/
rsync -avz --progress --delete -e "ssh -p 22 -i /root/.ssh/migration_key" /var/www/ root@NEW_SERVER_IP:/var/www/
rsync -avz --progress --delete -e "ssh -p 22 -i /root/.ssh/migration_key" /etc/ root@NEW_SERVER_IP:/etc/
The --delete flag ensures files deleted on the source are removed on the destination. Run this while the old server is still serving traffic — it handles the bulk of the data transfer.
Database dump and transfer
# On old server
mysqldump --all-databases --single-transaction -u root -p > /tmp/full_db_backup.sql
rsync -avz -e "ssh -p 22" /tmp/full_db_backup.sql root@NEW_SERVER_IP:/tmp/
# On new server
mysql -u root -p < /tmp/full_db_backup.sql
Before cutover — second incremental rsync
Immediately before cutover, run rsync again. This second run copies only files that changed since the first run — typically very fast (minutes, not hours):
rsync -avz --checksum --delete -e "ssh -p 22 -i /root/.ssh/migration_key" /home/ /var/www/ root@NEW_SERVER_IP:/
Use --checksum on the second run to catch files with updated timestamps but unchanged content.
DNS TTL Strategy and Cutover Timing for Near-Zero Downtime
By the time you are ready to cut over, your DNS TTL should already be at 300 seconds (from Step 4 in the pre-migration checklist). Here is the cutover sequence:
- Run the second incremental rsync (above)
- Put the old server into maintenance mode or disable write operations (for example, set your application to read-only or enable a maintenance page)
- Run a final database sync to capture the last few minutes of writes
- Update DNS A records to point to the new server IP
- Start all services on the new server and verify they are healthy
- Wait 5–10 minutes (your TTL) — new visitors are now hitting the new server
- Verify the old server receives no new traffic by monitoring its access logs
The window between step 2 and step 7 is your actual downtime. With this approach, it is typically under 2 minutes.
Post-Migration Validation: Services, Configs, and IP References
Service health check
systemctl status nginx apache2 mysql php-fpm
journalctl -xe --since "10 minutes ago"
Scan for old IP references in config files
grep -r "OLD_SERVER_IP" /etc /var/www /home --include="*.conf" --include="*.php" --include="*.env" --include="*.yml"
Replace every occurrence with the new server IP or a hostname. Hard-coded IPs in application config files are the most common cause of post-migration breakage.
Test every critical path
- Web application loads and logs in correctly
- Email sending and receiving works (check MX records point to new server if self-hosted)
- Cron jobs run (check
/var/log/syslogor/var/log/cronthe next morning) - SSL certificates are valid on the new domain
- Database connections succeed from application layer
Leave the old server running for 48 hours
Do not decommission the old server immediately. Keep it running but stop all services. If any issue surfaces on the new server in the first 48 hours, the old server is your rollback target. After 48 hours of clean operation, it is safe to terminate.
Server migrations are high-stakes and time-sensitive. If you are managing a migration for a client and cannot afford downtime surprises, CloudHouse's server migration service handles the full process — inventory, rsync transfer, DNS cutover, post-migration validation, and 48-hour monitoring — with a money-back guarantee on downtime.
