Difficulty: ★★☆☆☆
This guide shows how to move your current installation of Manjaro to a new drive and encrypt it with LUKS.
I’ve prepared it based on what I’ve been doing with my own laptop, so there’ll be some references to my own setup.
It assumes your system has UEFI (instead of BIOS) and your partition table is GPT (and not MBR).
About the boot partition
My system had three partitions:
-
/dev/sda1
- the EFI partition -
/dev/sda2
- the/boot
partition, holding the GRUB config and Linux kernels -
/dev/sda3
- the root partition, holding the Manjaro installation and my data
You can check out yours with lsblk
.
Why a separate /boot
?
- Your boot time will be shorter if GRUB will be unencrypted (it resides in /boot)
- if you dual(or triple, or whatever the number)-boot your machine with multiple Linux installs, they can share /boot, so you don’t need to have all installs duplicating the same files to
/boot
in their partition; only one at a time would be picked for the computer boot-up, anyway.
If you don’t have a dedicated partition for /boot
and you want to create one like me
(it’s assumed in the guide, that you do), just copy the files from your /boot
(skipping /boot/efi
) to the external drive. They’ll be used later.
If you don’t want separate /boot
, you might need to set up GRUB and probably the initial RAM disk differently than how I show here.
That’s because /boot
(which hosts GRUB) will also be encrypted1.
For that setup you’ll need to change /etc/default/grub
in the later part of this tutorial:
- uncomment or add
GRUB_ENABLE_CRYPTODISK=y
- include the
cryptodisk=<KEY>
directive toGRUB_CMDLINE_LINUX_DEFAULT
- maybe2 add loading of the LVM kernel module to
GRUB_CMDLINE_LINUX_DEFAULT
I created that setup before the current one, but I wasn’t satisfied with the boot time,
and I didn’t want to spend more time on investigating GRUB. That would be necessary if I were to cut down the number of hashing rounds for encryption, so that it doesn’t have that >10 second wait on boot.
Can you put the new drive side-by-side with the old one?
First you need to boot the laptop from a live USB, so that the system you want to copy isn’t running.
No, I have only a single drive-slot.
Copy your current partitions to an external drive with dd
, like so3:
sudo dd if=/dev/sda1 of=/run/media/manjaro/the_external_drive/efi_partition.bin bs=4M status=progress
sudo dd if=/dev/sda2 of=/run/media/manjaro/the_external_drive/boot_partition.bin bs=4M status=progress
sudo dd if=/dev/sda3 of=/run/media/manjaro/the_external_drive/root_partition.bin bs=4M status=progress
Yes, I have multiple drive-slots.
Go through the next section about partitioning first, then use dd
to copy the partitions directly:
# assuming "sda" is the old drive and "sdb" is the new drive; the names can also look like "nvme0"
sudo dd if=/dev/sda1 of=/dev/sdb1 bs=4M status=progress
sudo dd if=/dev/sda2 of=/dev/sdb2 bs=4M status=progress
sudo dd if=/dev/sda3 of=/dev/sdb2 bs=4M status=progress
Partitioning the new drive
Partition the drive, so you can copy the old partitions to it. I used GParted
for that, you can use fdisk
, KDE Partition Manager
, or whatever you want, but I’m not gonna show how to do it. Shouldn’t be a big problem, though
The types/filesystems of the partitions you create don’t matter, because they’ll be overwritten when being copied to with dd
.
If you didn’t start going through this tutorial with a partition for /boot
, please create a 512 megabyte (or however big you deem sensible) ext4
partition for it. You’ll be able to copy your old files to it when we mount it later on.
You should probably set the flags boot
and esp
flags on your EFI partition. Flags are kept in the partition table, not in the partitions themselves. I don’t know if these flags are strictly necessary, though4.
After the partitioning, I ended up with this layout (from lsblk
):
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
# ...omitted lines...
# manjaro live USB
sda 8:0 1 28.7G 0 disk /run/miso/bootmnt
├─sda1 8:1 1 2.4G 0 part
└─sda2 8:2 1 4M 0 part
# the external drive holding the partition images
sdb 8:16 0 1.8T 0 disk
└─sdb1 8:17 0 1.8T 0 part /run/media/manjaro/Seagate Backup Plus Drive
# the new drive
nvme0n1 259:0 0 953.9G 0 disk
├─nvme0n1p1 259:4 0 200M 0 part # will be /boot/efi
├─nvme0n1p2 259:5 0 512M 0 part # will be /boot
└─nvme0n1p3 259:6 0 953.2G 0 part # will hold the encrypted root partition
Preparing LVM in LUKS
Note that all (or most) the code here is also available as scripts on my repo - moving partitions to the new layout, mounting for chroot, adjusting configs and building GRUB.
First, set up some variables you’ll be using throughout the process. You’ll need change these so they match your system and personal preferences, of course.
export EFI_PARTITION=/dev/nvme0n1p1
export BOOT_PARTITION=/dev/nvme0n1p2
# this partition will be the LUKS container, holding the LVM and your Linux install
export PARTITION_FOR_LUKS=/dev/nvme0n1p3
# name of the LVM group we'll create
export VG_NAME=vg0
# name of the LVM volume that will host the system
export OS_VOLUME_NAME=manjaro
Make the chosen partition into a LUKS container:
sudo cryptsetup luksFormat --type luks1 $PARTITION_FOR_LUKS
I’m using luks1
instead of luks2
, because the latter isn’t handled by GRUB yet.
Now we need to open the newly created LUKS container (you can use any other name than crypt
, of course)
sudo cryptsetup luksOpen $PARTITION_FOR_LUKS crypt
What people usually recommend (e.g. paragraph 2.1.6 from cryptsetup
’s FAQ) is to fill the LUKS container with zeroes, so that it looks like random data on the drive, but because that doesn’t seem so dangerous I’m skipping that step.
Next, mark the opened LUKS container as a “physical volume” for LVM, and create the LVM group:
sudo lvm pvcreate /dev/mapper/crypt
sudo vgcreate $VG_NAME /dev/mapper/crypt
And finally, create the LVM volume that will host your OS. I’ve chosen a size (853 gigabytes) that will leave me 100 gigs for creating a new volume with another Linux install in the future for experiments:
sudo lvcreate -L 853G -n $OS_VOLUME_NAME $VG_NAME
Now, lsblk
(for me) reports this layout:
nvme0n1 259:0 0 953.9G 0 disk
├─nvme0n1p1 259:4 0 200M 0 part
├─nvme0n1p2 259:5 0 512M 0 part
└─nvme0n1p3 259:6 0 953.2G 0 part
└─crypt 254:0 0 953.2G 0 crypt
└─vg0-manjaro 254:1 0 853G 0 lvm
Restoring the old partitions on the new drive
Now, cd
into the place where you’ve stored the partition images, and copy them over to the new partitions one by one:
export OS_VOLUME_PATH=/dev/${VG_NAME}/${OS_VOLUME_NAME}
sudo dd if=efi_partition_image.bin of=$EFI_PARTITION bs=8M status=progress
sudo dd if=boot_partition_image.bin of=$BOOT_PARTITION bs=8M status=progress
sudo dd if=root_partition_image.bin of=${OS_VOLUME_PATH} bs=8M status=progress
In my case, the root partition has more space than it had on the previous drive. Because a filesystem retains its size when copied over with dd
, it won’t be making use of that additional space. That’s how you expand the (ext4) filesystem so that it takes all the space available in the volume:
sudo resize2fs ${OS_VOLUME_PATH}
If for the EFI and boot partitions you’ve also allocated more space than they had on the previous drive,
you can enlarge their filesystems accordingly:
sudo resize2fs $EFI_PARTITION
sudo resize2fs $BOOT_PARTITION
Chrooting into the old Linux install
If you’d reboot the system now and tried booting from the EFI partition, you’d fail. We still need to adjust some files.
To do that, we first need to mount the partitions we’ve created for the live Linux we’re working in:
sudo mount $OS_VOLUME_PATH /mnt
sudo mount $BOOT_PARTITION /mnt/boot
sudo mount $EFI_PARTITION /mnt/boot/efi
You’ll be able to browse your old files in /mnt
right now.
Next you need to bind-mount some pseudo-directories:
sudo mount --bind /proc /mnt/proc
sudo mount --bind /sys /mnt/sys
sudo mount --bind /dev /mnt/dev
sudo mount --bind /dev/pts /mnt/dev/pts
Now, everything’s prepared for using chroot
to “get inside” that old install:
sudo chroot /mnt
You should now have a root shell running in your old Linux system.
Modifying the “tab” files
Now that you’re chrooted into your old Linux install, we need to fixup a few things in order to make it bootable.
First, run blkid
command to get the UUID of the partition hosting your LUKS container. For me, the output looks like this:
/dev/loop1: TYPE="squashfs"
/dev/mapper/vg0-manjaro: UUID="e980c99e-acb7-4264-9ed3-300f65694b42" BLOCK_SIZE="4096" TYPE="ext4"
/dev/nvme0n1p3: UUID="050a93bf-d0d3-4d01-83c7-b65d060d2cc5" TYPE="crypto_LUKS" PARTUUID="e18e4927-c79d-4283-a1b9-e2f41cb92a2d"
...omitted...
Because my LUKS container is hosted on /dev/nvme0n1p3
, I note the UUID 050a93bf-d0d3-4d01-83c7-b65d060d2cc5
. This UUID needs to be added to /etc/crypttab
file (you can use nano
or vim
to edit the files), to instruct the booting system to open the container. The line in the file will look like this:
crypt UUID=050a93bf-d0d3-4d01-83c7-b65d060d2cc5 none luks
As previously, I’m using crypt
as the name under which the unencrypted partition will appear.
Now, let’s edit /etc/fstab
. Because the UUIDs of all the partitions are copied over from the images you might not need to do that, but I wanted the root filesystem (/
) mount to clearly point to the LVM volume containing the Linux install (/dev/vg0/manjaro
). My full fstab
looks like this:
UUID=7E5B-9C2C /boot/efi vfat defaults,noatime 0 2
UUID=4f3c8672-650d-4a8b-9697-1817ec53bb78 /boot ext4 defaults,noatime,discard 0 2
/dev/vg0/manjaro / ext4 defaults,noatime,discard 0 1
tmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0
/swapfile none swap defaults 0 0
Rebuilding the initial RAM disk and GRUB
We need to make sure that the initial RAM disk that bootstraps your system during boot can work with LUKS and LVM. So you need to add lvm2
and encrypt
modules to the HOOKS
variable in /etc/mkinitcpio.conf
. I saw advice saying they should be after keyboard
and before filesystems
.
That’s how the variable looks for me:
HOOKS="base udev autodetect modconf block keyboard keymap encrypt lvm2 filesystems"
Next, add a cryptdevice
instruction pointing to your LUKS partition (should be the same UUID as in your crypttab
), to GRUB_CMDLINE_LINUX_DEFAULT
in /etc/default/grub
. On my system (notice other parameters mindlessly stolen from a default encrypted Manjaro install):
GRUB_CMDLINE_LINUX_DEFAULT="cryptdevice=UUID=050a93bf-d0d3-4d01-83c7-b65d060d2cc5:crypt apparmor=1 security=apparmor udev.log_priority=3"
Now, run:
mkinitcpio -P
Now, something that will be needed so that GRUB can work with EFI 5:
mount -t efivarfs efivarfs /sys/firmware/efi/efivars
Prepare the GRUB config:
grub-mkconfig -o /boot/grub/grub.cfg
For me, it gives this output:
Generating grub configuration file ...
Found theme: /usr/share/grub/themes/manjaro/theme.txt
Found linux image: /boot/vmlinuz-5.4-x86_64
Found initrd image: /boot/amd-ucode.img /boot/initramfs-5.4-x86_64.img
Found initrd fallback image: /boot/initramfs-5.4-x86_64-fallback.img
Warning: os-prober will be executed to detect other bootable partitions.
Its output will be used to detect bootable binaries on them and create new boot entries.
grub-probe: error: cannot find a GRUB drive for /dev/sdb1. Check your device.map.
grub-probe: error: cannot find a GRUB drive for /dev/sdb1. Check your device.map.
Adding boot menu entry for UEFI Firmware Settings ...
Found memtest86+ image: /boot/memtest86+/memtest.bin
done
Notice that error with /dev/sdb1
which is the previous location of one of the partitions. I can’t figure out how to fix it or how to “check my device.map”, but that doesn’t seem to be affecting anything.
And now, the final step - install GRUB to the EFI partition:
# the actual partition might be different for you, of course
grub-install /dev/nvme0n1p1
My output:
Installing for x86_64-efi platform.
Installation finished. No error reported.
And that’s it! The system should be ready to go.
Now reboot your computer. You should see GRUB, after picking your OS you will be asked for the passphrase for your LUKS container, and after that your old system should boot normally.
Footnotes:
- To my knowledge, it’s not possible to have the EFI partition encrypted as well.
- I don’t remember if that was really necessary, and I don’t have the setup to test it anymore.
- If you’re interested in some discussion about the
bs
parameter, you can check out this. - Oh no, cargo culting! …But I really don’t wanna spend more time on this (I spent a lot already), to see if the OS wouldn’t boot without the flags.
- I got this trick from here