How to move luks encrypted disk to smaller SSD drive (using LVM)

In this tutorial, we are going to clone a Linux encrypted hard drive with the operating system. For this tutorial, we are going to encrypt the disk and use LVM.

In summary, we first encrypt the whole disk. Once we have the encrypted disk, we will mount it and then create the LVM logical partitions inside of it. Once we have the logical partitions we will create the swap and data partitions. Finally, we use rsync to copy files from the old disk to the new one.

WARNING: Make sure you backup all your data. The steps in this tutorial could destroy all your data!!

Since we move to smaller disk we assume that the used space is less than the new SSD space, if not move data to another disk.

Step 1: Create partitions on the new disk

Open fdisk command and create two partitions, one of 256mb for /boot and the other with the rest of the space. We are going to use LVM on the large partition.

You can check more info about the drive with the command:

sudo smartctl -a /dev/sdX

Create the first partition

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1):  
First sector (2048-468862127, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-468862127, default 468862127): +256M

Now create the second one:

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): e
Partition number (2-4, default 2):
First sector (526336-468862127, default 526336):
Last sector, +sectors or +size{K,M,G,T,P} (526336-468862127, default 468862127):

Note that we used extended for the second partition.

Command (m for help): t
Partition number (1,2, default 2): 2
Partition type (type L to list all types): 82
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

Make sure that the second partition is Linux LVM

Device     Boot  Start       End   Sectors   Size Id Type
/dev/sdb1         2048    526335    524288   256M 83 Linux
/dev/sdb2       526336 468862127 468335792 223.3G 8e Linux LVM

Step 2: Encrypt the new drive

cryptsetup luksFormat /dev/sdx2
cryptsetup luksOpen /dev/sdx2 new_disk

Most of the guides recommend filling with zeros the new drive since this is an SSD drive we will skip that step.

Step 3: Create LVM volumes

In this step, we are going to use the commands pvcreate and vgcreate

pvcreate /dev/mapper/new_disk
vgcreate root /dev/mapper/new_disk

The first command will create the physical volume. The second command will create the volume group.

Step 4: Create logical volumes

Now we are going to create the swap and data logical volumes. Since our SSD was small we use 6G as swap, but feel free to add more if you have a big disk.

 lvcreate -L 6G       -n swap root
 lvcreate -l 100%FREE -n root root

Step 5: Partition initialization

First, we are going to initialize the swap partition:

 mkswap /dev/mapper/root-swap

Now the /boot and / partition:

 mkfs -t ext4 /dev/mapper/root-root
 mkfs -t ext2 /dev/sdx1 # This will initialize /boot partition

We used ext4 for the root partition and ext2 for the /boot.

Step 6: Copy all the files (rsync)

Now that we have all our partitions ready for use, we are going to use rsync to copy all the files from the original partition to the new one.

mount /dev/mapper/root-root /new_disk
rsync -raHAXx -v / /new_disk

First, we mount the new partition to the /new_disk directory and then we use the rsync command to copy all the files.

Note that we used a lot of parameters on the rsync, but the most important one is x. We used x to avoid copy files from mount points.

Now we need to do the same with the boot partition:

mount /dev/sdx1 /mnt/boot
 rsync -raHAXx -v /boot/ /mnt/boot/

Step 7: Update configuration

This is the hardest steps of all. We need to update the configuration files like crypttab, fstab, etc.

First identify your old and new UUID of your disk using blkid:

blkid

The output should be like this one:

/dev/mapper/old-disk: UUID="adaced19-d99d-4c71-b934-33fed03caa56" TYPE="ext4"
/dev/mapper/old-swap: UUID="2ac61081-6d62-4de7-94b1-98d9ead93733" TYPE="swap"
/dev/mapper/root-swap: UUID="35ffeab8-2a35-469f-8886-9c3cbe56aa0a" TYPE="swap"
/dev/mapper/root-root: UUID="2db0830b-fd1f-48e0-b496-d0bd88c6f2f6" TYPE="ext4"

We recommend executing a recursive grep with the old disk UUID on the new disk and replace it with the new one.

Update /etc/fstab

First we will update the fstab, make sure you update to the correct values, use the following as an example:

/dev/mapper/root-root /               ext4    errors=remount-ro 0       1
# /boot was on /dev/sdX1 during installation
UUID=3d7e56b3-63a4-4611-8a50-f2ca9c15efd6 /boot           ext2    defaults        0       2
/dev/mapper/root-swap none            swap    sw              0       0

Our fstab only used the UUID for the /boot partition, for the other partition we used /dev/mapper/root-X or the name you used in the previous steps.

Update crypttab

Our crypttab contained an entry of the type crypto_LUKS (search for this type in blkid), on the new disk this corresponds to the /dev/mapper/new_disk

you can list all crypto_LUKS disks with:

blkid | grep crypto_LUKS
new_disk /dev/disk/by-uuid/5157f665-75cc-41ec-af0d-6dafe7c46b42 none luks

In our case we need to use the UUID of the /dev/mapper/new_disk with type LVM2_member

Step 8: initrd and grub update

First, we need to update grub config, open the file /mnt/boot/grub/grub.cfg and search for the old UUID and replace it with the new ones.

We need to update the initrd and grub on the new disk after all the config changes:

mount --bind /dev /new_disk/dev
chroot /new_disk
mount /dev/sdX1 /boot # we mount the new boot partition
mount /proc
update-initramfs -u -k all
update-grub

Now we are ready to install grub:

Exit chroot and then execute:

grub-install --root-directory=/new_disk /dev/sdx

Appendix

Cannot wipe header on device

Make sure that your partition type is Linux LVM.

mount: can't find /proc in /etc/fstab

Add the following line to the /etc/fstab

none /proc proc defaults 0 0