Moving a Linux VPS to a new server is usually less about one command and more about sequencing. If you copy files too early, your data goes stale. If you switch DNS too soon, users land on an incomplete system. If you try to clone everything at once, you can easily bring across temporary paths and host-specific settings that do not belong on the new machine.
This article is adapted from a GSVPS tutorial on Linux VPS migration. Original source:
https://www.gsvps.com/articles/linux-vps-ru-he-qian-yi-dao-xin-fu-wu-qi-2026-zui-xin-rsync-jiao-cheng-ji-hu-1-1-wu-sun-qian-yi-wang-zhan-docker-he-shu-ju
The practical goal is not "zero risk." It is a controlled migration with a short write-free window and a clear rollback path.
1. Start with an inventory, not with rsync
Before copying anything, write down what actually lives on the old server:
- web roots such as
/var/www - Nginx or Apache config
- application env files and secrets
- database engines and database names
- Docker Compose files, bind mounts, and named volumes
- cron jobs
- SSL certificate paths
- firewall rules and open ports
Also note what should not be copied blindly:
-
/proc,/sys,/dev,/run - temporary files
- mounted backup disks
- bootloader state
- network interface settings tied to the old host
That distinction matters. A migration usually fails because someone copied "everything" without deciding what "everything" meant.
2. Prepare the new server first
The destination host should be reachable and basically ready before any final sync:
- create the admin user you will keep using
- add SSH keys
- install the packages your stack needs
- confirm time, hostname, and firewall rules
- make sure the target disks are mounted where you expect
Useful early checks:
hostnamectl
ip addr
df -h
lsblk
systemctl --failed
If the new server cannot pass basic health checks, do not start the migration yet.
3. Lower DNS TTL before the cutover
If a site or API is moving, lower DNS TTL well before the migration window. That gives you a faster switchover later and reduces the period where some users still hit the old host.
This does not eliminate downtime by itself. It only shortens propagation pain when the final change happens.
4. Use rsync for repeatable file transfer
For website files, application directories, and many bind-mounted workloads, rsync is still one of the most useful tools because you can run it more than once.
A common pattern is:
- run an initial sync while services are still live
- validate the new server
- stop write-heavy services briefly
- run one final sync
- switch traffic
Example for a web root:
sudo rsync -aHAXx --numeric-ids --delete --info=progress2 \
/var/www/ user@NEW_SERVER:/var/www/
Flags here matter:
-
-apreserves recursion, permissions, timestamps, and symlinks -
-HAXhelps preserve hard links, ACLs, and xattrs where relevant -
-xkeeps the copy on one filesystem -
--numeric-idsavoids UID or GID name mismatches -
--deletekeeps the destination aligned with the source
Do not use --delete casually against the wrong path. Verify both source and destination before pressing Enter.
5. Treat databases separately from static files
If the application writes to MySQL, MariaDB, or PostgreSQL, file sync alone is not enough.
Typical export commands:
mysqldump --single-transaction --routines --triggers DB_NAME > db.sql
pg_dump -Fc DB_NAME > db.dump
Those should be imported on the new server after the database service is prepared.
For busy applications, the cleanest cutover is usually:
- enable maintenance mode or temporarily stop writes
- take the final dump or replication-consistent copy
- import on the new host
- run the final file sync
That write-free window is where you win or lose data consistency.
6. For Docker, migrate config and data intentionally
If the workload runs under Docker Compose, copy the Compose files, env files, and persistent data paths deliberately rather than assuming the container image is the hard part.
A simple sequence is:
docker compose config
docker compose down
sudo rsync -aHAX --delete /srv/app/ user@NEW_SERVER:/srv/app/
Then on the new server:
docker compose pull
docker compose up -d
docker compose ps
If you use named volumes instead of bind mounts, inspect where the actual persistent data lives before moving anything.
7. Validate before DNS cutover
Before sending production traffic to the new host, verify:
- the web server starts cleanly
- the application can connect to its database
- file permissions are correct
- scheduled jobs exist where needed
- TLS certificates are present or can be reissued
- uploads, login flows, and API writes still work
Useful checks include:
nginx -t
systemctl status nginx
docker compose logs --tail=100
ss -tlnp
curl -I http://127.0.0.1
If the service stack is not healthy locally, changing DNS only hides the real problem behind a network symptom.
8. Keep rollback simple
Do not tear down the old server immediately after cutover.
Keep it available long enough to:
- compare logs
- recover missed files
- re-check database state
- reverse DNS if a critical issue appears
A migration plan is better when rollback is boring.
Final takeaway
The original GSVPS article focuses on using rsync to move a Linux VPS with minimal disruption. That is a sensible base, but the real success condition is broader: prepare the target host, separate static files from live data, run repeatable syncs, and keep the final write window short and explicit.
If you treat migration as a sequence instead of a copy job, rsync becomes a reliable part of the process rather than a gamble.
Top comments (0)