Full Disk Encryption on Arch Linux: NVMe, GRUB2, LVM and LUKS

Last week I had to install my new work computer. Although I am a Debian guy, I thought I should give a chance to Arch Linux as well.
In theory full disk encryption and Linux is not a big deal (there's a lot of documentation out there) and it should be pretty straight forward. In practice, probably because it was the first time doing it on Arch, it took me some time to figure it out how to do it right.

My biggest problem was that the current version of grub shipped with Arch doesn't include support the following combination: NVMe, LVM, LUKS. Apparently the git version has the fix for that issue.

So here is what I did (This post comes without warranty of any kind! I do not issue any guarantee that this will work for you!)

  • Partition the disk - no Windows, no UEFI needed, my disk is only 256G and I will need only one primary partition so... there is no reason to use GPT.
parted -a optimal -s /dev/nvme0n1 mklabel msdos
parted -s /dev/nvme0n1 mkpart primary 2048s 100%
  • Encrypt the newly created partition
cryptsetup luksFormat /dev/nvme0n1p1
cryptsetup luksOpen /dev/nvme0n1p1 disk
  • Setup logical volumes
pvcreate /dev/mapper/disk
vgcreate vg0 /dev/mapper/disk
lvcreate -L 32G vg0 -n swap
lvcreate -L 15G vg0 -n root
lvcreate -l +100%FREE vg0 -n home
  • Create filesystem
mkswap -L swap /dev/vg0/swap
mkfs.ext4 /dev/vg0/root
mkfs.ext4 /dev/vg0/home
  • Mount the partitions
mount /dev/vg0/root /mnt
mkdir -vp /mnt/home
mount /dev/vg0/home /mnt/home
  • Set mirror list
pacman -Sy
pacman -S pacman-contrib
cd /etc/pacman.d/
wget "archlinux.org/mirrorlist/?country=SE" -O mirrorlist.b
sed -i 's/^#//' mirrorlist.b
rankmirrors -n 3 mirrorlist.b > mirrorlist
  • Install base system
pacstrap /mnt base base-devel vim less dhclient
genfstab -p -U /mnt > /mnt/etc/fstab
  • Chroot time!
arch-chroot /mnt /bin/bash
  • Localization
echo "en_US.UTF-8 UTF-8" > /etc/locale.gen
export LANG=en_US.UTF-8
echo LANG=en_US.UTF-8 > /etc/locale.conf
rm -f /etc/localtime
ln -s /usr/share/zoneinfo/Europe/Stockholm /etc/localtime
hwclock --systohc --utc
  • Set the hostname
echo jonas > /etc/hostname
vim /etc/hosts
...	localhost.localdomain	localhost jonas
::1		localhost.localdomain	localhost jonas
  • Install various packages
pacman -S wget
  • Identify the network card and enable dhcp client
ip link
systemctl enable dhcpcd@<interface>.service
systemctl enable dhcpcd.service
  • Add a new user
useradd -m -g users -s /bin/bash jonas
passwd jonas
 ## User privilege specification
 root ALL=(ALL) ALL
 jonas ALL=(ALL) ALL
  • Set the root password
  • Create a key so I won't enter the LUKS passphrase twice
dd if=/dev/urandom of=/crypto_keyfile.bin bs=512 count=4
cryptsetup luksAddKey /dev/nvme0n1p1 /crypto_keyfile.bin
  • Create the initial ramdisk environment
vim /etc/mkinitcpio.conf
HOOKS="base udev autodetect modconf block encrypt lvm2 resume filesystems keyboard fsck"
mkinitcpio -p linux
  • The current version of grub shipped with Arch doesn't include support for NVMe, but grub-git it seems it does
vim /etc/pacman.conf
SigLevel = Optional TrustAll
Server = http://repo.archlinux.fr/$arch
pacman -Syu
pacman -S yaourt
# required packages to build grub-git
pacman -S git rsync freetype2 ttf-dejavu python autogen help2man fuse
su -l jonas
# add unifont gpg key (more details here[1])
export KEY="1A09227B1F435A33"
gpg --recv-keys $KEY
gpg --edit-key $KEY
# install grub-git (please note that you will need at least 2G available on your /tmp)
yaourt -S grub-git
  • We don't need to be "jonas" anymore
  • Now that we have grub installed, let's configure and install it
vim /etc/default/grub
grub-mkconfig -o /boot/grub/grub.cfg
grub-install /dev/nvme0n1
  • Security considerations
chmod 000 /crypto_keyfile.bin
chmod -R g-rwx,o-rwx /boot
  • Done!

[1]: https://bbs.archlinux.org/viewtopic.php?pid=1488734#p1488734

One thought on “Full Disk Encryption on Arch Linux: NVMe, GRUB2, LVM and LUKS”

  1. Bit late to the party, just leaving this here in case anyone runs this and encounters issues with the bootloader like I did.
    Instead of using yaourt, I ended up installing git, cloning the grub-git package from the AUR, makepkg and installing it. Once that was done I had to:
    exit chroot
    mkdir /mnt/hostrun
    mount –bind /run /mnt/hostrun
    arch-chroot /mnt /bin/bash
    mkdir /run/lvm
    mount –bind /hostrun/lvm /run/lvm

    then I was able to:

    grub-mkconfig -o /boot/grub/grub.cfg
    grub-install –target=i386-pc /dev/sdx

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.