How to Move a Linux Server to New Hardware (Clone the Disk or Rebuild Clean)

The old PC is wheezing, or you've bought a mini PC that uses a tenth of the power. Moving a Linux server is far less painful than moving a Windows one, and if you've followed this series — data in ~/docker, configs in /etc, backups that you've tested — you have a choice: clone the disk exactly, or rebuild clean and restore. Both are described here; the second is usually better.
Quick reference
| Approach | Best when | Time |
|---|---|---|
| Clone the disk (Clonezilla / dd) | same architecture, you want everything identical, can't face reinstalling | 1 hour |
| Rebuild and restore | moving between very different hardware, Pi ↔ x86, or the old install has accumulated cruft | an afternoon |
Either way, finish with the same checklist at the end.
Option A: Clone the disk
- Download Clonezilla Live, write it to a USB stick (Rufus), and boot the old server from it with the new drive attached (USB adapter, or a second bay).
- Choose device-device → disk_to_local_disk, source = old disk, target = new disk. Confirm twice. If the new disk is bigger, choose the -k1 option to grow the partition proportionally, or grow it afterwards (tutorial 64).
- Move the new drive into the new machine and boot.
For a drive on another machine over the network, dd through SSH works too: sudo dd if=/dev/sda bs=4M status=progress | ssh john@newserver "sudo dd of=/dev/sda bs=4M" — only with the old system booted from a live USB, never while it's running.
Then fix what hardware changed:
- Network interface name changed (enp3s0 → eno1): ip a for the new name, update /etc/netplan/*.yaml, sudo netplan apply.
- DHCP reservation on the router is tied to the MAC address: update it to the new machine's.
- sudo update-grub if it won't boot; the UUIDs are copied so fstab should be fine.
- A different GPU: Jellyfin's /dev/dri mapping may need a group change.
Option B: Rebuild clean and restore
Cleaner, and the better choice most of the time.
- Install Ubuntu Server on the new machine (tutorial 1), same username and UID (id on the old server; the installer's first user is 1000, which is usually what you had).
- Basics: SSH keys, sudo user, updates, UFW, Fail2ban, hostname and time zone, static IP (tutorials 3 to 9). Half an hour with this series open.
- Install Docker (tutorial 24) and anything host-installed — Nginx, MariaDB, Samba, Tailscale. ~/packages-before.txt from the old server (dpkg --get-selections) tells you what you had.
- Restore data: from the backup drive or restic (restic restore latest --target /), or rsync straight from the old machine while it's still on: ` rsync -aAX john@oldserver:/home/john/ /home/john/ sudo rsync -aAX john@oldserver:/etc/ /tmp/old-etc/ # review, then copy what you need sudo rsync -aAX john@oldserver:/srv/ /srv/ sudo rsync -aAX john@oldserver:/var/www/ /var/www/ ` Don't blindly copy /etc over the new one — pick the files you edited (nginx/sites-available, samba/smb.conf, fail2ban/jail.local, ssh/sshd_config, msmtprc, exports, fstab lines for data drives).
- Databases: restore dumps (mysql < dump.sql), not files.
- cd ~/docker/* and docker compose up -d in each folder. Images download; data is already there.
The checklist (both options)
- hostname -I is the IP everything expects (reservation updated, or Netplan edited).
- ~/.ssh/known_hosts on your laptop: delete the old line for the server's IP or you'll get the "host identification changed" warning (expected with a rebuild).
- Data drives: lsblk -f and fstab by UUID; sudo mount -a.
- systemctl --failed, docker ps, sudo ufw status.
- Reverse proxy certificates: Certbot's /etc/letsencrypt (or Caddy's ./data) restored, or just re-request.
- Tailscale: sudo tailscale up and remove the old machine from the admin console.
- DuckDNS cron, msmtp config, smartd, backup script and its cron or timer.
- Pi-hole: if the router points at the server's IP, make sure the new one has that IP before switching the old one off.
- Run the backup script once on the new machine and check the log.
Keep the old server for a week
Switch it off but don't wipe it. Something always surfaces — a cron job you'd forgotten, a Samba share someone uses once a month. After a week with no surprises, wipe it or repurpose it as the backup target.
Troubleshooting
Cloned disk won't boot on UEFI/BIOS mismatch. The old machine was BIOS and the new one is UEFI (or vice versa). Rebuilding is faster than converting.
Permission errors on restored files. UIDs differ. ls -ln and sudo chown -R 1000:1000 as appropriate.
Docker apps start but data is empty. Compose files restored to a different path than the data. Match the folder structure exactly.
Everything works but it's slow. The new NVMe is fine; the old fstab had noatime/mount options you didn't carry over, or the BIOS has power saving at maximum.
Wrapping up
Clone if you must, rebuild if you can. With data in ~/docker, configs you know you edited, tested backups and this checklist, a server migration is an afternoon — and the rebuild leaves you with a clean machine that you understand completely.
