In this tutorial, I’ll show you how to install Arch Linux but with an encrypted rootfs (/) and with a bootloader-less setup (direct UEFI boot)
- Networking access
- Machine MUST support UEFI (non-secured mode)
- You have some knowledge about how things work (partitioning, UEFI, bootloader, …), you’re an Arch Linux user after all.
- UEFI boot will save you some precious boot time… meanwhile it will be a pain to fix if something goes wrong and render your machine unbootable (bad kernel/initramfs).
- If you’re using more than 1 OS, I’d recommend you to just stick with good-ol’ GRUB bootloader.
- You must disable the secure boot mode of the UEFI because the kernel file is unsigned, you could sign it after the setup is done and then enable secure boot again.
1. Booting into Live Arch Linux
Nothing special, just create a bootable media from Arch Linux ISO and then boot it, if you see a different menu than this with a fancy Arch Linux logo (GRUB menu) then your machine isn’t booted by using UEFI or something goes wrong while you create the boot media, try again until you see such similar menu as above.
Select Arch Linux archiso x86_64 UEFI CD
Here you have the Arch Linux Live running on your PC, this is how the disk is configured on my PC, there’s only 1 20GB physical disk which is sda and it’s totally empty (no partition).
Starting off by partitioning the disk with
Chose GPT here, I don’t know if UEFI will boot with DOS or other kinds of partition table or not but just chose GPT
Create partition as above. Here I have 512MB partition #1 which we will use it for /boot to store the kernel and initramfs, the total of it will be just around 50MB so you could create as low as somewhere 80MB but I want to leave some extra space for backup/alternative kernel and such. The second partition will be for LUKS encrypted rootfs so it will take up the rest.
You need to create a separated /boot partition for UEFI to boot the kernel because UEFI don’t understand what LUKS is thus it can’t be merged into rootfs
Do not create another partition for SWAP because it will be unencrypted, create SWAP as a file later on the encrypted rootfs if you want to use SWAP
Write to the disk and exit cfdisk.
Now we need to turn /dev/sda2 into a LUKS container by
cryptsetup luksFormat /dev/sda2
Open (decrypt) the LUKS container with
cryptsetup open /dev/sda2 new_rootfs
This is how LUKS works: It reads the encrypted data (raw disk format) on your block disk, decrypts it and put it to a virtual block device at /dev/mapper/ so you need to interacts with the virtual block device and not the real block device itself (which containing LUKS). Here I have the decrypted virtual block device at /dev/mapper/new_rootfs
Now we need to format it, it’s necessary for the /boot partition to be FAT32 for UEFI to read it so we need to format /dev/sda1 with
mkfs.vfat -F32 /dev/sda1
And the decrypted sda2 block device (located at /dev/mapper/new_rootfs) which will contain the rootfs, you can use whatever the filesystem you like, as long as you add the necessary module to the kernel initramfs.
Here notices: You need to mount the rootfs first because we will need to mount the /boot over /mnt/boot and it doesn’t make sense if you do it in reverse, the /boot will get ignored and nothing will write to it if you do it in reverse
Start by mounting rootfs:
mount /dev/mapper/new_rootfs /mnt
Create the /boot directory on the rootfs:
Mount sda1 into the /mnt/boot so the pacstrap could install kernel into it:
mount /dev/sda1 /mnt/boot
That’s it for the partition setup, now we will continue the next step on the actual Arch Linux installation.
2. Arch Linux Setup
This step is fairly simple, just do install as you would do it with normal Arch Linux installation with /mnt as rootfs
Starting with installing the base, you could add more package after base-devel if you’d like but here’s the basic.
pacstrap /mnt base base-devel linux
500KB/s??? Pacstrap is dumb and sometimes it cannot figure out what’s the best mirror to download from so here’s how you could manually select the nearest mirror:
Edit the file /etc/pacman.d/mirrorlist and delete every other mirror except the closest one to you, I’m in Vietnam so here I kept the Vietnamese mirror and delete the rest.
Save it, run pacstrap again, see how fast it is now?
Wait for the pacstrap to complete and then generate fstab file with:
genfstab -U /mnt >> /mnt/etc/fstab
Now check if the fstab has properly generated, it must have the rootfs (/) and the /boot in there, these 2 should have been added automatically by genfstab but if it doesn’t, either you’ve done something wrong with the mounting step or genfstab is broken, try to add it manually.
I’d recommend using UUID when interacting with fstab to prevent unexpected behavior
Here you have to chroot into the installed rootfs, what is chroot? It allows you to “join” into the installed rootfs environment as you were booted into it, meanwhile, the kernel still is from the host (Arch Linux Live), all the changes you made in here will be saved into your final installation disk (/dev/mapper/new_rootfs).
Chroot into the installed directory with
Now when you’re inside the chroot, declaring the language and generate the locale with
echo LANG=en_US.UTF-8 > /etc/locale.conf echo "en_US.UTF-8 UTF-8" > /etc/locale.gen locale-gen
I only do 1 step of adding locale because I’ve forgotten the rest when taking screenshots for this tutorial. You could set up the Desktop environment and install things here if you like, I’ll skip it because that’s not what this tutorial is for.
Now the important step: While in chroot, edit the file /etc/mkinitcpio.conf and add encrypt to HOOKS as the picture above.
You will need to add keymap before the encrypt if you want to use keymap other than the US standard keymap.
Save the mkinitcpio.conf and to the next step
Now you will need to regenerate the initramfs for the kernel to be able to decrypt the encrypted rootfs with the added encrypt module.
First, check your installed kernel version with
You can see the only installed kernel is 4.19.2-arch1-1-ARCH (ignore the extramodules-ARCH)
NOTE: Do not use uname -r to check for kernel version here, this command will return the current kernel which is used to boot and it’s from Arch Linux Live, it may or may not be the same version as the kernel which you’ve installed to the rootfs
Get the name of the install kernel in /boot (vmlinuz-* for the kernel, initramfs-*.img for the initramfs) for use in the next step, if you use other kernels like Zen then the name will be different
Generate new initramfs with
mkinitcpio -g /boot/initramfs-linux.img -k 4.19.2-arch1-1-ARCH
Modify the command as needed
Now exit from chroot to the Arch Linux Live, I’m paranoid here so I’ve done another sync to make sure everything was flushed down the disk and then reboot, continue to boot with the Arch Linux bootable media.
3. Configure EFI to boot the kernel
In the Arch Linux boot menu, chose UEFI Shell x86_64 v2 this time to get into the EFI Shell
Here’s how the EFI Shell looks like, you could press ESC to skip startup.nsh if you’ve configured it to boot something else.
Here types map to see which partition the EFI has recognized, it’s kinda similar to Linux, here I have FS0 and FS1
Use ls fsX: (with X is the FS# from the mapping table above)
What you’re trying to find here is the partition which contains the kernel files (/boot)
Here we found that the fs0 is the one that we need, it has vmlinuz and initramfs
We need to add a new boot entry at 0 points to vmlinuz-linux so it will get booted first with the command:
bcfg boot add 0 fs0:\vmlinuz-linux "Arch Linux"
Now create a new text file for storing the cmdline for the kernel with
Here you put the necessary kernel cmdline to boot your rootfs, in this example we have
cryptdevice=/dev/sda2:new_rootfs root=/dev/mapper/new_rootfs rw initrd=\initramfs-linux.img
NOTICE: Add extra spaces at the beginning of the line in the file. There is a byte order mark at the beginning of the line that will squash any character next to it which will cause an error when booting.
If you use SSD for rootfs, you could add a flag to allow discarding on LUKS encrypted drive with :allow-discards added after the cryptdevice, it will becomes cryptdevice=/dev/sda2:new_rootfs:allow-discards
If you want to use intel-ucode, you need to add an extra initrd before the actual linux initramfs, it will be something like this:
cryptdevice=/dev/sda2:new_rootfs root=/dev/mapper/new_rootfs rw initrd=\intel-ucode.img initrd=\initramfs-linux.img
Press F2 to save and then F3 to exit.
Now insert the cmdline to the boot entry #0 with
bcfg boot -opt 0 fs0:\cmdline.txt
reboot your machine with reset, now you don’t need the Arch Linux bootable media anymore, you could pull it out and let your machine boot normally.
Here you can see it’s booting and the kernel asked you to typing password for unlocking the rootfs
That’s it, that’s how you configure your machine to boot the kernel with UEFI meanwhile use LUKS for the rootfs. Comment below if you have any questions or stuck on somewhere along the line.