Arch Linux ‐‐ Install Notes - arluke/homelab GitHub Wiki

Intro

This is more for my own personal reference but if it helps someone else then all the better. I am far from an expert on this and this is just me compiling the things I've found in solving my own issues. Very much a work in progress but should give you a functioning system.

Guide is functionalish as of February 2025 on linux-lts, kernel 6.13.4-arch1-1.

Prep

Wipe drives

Root filesystem is assumed to be on /dev/nvme0n1. md raid5 for /home is assumed to be on /dev/nvme1n1, /dev/nvme2n1, /dev/nvme3n1. Adjust accordingly or you're gonna have a bad time.

for i in {0..3}; do \
    wipefs -a /dev/nvme${i}n1;
    sgdisk --zap-all /dev/nvme${i}n1;
    sgdisk -o /dev/nvme${i}n1;
    done;

Partition Disks

sgdisk -n1:4096:+1GiB -t1:ef00 /dev/nvme0n1;
sgdisk -n2:0:+896GiB  -t2:8309 /dev/nvme0n1

Encryption

cryptsetup -v luksFormat /dev/nvme0n1p2;
cryptsetup open /dev/nvme0n1p2 root

Format

mkfs.btrfs /dev/mapper/root;
mkfs.fat -F32 /dev/nvme0n1p1

Mounting / Subvols

Initial Mount and Top-Level Subvol creation

mount -o defaults,discard /dev/mapper/root /mnt;
btrfs subvol create /mnt/@;
umount /mnt

Remount rootfs with subvol=@ flag. Create remaining subvols and mount /efi

mount -o defaults,discard,subvol=@ /dev/mapper/root /mnt;
mkdir -p /mnt/var/cache/pacman;
btrfs subvol create /mnt/.snapshots /mnt/var/log /mnt/var/cache/pacman/pkg;

mount --mkdir -o uid=0,gid=0,fmask=0077,dmask=0077,discard /dev/nvme0n1p1 /mnt/efi;

Allocate and Activate swapfile

btrfs filesystem mkswapfile --size 32G /mnt/.swapfile;
swapon /mnt/.swapfile

Pacstrap the base system and chroot into the new environment.

pacstrap -K /mnt base linux linux-headers linux-firmware amd-ucode efibootmgr gdisk btrfs-progs mdadm sudo neovim systemd-ukify sbsigntools sbctl efitools networkmanager openssh;
genfstab -U /mnt >> /mnt/etc/fstab;
printf '\nEDITOR=nvim' >> /mnt/etc/bash.bashrc;
arch-chroot /mnt

[!IMPORTANT] If you are on an Intel-based architecture, replace amd-ucode with intel-ucode

Do not forget the -U flag for genfstab. Filesystem labels can change between reboots (especially PCIe flash) resulting in a failure to boot. This will create the /etc/fstab file in your new environment using the partition UUID instead of labels.

Build /home

sgdisk -n1:4096:+1792GiB -t1:fd00 /dev/nvme1n1;
sgdisk -n1:4096:+1792GiB -t1:fd00 /dev/nvme2n1;
sgdisk -n1:4096:+1792GiB -t1:fd00 /dev/nvme3n1;
mdadm --create --verbose /dev/md/data  --level=5 --raid-devices=3 \
    /dev/nvme1n1p1 /dev/nvme2n1p1 /dev/nvme3n1p1

cryptsetup -v luksFormat /dev/md/data;
cryptsetup open /dev/md/data data;
mkfs.btrfs /dev/mapper/data

mount /dev/mapper/data /data
btrfs subvol create /data/@home
umount /data
mount --mkdir -o defaults,discard,subvol=@home /dev/mapper/data /home

openssl genpkey -algorithm RSA -out /etc/cryptsetup-keys.d/data.pem
echo "data     UUID=${uuid}     /etc/cryptsetup-keys.d/data.pem     luks,discard,tries=3" > /etc/crypttab
echo "UUID=${uuid}     /home     btrfs     rw,relatime,ssd,discard,space_cache=v2,subvol=/@home     0 0 >> /etc/fstab

