Arch Linux Install with BTRFS, LUKS, and systemd-boot, dual-booted with a UKI and Windows 11 on a shared EFI partition
Last updated 2023-08-06
Disclaimer: I have personally tested every step of this. However, I'm not responsible for anything you do.
- Boot Windows, install the latest updates, remove OEM bloatware, open Disk Management, and shrink the Windows partition to make room for Arch.
- Download the latest Arch ISO and flash it with Etcher.
Control Panel > Power Options > Choose what the power buttons do > Change settings that are currently unavailable
> UncheckFast startup
.regedit > HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation
> Create a newDWORD
, name itRealTimeIsUniversal
, and set it to1
.- Boot gparted-live, move the last two tiny Windows partitions to the left.
- Turn off secure boot in BIOS, reboot into the Arch ISO.
- Turn down brightness:
echo 20 > /sys/class/backlight/<screen>/brightness
. - Connect to Ethernet/WiFi:
iwctl
>station <device> scan
>station <device> get-networks
>station <device> connect <SSID>
>ping 1.1.1.1
. cat /sys/firmware/efi/fw_platform_size
> check 64-bit.timedatectl
> check NTP active, RTC not in local TZ.fdisk -l
to check disks.cfdisk /dev/nvme0n1
>[New]
to create a newLinux Filesystem
partition. Write and quit.- Setup and open LUKS
cryptsetup luksFormat /dev/nvme0n1pX
cryptsetup open /dev/nvme0n1pX luks
- Create and mount BTRFS
mkfs.btrfs -L arch /dev/mapper/luks mount /dev/mapper/luks /mnt
- Create BTRFS subvolumes
btrfs subvolume create /mnt/@ btrfs subvolume create /mnt/@swap btrfs subvolume create /mnt/@home btrfs subvolume create /mnt/@log btrfs subvolume create /mnt/@cache btrfs subvolume create /mnt/@scratch
- Remount.
umount /mnt mount -o noatime,ssd,compress=zstd,subvol=@ /dev/mapper/luks /mnt
- Create mountpoints.
mkdir /mnt/{boot,home,var/log,var/cache,scratch,btrfs}
- Mount subvols.
mount -o noatime,ssd,compress=zstd,subvol=@home /dev/mapper/luks /mnt/home mount -o noatime,ssd,compress=zstd,subvol=@log /dev/mapper/luks /mnt/var/log mount -o noatime,ssd,compress=zstd,subvol=@cache /dev/mapper/luks /mnt/var/cache mount -o noatime,ssd,compress=zstd,subvol=@scratch /dev/mapper/luks /mnt/scratch mount -o noatime,ssd,compress=zstd,subvolid=5 /dev/mapper/luks /mnt/btrfs # const 5 for BTRFS's root
- Mount EFI partition.
mount /dev/nvme0n1p1 /mnt/boot
- Create swapfile.
cd /mnt/btrfs/@swap btrfs filesystem mkswapfile --size 20g --uuid clear ./swapfile swapon ./swapfile cd
- Configure mirrorlist
cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.bak # backup mirrorlist reflector -c "CA" -f 12 -l 10 -n 12 --save /etc/pacman.d/mirrorlist #(replace CA with your country) pacman -Syy
- Uncomment following lines for 32-bit pkgs:
vim /etc/pacman.conf --- [multilib] Include = /etc/pacman.d/mirrorlist
- Install base system.
pacstrap -K /mnt base base-devel linux-lts linux-firmware btrfs-progs \ amd-ucode mesa xf86-video-amdgpu vulkan-radeon libva-mesa-driver mesa-vdpau \ networkmanager sudo neovim git reflector
- Init
fstab
and verify after.genfstab -U /mnt >> /mnt/etc/fstab
- Chroot into the new system.
arch-chroot /mnt
- Set timezone.
ln -sf /usr/share/zoneinfo/America/Toronto /etc/localtime # replace with your timezone hwclock --systohc --utc
- Set locale: uncomment desired locales from
/etc/locale.gen
.locale-gen echo "LANG=en_CA.UTF-8" > /etc/locale.conf export LANG=en_CA.UTF-8
- Set hostname.
echo "arch" > /etc/hostname # replace with your hostname
- Add hosts.
vim /etc/hosts --- 127.0.0.1 <hostname>.localdomain localhost ::1 localhost.localdomain localhost
- Set root password.
passwd
- Create user.
useradd -mG wheel,storage,power,log,adm,uucp,tss,rfkill -s /bin/bash <username> # replace with your username passwd <username>
- Give user sudo access.
EDITOR=nvim visudo --- raymo ALL=(ALL:ALL) ALL # for passworded sudo raymo ALL=(ALL:ALL) NOPASSWD:ALL # for passwordless sudo # one of the two above, replace raymo with your username
- Enable networkmanager.
systemctl enable NetworkManager
mkinitcpio
.vim /etc/mkinitcpio.conf --- HOOKS=(base keyboard systemd autodetect modconf kms block keymap sd-vconsole sd-encrypt btrfs filesystems fsck)
- Configure kernel command line.
vim /etc/kernel/cmdline --- root=/dev/mapper/luks rootflags=subvol=@,x-system.device-timeout=30 rw quiet splash bgrt_disable resume=/dev/mapper/luks resume_offset=<offset>
- Get offset from:
btrfs inspect-internal map-swapfile -r /btrfs/@swap/swapfile
- Create crypttab.
luks UUID=<uuid> - discard,tpm2-device=auto
- Get UUID from:
blkid /dev/nvme0n1pX
- Configure
.preset
.vim /etc/mkinitcpio.d/linux-lts.preset
- Uncomment
*_uki=
lines, replace any/efi/*
with/boot/*
, comment out*_image=
lines, uncomment splash if desired. - Make sure
/boot/EFI/Linux
exists (whereuki
points to)
- Install
systemd-boot
.chmod 700 /boot /boot/loader/random-seed bootctl --path=/boot install
mkinitcpio -P
- Install userspace apps.
pacman -S plasma kde-applications
- Enable
sddm
.systemctl enable sddm
- Configure
make
.vim /etc/makepkg.conf --- MAKEFLAGS="-j$(nproc --ignore=2)" # 2 less than total threads
- Install
yay
.git clone https://aur.archlinux.org/yay.git cd yay makepkg -si
- Exit chroot, unmount, shutdown.
exit umount -R /mnt shutdown now
- If
target is busy
error, check with:fuser -m /mnt
- Configure BIOS boot order. Set Linux as first boot option because
systemd-boot
will auto-detect Windows and add it to the boot menu. - Boot into Arch and pat yourself on the back.
- Enroll TPM so you don't have to keep typing in your LUKS password.
sudo systemd-cryptenroll --tpm2-device=<path> --tpm2-pcrs=7 /dev/nvme0n1pX
- Get path from:
sudo systemd-cryptenroll --tpm2-device=list
- Install UKI pacman hook to trigger rebuild after ucode update:
vim /etc/pacman.d/hooks/ucode.hook --- [Trigger] Operation=Install Operation=Upgrade Operation=Remove Type=Package # Change to appropriate microcode package Target=amd-ucode # Change the linux part above and in the Exec line if a different kernel is used Target=linux [Action] Description=Update Microcode module in initcpio Depends=mkinitcpio When=PostTransaction NeedsTargets Exec=/bin/sh -c 'while read -r trg; do case $trg in linux) exit 0; esac; done; /usr/bin/mkinitcpio -P'
- Install
sbctl
andefitools
. - Backup your existing keys:
for var in PK KEK db dbx ; do efi-readvar -v $var -o old_${var}.esl ; done
- Reboot into bios, enable secureboot and delete the manufacturer PK.
- Setup sbctl:
sudo sbctl status sudo sbctl create-keys sudo chattr -i /sys/firmware/efi/efivars/{PK,KEK,db}* sudo sbctl enroll-keys -m sudo sbctl verify # shows you what to sign sudo sbctl sign -s /boot/EFI/Boot/bootx64.efi sudo sbctl sign -s /boot/EFI/Linux/arch-linux-lts.efi sudo sbctl sign -s /boot/EFI/Linux/arch-linux-lts-fallback.efi sudo sbctl sign -s /boot/EFI/systemd/systemd-bootx64.efi
- Add a hook for automatically signing after upgrades:
sudo vim /etc/initcpio/post/uki-sbctl --- #!/usr/bin/env bash sbctl sign-all --- sudo chmod +x /etc/initcpio/post/uki-sbctl
- Then enable secure boot, set an admin bios password, and reboot.
I've got another question.
After step 27 there's no mkinitcpio command. Why?