Debian clone, or how to make a copy of an existing Debian install

I needed to install the system on about two dozen computers. Ended up copying an already set-up system, for a few reasons:

  • same system across all the computers (about 20 of them);
  • that system was already configured after install/copy.

Turns out for these things you’re supposed to build a livecd image and use that to click through the machines above. Building an image, from what I read around the internet, is interesting but time-consuming. So the simple solution: make a clean copy of the system onto another hard drive, or a flash drive. That’s how this guide came about.

Stage 0:
Before anything else, plug in the “target” drive and figure out the letters for the source and target drives.

The system usually sits on /dev/sda1; to check, use:

fdisk -l

In my case the source is /dev/sda, target is /dev/sdb. Same command lets you format the target drive if needed, and mkfs/mkswap handle the filesystem and swap.
IMPORTANT: don’t forget to mark the new system partition bootable.

Mount the target disk’s partition:

mkdir /mnt/clone  
mount -o rw /dev/sdb1 /mnt/clone

We’ll use the /mnt/clone folder going forward.

Stage 1:
Clone/copy the whole system to the target partition:

cp -ax / /mnt/clone

the a flag archives the data,
the x flag skips nonexistent partitions.

After copying, move to the other partition by temporarily mounting the essential parts of the current system into the new one:

mount -o bind /dev/ /mnt/clone/dev  
mount -t proc none /mnt/clone/proc  
mount -t sysfs none /mnt/clone/sys

And switch to the new root directory:

chroot /mnt/clone

Stage 2:
Setting up shop. The new partition has a different UUID, quick way to plug it in:

cd /etc  
mv ./fstab ./fstab.bak  
echo UUID=`blkid && grep '/dev/sdb1' && grep -o -E '[a-zA-Z|0-9|\-]{36}'` / ext4 errors=remount-ro 0 1 >> ./fstab

if you also have a swap partition, run the same command again with the swap partition number:

echo UUID=`blkid && grep '/dev/sdb2' && grep -o -E '[a-zA-Z|0-9|\-]{36}'` swap swap defaults 0 0 >> ./fstab

Also don’t forget to update the kernel, so the fstab changes actually take effect:

update-initramfs -u

Now update the GRUB config and install it into the MBR of the new /dev/sdb disk — in our case we’ll use GRUB’s “Recovery Mode”, so first enable it in /etc/defaults/grub, then run:

update-grub  
grub-install /dev/sdb

Last treat: delete the “ethernet devices” list, to avoid eth0 getting renamed to eth1 and so on when you plug the drive into another machine:

rm /etc/udev/rules.d/70-persistent-net.rules

That saves you from editing /etc/network/interfaces.

Stage 3:
Put the box back where it belongs. Exit the new root and unmount everything tied to it:

exit  
umount /mnt/clone/sys  
umount /mnt/clone/proc  
umount /mnt/clone/dev  
umount /mnt/clone

Stage REBOOT:
While GRUB is booting, quickly hit the down arrow until you land on the menu entry (recovery mode) at the end. Press e to temporarily edit that entry, and in the text change /dev/sdb to /dev/sda — for some setups that might be hd1 to hd0 instead. Then press F10 to boot that entry.

The system will ask for the root password on boot; after entering it, run:

update-grub

That locks in the changes you made in the GRUB menu, and now you can safely REBOOT.