Ultimate rsync one-liner for full VPS migration
I am mostly leaving this note to myself for future reference - but maybe someone else will find it useful too.
When MassiveGrid decided that right about now is a jolly good time to raise their prices from ~$25 for my VPS to just under $100, I felt that the grand VPS migration I’ve been contemplating for a little while now is actually overdue.
To spare you my soul searchings, I went with Hetzner Cloud - they have locations I want (kinda), prices I’m happy with, and much, much newer hardware. Apparently, and this is sarcasm for those who missed it, by moving from 24-vCPU VPS built on top of 11 year old Haswell, to only a 4 vCPU, but running atop state-of-the-art AMD EPYC chip, means not losing much if at all in the overall performance, where multi-core is concerned (conversely, 300% win for single-threaded applications, which is nice).
But I digress. The thing which made my write this post, was: how ridiculously easy was that to migrate from one VPS to the other, with all the Docker containers and custom configs, and all, with one well targeted rsync command. I will leave it with some basic documentation here, for future generations to learn:
rsync -avzHSX \
# Use numeric IDs; prevents permission mess by ignoring
# user names during transfer.
--numeric-ids \
# Enhanced progress output; cleaner than the old style.
--info=progress2 \
# Runs rsync as sudo on remote; allows root-level access
# without needing to SSH directly as root.
--rsync-path="sudo rsync" \
# EXCLUSIONS: Prevent overwriting hardware-specific files.
--exclude='/dev/*' \ # Skip device nodes
--exclude='/proc/*' \ # Skip process info
--exclude='/sys/*' \ # Skip hardware info
--exclude='/tmp/*' \ # Skip temp files
--exclude='/run/*' \ # Skip runtime state
--exclude='/mnt/*' \ # Skip external mounts
--exclude='/media/*' \ # Skip removable media
--exclude='/lost+found' \ # Skip recovery fragments
--exclude='/etc/fstab' \ # KEEP target mount rules
--exclude='/etc/mtab' \ # Skip mount table
--exclude='/boot/*' \ # KEEP target kernel/grub
--exclude='/etc/modules' \ # KEEP target drivers
--exclude='/etc/network/*' \ # KEEP network (Debian)
--exclude='/etc/netplan/*' \ # KEEP network (Ubuntu)
# TRANSPORT: Secure shell tunnel.
-e ssh \
# SOURCE: Remote root directory contents.
myusername@myvps:/ \
# DESTINATION: Local root directory.
/
The one bit of config it required (well, two actually) were:
- Creating
~/.ssh/configentry formyvps- its running on a non-standard port (as it should be) - Copying my private key to access VPS, because password login was disabled (again, as it should be).
This was literally it. rsync copied ~35G in something like 15 minutes, I rebooted the target system et voila - after pointing Cloudflare’s DNS to the new IP address, literally everything started working again (or at the very least, I didn’t discover yet things that are broken).