6 min read
Installing Arch Linux

0) Prep & Clock

Boot the Arch ISO, get a shell, and connect to the network (iwctl for wifi; wired connections should be automatically handled). Check and sync time:

timedatectl status
timedatectl set-ntp true

1) Partition your disk

This is what I used for a system with 16 GiB RAM and 512 GiB

  • EFI System Partition (ESP): 1 GiB, FAT32 → /dev/sda1
  • Swap: 16 GiB → /dev/sda2
  • Root: rest of disk (Btrfs, inside LUKS) → /dev/sda3

Create them with fdisk/cgdisk and set the ESP type to EFI System.

2) Encrypt & Format

Data-at-rest encryption keeps your information safe only when the computer is not on.

# LUKS on root
cryptsetup luksFormat /dev/sda3
cryptsetup open /dev/sda3 cryptroot

# Filesystems
mkfs.btrfs -L rootfs /dev/mapper/cryptroot
mkfs.fat -F 32 /dev/sda1
mkswap /dev/sda2

3) Mount

mount /dev/mapper/cryptroot /mnt
mount --mkdir /dev/sda1 /mnt/boot
swapon /dev/sda2

(Optional) Create Btrfs subvolumes before mounting if you want them; I used a single root for simplicity.

4) Base Install

pacstrap -K /mnt base linux linux-firmware intel-ucode vim btrfs-progs networkmanager

Generate fstab and harden ESP mount with umask=0077:

genfstab -U /mnt >> /mnt/etc/fstab
# Edit the ESP line in /mnt/etc/fstab and add: umask=0077

5) Chroot & Basic System Config Speedrun

arch-chroot /mnt

Timezone & clock

ln -sf /usr/share/zoneinfo/America/Los_Angeles /etc/localtime
# Or your timezone
hwclock --systohc

Locale

locale-gen
echo 'LANG=en_US.UTF-8' > /etc/locale.conf

Hostname & hosts

echo '<hostname>' > /etc/hostname
cat >> /etc/hosts <<EOF
127.0.0.1   localhost
::1         localhost
127.0.1.1   <hostname>.localdomain <hostname>
EOF

6) Enable initramfs to unlock LUKS

Edit hooks in /etc/mkinitcpio.conf to include encrypt before filesystems. Example:

HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt filesystems fsck)

Build:

mkinitcpio -P

7) systemd-boot

bootctl install

/boot/loader/loader.conf

default arch.conf
timeout 0
console-mode keep
editor no

Find the UUID of the LUKS container:

blkid -s UUID -o value /dev/sda3

/boot/loader/entries/arch.conf

title   Arch Linux
linux   /vmlinuz-linux
initrd  /intel-ucode.img
initrd  /initramfs-linux.img
options cryptdevice=UUID=<UUID>:cryptroot root=/dev/mapper/cryptroot rw quiet

/boot/loader/entries/arch-fallback.conf

title   Arch Linux (fallback initramfs)
linux   /vmlinuz-linux
initrd  /intel-ucode.img
initrd  /initramfs-linux-fallback.img
options cryptdevice=UUID=<UUID>:cryptroot root=/dev/mapper/cryptroot rw quiet

Exit and reboot:

exit
reboot

8) Making a User

Log in as root.

systemctl enable --now NetworkManager
pacman -S sudo pam-u2f exfatprogs

Create your user and a temporary password:

useradd -m -G wheel magmawolf8
passwd magmawolf8

Enable sudo for the wheel group:

export EDITOR=vim
visudo
# Uncomment: %wheel ALL=(ALL:ALL) ALL

9) Configure FIDO2

Create key file:

su - magmawolf8
mkdir -p ~/.config/Yubico

Enroll two YubiKeys (replace <hostname>):

# First key
pamu2fcfg -o pam://<hostname> -i pam://<hostname> > ~/.config/Yubico/u2f_keys

# Second key (append with -n)
pamu2fcfg -o pam://<hostname> -i pam://<hostname> -n >> ~/.config/Yubico/u2f_keys

Edit /etc/pam.d/system-auth.

Add above the pam_unix.so line:

