Nov 07, 2018
Arch Linux - UEFI, systemd-boot, LUKS, and btrfs
I recently purchased a new laptop (Dell XPS 13 9370) and needed to install Arch onto it.
I thought I’d finally document the steps I took because I always seem to forget what I did
the last time (one of the joys of Arch is that it rarely needs to be reinstalled).
There are a lot of helpful guides online about different installation setups, but I could never
find one that met all of my requirements:
- UEFI using systemd-boot
- Encryption
- btrfs with subvolumes
General
Create netctl interface for wifi:
1
| cp /etc/netctl/examples/wireless-wpa /etc/netctl/wlp2s0-home
|
Edit wlp2s0-home to use the proper SSID and WPA key:
1
| netctl start wlp2s0-home
|
Configure time:
1
| timedatectl set-ntp true
|
Edit /etc/pacman.d/mirrorlist to prioritize local mirrors.
Partitioning and File System Creation
Use gdisk to create the boot partition and the main partition to be encrypted:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| gdisk /dev/nvme0n1
o (Create a new empty GUID partition table (GPT))
Proceed? Y
n (Add a new partition)
Partition number 1
First sector (default)
Last sector +512M
Hex code EF00
n (Add a new partition)
Partition number 2
First sector (default)
Last sector (press Enter to use remaining disk)
Hex code 8300
w
Y
|
Set up the encryption container:
1
2
3
4
| cryptsetup luksFormat /dev/nvme0n1p2
Are you sure? YES
Enter passphrase (twice)
cryptsetup open /dev/nvme0n1p2 luks
|
Format to FAT32 for the boot and btrfs for the root:
1
2
| mkfs.vfat -F32 /dev/nvme0n1p1
mkfs.btrfs /dev/mapper/luks
|
Since I’d like to keep separate snapshots of home in case a root snapshot needs to be restored,
I create a subvolume for both (see here for details). I also create one for /var
so that its noisy state isn’t included in snapshots.
noatime and nodiratime are used to prevent a write every time a file or directory is accessed
(not great for a COW filesystem like btrfs).
lzo is used for compression because it’s faster at the expense of disk space (of which I have plenty).
I don’t use discard because it has a performance cost: I just issue manual trim commands with fstrim.
1
2
3
4
5
6
7
8
9
10
| mount /dev/mapper/luks /mnt
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@var
umount /mnt
mount -o subvol=@,ssd,compress=lzo,noatime,nodiratime /dev/mapper/luks /mnt
mkdir /mnt/{boot,home,var}
mount -o subvol=@home,ssd,compress=lzo,noatime,nodiratime /dev/mapper/luks /mnt/home
mount -o subvol=@var,ssd,compress=lzo,noatime,nodiratime /dev/mapper/luks /mnt/var
mount /dev/nvme0n1p1 /mnt/boot
|
Installation and Configuration
Install base Arch with some necessities:
1
| pacstrap /mnt base base-devel btrfs-progs neovim sudo zsh zsh-autosuggestions zsh-completions zsh-syntax-highlighting intel-ucode wpa_supplicant
|
Generate fstab:
1
| genfstab -U /mnt >> /mnt/etc/fstab
|
It should look something like this:
1
2
3
4
| /dev/mapper/luks / btrfs rw,noatime,nodiratime,ssd,compress=lzo,subvol=@ 0 0
/dev/mapper/luks /home btrfs rw,noatime,nodiratime,ssd,compress=lzo,subvol=@home 0 0
/dev/mapper/luks /var btrfs rw,noatime,nodiratime,ssd,compress=lzo,subvol=@var 0 0
/dev/nvme0n1p1 /boot/efi vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro 0 2
|
Setting up other stuff:
1
2
3
4
5
6
7
8
9
10
11
| cp /etc/netctl/wlp2s0-home /mnt/etc/netctl
cp /etc/pacman.d/mirrorlist /mnt/etc/pacman.d/mirrorlist
arch-chroot /mnt /bin/zsh
echo some_hostname > /etc/hostname
chsh -s /bin/zsh
ln -sf /usr/share/zoneinfo/US/Pacific /etc/localtime
hwclock --systohc
nvim /etc/locale.gen (uncomment en_US.UTF-8)
locale-gen
echo LANG=en_US.UTF-8 > /etc/locale.conf
passwd
|
Edit /etc/hosts:
1
2
3
| 127.0.0.1 localhost
::1 localhost
127.0.1.1 some_hostname.localdomain some_hostname
|
Modify /etc/mkinitcpio.conf to add encrypt and btrfs:
1
| HOOKS="base udev autodetect modconf block encrypt btrfs filesystems keyboard fsck"
|
And generate:
Then install systemd-boot:
1
| bootctl --path=/boot install
|
Get UUID of cryptoLUKS partition:
Create /boot/loader/entries/arch.conf:
1
2
3
4
5
| title Arch Linux
linux /vmlinuz-linux
initrd /intel-ucode.img
initrd /initramfs-linux.img
options cryptdevice=UUID=UUID_FROM_ABOVE:luks:allow-discards root=/dev/mapper/luks rootflags=subvol=@ rd.luks.options=discard rw mem_sleep_default=deep
|
mem_sleep_default=deep is needed for my laptop to enter deep (S3) sleep.
Edit /boot/loader/loader.conf:
Reboot:
1
2
3
| exit
umount -R /mnt
reboot
|
My Personal Preferences
After all of that, you should have a fully functioning Arch install. Everything from here on is
just my own personal flavoring.
Set up lightdm with autologin (identity already proven with encryption password so why bother):
1
2
3
4
5
| pacman -S lightdm lightdm-gtk-greeter accountsservice
systemctl enable lightdm
groupadd -r autologin
useradd -m -g users -G wheel,autologin -s /bin/zsh austin
passwd austin
|
Edit /etc/lightdm/lightdm.conf:
1
2
| [Seat:*]
autologin-user=austin
|
Add user to sudo:
Uncomment and log in as user:
1
2
| %wheel ALL=(ALL) ALL
exit
|
Install Intel GPU and laptop stuff:
1
| sudo pacman -S xf86-video-intel xorg-server xf86-input-libinput
|
Install more useful packages:
1
2
| sudo pacman -S ttf-dejavu gnome-terminal pulseaudio pavucontrol firefox
openssh git
|
Install i3:
1
| sudo pacman -S i3-gaps i3status rofi
|
Reboot into i3:
Automatic wireless connect with netctl-auto:
1
2
| sudo systemctl enable netctl-auto@wlp2s0
sudo systemctl start netctl-auto@wlp2s0
|
Correcting Errors
If something went wrong and you need to get back in from the live image:
1
2
3
4
5
6
| cryptsetup open /dev/nvme0n1p2 luks
mount -o subvol=@,ssd /dev/mapper/luks /mnt
mount -o subvol=@home,ssd /dev/mapper/luks /mnt/home
mount -o subvol=@var,ssd /dev/mapper/luks /mnt/var
mount /dev/nvme0n1p1 /mnt/boot
arch-chroot /mnt /bin/zsh
|
Further Reading
Last Edited: Dec 20, 2022