Skip to content

Instantly share code, notes, and snippets.

@Raymo111
Last active April 6, 2024 09:09
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Raymo111/5771e425d6e0b9b095660696b92e1a3e to your computer and use it in GitHub Desktop.
Save Raymo111/5771e425d6e0b9b095660696b92e1a3e to your computer and use it in GitHub Desktop.
Arch Linux Install with BTRFS, LUKS, and systemd-boot, dual-booted with a UKI and Windows 11 on a shared EFI partition

Arch Linux Install with BTRFS, LUKS, and systemd-boot, dual-booted with a UKI and Windows 11 on a shared EFI partition

By Raymo111

Last updated 2023-08-06

Disclaimer: I have personally tested every step of this. However, I'm not responsible for anything you do.

Pre-install

  1. Boot Windows, install the latest updates, remove OEM bloatware, open Disk Management, and shrink the Windows partition to make room for Arch.
  2. Download the latest Arch ISO and flash it with Etcher.
  3. Control Panel > Power Options > Choose what the power buttons do > Change settings that are currently unavailable > Uncheck Fast startup.
  4. regedit > HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation > Create a new DWORD, name it RealTimeIsUniversal, and set it to 1.
  5. Boot gparted-live, move the last two tiny Windows partitions to the left.
  6. Turn off secure boot in BIOS, reboot into the Arch ISO.

Install

  1. Turn down brightness: echo 20 > /sys/class/backlight/<screen>/brightness.
  2. Connect to Ethernet/WiFi: iwctl > station <device> scan > station <device> get-networks > station <device> connect <SSID> > ping 1.1.1.1.
  3. cat /sys/firmware/efi/fw_platform_size > check 64-bit.
  4. timedatectl > check NTP active, RTC not in local TZ.
  5. fdisk -l to check disks.
  6. cfdisk /dev/nvme0n1 > [New] to create a new Linux Filesystem partition. Write and quit.
  7. Setup and open LUKS
cryptsetup luksFormat /dev/nvme0n1pX
cryptsetup open /dev/nvme0n1pX luks
  1. Create and mount BTRFS
    mkfs.btrfs -L arch /dev/mapper/luks
    mount /dev/mapper/luks /mnt
    
  2. 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
    
  3. Remount.
    umount /mnt 
    mount -o noatime,ssd,compress=zstd,subvol=@ /dev/mapper/luks /mnt
    
  4. Create mountpoints.
    mkdir /mnt/{boot,home,var/log,var/cache,scratch,btrfs}
    
  5. 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
    
  6. Mount EFI partition.
    mount /dev/nvme0n1p1 /mnt/boot
    
  7. Create swapfile.
    cd /mnt/btrfs/@swap
    btrfs filesystem mkswapfile --size 20g --uuid clear ./swapfile
    swapon ./swapfile
    cd
    
  8. 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
    
  1. 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
    
  2. Init fstab and verify after.
    genfstab -U /mnt >> /mnt/etc/fstab
    
  3. Chroot into the new system.
    arch-chroot /mnt
    
  4. Set timezone.
    ln -sf /usr/share/zoneinfo/America/Toronto /etc/localtime # replace with your timezone
    hwclock --systohc --utc
    
  5. 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
    
  6. Set hostname.
    echo "arch" > /etc/hostname # replace with your hostname
    
  7. Add hosts.
    vim /etc/hosts
    ---
    127.0.0.1 <hostname>.localdomain localhost
    ::1 localhost.localdomain localhost
    
  8. Set root password.
    passwd
    
  9. Create user.
    useradd -mG wheel,storage,power,log,adm,uucp,tss,rfkill -s /bin/bash <username> # replace with your username
    passwd <username>
    
  10. 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
    
  11. Enable networkmanager.
    systemctl enable NetworkManager
    
  12. mkinitcpio.
    vim /etc/mkinitcpio.conf
    ---
    HOOKS=(base keyboard systemd autodetect modconf kms block keymap sd-vconsole sd-encrypt btrfs filesystems fsck)
    
  13. 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
    
  1. Create crypttab.
    luks           UUID=<uuid>    -                       discard,tpm2-device=auto
    
  • Get UUID from:
     blkid /dev/nvme0n1pX
    
  1. 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 (where uki points to)
  1. Install systemd-boot.
    chmod 700 /boot /boot/loader/random-seed
    bootctl --path=/boot install
    
  2. mkinitcpio -P
  3. Install userspace apps.
    pacman -S plasma kde-applications
    
  4. Enable sddm.
    systemctl enable sddm
    
  5. Configure make.
    vim /etc/makepkg.conf
    ---
    MAKEFLAGS="-j$(nproc --ignore=2)" # 2 less than total threads
    
  6. Install yay.
    git clone https://aur.archlinux.org/yay.git
    cd yay
    makepkg -si
    
  7. Exit chroot, unmount, shutdown.
    exit
    umount -R /mnt
    shutdown now
    
  • If target is busy error, check with:
     fuser -m /mnt
    
  1. Configure BIOS boot order. Set Linux as first boot option because systemd-boot will auto-detect Windows and add it to the boot menu.
  2. Boot into Arch and pat yourself on the back.
  3. 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
    
  1. 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'
    
  2. Install sbctl and efitools.
  3. Backup your existing keys:
    for var in PK KEK db dbx ; do efi-readvar -v $var -o old_${var}.esl ; done
    
  4. Reboot into bios, enable secureboot and delete the manufacturer PK.
  5. 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
    
  6. 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
    
  7. Then enable secure boot, set an admin bios password, and reboot.
@marol75
Copy link

marol75 commented Dec 24, 2023

Thank you for script. I'm going to try it on my desktop. Two questions.

  1. Once (~a year ago) I tried to make swap-file, but it didn't work. I've read it's not supported by archlinux. Will it be ok to make swap partition (and encrypt it)?
  2. Step 45 - secure boot has already been enabled at step 42 or it's a mistake?

@marol75
Copy link

marol75 commented Jan 1, 2024

I've got another question.
After step 27 there's no mkinitcpio command. Why?

@Raymo111
Copy link
Author

Raymo111 commented Apr 6, 2024

I've got another question. After step 27 there's no mkinitcpio command. Why?

Updated, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment