Skip to content

Arch Linux Installation

This is a step by step installation of my own Arch Linux configuration.

The current installation is using the following options:

  • Boot & Firmware: UEFI
  • Bootloader: systemd-boot
  • Encryption: LUKS
  • Filesystem: Btrfs
  • Kernels: linux and linux-lts
  • Shell: Fish
  • Terminal Emulator: Kitty
  • Desktop Environment: KDE Choose one of the two
  • Window Manager: Hyprland Choose one of the two
  • Display Manager: sddm
  • File Manager: lf (TUI) + Dolphin (GUI)
  • AUR Helper: Yay
  • Network Manager: NetworkManager
  • Audio System: Pipewire
  • Desktop Notifications: Mako Hyprland
  • Status Bar: Waybar Hyprland
  • Application Launcher: Vicinae
  • Text Editor: NeoVim (TUI) + VSCode (GUI)
  • Browser: Firefox

To make the whole installation easier you can remotely connect (via SSH) to the system after setting up network (Ethernet or Wi-fi). Only need to enable the sshd service and setup a password.

SSH setup
systemctl start sshd
passwd

Set keyboard layout optional

Section titled “Set keyboard layout ”
Set desired keyboard layout
# List all available keymaps
localectl list-keymaps
# Replace with your desired keyboard layout
loadkeys pt-latin1
Connecting to Wi-Fi via iwd
iwctl
# Generally named wlan0 use "device list" to list all options
[iwd]# station NAME scan
[iwd]# station NAME get-networks
# Replace with your network name
[iwd]# station NAME connect SSID
[iwd]# exit
ping ping.archlinux.org
# Verify system clock is synchronised once internet connection is established
timedatectl

Before setting up any encryption or partitions, I like to wipe everything and fill it with random bytes (this will take a while depending on your drive size).

Wiping entire device
dd if=/dev/urandom of=/dev/DEVICE_NAME bs=1M status=progress

Now to set up the partitions. For now, I’m just using two partitions:

  • Boot partition: 1GB size (EFI System)
  • Root partition: Remaining space (Linux File System)

I do not have any swap partition for now as my current drive is small, so I rather trade performance for more space (I’ll use zram instead).

Mount PointPartitionPartition TypeSuggested size
/boot/dev/efi_partitionEFI SystemAt least 1GiB
//dev/root_partitionLinux File SystemRemaining space
Disk Partition Setup
fdisk /dev/DEVICE_NAME
# Create GPT partition table
g
# Boot partition
n
<use default>
<use default>
+1G
t
# `uefi` or generally `1` for EFI System, but double check the list of types
1
# Root partition
n
<use default>
<use default>
<use default>
# Save partition table
w

The partitions in lsblk should look something like:

Disk Partition Setup
NAME TYPE MOUNTPOINT SIZE
DEVICE_NAME disk ...
├─DEVICE_NAME1 part 1G
└─DEVICE_NAME2 part ...

This section covers encrypting the root partition with LUKS encryption.

Encryption setup
modprobe dm-crypt
modprobe dm-mod
cryptsetup -v luksFormat -s 512 -h sha512 /dev/root_partition
# Enter passphrase and do not forget it, or your data will be inaccessible

We’ll setup a Btrfs system with the following subvolumes:

SubvolumeMountpoint
@/
@home/home
@var_log/var/log
@pkg/var/cache/pacman/pkg
@snapshots/.snapshots
Btrfs Setup
# Skip this command if you're not using encryption
# Replace /dev/mapper/root by /dev/root_partition
cryptsetup open /dev/root_partition root
# Create Btrfs subvolumes
mkfs.btrfs -L root /dev/mapper/root
mkdir -p /mnt/arch_btrfs
mount -o compress=zstd /dev/mapper/root /mnt/arch_btrfs
btrfs subvolume create -p /mnt/arch_btrfs/@
btrfs subvolume create -p /mnt/arch_btrfs/@home
btrfs subvolume create -p /mnt/arch_btrfs/@var_log
btrfs subvolume create -p /mnt/arch_btrfs/@pkg
btrfs subvolume create -p /mnt/arch_btrfs/@snapshots
umount /mnt/arch_btrfs
# Mount the subvolumes
mount -o compress=zstd,subvol=@ /dev/mapper/root /mnt
mount -o compress=zstd,subvol=@home --mkdir /dev/mapper/root /mnt/home
mount -o compress=zstd,subvol=@var_log --mkdir /dev/mapper/root /mnt/var/log
mount -o compress=zstd,subvol=@pkg --mkdir /dev/mapper/root /mnt/var/cache/pacman/pkg
# Format boot partition and mount
mkfs.fat -F 32 /dev/efi_partition"
mount -o fmask=0077,dmask=0077 --mkdir /dev/efi_partition /mnt/boot

