Let me preface this post by saying that if you’re trying Linux for the first time, install Fedora. Fedora strikes a great balance of new features, stability and a “just works” factor. I’ve been using Fedora as my daily driver for years and the main reason I switched to Arch is because I wanted the Arch DIY installation experience, imperfections and all.

That said, here goes!

I installed Arch Linux on my Thinkpad P14s Gen 1 ( AMD ). I wanted the install to be as similar as possible to my old Fedora install. That means GNOME on Wayland, Pipewire audio, btrfs filesystem on a LUKS encrypted partition with a neat graphical boot splash screen that prompts for the password.

Arch install guides are dime-a-dozen, so after basic install steps I’m going to focus on the post-install fixes and configuration that I did to make the install feel complete.

Backing up the old install

Before installing Arch I decided to back up some important bits and pieces of my existing Fedora install.

  • Back up fstab and crypttab
  • Back up Virt XML files for VMs
  • Back up GPG, SSH keys and
  • Back up home directory files ( without config stuff )
  • List of installed Flatpaks ( for reference later )
  • List of installed Fedora packages ( for reference later )

SecureBoot

For now I’ve disabled SecureBoot on my laptop. There’s a way to get this working and sign your own bootloader, initramfs, kernel etc. but I’m going to figure that out later.

Installation Steps

These were the basic steps I took for my Arch install.

I booted the system up with an Arch Installer USB.

Partitioning and formatting the SSD

Using fidsk I created a GPT partition table on my SSD ( nvme0n1 ) with three partitions:

  1. 600MB for EFI ( nvme0n1p1 )
  2. 1GB Boot ( nvme0n1p2 )
  3. Rest of Disk ( nvme0n1p3 )

I formatted the EFI partition as vfat

mkfs.vfat /dev/nvme0n1p1

I formatted the boot partition as ext4

mkfs.ext4 /dev/nvme0n1p2

I set up LUKS encryption for nvme0n1p3

LUKS encryption with dm-crypt

The AMD Ryzen 7 4750U CPU has SHA extension that accelerates SHA-1 and SHA-256, but not SHA-512. For that reason I stuck with SHA-256, which is the default for LUKS.

I created an encrypted LUKS partition on nvme0n1p3 with 5000 iterations to hash the password:

cryptsetup luksFormat -i 5000 --label system-luks /dev/nvme0n1p2

