2021-04-10

Copy Encrypted Partition between Disks

linux   index

Recently, I had to copy/move an openSUSE Tumbleweed encrypted partition, and its EFI boot files, from one USB drive to another.

All the below are specific to this particular case. But, I’m sure it can be adapted to other similar situations as well.

Preparing Space

My target device already had an OS and a EFI boot partition. So, first I had to create space on the target.

Since the source partition is encrypted, and we are moving irrespective of the internal file system, we need to make the target partition size to be at least the same size, or preferably larger.

I did the resize using a GParted live disk.

Copy the Partition

This can be done with a simple dd. The most critical part here is to get the source /dev/sdXn and target /dev/sdYn partitions right.

dd if=/dev/sdXn of=/dev/sdYn bs=1M status=progress

Copy the EFI Files

We also need to copy the EFI bootloader files from the original disk boot partition, to the target. These are found in small FAT16 or FAT32 partitions.

Mount the source boot partition, and copy the following directory /boot/efi/EFI/opensuse to the EFI directory of the target disk’s boot partition.

Mount the Target Partition

Before booting, there are a few things to fix, so we need to mount our partition on another host system.

Obviously, if this step fails, and we can’t see our files, the partition is corrupted and there is no use continuing further…

cryptsetup --type luks open /dev/sdYn target 
mount /dev/mapper/target /mnt

Resize the File system

Since we copied into a larger area, we need to resize the file system to take the whole available space.

Each file system has its own commands, in my case it is btrfs, so we can resize it as follows.

# expanding a mounted btrfs partition
btrfs filesystem resize max /mnt

For ext2/ext3/ext4 file systems, resize2fs can be used.

Fix the Boot Partition UUID

Since the boot partition has changed, we need to update the reference in the mounted /mnt/etc/fstab to the correct UUID of the new disk.

Regenerate the Initrd

After doing all of the above, I rebooted to test the process. I was initially happy the bootloader was recognized, and it started booting the moved partition.

But, it didn’t go far, and the boot stalled for a minute or so, before complaining about the missing old boot partition UUID.

Apparently, the openSUSE Initrd includes this UUID as well, so we need to regenerate it, by going into a chroot environment on the host machine where we mounted the target, and run mkinitrd.

# Arch Linux has a script that prepares the chroot for us:
arch-chroot /mnt

# Now we are in the openSUSE environment and we can run:
/usr/bin/mkinitrd

After this the reboot worked fine, and the move is complete.