auth    [success=2 default=ignore]  pam_u2f.so cue origin=pam://<hostname> appid=pam://<hostname>

Then reboot and test you can log in as magmawolf8 using the keys.

If successful and you want key-only auth:

passwd -l magmawolf8   # lock user password
passwd -l root         # lock root for extra safety

10) Networking (systemd-resolved + DoT)

sudo systemctl enable --now systemd-resolved

Create a drop-in config file: /etc/systemd/resolved.conf.d/dnssec-tls.conf

[Resolve]
DNSOverTLS=opportunistic
DNSSEC=allow-downgrade
DNS=<your.dns.server,another.dns.server>

Tell NetworkManager to use resolved: /etc/NetworkManager/conf.d/dns.conf

[main]
dns=systemd-resolved

Point things to the stub:

sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

Disable autoconfigured DNS on your connection (adjust name as needed):

nmcli connection modify "Wired connection 1" ipv4.ignore-auto-dns yes
nmcli connection modify "Wired connection 1" ipv6.ignore-auto-dns yes

Reboot and verify:

resolvectl status   # ISP-provided DNS should be inactive on eno1 or wherever you get internet from

11) GUI Stack with Hyprland

Update, then install some core packages:

sudo pacman -Syu
sudo pacman -S wayland xorg-xwayland hyprland alacritty \
  noto-fonts noto-fonts-cjk noto-fonts-emoji noto-fonts-extra \
  xdg-desktop-portal-hyprland xdg-user-dirs
xdg-user-dirs-update

QT (for hyprpolkitagent):

sudo pacman -S qt5-wayland qt5-svg   # (qt6-wayland should already be present)
sudo pacman -S hyprpolkitagent
# Put in Hyprland config:  exec-once = systemctl --user start hyprpolkitagent

Thermal stuff, only for Intel CPUs:

sudo pacman -S cpupower thermald
sudo systemctl enable --now thermald
sudo systemctl enable cpupower

12) Ly Login Manager with FIDO2

Install dev tools and build ly:

sudo pacman -S base-devel python git less zig
git clone -b fido2-integration https://github.com/magmawolf8/ly
cd ly
zig build
sudo zig build installexe   # systemd is default init

Tweak services:

sudo systemctl disable [email protected]
sudo systemctl enable ly

Edit ly’s config.ini and set:

require_fido2=true

Reboot your system and confirm that the YubiKey login works for ly.

sudo pacman -S openssh
# OpenSSH supports FIDO2 keys (types: ecdsa-sk, ed25519-sk).
# Follow: https://developers.yubico.com/SSH/Securing_SSH_with_FIDO2.html

Set your identity for Git purposes (if you need to):

git config --global user.name  "<Your Name>"
git config --global user.email "<[email protected]>"

14) Configuring Hyprland

Place config in ~/.config/hypr/hyprland.conf (and tweak as desired).

Idle/lock & notification functionality:

sudo pacman -S hypridle hyprlock mako

15) Audio (PipeWire)

sudo pacman -S pipewire wireplumber pipewire-audio pipewire-alsa pipewire-pulse pipewire-jack
systemctl --user enable --now pipewire pipewire-pulse
wpctl set-profile "<card name>" "output:hdmi-stereo+input:analog-stereo"

16) Printer Discovery (CUPS + Avahi mDNS)

sudo pacman -S cups cups-pdf nss-mdns avahi
sudo systemctl enable cups.socket
sudo systemctl enable avahi-daemon

/etc/systemd/resolved.conf.d/mdns-disable.conf

[Resolve]
MulticastDNS=no

/etc/nsswitch.conf:

hosts: mymachines mdns_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] files myhostname dns

17) Hypr Ecosystem & Apps

sudo pacman -S wofi hyprpaper hyprcursor
# Set wallpaper per https://wiki.hypr.land/Hypr-Ecosystem/hyprpaper/
# Set cursor per hyprcursor instructions
sudo pacman -S firefox discord

19) Wrap it up

Reboot one more time to make sure that everything works:

  • Unlock the disk -> FIDO2 login (ly) -> Hyprland -> network/DNSSEC -> audio -> printing

Have fun with your Arch installation!