Next we open the encrypted partition. Note the extra options for SSD optimizations and persistence ( See: https://wiki.archlinux.org/title/Dm-crypt/Specialties for more information )

cryptsetup luksOpen --allow-discards --perf-no_read_workqueue --perf-no_write_workqueue --persistent /dev/nvme0n1p3 system-luks

This opens up a device-mapper disk I can use under /dev/mapp/system-luks

Set up btrfs with subvolumes then mount them

Next I set up btrfs on /dev/mapper/system-luks

Format the device as btrfs with the label “arch-linux”

mkfs.btrfs -L arch-linux /dev/mapper/system-luks

I mounted the new btrfs filesystem to /mnt with options for zstd compression and autodefrag.

mount -t btrfs -o compress=zstd:1,autodefrag /dev/mapper/system-luks /mnt

Next I made subvolumes for root (@), home (@home) and snapshots (@snapshot)

btrfs subvolume create /mnt/@ && \
btrfs subvolume create /mnt/@home && \
btrfs subvolume create /mnt/@snapshot

After creating these subvolumes I unmounted the btrfs filesystem from /mnt, made new directories for the subvolumes to be mounted and then mounted the filesystem again

umount /mnt && \
mkdir /mnt/{home,.snapshot} && \
mount -t btrfs -o compress=zstd:1,autodefrag,ssd,space_cache=v2,subvol=/@ /mnt && \
mount -t btrfs -o compress=zstd:1,autodefrag,ssd,space_cache=v2,subvol=/@home /mnt/home && \
mount -t btrfs -o compress=zstd:1,autodefrag,ssd,space_cache=v2,subvol=/@ /mnt/.snapshot 

Mount bootloader and EFI partitions

After encrypted btrfs is all mounted, we can mount the boot and EFI partitions in the right place. I’m aware that there are probably simpler ways to accomplish this, but I’m replicating the layout and configuration of my old Fedora install ( separate boot partition with GRUB etc. ).

mkdir /mnt/boot && \
mount /dev/nvme0n1p2 /mnt/boot && \
mkdir /mnt/boot/EFI && \
mount /dev/nvme0n1p1 /mnt/boot/EFI 

Pacstrap

This is is the fun part. I used pacstrap to install packages to the new mountpoints. My internet connectivity worked automatically with the installer ISO because I was plugged in to Ethernet.

Most Arch install guides recommend a fairly modest list of packages to install at the first but I had a pretty good idea of what I wanted, so I decided to install it all from the get-go! I still had to add more packages later but this gave me a pretty functional GNOME/Wayland desktop with Pipewire sound out of the box.

pacstrap -i /mnt \
base \ 
base-devel \
amd-ucode \
grub \
efibootmgr \
dosfstools \
openssh \
os-prober \
mtools \
linux \
linux-headers \
mkinitcpio \
vim \
vi \
NetworkManager \ 
wireless_tools \
wpa_supplicant \
linux-firmware \
iproute2 \
bluez \
bluez-utils \
firewalld \
podman \
sudo \
nmap \
hdparm \
less \
tmux \
pipewire \
pipewire-pulse \
pipewire-media-session \
gnome \
gnome-extras \
gnome-bluetooth \
virt-manager \
libvirt \
qemu-desktop \
libguestfs \
vlc \
firefox \
wine \
flatpak \
ffmpeg \
mpv \
btrfs-progs \
fwupd \
git \
htop \
net-tools \
tcpdump \

This command might take a while to download packages and install everything

Generate fstab file and confirm device UUID

Now that packages are installed I can create an fstab file to ensure my system knows where and how to mount everything. The genfstab tool will fill in an fstab file by auto-detecting current mounts ( below a mount point specified as an option ).

genfstab -U /mnt >> /mnt/etc/fstab

It’s a good idea to check the device UUIDs afterward and make sure they’re correct.

chroot to the new Arch install

I change root ( chroot ) to the new Arch install so I can so some more configuration and install the bootloader

arch-chroot /mnt

Locale and Timezone

It’s important to configure locale and timezone before booting the new system. I made the mistake of skipping this step and then I ran into some strange issues before realizing.

Add en_US.UTF-8 to /etc/locale.gen and then run locale-gen

Set the Timezone:

ln -sf /usr/share/zoneinfo/Australia/Canberra /etc/localtime

Run hwclock to generate /etc/adjtime:

hwclock --systohc

Set up initial ramdisk with mkinitcpio

Arch has a tool called mkinitcpio which configures the initial ramdisk with any extra binaries, kernel modules or hooks needed at boot time. It’s configured in the file /etc/mkinitcpio.conf. This is the config I used to start with. I had to come back to this again later to set up the pretty bootsplash screen.

Note that I have the btrfs binaries to read the btrfs filesystem. I also havesystemd, sd-encrypt and sd-vconsole as hooks so the initial ramdisk has what it needs to prompt for a LUKS encryption password.

MODULES=()
BINARIES=(btrfs)
FILES=()
HOOKS=(base systemd autodetect keyboard sd-vconsole modconf block sd-encrypt filesystems fsck)

Set root password and make a new user

Can’t forget to use passwd to set a root password before rebooting so I can acually log in to the system.

I also added my regular user account

useradd -m woody && passwd woody

Install GRUB EFI bootloader with LUKS config

Next I installed the GRUB EFI bootloader to /boot/efi:

grub-install --target=x86_64-efi --bootloader-id=grub_uefi --efi-directory=/boot/efi --recheck

I configured some locale stuff for GRUB with this command:

mkdir /boot/grub/locale && cp /usr/share/locale/en@quot/LC_MESSAGES/grub.mo /boot/grub/locale/en.mo

I edited the default GRUB config (/etc/default/grub) with the UUID of my encrypted LUKS device. Make sure you get the right UUID. I initally used the wrong one and couldn’t figure out why my system wouldn’t boot. These are the lines I edited:

GRUB_ENABLE_CRYPTODISK=y
GRUB_CMDLINE_LINUX="cryptdevice=UUID=abc123yz-abc1-abc2-abcd1234wxyz:root

Make a GRUB config file in the boot partition from the new GRUB defaults:

grub-mkconfig -o /boot/grub/grub.cfg

Arch is installed. Now I can move on to post-install configuration and fixes

Post-install config and fixes:

There was a bunch of post-install configuration and fixes I had to make. Some of them had to wait until after the system was installed while others were problems that I just stumbled upon and fixed.

GNOME Terminal wont start

GNOME Terminal didn’t start after my first login. Some Reddit threads kept suggesting that this happens when locale set up steps were skipped during install, but I knew it wasn’t just that. It turns out I had to set the Language in GNOME Settings:

  • Select a language under the “Regions and Language” section then log out and back in again

Enable NetworkManager and Firewalld

To manage network and firewall configuration, I enabled both NetworkManager and Firewalld

sudo systemctl enable NetworkManager.service && \
sudo systemctl enable firewalld.service

Trackpad multi-touch stopped working after sleep

I had a very annoying issue where my laptops trackpad would stop responding to multi-touch gestures. The fix was to add psmouse.synaptics_intertouch=0 the GRUB_CMDLINE_LINUX_DEFAULT options in /etc/default/grub.

Configure sudo

I had to manually edit the sudoers file to enable members of the wheel group to run any command. After that I added my woody user to wheel as a supplementary group.

sudoers:

## Uncomment to allow members of group wheel to execute any command
%wheel ALL=(ALL:ALL) ALL

User to wheel group:

usermod -aG wheel woody

GNOME Power Profiles missing

The GNOME Power Profiles feature that lets you select:

  • Performance
  • Balanced
  • Power Saving

was missing from the top bar. I had to install the power-profiles-daemon package to enable it.

Firefox Wayland

Firefox does not launch as a Wayland app by default. I wanted that smooth Wayland performance so I added this to my ~/.bash_profile. It checks if the login session is Wayland and sets an environment variable to tell Firefox to lauch in Wayland mode

if [ "$XDG_SESSION_TYPE" == "wayland" ]; then
    export MOZ_ENABLE_WAYLAND=1
fi

GNOME 42 Screen Recording doesn’t work

GNOME 42 includes an awesome screen recording tool that you can bring up by pressing the PrintScreen key on your keyboard. Unfortunately it didn’t work out of the box with GNOME on Arch. I had to install the gst-pipewire package to get it to work.

Podman rootless containers

Podman rootless containers just work in Fedora, but Arch required a few steps to configure. I basically just followed the ArchWiki steps here:

https://wiki.archlinux.org/title/Podman#Rootless_Podman

Pretty boot screen

A pretty graphical bootsplash ( Like Fedora ) took bit of tinkering to configure in Arch. I had to configure a some software called Plymouth in a way that allows a smooth graphical transition from the LUKS password prompot right through to the GDM login screen.

I had to install the packages from AUR hence I configured this all post-install. I used yay to install gdm-plymouth

yay -S gdm-plymouth

After I installed a GDM aware version of Plymouth, I had to go back into my /etc/initcpio.conf file and add some hooks and modules.

My /etc/initcpio.conf now looks like:

MODULES=(amdgpu)
BINARIES=(btrfs)
FILES=()
HOOKS=(base systemd sd-plymouth autodetect keyboard sd-vconsole modconf block sd-encrypt filesystems fsck)

So now in the initramfs I have the amdgpu module to enable graphics and the sd-plymouth hook.

After Plymouth in installed I picked and configured a theme. I chose a great looking one called plymouth-theme-arch-glow which is a package in AUR.

After the theme package is installed it can be set as the default. This command will also rebuild the initial ramdisk to include the theme:

plymouth-set-default-theme -R plymouth-theme-arch-glow

Now it looks pretty when we reboot!

Conclusion

All of this could be accomplished with a few easy clicks in Fedora’s Anaconda installer. I’d recommend that for most people. Building an Arch system like this and having to manually configure everything is a great learning experience. Little things like AUR also make Arch very appealing. Time will tell if I stick with Arch as my daily driver or switch back to Fedora for a better “just works” experience.