Basic System Configuration

Set localtime and generate locales

Select the appropriate timezone for your system

ln -sf /usr/share/zoneinfo/America/Phoenix /etc/localtime;
hwclock --systohc
nvim /etc/locale.gen;
locale-gen;
echo LANG=en_US.UTF-8 >> /etc/locale.conf
echo KEYMAP=us >> /etc/vconsole.conf;
echo ${HOSTNAME} >> /etc/hostname;
nvim /etc/hosts
  SET:
    127.0.0.1        localhost  
    ::1              localhost  
    127.0.0.1        HOSTNAME.LOCALDOMAIN        HOSTNAME

sudo user and config sudo

groupadd --gid 5001 ssh-users;
groupadd --gid 6000 arluke;
useradd --uid 6000 --gid 6000 --groups arluke,ssh-users,wheel --shell /bin/bash --home /home/arluke --create-home arluke;
echo '%wheel ALL=(ALL:ALL) ALL' > /etc/sudoers.d/00_wheel;
passwd arluke

Configure Networking Packages

echo AllowGroups ssh-users > /etc/ssh/sshd_config.d/10-AllowGroups.conf;
systemctl enable NetworkManager sshd

Update appropriate hooks in /etc/mkinitcpio.conf

HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck)

Set kernel commandline options for encryption and btrfs root in /etc/cmdline.d/root.conf

rd.luks.name=${DEVICE_UUID}=root root=/dev/mapper/root rootflags=subvol=@ rw rootfstype=btrfs rd.shell=0 rd.emergency=reboot rd.luks.options=discard

Unified Kernel Image (UKI)

Create UKI key config: /etc/kernel/uki.conf

[UKI]
OSRelease=@/etc/os-release
PCRBanks=sha256
 
[PCRSignature:initrd]
Phases=enter-initrd
PCRPrivateKey=/etc/kernel/pcr-initrd.key.pem
PCRPublicKey=/etc/kernel/pcr-initrd.pub.pem

Generate UKI keys

ukify genkey --config=/etc/kernel/uki.conf

Update the preset file to enable UKI: /etc/mkinitcpio.d/linux.preset

# mkinitcpio preset file for the 'linux' package

#ALL_config="/etc/mkinitcpio.conf"
ALL_kver="/boot/vmlinuz-linux"

PRESETS=('default' 'fallback')

#default_config="/etc/mkinitcpio.conf"
#default_image="/boot/initramfs-linux.img"
default_uki="/efi/EFI/Linux/arch-linux.efi"
default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"

#fallback_config="/etc/mkinitcpio.conf"
#fallback_image="/boot/initramfs-linux-fallback.img"
fallback_uki="/efi/EFI/Linux/arch-linux-fallback.efi"
fallback_options="-S autodetect"

Create EFI boot directories and install bootloader files

mkdir -p /efi/EFI/Linux
mkinitcpio -p linux
bootctl install

Secure Boot

If your system secure boot is not already in setup mode, reboot into BIOS and make it so.

sudo sbctl status
sudo sbctl create-keys
sudo sbctl enroll-keys
sudo sbctl verify
sudo sbctl sign -s /efi/EFI/BOOT/BOOTX64.EFI;
sudo sbctl sign -s /efi/EFI/Linux/arch-linux-fallback.efi;
sudo sbctl sign -s /efi/EFI/Linux/arch-linux.efi;
sudo sbctl sign -s /efi/EFI/systemd/systemd-bootx64.efi
  • Reboot and enable secure boot in BIOS
sudo sbctl status

Post-Install Stuff

This section is largely a notepad for me to remember application and other important settings.

Packages

sudo pacman -Sy 7zip base-devel curl fastfetch gdisk git less nftables pciutils powertop unzip vlc wget zip

Fonts

sudo pacman -Sy noto-fonts noto-fonts-extra ttf-arimo-nerd ttf-font-awesome

yay (aur helper)

