Skip to content

Zero-Downtime cPanel Migration: A Step-by-Step Rsync + DNS Strategy

Move accounts between servers without dropping a single request. This guide covers the rsync workflow, DNS cutover timing, and verification steps that actually work.

Written by AISali·July 26, 2026·5 min read
Zero-Downtime cPanel Migration: A Step-by-Step Rsync + DNS Strategy

Migrating cPanel accounts between servers is a rite of passage for every hosting reseller. Whether you're upgrading hardware, switching data centers for lower latency, or escaping a provider that just raised prices again, the fear is always the same: downtime, lost emails, angry customers.

This guide walks through a proven rsync-based migration strategy that keeps sites live through the entire process. No magic tools, no vague hand-waving — just the exact sequence of commands and DNS changes that minimize risk.

Why Rsync Over cPanel's Built-in Transfer Tool?#

cPanel's "Transfer Tool" (WHM → Transfers → Transfer Tool) works fine for small accounts and low-traffic sites. But it has real limitations:

  • It copies everything in one shot, which means larger accounts (10 GB+) can take hours during which the source data is stale on the destination.
  • It doesn't handle incremental syncs gracefully — if the first attempt fails partway, you're often starting over.
  • Email delivered during the transfer window can land on the old server and never make it to the new one.

Rsync solves these problems because it's incremental. You can run it multiple times: the first pass copies the bulk, subsequent passes only copy what changed. The final sync takes seconds, not hours.

Prerequisites#

Before you start, make sure you have:

  • Root SSH access on both source and destination servers
  • The destination server running the same (or newer) cPanel/WHM version
  • Sufficient disk space on the destination (check with df -h)
  • A list of accounts to migrate (or migrate all)
  • Customer notification sent (optional but professional)

Also confirm the destination server's basic services are running:

code
/usr/local/cpanel/cpkeyclt
/scripts/restartsrv_httpd
/scripts/restartsrv_exim

Step 1: Generate the cPanel Backup on the Source#

SSH into the source server and generate a packaged backup for each account. For a single account:

code
/scripts/pkgacct username

This creates /home/cpmove-username.tar.gz. The pkgacct script is fast because it doesn't compress the homedir — it uses a filelist approach.

For bulk migration, script it:

code
for user in $(/scripts/listaccts | awk '{print $1}'); do
  /scripts/pkgacct $user
done

Tip: Run this during off-peak hours. The packaged files can be 60-80% of the live account size.

Step 2: Transfer the Backup with Rsync#

From the destination server, pull the backups:

code
rsync -avz --progress root@SOURCE_IP:/home/cpmove-*.tar.gz /home/

The -a flag preserves permissions and timestamps, -v gives you verbose output, and -z compresses during transfer. On a 1 Gbps connection between data centers, expect roughly 100-120 MB/s throughput.

For accounts with large media directories (uploads, backups stored in home), transfer the homedir data separately with rsync's --delete flag to catch removals:

code
rsync -avz --delete root@SOURCE_IP:/home/username/ /home/username/

Step 3: Restore Accounts on the Destination#

SSH into the destination and restore each account:

code
/scripts/restorepkg username

For bulk restore:

code
for user in $(ls /home/cpmove-*.tar.gz | sed 's/.*cpmove-//;s/\.tar\.gz//'); do
  /scripts/restorepkg $user
done

Verify each account restored correctly:

code
/scripts/listaccts | grep username

Check that DNS zones, addon domains, email accounts, and databases all came through. A quick spot-check:

code
/scripts/whoowns domain.com
mysql -e "SHOW DATABASES;" | grep username

Step 4: The Critical Rsync Delta Sync#

Here's where the zero-downtime magic happens. Between the initial backup and now, the source server has been serving live traffic — new emails, database writes, file uploads. Run a delta sync to capture everything that changed.

Sync home directories:

code
rsync -avz --delete root@SOURCE_IP:/home/username/ /home/username/

Sync MySQL databases (run on source, pipe to destination):

code
ssh root@SOURCE_IP "mysqldump --single-transaction --routines --triggers username_db" | mysql username_db

Sync email (if using Maildir format, which cPanel defaults to):

code
rsync -avz root@SOURCE_IP:/home/username/mail/ /home/username/mail/

This delta sync typically completes in under 60 seconds for most accounts. The window of potential data loss is just this sync duration.

Step 5: DNS Cutover — The Timing Game#

This is where most migrations go wrong. The strategy:

  1. Lower your TTL 24-48 hours before migration. Set A records and MX records to a 300-second (5 minute) TTL. This ensures DNS caches expire quickly during cutover.
  1. Stop services on the source (or use iptables to redirect):
code
   /scripts/stopallhttpd
  1. Run one final rsync delta (the window is now ~30 seconds).
  1. Update DNS A records to point to the destination IP. With a 300s TTL, most of the internet will see the new IP within 5-10 minutes.
  1. Update MX records if the mail server IP changed.

If you manage DNS through WHM on the source, you can also use the "DNS Functions → Synchronize DNS Records" feature, or simply update the zone files and reload named:

code
/scripts/dnscluster syncall
rndc reload

Step 6: Post-Migration Verification#

Don't just assume it worked. Check these:

  • Websites load: Curl each domain from an external location to confirm you're hitting the new server: curl -I https://domain.com — check the response and verify the IP.
  • Email sends and receives: Send a test message to and from a migrated mailbox.
  • SSL certificates: Run /usr/local/cpanel/bin/checkallsslcerts to ensure AutoSSL renews properly on the new IP.
  • Cron jobs: crontab -l -u username to verify they transferred.
  • Error logs: Tail the Apache error log for the first hour: tail -f /usr/local/apache/logs/error_log

Keeping the Source Online as a Safety Net#

Don't decommission the source server immediately. Keep it running for 48-72 hours with the old DNS zones still resolving (for any stragglers with cached records). You can even set up a simple redirect on the source to catch edge cases.

If you're running a platform like Salieno Core that handles multi-server provisioning, the migration metadata and licensing can follow the account automatically — but the rsync and DNS fundamentals above remain the same regardless of your control panel stack.

The Bottom Line#

Zero-downtime migration isn't about a single clever trick. It's about sequencing: package, transfer, restore, delta sync, cutover. Each step is simple on its own. The discipline is in running them in the right order and resisting the urge to skip the final delta sync because "it's probably fine." It's never fine. Run the sync.

Share

0 comments

Loading comments…

More from the blog