The partitions in lsblk should look something like:

Disk Partition Setup
NAME TYPE MOUNTPOINTS
DEVICE_NAME disk
├─efi_partition part /mnt/boot
└─root_partition part
└─root crypt /mnt/var/cache/pacman/pkg
/mnt/var/log
/mnt/home
/mnt

If not using LUKS encryption, the root_partition will map directly to the subvolumes without the intermediary root.

Update mirrorlist
reflector --save /etc/pacman.d/mirrorlist --latest 5 --protocol https --country Portugal,Netherlands,Germany --sort rate
Installing essential packages
pacman -Sy
# Remove zram-generator if using swap partition
pacstrap -K /mnt --needed base base-devel linux linux-headers linux-lts linux-lts-headers linux-firmware btrfs-progs snapper networkmanager efibootmgr neovim zram-generator
Setup snapper backups
arch-chroot -S /mnt snapper --no-dbus -c root create-config /
arch-chroot -S /mnt snapper --no-dbus -c home create-config /home
# Delete automatically created subvolumes by snapper
btrfs subvolume delete /mnt/home/.snapshots
btrfs subvolume delete /mnt/.snapshots
# Replace /dev/mapper/root by your /dev/root_partition if not using encryption
mount -o compress=zstd,subvol=@snapshots --mkdir /dev/mapper/root /mnt/.snapshots
chmod 750 /mnt/.snapshots
Fstab Generation
genfstab -U /mnt >> /mnt/etc/fstab

Change root to the new system:

Terminal window
arch-chroot /mnt
Terminal window
systemctl enable snapper-timeline.service
systemctl enable snapper-cleanup.service

Add sd-encrypt to HOOKS in /etc/mkinitcpio.conf.

etc/mkinitcpio.conf
HOOKS=(base systemd autodetect microcode modconf kms keyboard keymap sd-vconsole block sd-encrypt filesystems fsck)

You can search the available timezones by using ls /usr/share/zoneinfo and then ls /usr/share/zoneinfo/Region when you choose your region.

Setting your timezone
ln -sf /usr/share/zoneinfo/Region/City /etc/localtime
hwclock --systohc

Add the NTP pools to your etc/systemd/timesyncd.conf:

etc/systemd/timesyncd.conf
#NTP=
#FallbackNTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org
NTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org
FallbackNTP=0.pool.ntp.org 1.pool.ntp.org
Enable timesyncd service
systemctl enable systemd-timesyncd.service

Uncomment wanted locales in /etc/locale.gen.

/etc/locale.gen
#en_GB.UTF-8 UTF-8
#ja_JP.UTF-8 UTF-8
#pt_PT.UTF-8 UTF-8
en_GB.UTF-8 UTF-8
ja_JP.UTF-8 UTF-8
pt_PT.UTF-8 UTF-8
Generate locales
locale-gen

Create /etc/locale.conf and set your language preferences.

/etc/locale.conf
LANG=en_GB.UTF-8
LANGUAGE=en_GB
LC_CTYPE=en_GB.UTF-8
LC_NUMERIC=en_GB.UTF-8
LC_TIME=pt_PT.UTF-8
LC_COLLATE=C.UTF-8
LC_MONETARY=pt_PT.UTF-8
LC_MESSAGES=en_GB.UTF-8
LC_PAPER=en_GB.UTF-8
LC_NAME=en_GB.UTF-8
LC_ADDRESS=pt_PT.UTF-8
LC_TELEPHONE=pt_PT.UTF-8
LC_MEASUREMENT=pt_PT.UTF-8
LC_IDENTIFICATION=en_GB.UTF-8

Create /etc/vconsole.conf and set your console keyboard layout.

etc/vconsole.conf
KEYMAP=pt-latin1

Set your hostname in /etc/hostname.

etc/hostname
myhostname
Enable NetworkManager
systemctl enable NetworkManager.service
Terminal window
mkinitcpio -P
Terminal window
passwd

This is the setup for systemd-boot bootloader, if you want to use other bootloader like GRUB, read the appropriate wiki page.