git clone https://aur.archlinux.org/yay.git ~/git/yay
cd ~/git/yay
makepkg -si

Graphics Configuration

AMD

sudo pacman -S mesa vulkan-radeon

NVIDIA

[!IMPORTANT] The particular package you require will depend on the generation of your GPU architecture. See the NVIDIA ArchWiki page for further detail.

sudo pacman -Sy nvidia-open nvidia-utils

Update /etc/mkinitcpio.conf to load modules during initramfs

MODULES=(... nvidia nvidia_modeset nvidia_uvm nvidia_drm ...)  
sudo reboot

[!IMPORTANT] There are two kernel parameters for the nvidia_drm module to be considered: modeset and fbdev. Both are enabled by default when using the nvidia-utils package. Both are required for Hyprland on Linux 6.11 or later.

Verify these both output 'Y':

sudo cat /sys/module/nvidia_drm/parameters/modeset;
sudo cat /sys/module/nvidia_drm/parameters/fbdev

If not...

sudo echo options nvidia_drm modeset=1 fbdev=1 > /etc/modprobe.d/nvidia-drm.conf

Set maximum power limit at boot: /etc/systemd/system/nvidia-power-limit.service

[Unit]  
Description=Set NVIDIA GPU Power Limit  

[Service]  
Type=oneshot  
ExecStart=/usr/bin/nvidia-smi -pl 320  

[Install]  
WantedBy=multi-user.target
sudo systemctl enable nvidia-power-limit.service

Audio

Install audio packages. pipewire and pipewire-pulse are installed in lieu of pulseaudio.

sudo pacman -Sy alsa-firmware alsa-utils pipewire pipewire-alsa pipewire-jack pipewire-pulse wireplumber pavucontrol;
systemctl --user enable pipewire pipewire-pulse wireplumber

Set default device in /etc/asound.conf, Where $card is the card number output from aplay -l

defaults.pcm.card ${card}
defaults.ctl.card ${card}

Open pavucontrol and set SSL 2+ MkII profile to "Pro Audio" to split channels and isolate the mic

Desktop Environment

KDE Plasma

sudo pacman -Sy sddm plasma konsole dolphin kate
sudo systemctl enable sddm

Hyprland

sudo pacman -Sy hyprland hyprlock hyprpaper kitty sddm waybar wofi

NVIDIA environmental variables: ~/.config/hypr/hyprland.conf

env = LIBVA_DRIVER_NAME,nvidia
env = __GLX_VENDOR_LIBRARY_NAME,nvidia
env = NVD_BACKEND,direct

Electron Apps: ~/.config/hypr/hyprland.conf

[!Warning] This can cause issues like being unable to assign keybinds in Discord vs the default running on xwayland. It's better to use as a flag for individual applications. Needs further investigation.

env = ELECTRON_OZONE_PLATFORM_HINT,auto

Applications

kitty (terminal)

sudo pacman -Sy kitty

On first SSH into system, use `kitten ssh user@hostname'

gnome-keyring

Secrets management in Hyprland.

sudo pacman -Sy gnome-keyring libsecret seahorse

gnome-text-editor

sudo pacman gnome-text-editor

nautilus

sudo pacman nautilus

discord

sudo pacman -Sy discord noto-fonts-extra

piper

Mouse configuration for Logitech devices (must be USB connected)

sudo pacman -Sy piper

obsidian

sudo pacman -Sy obsidian

keyd (remapping inputs)

sudo pacman -Sy keyd

Gaming

gamescope

Tweaks

[!CAUTION] These are tweaks for my system that I have found fix various performance issues. Use at your own risk.

vim /etc/sysctl.d/50-coredump.conf

# disable core dumps
fs.suid_dumpable=0
kernel.core_pattern=|/bin/false
vim /etc/sysctl.d/90-vm.parameters.conf 
# reduce disk swapping
vm.swappiness = 10
# set dirty cache size
vm.dirty_bytes = 4194304
vm.dirty_background_bytes = 4194304