This article is not officially supported.
The Arch Linux community does not offer support for the information contained in this page; for installation procedures, the Installation guide is the only officially supported document. The content below is mainly maintained by User:ZachHilman, who last reviewed it on 27 October 2022, and it may be out of date or inaccurate.
Secure Arch Linux setup for a new computer combining Btrfs for the root filesystem, LUKS2 (as opposed to LUKS1) for encryption (this is to allow enrolling a TPM2 into a keyslot), Secure Boot (using sbctl), along with plymouth-gitAUR for a nice boot animation, (optional) TPM2 key enrollment with a PIN instead of entering a password, an encrypted swap partition as opposed to a swapfile, and boot from a Unified kernel image as opposed to GRUB or another traditional bootloader.
I haven't fully evaluated this setup yet, but have successfully installed it twice (in a VM and on hardware). I created this guide due to the lack of single guide combining all of the things I wanted. Any comments appreciated! I try to explain decisions and commands in the guide, but make sure you understand what you run and why. I take no responsibility for insecure or damaged systems.
This guide is inspired by and/or uses steps from:
Identify Drive and Secure Erase
Follow the standard installation guide up to the point where partitioning begins. You will need an internet connection and may want to set up SSH into the install disk so you can use copy/paste and other niceties from a 2nd computer, but it is not required.
(Optional) Secure Erase Disk
Identify the drive you want to install on:
Dual-booting or multiple OS on a single drive is out of scope of this guide. We are going to completely erase this disk, so make sure there isn't anything important on it.
For the rest of this section, '*DRIVE*' refers to your selected disk from the last step (i.e. '/dev/sda' or '/dev/nvme0n1'
Open a plain encrypted container (with random key) over the entire target drive:
cryptsetup open --type plain *DRIVE* container --key-file /dev/urandom
Make sure the container mounted properly, you should see a disk for '/dev/mapper/container'
Zero Out the encrypted container. Because of the encryption layer, this will be pseudorandom bits on the actual disk, and because of the random key it will not be possible to determine the pattern here.
dd if=/dev/zero of=/dev/mapper/container status=progress bs=1M
Close the encrypted container
cryptsetup close container
Partition Drive, Encryption, and Filesystems
Optional, but just to ensure no remnants of the secure erase mess anything up, zap the drive
sgdisk --zap-all *DRIVE*
Now do the actual partitioning. You can adjust the sizes of the EFI partition (though at least 300 MB is recommended) and the swap partition (if you have a lot of storage, RAM size + 2GB is good). We are naming drives here so we can use the names instead of potentially volatile names like '/dev/sda'.
sgdisk --clear --new=1:0:+512MiB --typecode=1:ef00 --change-name=1:EFI --new=2:0:+16GiB --typecode=2:8200 --change-name=2:cryptswap --new=3:0:0 --typecode=3:8300 --change-name=3:cryptsystem *DRIVE*
Verify that the partitions are set up properly
Create the encrypted system partition. Note that we explicitly specify LUKS2 as well as our encryption parameters.
cryptsetup luksFormat --type luks2 --align-payload=8192 -s 256 -c aes-xts-plain64 /dev/disk/by-partlabel/cryptsystem
Open the new encrypted system partition.
cryptsetup open /dev/disk/by-partlabel/cryptsystem system
Open an encrypted swap container, using a random key.
cryptsetup open --type plain --key-file /dev/urandom /dev/disk/by-partlabel/cryptswap swap
Make swap partition
mkswap -L swap /dev/mapper/swap
Mount swap partition
swapon -L swap
Create the filesystem
mkfs.btrfs --label system /dev/mapper/system
Mount at root
mount -t btrfs LABEL=system /mnt
Create the root subvolume (this will be '/' on the final system)
btrfs subvolume create /mnt/@root
Create the home directory subvolume (this will hold all user data)
btrfs subvolume create /mnt/@home
Create a subvolume for snapshot storage
btrfs subvolume create /mnt/@snapshots
Unmount root so we can change mount options
umount -R /mnt
Remount the root subvolume with options. The compression here is optional, zstd offers the best storage but you may prefer a different algorithm for speed, or omit entirely. Only use ssd if you are on an SSD. You can also enable atime if desired, but it comes with overhead.
mount -t btrfs -o defaults,x-mount.mkdir,compress=zstd,ssd,noatime,subvol=@root LABEL=system /mnt
Mount the home subvolume (same deal with options as previous step)
mount -t btrfs -o defaults,x-mount.mkdir,compress=zstd,ssd,noatime,subvol=@home LABEL=system /mnt/home
Mount the snapshots volume to '/.snapshots' (same deal with options as previous step)
mount -t btrfs -o defaults,x-mount.mkdir,compress=zstd,ssd,noatime,subvol=@snapshots LABEL=system /mnt/.snapshots
EFI System Partition
Format the partition as FAT-32, with label 'EFI'
mkfs.fat -F32 -n EFI /dev/disk/by-partlabel/EFI
Make the mount directory
Mount the ESP
mount LABEL=EFI /mnt/efi
Install Base System
Bootstrap the base system. You can substitute a different kernel here if desired.
pacstrap /mnt base linux linux-firmware
Generate the filesystem table. Unlike the default installation guide, we choose to use labels instead of UUIDs for mounts.
genfstab -L -p /mnt >> /mnt/etc/fstab
We need to edit the fstab to ensure the swap gets mounted correctly. Open the file '/mnt/etc/fstab' and replace 'LABEL=swap' with '/dev/mapper/swap'.
With that change, the kernel will expect an opened encrypted container called swap, so add the following to the file '/mnt/etc/crypttab' to have it opened on boot.
swap /dev/disk/by-partlabel/cryptswap /dev/urandom swap,offset=2048,cipher=aes-xts-plain64,size=256
Note that this will generate a random key every boot, so swap will not be persistent. This has implications on hibernation, so be aware.
Change root into the new system
Set Timezone (you can 'ls /usr/share/zoneinfo' to see options)
ln -sf /usr/share/zoneinfo/*FILL IN*/*FILL IN* /etc/localtime
Set hardware clock offset
Edit the file '/etc/locale.gen' with the locales you want available
Create the locales
Edit '/etc/locale.conf', add the line below with your chosen locale
Set your hostname by editing '/etc/hostname'
Install More Packages
pacman -Syu networkmanager base-devel btrfs-progs gptfdisk nano zsh sudo ttf-dejavu sbctl *intel or amd depending*-ucode polkit
Make sure to select the right microcode package for your architecture
Unified Kernel Image Setup
Edit the HOOKS for mkinitcpio. Replace the HOOKS= line with
HOOKS=(base systemd sd-plymouth modconf keyboard block filesystems btrfs sd-encrypt fsck)
We are switching from busybox-based init to systemd, as it is required in order for plymouth to work with the way we are doing encryption. We also add the btrfs hook, and the encryption hook so our system will get loaded.
Set the kernel parameters by copying the following into '/etc/kernel/cmdline'
fbcon=nodefer rw rd.luks.allow-discards quiet bgrt_disable root=LABEL=system rootflags=subvol=@root,rw splash vt.global_cursor_default=0
We set the options to load the encrypted root, hide extra logging, and load plymouth for the splash screen.
Add the following line into the (new) file '/etc/crypttab.initramfs'. This is like the crypttab, but gets loaded early in boot, so we can use it to load our encrypted system.
system /dev/disk/by-partlabel/cryptsystem none timeout=180,tpm2-device=auto
Notice the 'tpm2-device=auto'. If you don't have a TPM2 or don't want it used to unlock your drive, remove that part and the trailing comma.
Create secure boot keys
Generate the signed Unified Kernel Image bundle
sbctl bundle -s /efi/main.efi
If this doesn't work because of a 'missing EFI system partition', that's likely because of the chroot operation. In that case, prefix the command with 'ESP_PATH=/efi' and run again. As long as there is a file called main.efi in the directory `/efi` it's good for now.
Add UEFI boot entry for the unified kernel image
efibootmgr --create --disk *DRIVE* --part *PARTITION NUMBER* --label "Linux" --loader 'main.efi' --unicode
(Tip: Use 'fdisk -l' to verify drive/partition number)
Set root password
Create an admin user account. You probably want this anyway, and we need one to build an AUR package (makepkg doesn't like root)
useradd -m -G wheel,storage,power -g users -s/usr/bin/zsh *USERNAME*
Set the new user password
Enable sudo access for the wheel group with password. Look for and uncomment the desired like in '/etc/sudoers'
Start shell as the new user
sudo -u *USERNAME* -i
Create a build directory
mkdir Build && cd Build
Clone auraAUR, and AUR helper. Not strictly required, but it's convenient for updating AUR packages in the future. You can alternatively just install plymouth-gitAUR directly.
git clone https://aur.archlinux.org/aura.git
cd aura && makepkg -is
Remove the temp directory. Aura will update itself when running 'aura -Au'
cd .. && rm -rf aura
Exit the sudo impersonation
Install plymouth-gitAUR, a splash screen program
aura -Ax plymouth-git
Set the default theme and rebuild the initramfs
plymouth-set-default-theme -R spinner
Regenerate the unified kernel image and sign it
sbctl generate-bundles -s
This stop is OPTIONAL. Doing do allows the TPM2 chip of your device to unlock the root partition. Here, this is configured with a PIN (letters/numbers validated by TPM) and set to reject changes to the system configuration. Be sure you understand the security implications of this, and possibly set a dictionary lockout (i.e. too many tries must wait a day) on the PIN
There should only be one, otherwise you need to figure out which is the main one and/or pick
systemd-cryptentoll --tpm2-device=*DEVICE FROM LAST STEP* --tpm2-pcrs=0+7 --tpm2-with-pin=yes /dev/disk/by-partlabel/cryptsystem
Reboot into system
Reboot the system into UEFI setup. Enable 'Setup Mode' in secure boot settings. MAKE SURE you understand the implications of this, and check to make sure it is safe for your device. Some laptops have been bricked erasing the default keys.
Once booted, login and enroll the secure boot keys. THIS CAN BRICK YOUR DEVICE. On some systems, OpROMs (Option ROMs, essentially UEFI-level device drivers) may be present and required, which have to be signed with secure boot to work. If you do this improperly, the device WILL BE BRICKED. For more information, see sbctl's man pages. ONLY RUN THE FOLLOWING IF YOU KNOW WHAT YOU ARE DOING
Enable NTP Time
timedatectl set-ntp true
If you have any comments, please don't hesitate. Hope this worked well for you and you can use a modern encrypted install.