systemd-boot setup
bootctl install
# Get UUID of `root_partition" and put it on our future entry
blkid /dev/root_partition >> /boot/loader/entries/arch.conf
# Duplicate entry for LTS kernel (can do it later after configuring normal kernel)
cp /boot/loader/entries/arch.conf /boot/loader/entries/arch-lts.conf

Edit the bootloader configuration in /boot/loader/loader.conf.

boot/loader/loader.conf
default @saved
timeout 5
console-mode max

Create entries for each kernel in /boot/loader/entries/.

boot/loader/entries/arch.conf
title Arch Linux
linux /vmlinuz-linux
initrd initramfs-linux.img
options rd.luks.name=DEVICE-UUID=root root=/dev/mapper/root rootflags=subvol=@
boot/loader/entries/arch-lts.conf
title Arch Linux (LTS)
linux /vmlinuz-linux-lts
initrd initramfs-linux-lts.img
options rd.luks.name=DEVICE-UUID=root root=/dev/mapper/root rootflags=subvol=@
Terminal window
pacman -S --needed fish
Create your user
useradd -m -G wheel -s /usr/bin/fish USERNAME
passwd USERNAME
export EDITOR=nvim
visudo

The last command is used to configure our sudo users. Uncomment one of the lines whether you want sudo to be used with or without password.

#%wheel ALL=(ALL:ALL) ALL
%wheel ALL=(ALL:ALL) ALL
# or
#%wheel ALL=(ALL:ALL) NOPASSWD: ALL
%wheel ALL=(ALL:ALL) NOPASSWD: ALL

Once installed (it is enabled on install), this will send your installed packages, the architecture and the mirror you’re using to Arch Linux developers. This information is anonymous and can’t be used to identify the user, and is only used to help the developers prioritise their efforts.

Terminal window
pacman -S --needed pkgstats

This setup depends on your card. Always better to check the Arch Wiki for this, especially with NVIDIA cards.

This is always changing with NVIDIA drivers, so check compatibility in the wiki.

Install NVIDIA drivers
pacman -S --needed nvidia-open-dkms nvidia-utils

I haven’t used an AMD GPU yet, as my desktop with one is still running Windows. Check the wiki for how to install AMD drivers.

Terminal window
pacman -S --needed kitty

If qt6-multimedia-ffmpeg pipewire-jack noto-fonts aren’t specified, the installation will ask you to choose between these and other options.

Install KDE packages
pacman -S --needed plasma-meta ark plasma-workspace qt6-multimedia-ffmpeg pipewire-jack noto-fonts
Install Hyprland packages
pacman -S --needed hyprland
Rebooting...
exit
sync
umount -R /mnt
reboot now

Add the zram configuration to /etc/systemd/zram-generator.conf.

etc/systemd/zram-generator.conf
[zram0]
Enable zram service
systemctl start /dev/zram0
Wi-Fi configuration with NetworkManager
nmcli device wifi list
nmcli device wifi connect SSID_OR_BSSID password PASSWORD
nmcli connection show
ping ping.archlinux.org
Yay setup
mkdir tools # optional
sudo pacman -S --needed git base-devel
cd tools
git clone https://aur.archlinux.org/yay.git
cd yay && makepkg -si

Periodically update mirrorlist with reflector.

Setup reflector
yay -S --needed reflector

Configure the settings in /etc/xdg/reflector/reflector.conf.

etc/xdg/reflector/reflector.conf
--save /etc/pacman.d/mirrorlist
--protocol https
# --country France,Germany
--country Portugal,Netherlands,Germany
--latest 5
--sort age
--sort rate
Enable reflector services
sudo systemctl enable reflector.timer
Install SSH
yay -S --needed openssh
Install sddm
yay -S --needed sddm
sudo systemctl enable sddm.service
Install Pipewire
yay -S --needed pipewire wireplumber
Install file managers
yay -S --needed lf dolphin
Install browsers
yay -S --needed firefox
Install fonts
yay -S --needed noto-fonts noto-fonts-cjk noto-fonts-emoji ttf-noto-nerd
Install Bluetooth
yay -S --needed bluez bluez-utils
sudo systemctl enable bluetooth.service
# Start now
sudo systemctl start bluetooth.service
Terminal window
yay -S --needed visual-studio-code-bin
Terminal window
yay -S --needed fastfetch
Terminal window
yay -S --needed mise
Terminal window
yay -S --needed python-pipx
Terminal window
yay -S --needed xdg-desktop-portal-hyprland
Terminal window
yay -S --needed hyprpolkitagent
Terminal window
yay -S --needed libnotify mako
Terminal window
yay -S --needed pipewire-jack waybar