| title | arch-install-luks-btrfs | |
|---|---|---|
| tags |
|
|
| created | 2024-10-14 08:49 | |
| modified | 2023-11-23 18:06:53 UTC | |
| moc | [[_geek-room]] |
- arch-install-luks-btrfs
- Arch Linux Full-Disk Encryption Base System Installation Guide
- Preface
- Pre-installation
- Arch Base Installation
- Configure the system
- Generate an fstab file
- Enter new system chroot
- Time zone
- Localization
- Network configuration
- (Optional) Swap File Creation
- Initramfs
- Fundamental Software Installation
- Root password
- Add Linux User
- Boot loader
- (recommended) Embed a keyfile in initramfs
- Post-installation
- Speeding up LUKS decryption in GRUB
- (recommended) Secure Boot - Hardening against Evil Maid attacks
- Creating keys
- Signing bootloader and kernel
- Enroll keys in firmware
- Copy all *.cer, *.esl, *.auth to the EFI system partition
- Boot into UEFI firmware setup utility (frequently but incorrectly referred to as "BIOS")
- Set OS Type to Windows UEFI mode
- Clear preloaded Secure Boot keys
- Set or append the new keys
- Set UEFI supervisor (administrator) password
- Exit and save changes
- Check if Secure Boot was enabled
- Docker on BTRFS Storage Driver
Arch Installation includes LUKS, BTRFS+Backup, Base Installation, Secure Boot.
- MAIN ARTICLE: https://gist.github.com/huntrar/e42aee630bee3295b2c671d098c81268
- https://www.nishantnadkarni.tech/posts/arch_installation/
- https://www.dwarmstrong.org/archlinux-install/
- https://btrfs.readthedocs.io/en/latest/btrfs-man5.html#compression
- https://github.com/Szwendacz99/Arch-install-encrypted-btrfs
- https://gist.github.com/mruiz42/83d9a232e7592d65d953671409a2aab9
- https://wiki.archlinux.org/title/btrfs
- https://wiki.archlinux.org/title/dm-crypt/Encrypting_an_entire_system
- https://wiki.tnonline.net/w/Btrfs/Compression
This guide provides instructions for an Arch Linux installation featuring full-disk encryption via BTRFS on LUKS and an encrypted boot partition (GRUB) for UEFI systems.
Following the main installation are further instructions to harden against Evil Maid attacks via UEFI Secure Boot custom key enrollment and self-signed kernel and bootloader.
You will find most of this information pulled from the Arch Wiki and other resources linked thereof.
Note: The system was installed on an NVMe SSD, substitute /dev/nvme0nX with /dev/sdX or your device as needed.
Plug in your Ethernet and go, or for wireless consult the all-knowing Arch Wiki.
iwctl
[iwd]# device list -> note your device
[iwd]# station <device> get-networks
[iwd]# station <device> connect <SSID>
# second variant
iwctl --passphrase <heslo> station <device> connect <SSID>
# test connection
ping archlinux.orgtimedatectl set-ntp truepacman -Syy
pacman -S reflector
cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.bak
reflector --country 'Czechia' --age 24 --verbose --sort rate --save /etc/pacman.d/mirrorlist
# OR
reflector -c "CZ" -f 12 -l 10 -n 12 --save /etc/pacman.d/mirrorlistpacman -S fbset terminus-font
fbset -g 2048 1080 2048 1080 32
setfont ter-132npacman -Syy btrfs-progslsblk| Number | Start (sector) | End (sector) | Size | Code | Name |
|---|---|---|---|---|---|
| 1 | 2048 | 1130495 | 256.0 MiB | EF00 | EFI System |
| 2 | 1130496 | 976773134 | 465.2 GiB | 8309 | Linux LUKS |
gdisk /dev/nvme0n1
# alternative apps
cfdisk
fdisko
n
[Enter]
0
+256M
ef00
n
[Enter]
[Enter]
[Enter]
8309
w
Create the LUKS1 encrypted container on the Linux LUKS partition (GRUB does not support LUKS2 as of May 2019)
cryptsetup luksFormat --type luks1 --use-random -S 1 -s 512 -h sha512 -i 5000 /dev/nvme0n1p2cryptsetup open /dev/nvme0n1p2 cryptbtrfsmkfs.btrfs -L "Arch Linux" /dev/mapper/cryptbtrfsmount /dev/mapper/cryptbtrfs /mntThis scheme can be adjusted to your needs, I'd suggest at least one subvolume for root (@) and one for snapshots (.@snapshots). varlog and tmp are created to easily disable Copy on Write on /var/log and /tmp.
btrfs sub cr /mnt/@
btrfs sub cr /mnt/@home
btrfs sub cr /mnt/@tmp
btrfs sub cr /mnt/@log
btrfs sub cr /mnt/@pkg
btrfs sub cr /mnt/@docker
btrfs sub cr /mnt/.@snapshotschattr +C /mnt/@log
chattr +C /mnt/@tmp
umount /mntmount -o defaults,noatime,discard,ssd,subvol=@ /dev/mapper/cryptbtrfs /mnt
mkdir -p /mnt/{home,var/log,var/cache/pacman/pkg,var/lib/docker,tmp,.snapshots}
# Discard and ssd options and are for ssd disks only
mount -o defaults,noatime,discard,ssd,subvol=@home /dev/mapper/cryptbtrfs /mnt/home
mount -o defaults,noatime,discard,ssd,subvol=@tmp /dev/mapper/cryptbtrfs /mnt/tmp
mount -o defaults,noatime,discard,ssd,subvol=@log /dev/mapper/cryptbtrfs /mnt/var/log
mount -o defaults,noatime,discard,ssd,subvol=@pkg /dev/mapper/cryptbtrfs /mnt/var/cache/pacman/pkg/
mount -o defaults,noatime,discard,ssd,subvol=@docker /dev/mapper/cryptbtrfs /mnt/var/lib/docker
mount -o defaults,noatime,discard,ssd,subvol=.@snapshots /dev/mapper/cryptbtrfs /mnt/.snapshotsmkfs.fat -F32 /dev/nvme0n1p1mkdir /mnt/efi
mount /dev/nvme0n1p1 /mnt/efipacstrap /mnt/ base base-devel linux linux-headers linux-firmware polkit git btrfs-progs efibootmgr mkinitcpio dhcpcd bash-completion sudo neovim nanogenfstab -U /mnt >> /mnt/etc/fstabCheck if the fstab is correctly created with defined btrfs parameters from previous chapter with neovim.
arch-chroot /mntlsblk| NAME | MAJ:MIN | RM | SIZE | RO | TYPE | MOUNTPOINT |
|---|---|---|---|---|---|---|
| nvme0n1 | 259:0 | 0 | 465.8G | 0 | disk | |
| ├─nvme0n1p1 | 259:5 | 0 | 256M | 0 | part | /efi |
| ├─nvme0n1p2 | 259:6 | 0 | 465.2G | 0 | part | |
| ..└─cryptbtrfs | 254:0 | 0 | 465.2G | 0 | crypt | /.snapshots |
| /var/lib/docker | ||||||
| /var/cache/pacman/pkg | ||||||
| /var/log | ||||||
| /tmp | ||||||
| /home | ||||||
| / |
Replace Europe/Prague with your respective timezone found in /usr/share/zoneinfo
ln -sf /usr/share/zoneinfo/Europe/Prague /etc/localtimeAssumes hardware clock is set to UTC
hwclock --systohc --utclocale-genecho LANG=en_US.UTF-8 > /etc/locale.conf
export LANG=en_US.UTF-8echo myhostname > /etc/hostnameThis is a unique name for identifying your machine on a network.
nvim /etc/hosts127.0.0.1 localhost
::1 localhost
127.0.1.1 myhostnameNow create empty (with 0 size) swap file: Create separate subvolume for swapfile. This subvolume is needed to let you make snapshot of /, which would not be possible with any file in it with CoW disabled!
btrfs su create /swap
chattr +C /swap
# Copy on Write should always be disabled on swap file, so it will be done in the next step
touch /swap/swapfile
# Check if C attribute is enabled (should be already if created in folder with disabled CoW attribute)
lsattr /swap/swapfile
# If not then disable CoW for swapfile manually
chattr +C /swap/swapfile
# Expanding empty file to 4GiB swap file
dd if=/dev/zero of=/swap/swapfile bs=1024K count=4096
chmod 600 /swap/swapfile
# Format the swap file.
mkswap /swap/swapfile
# Turn swap file on.
swapon /swap/swapfile
# You also need to update /etc/fstab to mount swapfile on boot
/swap/swapfile none swap sw 0 0Note: ordering matters.
HOOKS=(base udev autodetect modconf kms keyboard keymap consolefont block encrypt btrfs filesystems fsck)
# Add btrfsck to binaries
BINARIES=(btrfsck)mkinitcpio -Ppacman -S openssh networkmanager wpa_supplicant netctl
systemctl enable NetworkManager
systemctl enable sshd
pacman -S amd-ucode (for AMD) pacman -S intel-ucode (for INTEL)
mkinitcpio -p linuxpacman -S xorg
pacman -S mesapacman -S xorg
pacman -S nvidia nvidia-utils
sudo vim /etc/mkinitcpio.conf
# edit Modules and Files
MODULES=(nvidia nvidia_modeset nvidia_uvm nvidia_drm ...)
FILES="/etc/modprobe.d/nvidia.conf"
sudo mkinitcpio -P
nvim /etc/modprobe.d/nvidia.conf
# Add row to the file
options nvidia_drm modeset=1pacman -S virtualbox-guest-utils xf86-video-vmwarepasswduseradd -m -g users -G wheel,storage,power -s /bin/bash <user>
passwd <user>
pacman -S sudo
EDITOR=nvim visudo, (uncomment) %wheel ALL=(ALL:ALL) ALLpacman -S grub efibootmgr os-prober dosfstools mtoolsnvim /etc/default/grubGRUB_ENABLE_CRYPTODISK=y
blkid/dev/nvme0n1p2: UUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" TYPE="crypto_LUKS" PARTLABEL="Linux LUKS" PARTUUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"/etc/default/grub# allow-discards is only for ssd to let trim work with encryption enabled
GRUB_CMDLINE_LINUX="... cryptdevice=UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:cryptbtrfs:allow-discards"grub-install --target=x86_64-efi --bootloader-id=ARCH --efi-directory=/efi --recheckgrub-mkconfig -o /boot/grub/grub.cfg
This is done to avoid having to enter the encryption passphrase twice (once for GRUB, once for initramfs.)
mkdir /root/secrets && chmod 700 /root/secrets
head -c 64 /dev/urandom > /root/secrets/crypto_keyfile.bin && chmod 600 /root/secrets/crypto_keyfile.bin
cryptsetup -v luksAddKey -i 1 /dev/nvme0n1p2 /root/secrets/crypto_keyfile.binnvim /etc/mkinitcpio.confFILES=(/root/secrets/crypto_keyfile.bin)mkinitcpio -P/etc/default/grubGRUB_CMDLINE_LINUX="... cryptkey=rootfs:/root/secrets/crypto_keyfile.bin"grub-mkconfig -o /boot/grub/grub.cfgchmod 700 /bootThe installation is now complete. Exit the chroot and reboot.
exit
rebootYour system should now be fully installed, bootable, and fully encrypted.
If you embedded the keyfile in the initramfs image, it should only require your encryption passphrase once to unlock to the system.
For the standard Arch Linux post-installation steps, RTFM.
Warning: Before following this section, make sure you understand the importance of high entropy passwords. Information on how to generate secure passwords can be found at Wikipedia:Password strength.
Upon boot GRUB may in some cases take a long time to verify the password. This can be due to a high PBKDF iteration count, which you can check as follows:
cryptsetup luksDump /dev/nvme0n1p2The problem is that the iteration count for a given keyslot is generated when the key is added to ensure a balance between being high enough to protect against brute force attacks and low enough to allow for fast key derivation by estimating the capabilities of your computer. However, when GRUB is started, it might not have the same computational resources at hand, thus being vastly slower.
If your password provides enough entropy to counter common attacks by itself, you can lower this number:
cryptsetup luksChangeKey --pbkdf-force-iterations 1000 /dev/nvme0n1p2A minimum of 1000 iterations is recommended as per RFC 2898, but you should aim for higher values if you can (The cost for an attacker as well as the time for key derivation scale linearly).
Tip: GRUB tries enabled key slots sequentially. When adding keys, the --key-slot option can be used to specify a key slot explicitly.
With an encrypted boot partition, nobody can see or modify your kernel image or initramfs, but you would be still vulnerable to Evil Maid attacks.
One possible solution is to use UEFI Secure Boot. Get rid of preloaded Secure Boot keys (you really don't want to trust Microsoft and OEM), enroll your own Secure Boot keys and sign the GRUB boot loader with your keys. Evil Maid would be unable to boot modified boot loader (not signed by your keys) and the attack is prevented.
The following steps should be performed as the root user, with accompanying files stored in the /root directory.
pacman -S efitoolsuuidgen --random > GUID.txtCN is a Common Name, which can be written as anything.
openssl req -newkey rsa:4096 -nodes -keyout PK.key -new -x509 -sha256 -days 3650 -subj "/CN=my Platform Key/" -out PK.crt
openssl x509 -outform DER -in PK.crt -out PK.cer
cert-to-efi-sig-list -g "$(< GUID.txt)" PK.crt PK.esl
sign-efi-sig-list -g "$(< GUID.txt)" -k PK.key -c PK.crt PK PK.esl PK.authsign-efi-sig-list -g "$(< GUID.txt)" -c PK.crt -k PK.key PK /dev/null rm_PK.authopenssl req -newkey rsa:4096 -nodes -keyout KEK.key -new -x509 -sha256 -days 3650 -subj "/CN=my Key Exchange Key/" -out KEK.crt
openssl x509 -outform DER -in KEK.crt -out KEK.cer
cert-to-efi-sig-list -g "$(< GUID.txt)" KEK.crt KEK.esl
sign-efi-sig-list -g "$(< GUID.txt)" -k PK.key -c PK.crt KEK KEK.esl KEK.authopenssl req -newkey rsa:4096 -nodes -keyout db.key -new -x509 -sha256 -days 3650 -subj "/CN=my Signature Database key/" -out db.crt
openssl x509 -outform DER -in db.crt -out db.cer
cert-to-efi-sig-list -g "$(< GUID.txt)" db.crt db.esl
sign-efi-sig-list -g "$(< GUID.txt)" -k KEK.key -c KEK.crt db db.esl db.authWhen Secure Boot is active (i.e. in "User Mode") you will only be able to launch signed binaries, so you need to sign your kernel and boot loader.
Install sbsigntools
pacman -S sbsigntoolssbsign --key db.key --cert db.crt --output /boot/vmlinuz-linux /boot/vmlinuz-linux
sbsign --key db.key --cert db.crt --output /efi/EFI/arch/grubx64.efi /efi/EFI/arch/grubx64.efiIt is necessary to sign GRUB with your UEFI Secure Boot keys every time the system is updated via pacman. This can be accomplished with a pacman hook.
Create the hooks directory
mkdir -p /etc/pacman.d/hooksCreate hooks for both the linux and grub packages
/etc/pacman.d/hooks/99-secureboot-linux.hook[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = linux
[Action]
Description = Signing Kernel for SecureBoot
When = PostTransaction
Exec = /usr/bin/find /boot/ -maxdepth 1 -name 'vmlinuz-*' -exec /usr/bin/sh -c 'if ! /usr/bin/sbverify --list {} 2>/dev/null | /usr/bin/grep -q "signature certificates"; then /usr/bin/sbsign --key /root/db.key --cert /root/db.crt --output {} {}; fi' \ ;
Depends = sbsigntools
Depends = findutils
Depends = grep/etc/pacman.d/hooks/98-secureboot-grub.hook[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = grub
[Action]
Description = Signing GRUB for SecureBoot
When = PostTransaction
Exec = /usr/bin/find /efi/ -name 'grubx64*' -exec /usr/bin/sh -c 'if ! /usr/bin/sbverify --list {} 2>/dev/null | /usr/bin/grep -q "signature certificates"; then /usr/bin/sbsign --key /root/db.key --cert /root/db.crt --output {} {}; fi' \ ;
Depends = sbsigntools
Depends = findutils
Depends = grepcp /root/*.cer /root/*.esl /root/*.auth /efi/systemctl reboot --firmwareFirmwares have various different interfaces, see Replacing Keys Using Your Firmware's Setup Utility if the following instructions are unclear or unsuccessful.
Find the Secure Boot options and set OS Type to Windows UEFI mode (yes, even if we're not on Windows.) This may be necessary for Secure Boot to function.
Using Key Management, clear all preloaded Secure Boot keys (Microsoft and OEM).
By clearing all Secure Boot keys, you will enter into Setup Mode (so you can enroll your own Secure Boot keys).
The keys must be set in the following order:
db => KEK => PKThis is due to some systems exiting setup mode as soon as a PK is entered.
Do not load the factory defaults, instead navigate the available filesystems in search of the files previously copied to the EFI System partition.
Choose any of the formats. The firmware should prompt you to enter the type (Note: type names may differ slightly.)
*.cer is a Public Key Certificate
*.esl is a UEFI Secure Variable
*.auth is an Authenticated Variable
Certain firmware (such as my own) require you use the *.auth files. Try various ones until they work.
You must also set your UEFI firmware supervisor (administrator) password in the Security settings, so nobody can simply boot into UEFI setup utility and turn off Secure Boot.
You should never use the same UEFI firmware supervisor password as your encryption password, because on some old laptops, the supervisor password could be recovered as plain text from the EEPROM chip.
Once you've loaded all three keys and set your supervisor password, hit F10 to exit and save your changes.
If everything was done properly, your boot loader should appear on reboot.
od -An -t u1 /sys/firmware/efi/efivars/SecureBoot-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXThe characters denoted by XXXX differ from machine to machine. To help with this, you can use tab completion or list the EFI variables.
If Secure Boot is enabled, this command returns 1 as the final integer in a list of five, for example:
6 0 0 0 1
If Secure Boot was enabled and your UEFI supervisor password set, you may now consider yourself protected against Evil Maid attacks.
BTRFS is ideal for docker snapshots. Follow settings by this original article.