- Pre-Flight Boot the Arch Linux live USB in UEFI mode and confirm the firmware interface:
# CHECK UEFI FIRMWARE VARIABLES
ls /sys/firmware/efi/efivars
Set the keyboard layout immediately. The default US layout will mangle your LUKS passphrase during creation if you rely on a UK keyboard.
# LOAD UK KEYBOARD LAYOUT
loadkeys uk
Connect to the network and synchronise the system clock:
# TEST NETWORK CONNECTIVITY
ping -c 3 archlinux.org
# CONNECT WIRELESSLY VIA IWCTL IF REQUIRED
iwctl
# station wlan0 scan
# station wlan0 connect <ssid>
# SYNCHRONISE SYSTEM CLOCK
timedatectl set-ntp true
timedatectl status
- Storage Architecture The system resides on a single NVMe drive. The partition table divides the drive into an EFI system partition, an unencrypted boot partition, and a primary encrypted container:
| Partition | Size | Role | Filesystem |
|---|---|---|---|
/dev/nvme0n1p1 | 1 GiB | EFI System Partition | vfat, unencrypted |
/dev/nvme0n1p2 | 2 GiB | /boot | ext4, unencrypted |
/dev/nvme0n1p3 | ~253 GiB | LUKS2 container | encrypted XTS-plain64 |
Inside the LUKS container, Logical Volume Management carves out four volumes:
| Volume | Size | Filesystem | Role |
|---|---|---|---|
vg0/swap | 16 GiB | swap | virtual memory and hibernation |
vg0/root | 50 GiB | XFS | system root |
vg0/var | 20 GiB | XFS | variable data and logs |
vg0/home | ~167 GiB | XFS | user directories |
2.1 Wipe the Drive
# WIPE EXISTING SIGNATURES AND PARTITIONS
wipefs -a /dev/nvme0n1
2.2 Partition
# CREATE GPT PARTITION TABLE AND SLICES
parted -s /dev/nvme0n1 mklabel gpt
parted -s /dev/nvme0n1 mkpart ESP fat32 1MiB 1025MiB
parted -s /dev/nvme0n1 set 1 esp on
parted -s /dev/nvme0n1 mkpart primary ext4 1025MiB 3073MiB
parted -s /dev/nvme0n1 mkpart primary 3073MiB 100%
2.3 Encrypt the Root Partition
# INITIALISE LUKS2 CONTAINER WITH 512 BIT KEY
cryptsetup luksFormat --type luks2 --cipher aes-xts-plain64 --key-size 512 /dev/nvme0n1p3
# OPEN ENCRYPTED CONTAINER
cryptsetup open /dev/nvme0n1p3 cryptroot
2.4 LVM
# INITIALISE PHYSICAL VOLUME AND VOLUME GROUP
pvcreate /dev/mapper/cryptroot
vgcreate vg0 /dev/mapper/cryptroot
# ALLOCATE LOGICAL VOLUMES
lvcreate -L 16G -n swap vg0
lvcreate -L 50G -n root vg0
lvcreate -L 20G -n var vg0
lvcreate -l 100%FREE -n home vg0
2.5 Format
# FORMAT BOOT AND EFI PARTITIONS
mkfs.vfat -F32 /dev/nvme0n1p1
mkfs.ext4 /dev/nvme0n1p2
# FORMAT LOGICAL VOLUMES
mkfs.xfs /dev/vg0/root
mkfs.xfs /dev/vg0/var
mkfs.xfs /dev/vg0/home
mkswap /dev/vg0/swap
2.6 Mount Mount the filesystems in strict hierarchical order to prevent directory obscuration:
# MOUNT ROOT AND CREATE BASE DIRECTORY STRUCTURE
mount /dev/vg0/root /mnt
mkdir -p /mnt/{boot,home,var}
# MOUNT BOOT AND CREATE EFI MOUNT POINT INSIDE IT
mount /dev/nvme0n1p2 /mnt/boot
mkdir -p /mnt/boot/efi
mount /dev/nvme0n1p1 /mnt/boot/efi
# MOUNT REMAINING LOGICAL VOLUMES AND ACTIVATE SWAP
mount /dev/vg0/var /mnt/var
mount /dev/vg0/home /mnt/home
swapon /dev/vg0/swap
- Base Installation Install the base operating system, hardware drivers, Niri, and your Wayland utility stack:
# INSTALL BASE SYSTEM AND PACKAGES
pacstrap -K /mnt \
base base-devel linux linux-headers linux-firmware \
intel-ucode \
lvm2 cryptsetup xfsprogs e2fsprogs dosfstools \
neovim tmux git networkmanager man-db man-pages sudo \
mesa vulkan-intel intel-media-driver \
niri waybar rofi-wayland \
xdg-desktop-portal-gnome xdg-desktop-portal-gtk \
xdg-user-dirs polkit-gnome \
ly \
kitty wl-clipboard grim slurp \
swaybg swaylock swayidle mako \
pipewire pipewire-alsa pipewire-pulse pipewire-jack wireplumber pavucontrol \
bluez bluez-utils \
tlp tlp-rdw acpid brightnessctl \
ttf-ibm-plex noto-fonts noto-fonts-emoji ttf-jetbrains-mono-nerd
Generate the filesystem table using universally unique identifiers:
# GENERATE FILESYSTEM TABLE
genfstab -U /mnt >> /mnt/etc/fstab
cat /mnt/etc/fstab
- System Configuration Enter the new system installation:
# ENTER CHROOT ENVIRONMENT
arch-chroot /mnt
4.1 Timezone and Locale
# CONFIGURE TIMEZONE AND CLOCK
ln -sf /usr/share/zoneinfo/Africa/Lagos /etc/localtime
hwclock --systohc
# GENERATE AND APPLY LOCALE
sed -i 's/^#en_GB.UTF-8 UTF-8/en_GB.UTF-8 UTF-8/' /etc/locale.gen
locale-gen
echo "LANG=en_GB.UTF-8" > /etc/locale.conf
4.2 Keymap
Write the configuration directly to /etc/vconsole.conf. The initramfs generation hooks read this file automatically:
# PERSIST CONSOLE KEYBOARD LAYOUT
echo "KEYMAP=uk" > /etc/vconsole.conf
4.3 Network Identity
# SET HOSTNAME AND HOSTS ENTRIES
echo "arch" > /etc/hostname
cat <<EOF> /etc/hosts
127.0.0.1 localhost
::1 localhost
127.0.1.1 arch.localdomain arch
EOF
# ENABLE NETWORK MANAGEMENT
systemctl enable NetworkManager
4.4 Initramfs
Edit /etc/mkinitcpio.conf and configure the HOOKS array. Placing microcode immediately after autodetect bundles CPU microcode updates directly into the main kernel initramfs image:
# MODIFY INITRAMFS HOOKS
nvim /etc/mkinitcpio.conf
Ensure the line reads exactly:
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt lvm2 resume filesystems fsck)
Generate the boot images:
# COMPILE INITRAMFS IMAGES
mkinitcpio -P
- Bootloader
# INSTALL GRUB AND EFI BOOT MANAGEMENT TOOLS
pacman -S grub efibootmgr
Retrieve the UUID of your encrypted LUKS partition:
# LOCATE LUKS PARTITION UUID
blkid /dev/nvme0n1p3
Edit /etc/default/grub and populate the GRUB_CMDLINE_LINUX variable with the LUKS UUID and LVM volume mappings:
# CONFIGURE GRUB KERNEL PARAMETERS
nvim /etc/default/grub
Set the line as follows, substituting <uuid> with the actual string from blkid:
GRUB_CMDLINE_LINUX="cryptdevice=UUID=<uuid>:cryptroot root=/dev/mapper/vg0-root resume=/dev/mapper/vg0-swap"
Install the bootloader to the EFI directory and generate the configuration file:
# INSTALL GRUB TO EFI PARTITION
grub-install --target=x86_64-efi --efi-directory=/boot/efi \
--bootloader-id=GRUB --removable
# GENERATE GRUB CONFIGURATION
grub-mkconfig -o /boot/grub/grub.cfg
- User Management
# ASSIGN ROOT PASSWORD
passwd
# CREATE PRIMARY USER ACCOUNT WITH HARDWARE GROUPS
useradd -m -s /bin/bash -G wheel,video,audio,storage,input osaigbovo
passwd osaigbovo
# GRANT SUDO PRIVILEGES TO WHEEL GROUP
EDITOR=nvim visudo
Uncomment the %wheel ALL=(ALL:ALL) ALL line inside the sudoers file.
- System Services Enable required system daemons before exiting the chroot environment:
# ENABLE DISPLAY MANAGER AND HARDWARE SERVICES
systemctl enable ly
systemctl enable bluetooth
systemctl enable tlp
systemctl enable tlp-rdw
systemctl enable acpid
# MASK RFKILL UNITS TO PREVENT TLP CONFLICTS
systemctl mask systemd-rfkill.service systemd-rfkill.socket
PipeWire and WirePlumber operate exclusively as user session daemons. Modern Arch Linux packages configure socket activation by default. When you log in as osaigbovo for the first time, systemd automatically initiates the audio server and desktop portal infrastructure without requiring manual intervention.
7.1 Niri Configuration Create the Niri configuration directory and file under your standard user account after first boot:
# CREATE NIRI CONFIGURATION DIRECTORY
mkdir -p ~/.config/niri
nvim ~/.config/niri/config.kdl
Populate config.kdl with your environment variables, background, locker, idle management, and status bar configurations:
// CONFIGURE WAYLAND ENVIRONMENT VARIABLES FOR INTEL GRAPHICS
environment {
LIBVA_DRIVER_NAME "iHD"
XDG_SESSION_TYPE "wayland"
XDG_SESSION_DESKTOP "niri"
XDG_CURRENT_DESKTOP "niri"
QT_QPA_PLATFORM "wayland"
MOZ_ENABLE_WAYLAND "1"
}
// SPAWN SESSION DAEMONS AND UTILITIES AT STARTUP
spawn-at-startup "/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1"
spawn-at-startup "mako"
spawn-at-startup "waybar"
spawn-at-startup "swaybg" "-m" "fill" "-i" "/home/osaigbovo/.config/wallpaper.png"
spawn-at-startup "swayidle" "-w" "timeout" "300" "swaylock -f" "timeout" "600" "niri msg action power-off-monitors" "resume" "niri msg action power-on-monitors"
- Finalisation Exit the chroot environment, unmount all disks, deactivate the logical volumes, seal the LUKS container, and reboot the machine:
# EXIT CHROOT
exit
# DEACTIVATE SWAP AND UNMOUNT FILESYSTEMS
swapoff -a
umount -R /mnt
# DEACTIVATE VOLUME GROUP AND CLOSE LUKS CONTAINER
vgchange -an vg0
cryptsetup close cryptroot
# REBOOT SYSTEM
reboot