Arch Linux Laptop Setup
PURPOSE
These are my instructions for setting up an Arch Linux laptop. I have just purchased a Lenovo ThinkPad X1 Carbon, 11th Generation laptop, which arrived after a little more than two weeks. This laptop has a 13th generation Intel EVO vPRO CPU (Core i7-1370P), 64GiB RAM, and 2TiB NVMe SSD. It will also have a TPM2 chip. I will also repeat and refine these instructions for my aged Lenovo ThinkPad 25th Anniversary Edition, which also has a TPM2 chip in it, with 32GiB RAM and a 512GiB NVMe SSD.
These instructions will set up the following:
- encrypted root (using TPM2 chip)
- note: EFI partition will not be encrypted
- Unified Kernel Images (UKIs) with Secure Boot
- A Btrfs filesystem with root and home as subvolumes of the top-level top subvolume
- If desired, another filesystem can be used instead. Partition and format the disk(s) accordingly. I chose Btrfs for its snapshot capability (I will use snapper to manage my snapshots after the laptop is set up)
- systemd-boot as the bootloader
- systemd-homed for user home directory management
The intention is to document the entire installation process, using the standard Arch Linux installation instructions tailored for this purpose. The goal is to have this be repeatable.
NOTE: This document is a work in progress. Once I'm able to follow it with my new laptop, I will document any missed steps or gotchas I encounter along the way, and hopefully how I fix them.
CAVEAT LECTOR (Reader BEWARE): This guide is only ONE way to install Arch on a laptop. Do NOT blindly follow ANYTHING in this guide, mostly because if a lot of time has passed since this article was published the official Arch Installation Guide has likely evolved beyond the steps delineated here. Make sure you understand each and every command before you execute them. If there's something you don't understand, read the excellent Arch Manual Pages for the specific command, and also try to find the corresponding Arch Wiki article describing full details and alternatives (I try to link back to the Wiki several times throughout this article). Also note, this does not guarantee security of the target laptop, there may be latent, glaring deficiencies I have yet to identify. If you blindly follow these commands, and do not understand the why behind the decisions I've made (for myself, the primary intended audience of this article), you WILL NOT be supportable by the wider Arch Linux community (forums and IRC). I can offer assistance where I can, but my time is limited, and due to life I don't frequent the places Archers find help as much as I used to.
Possible Gaps in this document
- since I haven't used UKI with systemd-boot and Secure Boot, I'm not sure if the kernel cmdline will be protected
- I'll have to see if editing the cmdline at all before booting is possible
- possibly look into systemd-boot-password, but this package hasn't been updated since 2018
- this package may have been originally intended to be rolled into systemd
- but I can't find anything on the systemd site which mentions setting a boot password
- ANSWER With Secure Boot enabled, the kernel cmdline will not be editable with systemd-boot. So, to enter single user mode, I will likely need to disable Secure Boot (Reset to Setup Mode), boot from the Arch ISO, and perform whatever maintenance I need to do. See the notes on the Systemd-boot#Adding_loaders and UKI Booting Wiki articles which are the only places I could find this documented anywhere. Another thing: no boot menu beyond the UEFI firmware splash screen and prompts even shows with my UKI+SecureBoot setup; even though I have systemd-boot installed, it's not really used (unless the UEFI firmware doesn't find a kernel to boot).
- I mention setting UEFI BIOS passwords, but these may be defeatable through a physical attack on ThinkPads. I'm not sure if the X1 Carbon or 25th Anniversary (20K7) are susceptible to this, but it's something to keep in mind.
- The Hardware Maintenance Manuals (HMMs, can't copy direct links to them from the Lenovo site) for both of my ThinkPads state the following,"Attention: If the supervisor password has been forgotten and cannot be made available to the service technician, there is no service procedure to reset the password. The system board must be replaced for a scheduled fee."
- so, not even a depot technician can reset the password, suggesting that a simple screwdriver used to short a couple of pins won't work.
- The Hardware Maintenance Manuals (HMMs, can't copy direct links to them from the Lenovo site) for both of my ThinkPads state the following,"Attention: If the supervisor password has been forgotten and cannot be made available to the service technician, there is no service procedure to reset the password. The system board must be replaced for a scheduled fee."
- I read about a new attack called LogoFAIL, a particularly nasty image-processing vulnerability that could allow an attacker to install a maliciously crafted UEFI/BIOS logo image to the ESP to bypass the Secure Boot protections and execute arbitrary code.
- I can mitigate this to an extent by setting a UEFI BIOS password that needs to be entered in order to change the boot device (in order to boot off of USB or other medium)
- But this doesn't prevent a physical attacker removing the SSD, installing the malicious crafted image, and putting it back in my system
- I'll have to look into whether my X1 Carbon has a way to determine if the chassis has been opened, and not boot if it has (have to enter the UEFI supervisor password)
- Oh, beautiful! I used the Lenovo UEFI Simulator (see below) to determine there is a feature that the laptop can determine if the chassis has been tampered with, and require the supervisor password to boot if it has. Neat!
- I think this is an acceptable mitigation
- Oh, beautiful! I used the Lenovo UEFI Simulator (see below) to determine there is a feature that the laptop can determine if the chassis has been tampered with, and require the supervisor password to boot if it has. Neat!
- Lenovo released a firmware update, and included both my 25th Anniversary ThinkPad/20K7, and the new X1 Carbon.
- I was able to apply the new UEFI firmware with fwupd to my ThinkPad 25/20K7
- I suspect the process will be nearly identical for the X1 Carbon
- I'll be putting instructions for fwupd below, after first boot
- I can mitigate this to an extent by setting a UEFI BIOS password that needs to be entered in order to change the boot device (in order to boot off of USB or other medium)
- These instructions assume the system administrator only wants to install Arch Linux as the only operating system. If you intend to dual boot into another operating system (e.g. Windows, another Linux distribution, etc.), these instructions must be carefully adapted for that purpose. Especially with Windows, great care must be taken to avoid Windows making other operating systems unbootable, an exercise I am not interested in going through.
PREREQUISITES
- a laptop containing:
- Unified Extensible Firmware Interface Basic Input/Output System (UEFI BIOS, required for UKI)
- x86_64/amd64 CPU (Arch only supports this architecture)
- 1GiB RAM (necessary for installation, though Arch can run with 512MiB RAM)
- NVMe standard v1.4+ M.2 SSD (for NVMe Sanitize)
- a SATA SSD or HDD can be used, but the processes for securely erasing and ensuring the logical sector size is optimal will differ, and will not be covered in this article.
- TPM2.0+ cryptoprocessor (optional security chip, but highly recommended)
- latest Arch Linux ISO loaded onto bootable medium (USB flash drive, PXE boot, DVD/BD, etc.)
- latest memtest86+, also loaded onto bootable medium (optional, for testing system RAM)
PROCEDURE
!!WARNING!! These instructions will DESTROY ALL DATA on the target laptop, including the partition table and EFI partition, and any previous operating systems. Be sure your backups are sound AND TESTED prior to proceeding.
Preparation
- Power on the system, and enter the UEFI setup menu, to enable Secure Boot Setup Mode for the installation. Usually the firmware splash screen will give a hint as to how to do this. On my ThinkPad 25th Anniversary Edition I press
Enter
to interrupt the boot sequence, and thenF1
to enter the Setup Menu (this is the same for the ThinkPad X1 Carbon, pressEnter
thenF1
). Lenovo has a neat UEFI BIOS simulator, but my ThinkPad 25th Anniversay Edition (20K7) is not listed, probably because it's now too old to be covered by this tool (I bought it new in Q4 2017). To enable Secure Boot Setup Mode, at least on the X1 Carbon 11gen, navigate to Security/Secure Boot/Reset to Setup Mode. This actually disables Secure Boot (at least on this ThinkPad), which should allow booting the memtest86+ and Arch ISO images (see below). See your laptop's UEFI BIOS manual for details on how to do this (if you don't have a ThinkPad). - Verify the memtest86+ image, and load it onto a bootable medium (e.g., USB flash drive, CD/DVD/BD, PXE boot, etc.).
- OPTIONAL: Boot memtest86+. Your laptop may have a separate menu to choose the boot device, or you may need to go into the UEFI Setup as disabling Secure Boot above in order to boot off the removable medium. Once memtest86+ boots, it will pause awaiting input. This is where I recommend enabling multiple CPUs (SMP mode); despite what the memtest86+ README states, it's in SMP mode by default (press
F2
at the beginning to disable). It will then automatically start testing the system RAM after a few moments. memtest86+ will then run indefinitely, repeatedly testing RAM with each pass. Let a complete test finish; I recommend multiple passes (the last time I did this I let four full passes complete). The length of time this takes will vary depending on the size and speed of system RAM, CPU, and the number of CPU cores. Back when I did this in 2020 on my ThinkPad 25th Anniversary Edition (using the proprietary, non-open source version of memtest), it took nearly four days to execute a complete four-pass test on 32GiB RAM (I don't recall enabling SMP mode back then). With my new X1 Carbon, it took just over eight hours to make three test passes (passes 0-2), and it finished the fourth pass (pass 3) in just over 11 hours total. Not bad! - Verify the Arch Linux ISO, and load it onto a bootable medium.
- REQUIRED: Boot the Arch Linux ISO, and run the
nvme sanitize
operation once booted:
NOTE: we use the NVMe character device (i.e. nvme0) rather than the block device (nvme0n1), since we're applying the sanitize step to the entire device.# lsblk -f # determine device name for NVMe disk # nvme sanitize /dev/nvme0 --sanact=0x02 # change device accordingly
This command will return immediately. To view the progress, issue the following command:
The Sanitize Status (SPROG) is an unsigned 16-bit decimal integer (maximum value is# nvme sanitize-log /dev/nvme0
65535
, which means complete). The Sanitize Status (SSTAT) has a specific hexadecimal code, see nvme-sanitize-log(1) for details on what the different codes mean. When the sanitize was complete on my ThinkPad X1 Carbon, the code was0x101
, since the non-volatile storage has not been written to, and the most recent sanitize operation completed successfully. The Arch Wiki article regarding Sanitize is a little confusing, I missed the part where it said that the Estimated Time for Block Erase was set to60
, meaning it was estimated to take up to 60 seconds to complete. For me, this operation was quick (only taking a few seconds). If the estimated time for block erase is set to4294967295
, the time is indeterminate and could take several hours based on the size of your NVMe disk. However,lsblk -f
still shows the existing partition table (Lenovo did not give me the option of purchasing this laptop with Linux or without an operating system, so it came with Windows 11 Home as that was the no extra cost option). This is likely due to no overwrite, which is recommended to be avoided to preserve write endurance. Actually, I forgot to runpartprobe
, which would have loaded the new (empty) partition table into kernel memory, and I wouldn't have seen the existing Windows 11 Home partitions at all.
If you're using an older NVMe SSD (standard predating 1.4), you'll have to use thenvme format
command. The drawback to this is the caches on the controller interface and on the SSD itself will likely not be cleared, which could potentially mean data on disk is recoverable. Not ideal if the drive is to be encrypted (as this disk will be). The chances of recovering data from the encrypted partitions are low, but if your security paranoia is high enough it should be concerning. See the Arch Wiki for full details.
PROCEDURE
Once the preparation steps are complete, continue with the installation.
Initialization
-
If necessary, reboot into the Arch Linux ISO via bootable medium.
-
Set the console font:
# setfont ter-132b
At this point you can also set the keyboard map, if your keyboard layout is not the US keyboard layout. See the Arch Wiki for details if you need to do this.
-
Verify the EFI boot mode:
# cat /sys/firmware/efi/fw_platform_size
This should return
64
or32
if you're in UEFI mode. If this file does not exist, you have a legacy BIOS system (or your UEFI system is in legacy BIOS mode) and these instructions are not appropriate for your laptop. See the Arch Wiki for details. -
Connect to the Internet. I will be using WiFi for this, as my X1 Carbon does not have an Ethernet port.
-
First, verify the WiFi adapter is loaded and functional:
# ip link
Interface name should be a variation on wlan0 or wlpNs0 (e.g., wlp4s0), the 'N' will be different based on the order it appears on the PCI bus.
-
Ensure the wireless adapters are not blocked using the
rfkill
command with no options:# rfkill
It should at least return that the wlpNs0 or wlan0 device is unblocked by the kernel or hardware switch. See the rfkill caveat of the Wireless article on the Arch Wiki.
-
Use iwctl to connect to the WiFi network. This should obtain an IP address from DHCP automatically, depending on the network.
- List the wireless devices:
# iwctl device list
- If the device or its corresponding adapter is turned off, power it on:
# iwctl device <device> set-property Powered on # iwctl adapter <adapter> set-property Powered on
- Scan for networks and list the available networks:
# iwctl station <device> scan # command produces no output # iwctl station <device> get-networks
- Connect to the desired network:
You should be prompted for the network password.# iwctl station <device> connect <SSID>
- List the wireless devices:
-
Test that the network is functional:
# ping archlinux.org
-
At this point, consider logging into the new Arch Linux system from another computer, if only to load these instructions in a graphical web browser so you can copy and paste commands into the terminal emulator while logged into the laptop we're working on.
Before we startsshd
, we need to allow root to login with a password. Edit /etc/ssh/sshd_config and add the following line (the default isprohibit-password
but it's commented out; place this line just below that one):PermitRootLogin yes
Then run
passwd
to set a temporary root password (it need not be the same root password for the installed system). Note this is only for the live environment booted from the Arch ISO; I would not recommend enabling this in the installed system.
Startsshd
and determine the current IP address of this laptop (look at the wlan0 or wlpNs0 interface):# systemctl start sshd # ip a s
Then, on the other computer on the same network:
$ ssh root@<ip_addr>
-
-
Verify the system time is correct and synchronized:
# timedatectl
Note, the timezone might not be set, you can optionally set it with:
# timedatectl set-timezone 'America/New_York'
If the RTC is in the local timezone (
RTC in local TZ: yes
, the default in Windows for the longest time; it seems at least in Windows 11 Home this is no longer the case, thank God), set it to no:# timedatectl set-local-rtc no
-
Ensure the NVMe SSD is using the optimal logical sector size.
- Check to see what this is set to:
It should display which one is in use. As the Arch Wiki states, choose the best logical block size with zero Metadata (the Relative Performance output will show degraded, good, better, best, or some subset thereof). My X1 Carbon only showed logical block sizes of 512 (good) or 4096 (better), so I chose the better option.# nvme id-ns -H /dev/nvme0n1 | grep "Relative Performance" # change to proper NVMe disk device, as seen with lsblk -f
- If the logical block size needs to be changed, change it to the LBA Format value which is optimal.
This format should be quick, not as long as the sanitize step above.# nvme format --lbaf=1 /dev/nvme0n1
- Check to see what this is set to:
-
Partition the disks. Be sure to create a GPT partition table (GPT is part of the UEFI specification). We'll create two partitions, one small (512MiB) EFI partition which will be mounted at /efi, the Arch Wiki refers to this as the esp. The other will be a Linux partition, taking up the rest of the disk. You can optionally create a separate swap partition, which is what I'm most familiar with. However, such a swap partition would need to be encrypted separately, which could complicate the process of decrypting on boot.
I will use
parted
to partition the disks, as it is the most scriptable. Alternatively you can usefdisk
orgdisk
to use an interactive, menu-driven TUI (Text User Interface) to partition the disk. GNU parted also has its own interactive shell, but for brevity I will just be using rote commands without entering the interactive shell.Create an empty partition table (substitute nvme0n1 with the actual device name). Add both a fat32 partition (labeled esp) giving it the
esp
attribute, and create the enc partition, giving it the type btrfs and letting it take the rest of the disk. I also use the--align optimal
with percentages for the starting and ending sectors. Otherwiseparted
will complain about the partitions not being aligned (which would degrade performance).# parted --list # confirm partition tables on all block devices # parted --script --align optimal /dev/nvme0n1 mklabel gpt -- \ mkpart esp fat32 0% 512MiB \ set 1 esp on \ mkpart enc btrfs 512MiB 100%
Be sure to load the new partition table into memory, run the following command:
# partprobe
-
Create the vfat filesystem on the esp, /dev/nvme0n1p1:
# mkfs.fat -F 32 /dev/nvme0n1p1
-
Create the top-level Btrfs filesystem, on an encrypted device. Follow the instructions on the Arch Wiki. Set an empty passphrase for now; after first boot we will be setting a recovery key, and use the TPM2 cryptoprocessor in conjunction with Secure Boot to unlock the system as long as the disk isn't tampered with.
- Create the LUKS device, and create a top-level Btrfs filesystem:
# cryptsetup luksFormat /dev/nvme0n1p2 # empty passphrase! # cryptsetup open /dev/nvme0n1p2 top # mkfs.btrfs -L top /dev/mapper/top
- Create the root, and home Btrfs subvolumes. First, mount the top filesystem, then create the subvolumes, and finally unmount the top filesystem:
# mount /dev/mapper/top /mnt # btrfs subvolume create /mnt/root # btrfs subvolume create /mnt/root/home # umount /mnt
- Create the LUKS device, and create a top-level Btrfs filesystem:
-
Mount the root subvolume, create the home directory, and mount it:
# lsblk -f # get the UUID of the Btrfs filesystem # mount -t btrfs -o compress-force=zstd:5,subvol=/root UUID=<UUID> /mnt # mount -t btrfs -o compress-force=zstd:5,subvol=/root/home --mkdir UUID=<UUID> /mnt/home # chattr +C /mnt/home/
Due to limitations in the Linux VFS framework, it is not currently possible to have different mount options for different Btrfs subvolumes (see note at link); setting compression implies CoW (Copy on Write), and no subsequently mounted subvolume can have
nodatacow
enabled. Instead we enablenodatacow
on the /mnt/home/ directory, so any new systemd-homed image (a LUKS2 container) will have thenodatacow
attribute. Each of these systemd-homed LUKS2 images will have a Btrfs filesystem within it, and hopefully these internal Btrfs filesystems will have CoW set up. It turns out you can have subvolumes on these systemd-homed Btrfs filesystems. It takes a bit of a hack to get them mounted and owned by the systemd-homed user; this is where having passwordless sudo comes in handy.
Optionally create other subvolumes below /root/, like /root/etc or /root/var (or even /root/root, the root user's home directory). Btrfs subvolumes are separate namespaces, and snapshotting a parent subvolume does not include any subvolumes below it. You can think of them logically as separate partitions or filesystems, though hard links can be cross-subvolume (unlike with separate filesystems). Also, consider setting thenodatacow
attribute on relevant mount points (like /mnt/var, before entering the arch-chroot).
After I ran into issues with my first boot attempt on my X1 Carbon, I realized that having /etc in a separate subvolume is a bad idea. The systemd-gpt-auto detector doesn't yet seem to be able to read Btrfs subvolumes, and if the etc subvolume isn't mounted, the system can't read /etc/fstab. But this wasn't the only problem: my first boot attempt had no way to identify and unlock the LUKS2 container in the second GPT partition (more on that below). -
Create the swap subvolume and swap file, and enable it:
# btrfs subvolume create /mnt/swap # mount -t btrfs -o subvol=/root/swap --mkdir UUID=<UUID> /mnt/swap # btrfs filesystem mkswapfile --size 16g --uuid clear /mnt/swap/swapfile # swapon /mnt/swap/swapfile
-
Make the /mnt/efi directory, and mount the
esp
to it:# mount --mkdir /dev/nvme0n1p1 /mnt/efi
-
Synchronize the mirror list with
reflector
:# reflector --protocol rsync,https,http \ --country US \ --sort rate \ --latest 10 \ --fastest 10 \ --age 12 \ --save /etc/pacman.d/mirrorlist
-
Copy the base system and any packages you want installed with
pacstrap
. Note, we are not installing a kernel withpacstrap
, as the Arch Linux Installation Guide recommends, since we'll be installing and signing a Unified Kernel Image (UKI) in the section below. Most of these packages are optional at this point; we will be installing more once the installation is complete.# pacstrap -K /mnt base \ base-devel \ sudo \ btrfs-progs \ vim \ networkmanager \ man-db \ man-pages \ texinfo \ git \ tmux \ openssh \ sbctl \ efitools \ zsh \ mkinitcpio \ systemd-ukify \ intel-ucode \ qrencode \ tpm2-tss
Note: if your laptop has an AMD CPU install
amd-ucode
instead. And normallymkinitcpio
is a dependency of thelinux
package, so if we don't include it withpacstrap
it won't already be installed (it's not part ofbase
). -
Generate /mnt/etc/fstab:
# genfstab -U /mnt >> /mnt/etc/fstab # vim /mnt/etc/fstab # ensure all entries are correct
-
Get the UUID and Btrfs subvolume ID of the root partition, for later reference:
# echo "rd.luks.name=$(blkid | grep crypto_LUKS | grep -Po '\bUUID=".*?"' | sed 's/UUID=//' | tr -d '"')=top" | tee -a /mnt/etc/kernel/cmdline # get LUKS UUID and copy it to /etc/kernel/cmdline in new system # echo "root=$(blkid | grep /dev/mapper/top | grep -Po '\bUUID=".*?"')" | tee -a /mnt/etc/kernel/cmdline # btrfs subvolume list -p /mnt # get subvolid of root
Configure the System
- Change root into the new system:
# arch-chroot /mnt
- Set the timezone:
# ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime
- Run hwclock(8) to generate /etc/adjtime:
# hwclock --systohc
- Edit /etc/locale.gen and uncomment en_US.UTF-8 UTF-8 and other needed UTF-8 locales. Then generate locales:
# locale-gen
- Create /etc/locale.conf:
# echo 'LANG=en_US.UTF-8' | tee /etc/locale.conf
- Set the console keyboard layout, and make it persistent in /etc/vconsole.conf (if you set a different keyboard layout earlier, be sure to set the proper layout):
KEYMAP=us
- Create /etc/hostname:
fluorine
Unified Kernel Image Setup
-
Configure /etc/mkinitcpio.conf. Ensure it has the following in the
HOOKS=
line:HOOKS=(systemd autodetect modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck)
-
Edit /etc/kernel/cmdline, and set the following (this is where knowing the UUIDs come into play):
rd.luks.name=<LUKS partition UUID>=top root=UUID=<Btrfs top-level UUID> rw rootflags=subvol=/root
When I attempted my first boot, I did not have the
rd.luks.name
parameter with the LUKS container partition UUID (this UUID is visible from thelsblk -f
output). Without this parameter, the UKI cannot find the root subvolume, and the kernel doesn't even know to unlock the LUKS container. Please see the LUKS#Kernel parameters section of the Arch Wiki for a full discussion of this. Since this is the only LUKS container I intend to install and this UUID should persist for the life of this installation (except for the LUKS containers created by systemd-homed), I did not bother to set up /etc/crypttab and related files. -
Set up the kernel to be installed by systemd's
kernel-install
. There are a few options. If you don't specify theuki_generator
parameter in /etc/kernel/install.conf, it defaults to systemd's ukify which as of 2024-01-15 will only work ifsystemd-ukify
is installed (so I've added it to thepacstrap
command above). Alternatively you can adduki_generator=mkinitcpio
to /etc/kernel/install.conf to have mkinitcpio generate the UKI (it implicitly did this ifsystemd-ukify
was not installed prior to 2024-01-15). See UKI#kernel-install and the Kernel-install articles on the Arch Wiki for more details:# echo "layout=uki" >> /etc/kernel/install.conf
-
Mask the
mkinitcpio
pacman hooks:# mkdir -p /etc/pacman.d/hooks # doesn't exist already # ln -sf /dev/null /etc/pacman.d/hooks/60-mkinitcpio-remove.hook # ln -sf /dev/null /etc/pacman.d/hooks/90-mkinitcpio-install.hook
-
Next we need to install pacman-hook-kernel-install. But first, we need to create an unprivileged user so we can run
makepkg
(Arch forbids root from runningmakepkg
as PKBUILDs from the AUR are untested and could irreparably harm the installed system). We also give the wheel group sudo access; for convenience I allow sudo access without prompting for a password. See the sudoers(5) manual page if you'd rather have any unprivileged user in the wheel group submit their password to runsudo
. We'll create a regular user later in the systemd-homed section. Create the user:# useradd -G wheel,adm,disk -m admin # echo "%wheel ALL=(ALL) NOPASSWD: ALL" | tee /etc/sudoers.d/wheel # sudo -u admin -i
My initial plan was to install my AUR-helper pikaur, but it won't run in the arch-chroot (due to systemd not being PID 1).
$ cd $ git clone https://aur.archlinux.org/pacman-hook-kernel-install.git $ cd pacman-hook-kernel-install $ makepkg -firs $ logout
-
Set up Secure Boot with
sbctl
.sbctl
is not compatible with all systems. If it reports any errors, you may need to follow the manual process instead.
a. First, create the keys:# sbctl create-keys
b. Enroll the keys, being sure to enable the Microsft vendor certificates:
# sbctl enroll-keys --microsoft
At least on my X1 Carbon, entering Setup Mode clears the Platform key (there's a stern warning about it prompting you to confirm before entering Setup Mode, disabling Secure Boot). And the UEFI BIOS on this X1 Carbon has no way to enable Secure Boot after this (likely because the OS needs to install the Platform key). Contrary to what the
sbctl
maintainer said, the only way to reenable Secure Boot is withsbctl enroll-keys
. If you do not have a ThinkPad, it's possible that bothenroll-keys
and enabling Secure Boot in the UEFI firmware menu are required; the latter step was not required for my X1 Carbon. We'll see if my 25/20K7 has a similar "feature."
Not passing the--microsoft
or-m
flag could be dangerous! Without this flag, the Microsoft certificates will be removed. If your laptop uses an Option ROM that is signed by Microsoft or their third-party UEFI CA (Certificate Authority), not passing this flag could brick your laptop! Ensure you have a way to restore Secure Boot to factory defaults and keys if you don't want to heed this warning.
When I ran this, it listed two files in /sys/firmware/efi/efivars/ as immutable, so it said change them withchattr -i
:# chattr -i /sys/firmware/efi/efivars/{KEK-...,db-...} # use tab completion to get the full filenames # sbctl enroll-keys --microsoft
-
Install the
linux
,linux-firmware
, andlinux-headers
kernel packages:# pacman -Syu linux{,-{firmware,headers}}
This should automatically run mkinitcpio, and sign the UKI (both via the kernel-install plugins).
-
Install
systemd-boot
and sign its EFI executables:# bootctl install # sbctl sign --save /efi/EFI/systemd/systemd-bootx64.efi # sbctl sign --save /efi/EFI/BOOT/BOOTX64.EFI
-
Check the Secure Boot status:
# sbctl status
This might show that we're still in Setup Mode, and that Secure Boot is disabled. Otherwise it should show Setup Mode is disabled, and Secure Boot is enabled. I honestly don't remember, the final
sbctl status
after first successful boot should show Setup Mode is Disabled, and Secure Boot is Enabled. YMMV, depending on your laptop you may need to explicitly enable Secure Boot in the UEFI BIOS firmware settings after enrolling keys. -
Run
sbctl verify
. Note, due to limitations oflsblk -f
in the arch-chroot (at least at the time I was executing this installation), we need to set theESP_PATH=/efi
sosbctl verify
can find the ESP (/efi). It should show that the UKI we just installed is signed:# sbctl verify
Finalizing before first boot
- Set the root password:
# passwd
- Exit the arch-chroot, press
Ctrl-d
or typeexit
, thenEnter
. - Reboot:
# systemctl reboot
- Consider enabling a UEFI password (my X1 Carbon supports multiple levels of UEFI BIOS passwords) to protect against attackers who gain physical access to your laptop (i.e. if it is lost or stolen). My X1 Carbon has several options I would like to enable:
- Config
- Keyboard/Mouse
- Disable TrackPad. One of the main reasons I prefer ThinkPads is they come with the TrackPoint. I never liked touchpads on laptops, and the biggest problem I've always had is it registers taps while I'm typing. Even the touchpad on my MacBook Pros do this all the time. How hard is it to configure a default that the touchpad won't register a tap if keys have been pressed within within 200-300ms? I'm sure there are settings that can adjust this, but they seem unreliable when I've tried to use them. I did disable the TrackPad on my ThinkPad 25/20K7, but within Linux with libinput, which itself could be unreliable. Disabling it in the BIOS will also mean my wife won't be able to use my ThinkPads, and I'm OK with that.
- Keyboard/Mouse
- Security
- Password
- Supervisor password.
- Lock UEFI BIOS Settings (will require the Supervisor password)
- Password at Boot Device List (also will require Supervisor password)
- Internal Device Access
- Bottom Cover Tamper Detection
- Secure Boot
- Secure Boot. At this point, Secure Boot was already enabled due to the
sbctl enroll-keys
, and during the troubleshooting trying to fix first boot I could not reenable Secure Boot through the UEFI BIOS alone; I had to do it from the OS installation. Again, YMMV (your mileage may vary), laptops from other manufacturers might require both: enroll-keys and enable Secure Boot in the UEFI firmware settings.
- Secure Boot. At this point, Secure Boot was already enabled due to the
- Password
- Config
First Boot
If everything goes well, the system should boot into the Arch Linux system. It shouldn't prompt you for the LUKS password, but if it does simply press Enter
since earlier we set an empty passphrase (this is precisely what happened once I had a successful boot on my X1 Carbon; I suppose the kernel has to prompt for the keyboard input passphrase, even though it's empty). In a few steps we will be enabling the recovery password, and then set up the TPM2 cryptoprocessor to unlock the LUKS volume assuming the UKI is not tampered with.
- At the login prompt, enter the root username, and password when prompted for it.
- Set up the recovery password:
This should print the recovery key, and show a QR code which can be scanned to retrieve the key and store it in a password manager for future reference. Contrary to expectation, a QR code was NOT displayed; I'm not sure why (EDIT 2024-03-10: no QR code was likely because the package qrencode was not installed. It is an optional dependency of systemd, so I've added it to the# systemd-cryptenroll /dev/nvme0n1p2 --recovery-key
pacstrap
command above). On the second try (the first time I completely failed to capture the recovery key), I took a photo of the recovery key so if the TPM2 device doesn't unlock the LUKS container, I have a backup. TODO: Currently my 20K7 ThinkPad 25 uses a LUKS1 volume since that was all GRUB was compatible with the last time I set up this laptop. I have seen QR codes in text-only terminals before, so this should work even though a graphical user interface is not yet installed. But the QR code did not show in the Arch ISO Linux console; I guess what I had seen was in a graphical terminal emulator.systemd-cryptenroll
is only compatible with LUKS2 volumes, which is what we set up earlier (the default LUKS container is LUKS2 in the latest versions of cryptsetup). - Enroll the TPM2 key, and wipe the empty slot:
# systemd-cryptenroll /dev/nvme0n1p2 --wipe-slot=empty --tpm2-device=auto
- Reboot the system:
If all goes well, it should boot back to the login prompt without intervention (unless you require a UEFI BIOS password to boot the system).# systemctl reboot
Create non-root users with systemd-homed
- Log back in as root.
- Enable and start
systemd-homed.service
:# systemctl enable --now systemd-homed.service
- Ensure /home has the
C
(No_COW) extended attribute set:
It should show the following:# lsattr -d /home
If---------------C------ /home
C
doesn't appear, set No_COW:
...and check again. This is so the systemd-homed image loopback files have No_COW applied, so the outer Btrfs filesystem doesn't have the overhead associated with Copy on Write. It is intended for the mounted Btrfs filesystems contained within the unlocked LUKS2 containers will have COW enabled, so each individual top-level Btrfs filesystem can have its own snapshots and subvolumes.# chattr +C /home
- Create a user account and set its password:
Note, when I was setting this up for the first time, I didn't set thehomectl create <username> \ --storage=luks \ --fs-type=btrfs \ --shell=/usr/bin/zsh \ --member-of=adm,dbus,disk,input,uucp,wheel --disk-size=500G
--disk-size=500G
parameter. If this isn't specified, the LUKS2 container with Btrfs filesystem within it will take 85 percent of the available space. This isn't a huge problem for me right now, but it's something to keep in mind if you plan on having more than one regular user of the laptop.
Repeat for as many users as you wish to create. Note that if the--shell
parameter is not passed,homectl
defaults the user's shell to /bin/bash. - Log out as root:
Ctrl-d
,logout
, orexit
. - Log in as your primary user, using the password set above. This should unlock and mount the home directory.
Configure NetworkManager
We don't yet have a fully operational system, since the network manager (NetworkManager) hasn't been set up yet. If you'd rather another network manager, you can install that instead. Honestly, I would prefer to use systemd-networkd, but I haven't seen where it has a nice graphical applet which I like to use on laptops and anything with a graphical user interface (since I can quickly enable VPN access as an unprivileged user, as well as see the relative WiFi network strength, etc.).
- Enable and start the
systemd-resolved
andNetworkManager
service units:
NOTE: Do NOT install and run two network managers at once, unless you really know what you're doing! Basically, if you run multiple network managers you'll need to ensure that the sets of network interfaces they manage do not overlap. Since this takes a lot of extra thought, planning, and configuration work, it's best to only use one.$ sudo systemctl enable --now systemd-resolved.service NetworkManager.service
- List nearby WiFi networks:
$ nmcli device wifi list
- Connect to the desired WiFi network:
$ nmcli device wifi connect <SSID_or_BSSID> password "<password>"
- Test the connection:
$ ping archlinux.org
Upgrade the firmware of the laptop
I will use fwupdmgr
(part of fwupd) to download a list of available firmware from the Linux Vendor Firmware Service(LVFS), and upgrade my X1 Carbon's firmware. Alternatively, Lenovo provides a bootable ISO which can upgrade the firmware as well. If you do not have a ThinkPad, you may want to check the LVFS to see if your laptop is supported, or refer to the manufacturer's website.
The Arch Wiki mentions that one needs to use shim in order to chainload the EFI binary, but that looks fairly complicated to pull off, especially since shim seems to hard code some filenames and EFI executable paths. Alternatively, it mentions you can sign the EFI executables installed by fwupdmgr
so Secure Boot will boot from it. I will be using sbctl
to sign the EFI files. As of this writing (2023-12-16 17:46:32 -05:00), the Arch Wiki doesn't mention exactly how to do this. If this works as expected, I'll update the Arch Wiki with these details.
One other thing and this is CRUCIAL: Upgrading the firmware will modify hashes for it. The previous hashes will be stored in the TPM PCR registers (7+possibly others). This WILL cause the TPM to fail to unlock the LUKS2 container, and a recovery key (or regular user passphrase) will be required to boot after a firmware upgrade. I haven't yet tested how to work around this; but it involves a new feature of systemd called systemd-pcrlock
. As of this writing (2024-02-06, systemd 255), systemd-pcrlock
only works for external, removable drives encrypted with LUKS2. There are plans to make it handle root volumes, but that isn't released yet (and will likely not be out of experimental phases for a few systemd versions). Lennart Poettering, the lead developer of systemd, has opened a Request For Enhancement (RFE) to fwupd, to allow it to properly update the TPM2 PCRs when the firmware is updated, but that is very far from being production ready; even then it may still not be appropriate for laptops (possibly only really remote servers).
The current suggestion is to merely unlock the LUKS2 container for the root subvolume with the recovery key should a firmware upgrade cause the TPM to not unlock the container. We can call systemd-cryptenroll
to update the stored key. Since I've settled on this solution my last firmware update only seemed to be for the webcam, and did not cause the TPM2 to refuse to unlock the LUKS2 container. I'm monitoring a few LVFS Atom feeds for the X1 Carbon 11g, so it remains to be seen whether the next firmware update will cause this problem.
- Install fwupd and udisks2 (the latter is to be able to update the UEFI firmware). Using
pikaur
:$ pikaur -Syu udisks2 fwupd
- Enable and start the
udisks2
service:$ sudo systemctl enable --now udisks2.service
- Edit /etc/fwupd/fwupd.conf and add the following lines:
[uefi_capsule] DisableShimForSecureBoot=true
- Start the
fwupd
service (we do not enable it on boot, after a period of exactly two hours it shuts itself down, or at least that was my experience when I started it on my ThinkPad 25):$ sudo systemctl start fwupd.service
- Download the LVFS list:
Note, this seems to issue a non-critical error if the list hasn't been downloaded before on this system (I've run it on a few systems now, outside of my laptops).$ sudo -i # fwupdmgr refresh
- List all devices which are eligible for update:
# fwupdmgr get-updates
- Update all eligible devices:
We use# fwupdmgr --no-reboot-check update
--no-reboot-check
to ensure it doesn't prompt to reboot, we need to sign the fwupd EFI executable. I forgot to use this flag and didn't heed this warning when I rebooted after the first firmware update on my X1 Carbon, and that causd the TPM digest/hash to change so I could not unlock on reboot. - Sign the resulting EFI executable with
sbctl
:# sbctl sign --save /efi/EFI/arch/fwupdx64.efi # sbctl verify
- Reboot the laptop:
# systemctl reboot
At this point, the laptop will reboot. It should show progress information as the EFI executable flashes the firmware, and may reboot several times. Some laptop models may show blank screens or the screen may be completely off; DO NOT FORCE THE POWER OFF, as doing so could lead to a partially flashed firmware image, irreperably harming the firmware and bricking your device. It could take several reboots and many minutes (or even hours in some cases) as the process completes.
If all goes well Arch Linux should boot back to a login prompt, and you can proceed with the rest of the installation. If the firmware upgrade causes the TPM to refuse to unlock the LUKS2 container, enter your recovery key, and reenroll the TPM using this procedure:
- Determine which keyslot the TPM2 is using:
# export keyslot=$(sudo cryptsetup luksDump /dev/nvme0n1p2 --dump-json-metadata | jq -r '.tokens.[] | select(.type == "systemd-tpm2") | .keyslots.[]')
- Reenroll the TPM2:
# sudo systemd-cryptenroll --wipe-slot=${keyslot} --tpm2-device=auto
Conclusion
Now a basic Arch system should be ready to use! Follow the Arch Linux General Recommendations for setting up the laptop however you want.
For me, I use a basic X.org setup with XMonad and no desktop environment (DE, like GNOME, KDE Plasma, or Xfce), and intend to install borg (restore backup from my Arch Linux file server) and syncthing (mirrored directory).
As a matter of course and convenience, I enable passwordless sudo for the wheel group (alternatively, you could use the sudo group, but you'll need to modify the homectl
command above). I do not recommend doing this if you do not trust everyone in your household or your workplace, or wherever you will be using this laptop the most. If you frequently take this laptop out in public places, consider not doing this, to increase security. Enable passwordless sudo:
$ sudo -i
# echo "%wheel ALL=(ALL) NOPASSWD: ALL" | tee /etc/sudoers.d/wheel
The following is what I intend to install at the end of these instructions. Your list will likely be different! Again, I use pikaur as my AUR-helper, which is a drop-in replacement for pacman (it accepts the same options, with extensions that search the AUR for packages and install them and all dependencies with pacman underneath). What I like about pikaur is that by default it prompts you to review the PKGBUILD for any AUR packages you install. When an AUR package is upgraded, whether it be a new upstream major, minor, or patch release version, or if the AUR package maintainer has made a package release update, it shows you a diff between the old PKGBUILD and the new PKBUILD. It also pulls in all build and runtime dependencies, whether they're in the AUR, or part of core or extra. If they're build dependencies, by default pikaur will remove these once the package is built and installed (though this is configurable). Install everything:
$ pikaur -Syu xmonad{,-{contrib,utils} stalonetray borg syncthing alacritty qutebrowser vivaldi firefox mutt isync w3m evince bc tmuxp autokey-gtk zoom slack bitwarden-cli 1password-cli lm-sensors conky-cli wget curl openssl network-manager-applet wireguard-tools yegonesh arandr xorg-xrandr xorg-xset xorg-xsetroot zip unzip rsync clipmenu dunst simple-scan cups{,-filters} deluge-gtk dmidecode dzen2 etckeeper exfat-utils feh geoip gimp hplip aspell enchant i3lock iftop iotop imapfilter imagemagick inetutils inkscape xournalpp iperf3 nodejs-fast-cli iptraf-ng graphviz logrotate logwatch postfix lsof mailcap mediainfo mplayer mutt-ics neofetch nmap notmuch-{mutt,runtime} pacman-contrib pacserve pavucontrol pinfo rofi rust scrot signal-desktop sipcalc smartmontools snapper ssh-audit stress sysstat tcpdump wireshark texinfo texlive-{basic,fontsextra,latex{,extra}} traceroute ttf-cascadia-code ttf-intel-one-mono tuptime unhide webcamoid wego xautolock xclip xcursor-vanilla-dmz-aa xdotool xorg-{xev,xprop}
Next step, restoring stuff from backup, including what I have backed up from my private repositories on git.eldon.me. Also, I will be setting up the fingerprint reader with fprint, setting up my HP Color LaserJet MFP M283fdw for both printing and scanning, ensuring the webcam works (I specifically ordered this X1 Carbon so it would have a working webcam, the high end webcam option is currently incompatible with Linux because there aren't drivers for it yet), and setting up new SSH keys for the new laptop.
Once the new laptop has been running for a while, and most if not all the kinks have been worked out, I will set up snapper for my root subvolume and systemd-homed Btrfs filesystems, and set it up to back it up to my file server using borg.