Skip to content

Instantly share code, notes, and snippets.

@cristeaadrian
Last active February 4, 2025 10:54
Show Gist options
  • Save cristeaadrian/e88bef2d596bae5e43c0a8f25df0aab7 to your computer and use it in GitHub Desktop.
Save cristeaadrian/e88bef2d596bae5e43c0a8f25df0aab7 to your computer and use it in GitHub Desktop.
A guide that I use for my own future reference

/# Arch Linux Install Procedure A mostly vanilla Arch with BTRFS subvolumes and snapshotting, plus other tools that I use. Very opinionated!

Basic Installation Steps

  1. Set the keyboard layout to standard British: loadkeys uk

  2. Connect to the wireless internet connection:

$ systemctl start systemd-networkd systemd-resolved iwd
$ iwctl
$ station wlan0 scan
$ station wlan0 get-networks
$ station wlan0 connect <SSID>  # enter passphrase if prompted
$ exit
  1. Update system clock: timedatectl set-ntp true

  2. Partitioning:

    • Show current partitioning scheme: fdisk -l /dev/nvme0n1

    • Securely wipe current disk dd if=/dev/zero of=/dev/nvme0n1 bs=4096 status=progress

    • Use cfdisk to interactively create two partitions: a 512M EFI System, and the rest as a Linux root (x86-64). Enter it using: cfdisk /dev/nvme0n1

    • Encrypt the main partition:

      $ cryptsetup luksFormat /dev/nvme0n1p2
      $ cryptsetup open /dev/nvme0n1p2 luks
    • Create EFI partition: mkfs.vfat -F32 /dev/nvme0n1p1

    • Create root partition: mkfs.btrfs -L ARCH /dev/mapper/luks

  3. Create Btrfs Subvolumes:

    • Mount btrfs partition: mount /dev/mapper/luks /mnt

    • Create subvolumes:

    $ btrfs subvolume create /mnt/@
    $ btrfs subvolume create /mnt/@home
    $ btrfs subvolume create /mnt/@pkg
    $ btrfs subvolume create /mnt/@snapshots
    • Unmount everything: umount -R /mnt

    • Remount root partition:

      $ mount -o noatime,nodiratime,autodefrag,compress=zstd:1,discard=async,space_cache=v2,ssd,subvol=@ /dev/mapper/luks /mnt
      $ mkdir -p /mnt/{boot,home,var/cache/pacman/pkg,.snapshots,btrfs}
      $ mount -o noatime,nodiratime,autodefrag,compress=zstd:1,discard=async,space_cache=v2,ssd,subvol=@home /dev/mapper/luks /mnt/home
      $ mount -o noatime,nodiratime,autodefrag,compress=zstd:1,discard=async,space_cache=v2,ssd,subvol=@pkg /dev/mapper/luks /mnt/var/cache/pacman/pkg
      $ mount -o noatime,nodiratime,autodefrag,compress=zstd:1,discard=async,space_cache=v2,ssd,subvol=@snapshots /dev/mapper/luks /mnt/.snapshots
      $ mount -o noatime,nodiratime,autodefrag,compress=zstd:1,discard=async,space_cache=v2,ssd,subvolid=5 /dev/mapper/luks /mnt/btrfs
  4. Mount /boot: mount /dev/nvme0n1p1 /mnt/boot

  5. Install the OS and utilities: pacstrap /mnt base base-devel linux linux-firmware btrfs-progs amd-ucode mesa mesa-vdpau vulkan-radeon libva-mesa-driver man-db man-pages fish neovim iwd git gnupg

  6. Generate the fstab (and then optionally take a look at it to make sure it's fine): genfstab -U /mnt >> /mnt/etc/fstab

  7. Chroot into the new system: arch-chroot /mnt

  8. Change default shell to fish: chsh -s /usr/bin/fish, then go into it cause it's so much nicer.

  9. Timezone: ln -sf /usr/share/zoneinfo/Europe/London /etc/localtime

  10. Run hwclock to generate /etc/adjtime: hwclock --systohc

  11. Edit /etc/locale.gen to uncomment the en_GB.UTF-8 UTF-8 line (and the Hungarian and Romanian lines too, while you're at it), then run locale-gen

  12. Create minor configuration files:

$ localectl set-keymap --no-convert uk
$ echo LANG=en_GB.UTF-8 > /etc/locale.conf
$ echo KEYMAP=uk > /etc/vconsole.conf
$ echo adrians-{work/personal}-laptop > /etc/hostname
  1. Create hosts file (/etc/hosts) with these contents:
# /etc/hosts
127.0.0.1	localhost
::1		localhost
127.0.1.1	adrians-{work/personal}-laptop.localdomain	adrians-{work/personal}-laptop
  1. Create root password with: passwd

  2. Initramfs

    1. Change/add the following to /etc/mkinitcpio.conf:
    # /etc/mkinitcpio.conf
    HOOKS=(base systemd keyboard autodetect modconf kms block sd-vconsole btrfs filesystems fsck)
    ...
    MODULES_DECOMPRESS="yes"
    1. Create a new initramfs mkinitcpio -P
  3. Systemd-boot:

    • Initialize systemd-boot (none of that GRUB/ReFIND nastiness) bootctl --esp-path=/boot install

    • Find and store the UUID of nvme0n1p2 by running: blkid -s UUID -o value /dev/nvme0n1p2 > /boot/loader/entries/arch.conf .

    • Edit the previously created file /boot/loader/entries/arch.conf with the following contents (BEWARE! mitigations=off is insecure, though it will significantly increase performance on older CPUs):

      # /boot/loader/entries/arch.conf
      title Arch Linux
      linux /vmlinuz-linux
      initrd /amd-ucode.img
      initrd /initramfs-linux.img
      options cryptdevice=UUID=<UUID-OF-ROOT-PARTITION>:luks:allow-discards root=/dev/mapper/luks rootflags=subvol=@ rd.luks.options=discard rw lsm=landlock,lockdown,yama,apparmor,bpf nowatchdog nomce mitigations=off zswap.enabled=0
    • Edit the file /boot/loader/loader.conf:

      # /boot/loader/loader.conf
      default arch.conf
  4. Reboot:

$ exit
$ umount -R /mnt
$ reboot
  1. Rejoice! 🎉

After first boot

  • Login with username root and the password you made previously

Network Configuration:

  1. Start systemd serices required for networking: systemctl start systemd-networkd.service systemd-resolved.service iwd.service

  2. Temporarily configure systemd-networkd by editing /etc/systemd/network/25-wireless.network and adding:

# /etc/systemd/network/25-wireless.network
[Match]
Name=wlan0

[Network]
DHCP=yes
  1. Restart the services: systemctl restart systemd-networkd.service systemd-resolved.service iwd

  2. Connect to wireless network using iwd:

$ iwctl
$ station wlan0 scan
$ station wlan0 get-networks
$ station wlan0 connect <SSID>  # enter passphrase if prompted
$ exit
  1. Verify with a ping: ping -c 3 google.com

ZRAM-based swap:

  1. Since we have no swap partition / file, we’ll install the cool kids zram-generator: pacman -S zram-generator
  2. Create /etc/systemd/zram-generator.conf:
# /etc/systemd/zram-generator.conf
[zram0]
zram-size = ram
compression-algorithm = zstd
$ systemctl daemon-reload
$ systemctl start /dev/zram0
$ swapon

Adding a new user

  1. Create the new user:
$ useradd -m -g users -G wheel adrian
$ passwd adrian
$ chsh -s /usr/bin/fish adrian
  1. Edit /etc/sudoers and add this line adrian ALL=(ALL) ALL (after root ALL=(ALL) ALL)

  2. Add these lines at the end of the sudoers file by running sudo EDITOR=nvim visudo:

## Use neovim as the editor for visudo
Defaults editor=/usr/bin/nvim

## Add asterisks when entering password
Defaults pwfeedback

BTRFS Snapshots

  1. In order to make snapshotting as seamless as possible, we'll install a few helper tools:
    • Install snapper: pacman -S snapper

    • Create snapper config:

        ```bash
        $ umount /.snapshots
        $ rm -r /.snapshots
        $ snapper -c root create-config /
        ```
      
    • For the above config, I have changed the following values:

        ```bash
        ## /etc/snapper/configs/root
        ALLOW_USERS="yes"
        TIMELINE_LIMIT_HOURLY="5"
        TIMELINE_LIMIT_HOURLY="10"
        TIMELINE_LIMIT_WEEKLY="0"
        TIMELINE_LIMIT_MONTHLY="0"
        TIMELINE_LIMIT_YEARLY="0"
        ```
      
    • Enable systemd times for automatic snapshotting and cleanup:

        ```bash
        # systemctl enable --now snapper-timeline.timer
        # systemctl enable --now snapper-cleanup.timer
        ```
      
    • Enable automatic pacman snapshotting: pacman -S snap-pac

Random nice to haves

  • Add Chaotic-AUR for prebuilt AUR binaries! Intructions: https://aur.chaotic.cx/

  • Install support for battery, power, and thermals:

    $ pacman -S acpi acpi_call acpid power-profiles-daemon
    $ systemctl enable —now acpid
  • Install reflector for better arch mirrors:

    $ pacman -S reflector`
    $ nvim where/ever/config/file/is
    $ systemctl enable —now reflector.timer
  • Install bluetooth protocol stack packages:

    $ pacman -S bluez bluez-utils
    $ systemctl enable —now bluetooth
  • Install support packages & drivers for printers:

    $ pacman -S cups cups-pdf
    $ pacman -S foomatic-db-engine foomatic-db-ppds foomatic-db-nonfree foomatic-db-nonfree-ppds foomatic-db-gutenprint-ppds
    $ systemctl enable cups.service
  • Install SSH protocol support & sync packages:

    $ pacman -S openssh rsync
    $ systemctl enable sshd
  • Install firewall support:

    $ pacman -S firewalld
    $ systemctl enable firewalld
  • Enable automatic TRIM for SSD's, along with BTRFS scrub:

    $ systemctl enable --now fstrim.timer
    $ systemctl enable --now [email protected]
    $ systemctl enable --now [email protected]
  • Enable automatic pacman cache deletion:

    $ systemctl enable --now paccache.timer
  • Enable avahi daemon:

    $ pacman -S avahi
    $ systemctl enable --now avahi-daemon.service
  • Install sound stuff: pacman -S pipewire pipewire-alsa pipewire-pulse pipewire-jack pipewire-docs

Installing Gnome (Wayland)

  1. Install gnome and related packages
$ pacman -S gnome gnome-shell-extensions gnome-shell-extension-appindicator gnome-software-packagekit-plugin gnome-text-editor NetworkManager 
$ pacman -S tilix powerline-fonts archlinux-appstream-data wl-clipboard 
$ pacman -S nautilus-sendto nautilus-share python-nautilus seahorse-nautilus ffmpegthumbnailer webp-pixbuf-loader
$ pacman -S firefox fragments fprint foliate newsflash extension-manager-git 
$ systemctl enable gdm.service
  1. Gnome uses NetworkManager, so will remove the previous network management to use the nice GUI interface for WiFi:
$ systemctl disable systemd-networkd.service
$ systemctl enable NetworkManager.service
  1. After paru has been installed, the additional Gnome Circle apps can be added:
$ paru -S gdm-settings-git menulibre gnome-connections 
$ paru -S drawing mousai video-trimmer wike plots kooha bitstower-markets celluloid passes headlines rnote

Storing LUKS filesystem encryption key in a TPM2 chip

  1. Install the required TPM2 packages:
$ pacman -S tpm2-tss tpm2-tools
$ sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 /dev/nvme0n1p2
  1. Then, change the following lines in /boot/loader/entries/arch.conf. NOTE!! in rd.luks.name=<UUID-OF-UNENCRYPTED-DEVICE-SUCH-AS-/dev/nvme0n1p2>=luks the luks at the end refers to the name of the openened device chosen at the beginning, aka /dev/mapper/luks. I'm not sure why, but this is the only way I could get it to work correctly.
options rd.luks.name=<UUID-OF-UNENCRYPTED-DEVICE-SUCH-AS-/dev/nvme0n1p2>=luks rd.luks.options=discard,<SAME-AS-BEFORE>=tpm2-device=auto root=UUID=<UUID-OF-ENCRYPTED-DEVICE-SUCH-AS-/dev/mapper/luks> rootflags=subvol=@ rw lsm=landlock,lockdown,yama,apparmor,bpf audit=1 nowatchdog nomce mitigations=off zswap.enabled=0 quiet loglevel=3 systemd.show_status=true rd.udev.log_level=3 libahci.ignore_sss=1 sysctl.vm.swappiness=200

2.1 ...and in /etc/mkinitcpio.conf and then remake it with sudo mkinitcpio -P

# /etc/mkinitcpio.conf
MODULES=(tpm_tis)
...
HOOKS=(base systemd keyboard autodetect modconf kms block sd-vconsole sd-encrypt btrfs filesystems fsck)

2.2 Install audit framework for AppArmor. More information can be found here https://wiki.archlinux.org/title/AppArmor and here https://wiki.archlinux.org/title/Audit_framework.

$ pacman -S audit
$ systemctl enable --now auditd.service
  1. Rejoice again!

PS: steps taken mostly from here: https://gist.github.com/chrisx8/cda23e2d1fa3dcda0d739bc74f600175 and https://wiki.archlinux.org/title/Trusted_Platform_Module#systemd-cryptenroll

Others

Improving wifi connectivity issues:

Improving pacman

  • Install mkinitcpio-firmware so that those super annoying warnings when remaking mkinitcpio go away.

  • Enable pacman colour (which is great for the next step). Do sudo nvim /etc/pacman.conf and uncomment the line that says #Color.

Random packages that I always install

$ sudo pacman -S pkgstats bat ripgrep mosh tldr btop duf lsd fd python-pip git-delta zoxide units
$ sudo pacman -S noto-fonts noto-fonts-cjk noto-fonts-emoji noto-fonts-extra 
$ sudo pacman -S poetry python-black python-isort python-coverage flake8
$ sudo paru -S starship gnome-shell-extension-extended-gestures-git pycharm-professional font-victor-mono cider papirus-icon-theme otf-san-francisco-mono ttf-mac-fonts ttf-yosemite-san-francisco-font-git
$ sudo paru -S whatsapp-for-linux rar btrfs-assistant bleachbit czkawka-gui
  • Docker:

    $ sudo pacman -S docker docker-compose
    $ systemctl start docker.service
    $ sudo usermod -aG docker $USER
    $ newgrp docker
    $ docker run hello-world
  • Improve boot times (as far as I can tell everything is still functional after these, though you have to ensure the restart policy of the docker.service unit is set to Restart=on-failure):

    $ systemctl disable docker.service
    $ sudo systemctl disable NetworkManager-wait-online.service
    

Performance and maintenance

  1. Btrfs defragmenting and rebalancing
$ btrfs filesystem defragment -r -v -czstd /
$ btrfs balance start -dusage=20 /
  1. Install CachyOS for x86-64-v3 compiled packages and optimised kernel: https://github.com/CachyOS/linux-cachyos
  • update packages
  • install new kernel sudo pacman -S linux-cachyos
  • remove old kernel? sudo pacman -Rs linux
  • update /boot/loader/entries/arch.conf to point to the new kernel images, while adding new AMD PSTATE (EPP) drivers
    title Arch Linux
    linux /vmlinuz-linux-cachyos
    initrd /amd-ucode.img
    initrd /initramfs-linux-cachyos.img
    options rd.luks.name=f4d10b40-f2df-400c-b025-c66ac039aae0=luks rd.luks.options=discard,f4d10b40-f2df-400c-b025-c66ac039aae0=tpm2-device=auto root=UUID=1fd43ca3-0ccb-48a7-a688-af2ddbd7b99b rootflags=subvol=@ rw lsm=landlock,lockdown,yama,apparmor,bpf audit=1 nowatchdog nomce mitigations=off zswap.enabled=0 quiet loglevel=3 systemd.show_status=true rd.udev.log_level=3 libahci.ignore_sss=1 amd-pstate=active
  • set a preference governor:
    $ cpupower frequency-set -g powersave
    $ echo balance_performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference
  1. Enable systemd-oomd as described here: https://www.reddit.com/r/archlinux/comments/mk2lg6/how_to_properly_configure_systemdoomd/
  1. Add Firefox (and other browsers, including Brave), to RAM: https://wiki.archlinux.org/title/Firefox/Profile_on_RAM

Long-term:

Acknowledgements:

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