Installing ArchLinux with LVM on LUKS on a BIOS/GPT system with boot encryption. # Keyboard ``` loadkeys fr ``` List available fonts with `ls /usr/share/kbd/keymaps/**/*.map.gz`. # Fonts Do yourself a favour: increase the terminal font for visual comfort ;-) ``` setfont ter-124b ``` List available fonts with `ls /usr/share/kbd/consolefonts/`. # Boot mode Remember this guide is for BIOS boot firmware. As there are minor divergences with UEFI during partitioning and bootloader configuration. Check whether this guide is suited for you: ``` cat /sys/firmware/efi/fw_platform_size # BIOS => "No such file or directory" # UEFI => "32" or "64" ``` If the command returns an error ("No such file or directory"): your system booted in BIOS (or CSM; Compatibility Support Mode). Otherwise, if it returns `64` (or `32`): your system booted in UEFI 64-bit x64 (or 32-bit IA32), and you should not use that guide. # Connect to the network If the machine is not plugged to ethernet, connect using Wi-Fi: ``` ip a # identify your wireless card (usually wlan0) iwctl station wlan0 scan station wlan0 connect exit ``` Check your connection with: ``` ping -c 3 1.1.1.1 ``` If that last command returns time latencies, you are all set. # Partitioning We want LVM on LUKS. That means a layer of encryption (LUKS) will reside between LVM and the physical drive. It is better to have LVM **inside** the LUKS encryption[source](blank). (But it is more common to say LVM **on** LUKS.) {{ :install_archlinux_with_lvm_on_luks_bios:layers.png?nolink&600 |}} Steps will be as follow: - Safe (and long) disk wipe - Physical partitioning - (almost) full disk encryption - LVM partitioning Identify the drive you want to install the OS on. (Usually `/dev/sda` if you have only one drive connected to the motherboard.) ``` lsblk ``` We will assume the drive to be `/dev/sdz`. Change it accordingly. ## Safe (and long) disk wipe Before encryption, the disk is wiped and populated with random data (see why/how [here](blank)). ``` cryptsetup benchmark # if you want to chose the fastest algorithm (aes-xts for now) ALGO="aes-xts-plain64" cryptsetup open --type plain --cipher "$ALGO" -d /dev/urandom /dev/sdz to_be_wiped # hard drive points to 'to_be_wiped' lsblk # you should see the drive 'to_be_wiped' dd if=/dev/zero of=/dev/mapper/to_be_wiped status=progress # no need for /dev/urandom here, cryptsetup acts as a layer of randomness (see above command) ``` Time for coffee(s) ☕. Duration depends on speed and hard drive size. It took me 2 hours 15 minutes for 240G at ~35MB/s mean speed. ``` cryptsetup close to_be_wiped ``` ## Physical partitioning There are differences between GPT and MBR partition table layouts. To keep it short, you'll probably want GPT over MBR[1](https://wiki.manjaro.org/index.php/Some_basics_of_MBR_v/s_GPT_and_BIOS_v/s_UEFI#MBR). With BIOS/GPT, a BIOS boot partition is required (this is where GRUB embeds its `core.img`). ``` cfdisk /dev/sdz ``` Delete (``) every pre-existing partition. Create a `` primary partition of size `1M`. Set its type to `BIOS boot`. It is going to be unencrypted (BIOS boot) and will be used to store the second stage of BIOS bootloader. Use remaining `` as a `` primary partition. Set its type to `Linux LUKS` if available, else to `Linux filesystem`. Select `` to apply changes to disk. Then `` to exit `cfdisk`. Our drive is "physically" split in two: * `/dev/sdz1`: BIOS boot partition * `/dev/sdz2`: where LUKS, LVM and our system are going to stay ## (almost) full disk encryption Let's encrypt `/dev/sdz2`. As we want boot encryption, we will use LUKS1 instead of LUKS2. That is because GRUB knows how to proceed with decryption only with the former during bootload. | IMPORTANT NOTE | |:---------------------------| | You really should read this if you don't use a QWERTY layout. Indeed, the keyboard layout will by default be "us" (QWERTY) when GRUB will first ask us to decrypt our `/boot` partition at startup. There is little documentation on how to succeed and when it exists, it is either outdated or misleading. I really felt hit by a nerd snipper trying to solve that issue... A workaround is to type your passphrase as if it was typed on a QWERTY keyboard. If you have any info on how to solve this please tell me.| ``` cryptsetup luksFormat --type luks1 /dev/sdz2 # BEFORE typing your secure passphrase READ ABOVE ``` After initializing the LUKS partition, let's open it and map it to a name (`cryptlvm` here): ``` cryptsetup open /dev/sdz2 cryptlvm # open LUKS partition and map it to "cryptlvm" # type secure passphrase to decrypt ``` ## LVM partitioning Prepare logical volumes: ``` pvcreate /dev/mapper/cryptlvm # create a physical volume on top of the opened LUKS container vgcreate vg-arch /dev/mapper/cryptlvm # create a volume group (named here "vg-arch") lvcreate -L 8G vg-arch -n swap lvcreate -L 60G vg-arch -n root lvcreate -l 100%FREE vg-arch -n home ``` Format : ``` mkfs.ext4 /dev/vg-arch/root mkfs.ext4 /dev/vg-arch/home mkswap /dev/vg-arch/swap ``` Mount : ``` mount /dev/vg-arch/root /mnt mount --mkdir /dev/vg-arch/home /mnt/home swapon /dev/vg-arch/swap ``` # Install Partitioning is finally done. Let's install basic programs and write the partition table to our future system `fstab`: ``` pacstrap -K /mnt base base-devel linux linux-firmware neovim lvm2 grub git sudo openssh mkinitcpio dhcpcd iwd # my usual programs genfstab -U /mnt >> /mnt/etc/fstab ``` It's time to enter our new system: ``` arch-chroot /mnt ``` Set time: ``` ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime hwclock --systohc ``` Set locales. Edit `/etc/locale.gen` and uncomment `en_US.UTF-8 UTF-8` and/or other needed locales (e.g. `fr_FR.UTF-8 UTF-8`. ``` locale-gen ``` Create the `/etc/locale.conf` file and set the LANG variable: ``` LANG=en_US.UTF-8 ``` Set keymap. Set the console `/etc/vconsole.conf` for keyboard layout: ``` KEYMAP=fr ``` Set hostname. Create `/etc/hostname` file: ``` desired-hostname ``` Set the initramfs. Edit `/etc/mkinitcpio.conf`: ``` HOOKS=(base udev autodetect modconf kms keyboard keymap consolefont block encrypt lvm2 filesystems fsck) ``` ## Bootloader (GRUB) Configure GRUB to allow booting from `/boot` on a LUKS1 encrypted partition. Edit `/etc/default/grub` so it contains those lines: ``` GRUB_CMDLINE_LINUX="... cryptdevice=UUID=:cryptlvm ..." GRUB_ENABLE_CRYPTODISK=y ``` The first line sets the kernel parameters so the initramfs can unlock the encrypted root partition, using the `encrypt` hook. The `` is the one of the LUKS superblock (the big partition) (in this example /dev/sdz2). To find UUID : `blkid` for GPT (else `lsblk -f`). ``` grub-install --target=i386-pc --recheck /dev/sdz ``` Grub will be splitted on the boot loader partition as well as on the `/boot` partition of our encrypted filesystem. Generate GRUB's config file: ``` grub-mkconfig -o /boot/grub/grub.cfg ``` Regenerate the initramfs: ``` mkinitcpio -P ``` This is it. Everything should be fine. # Enter your passphrase once, not twice As boot and root are on the same partition you will be asked twice for your passphrase at startup. The first time, GRUB asks for the passphrase to decrypt the boot partition. The second time, it is the encrypt hook which asks you for the root partition's passphrase. If you do not want to be asked for your root partition password again, you will have to embed a keyfile in the initramfs and configure it to be used on system boot to decrypt and mount the root partition [source](https://bbs.archlinux.org/viewtopic.php?id=243152). So, when booting your system, GRUB will ask you to decrypt your `/boot` partition (remember the keyboard will be in QWERTY layout), then, the encrypt hook will ask you to decrypt the `root` partition. We will indeed avoid that by creating a keyfile. It will be read after boot decryption and used to decrypt the `root` partition in the mean time. Let's first create a keyfile and add it as LUKS key: ``` dd bs=512 count=4 if=/dev/random of=/root/cryptlvm.keyfile iflag=fullblock chmod 000 /root/cryptlvm.keyfile cryptsetup -v luksAddKey /dev/sdz2 /root/cryptlvm.keyfile ``` Add the keyfile to the initramfs image via `/etc/mkinitcpio.conf`: ``` FILES=(/root/cryptlvm.keyfile) ``` Recreate the initramfs image and secure the embedded keyfile: ``` mkinitcpio -P chmod 600 /boot/initramfs-linux* ``` Set the following kernel parameters to unlock the LUKS partition with the keyfile. Using the encrypt hook: ``` GRUB_CMDLINE_LINUX="... cryptkey=rootfs:/root/cryptlvm.keyfile" ``` Recreate `grub.cfg`: ``` grub-mkconfig -o /boot/grub/grub.cfg ``` If for some reason the keyfile fails to unlock the boot partition, systemd will fallback to ask for a passphrase to unlock and, in case that is correct, continue booting. # Exit to your system Congratulations! You can leave the installation medium to dive into your new system: ``` exit umount -R /mnt cryptsetup close cryptlvm reboot # remove USB key ``` Enjoy