Migrating Your Entire VPS to a New Server Without Downtime
Moving to a new VPS - a bigger plan, a different provider, or a fresh Getwebup instance - is one of those jobs that looks simple until you're two hours in and remember cron jobs, mail, and firewall rules all live on the old box too. Here's how to move the whole server, not just the website, without your visitors ever noticing.
Why "Just Copy the Website" Isn't Enough
Most VPS migration guides only cover the web files and the database. That's fine for a single WordPress site, but a real server usually carries more than that:
- Cron jobs (backups, WP-Cron workarounds, report generators)
- Mail - Postfix/Exim queues, mailboxes, SPF/DKIM keys tied to the old IP
- System users and their SSH keys
- Firewall rules (UFW/CSF) and fail2ban jail state
- SSL certificates and renewal hooks (Certbot/AutoSSL)
- Multiple sites or apps sharing the one box
Miss any of these and the new server "works" for a day, then something quietly breaks - a report cron that never fires again, or outbound mail that starts bouncing because the new IP has no reputation and no matching PTR record.
Step 1: Inventory the Old Server Before You Touch Anything
Don't start copying files yet. Spend twenty minutes writing down what's actually running:
# List enabled services
systemctl list-unit-files --state=enabled
# List installed packages (Debian/Ubuntu)
dpkg --get-selections > /root/old-packages.txt
Then check crontab -l for each account you know runs scheduled jobs (your own user and any app users), and note which system users actually have a login shell rather than a service account - those are the ones with real home directories and SSH keys worth carrying over.
If it's a cPanel VPS, this part is easier - WHM's Transfer Tool can pull entire cPanel accounts (files, mail, databases, DNS zones, cron jobs) to a new server in one job. For a plain unmanaged VPS, you're doing the inventory and the copy by hand, which is what the rest of this guide covers.
Step 2: Provision and Harden the New Server First
Set up the new VPS completely before you move a single byte of data:
- Match the OS version (or go newer, never older)
- Create your sudo user and install your public key before disabling password auth
- Install the same stack - Nginx/Apache, PHP-FPM version, MySQL/MariaDB version, Redis if you use it
- Set up UFW or CSF with the same rules as the old box
Getting SSH access locked down correctly on the new server before you route any real traffic to it matters - it's worth reading through SSH hardening for a VPS if you haven't already set that up on the old server either.
Step 3: Copy the Data With rsync, Not a Single tar Dump
rsync over SSH is the right tool here - it's resumable, it shows progress, and you can run it more than once without re-copying everything.
# From the new server, pull from the old one
rsync -avz --progress -e ssh root@OLD_SERVER_IP:/var/www/ /var/www/
rsync -avz --progress -e ssh root@OLD_SERVER_IP:/etc/nginx/sites-available/ /etc/nginx/sites-available/
rsync -avz --progress -e ssh root@OLD_SERVER_IP:/home/ /home/
For MySQL/MariaDB, dump per-database instead of copying raw data files - it's safer across MySQL versions:
mysqldump --single-transaction yourdatabase | gzip > yourdatabase.sql.gz
Run that once per database (skip the built-in information_schema, performance_schema, mysql, and sys schemas - those come with the server, not with your data).
Then scp or rsync those dumps to the new server and import them. If a database is large enough that mysqldump is painfully slow, see our guide on backing up MySQL on a VPS with mysqldump for the flags that speed it up.
For mail, copy the Maildir folders (not the queue - let old mail finish delivering on the old server):
rsync -avz --progress -e ssh root@OLD_SERVER_IP:/home/*/mail/ /home/
Step 4: Rebuild What Doesn't Copy Cleanly
Some things move better rebuilt than copied:
| Item | Why you rebuild it |
|---|---|
| Cron jobs | Copy the crontab text, but re-add with crontab -u user -e so paths and the user's environment are correct on the new box |
| SSL certificates | Don't copy Let's Encrypt certs - just re-issue with Certbot once DNS points here. Old certs reference the old server's ACME account |
| Firewall/fail2ban state | Recreate the rules; don't copy ban lists - a fresh start is fine, and stale bans can lock out legitimate traffic that changed IPs |
| Systemd services for custom apps | Copy the unit file, then systemctl daemon-reload && systemctl enable --now servicename |
Step 5: Test on the New Server Before Any DNS Change
Point your local machine at the new server without touching DNS yet, using a hosts file entry:
# On your local machine (not the server)
echo "NEW_SERVER_IP yourdomain.com www.yourdomain.com" | sudo tee -a /etc/hosts
Browse the site, log into wp-admin, test a form submission, check a cron-dependent feature. Remove the hosts entry when you're done so you don't forget it's there next week.
Step 6: Lower DNS TTL Ahead of the Cutover
Do this at least 24-48 hours before the actual switch. Log into cPanel's Zone Editor or your DNS provider and drop the TTL on your A record to 300 seconds (5 minutes). Full guidance is in our DNS propagation explainer, but the short version: a low TTL now means a fast, low-risk cutover later instead of a multi-hour window where some visitors hit the old server and some hit the new one.
Step 7: Cut Over
- Do a final
rsyncpass to catch anything changed since Step 3 (files and a fresh database dump) - Set the old server to read-only or put up a maintenance page, so nothing writes to it during the switch
- Update the A record (and AAAA if you use IPv6) to the new server's IP
- Watch traffic hit the new server:
tail -f /var/log/nginx/access.log - Once traffic has fully shifted (give it the TTL window plus a buffer), update MX records and mail client settings if the mail server moved too
Step 8: Keep the Old Server Alive for a Week
Don't cancel the old VPS immediately. DNS caching outside your control - ISP resolvers, some corporate networks, stale mobile DNS - can hang on to the old IP longer than your TTL suggests. Keep the old server running (even just for logging stragglers) for 5-7 days, then decommission it.
Prevention: Make the Next Migration Easier
- Keep infrastructure as code where you can - even a simple provisioning script beats rebuilding by memory
- Document custom cron jobs and systemd services somewhere outside the server itself
- Set up automated off-site backups so a migration is a restore job, not a from-scratch rebuild
- Use a config management tool (Ansible is the common choice) once you're running more than two or three servers
If this all sounds like more risk than you want to carry solo, Getwebup's support team handles full VPS-to-VPS migrations as part of onboarding - including the mail and DNS cutover - so open a ticket before you start moving anything by hand.
Frequently asked questions
Can I just clone the VPS disk instead of copying files manually?
Only if you're moving within the same provider and they offer a snapshot/clone-to-new-plan feature - that copies everything including the OS. Moving between providers almost always means a fresh OS install plus a file and database copy, since disk images usually aren't portable across hosting platforms.
Will my SSL certificate keep working after the move?
Not automatically. Let's Encrypt certificates are tied to files on the specific server and validated through your domain - copying the cert files over can work short-term, but you should re-issue with Certbot or AutoSSL on the new server once DNS points there, so renewals aren't pointing at a server that no longer exists.
How do I avoid mail getting lost during the switch?
Let the old server finish delivering anything already in its queue before you copy Maildir folders, and don't change MX records until after the website DNS has already cut over and settled. Moving mail last, once you've confirmed the new server is stable, avoids messages bouncing mid-transfer.
How long should I wait before shutting down the old server?
At least 5-7 days after the DNS cutover, even with a low TTL. Some DNS resolvers - especially on mobile carriers and corporate networks - cache records longer than they're supposed to, so keeping the old server reachable for a week avoids a small percentage of visitors hitting a dead IP.
Do I need to migrate cron jobs manually?
Yes - don't just copy crontab files over. Re-add each job with crontab -e on the new server so file paths, the PATH environment variable, and the user context match the new setup. A copied crontab that references old absolute paths will fail silently.