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
andcrypttab
- 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:
- 600MB for EFI (
nvme0n1p1
) - 1GB Boot (
nvme0n1p2
) - 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.