Skip to content

Instantly share code, notes, and snippets.

@hbthen3rd
Last active March 4, 2026 13:22
Show Gist options
  • Select an option

  • Save hbthen3rd/aa1fa8d21ab9de30aaaa150b37bf97d9 to your computer and use it in GitHub Desktop.

Select an option

Save hbthen3rd/aa1fa8d21ab9de30aaaa150b37bf97d9 to your computer and use it in GitHub Desktop.
This guide documents what I did to get Arch Linux running on my Raspberry Pi 5.

HB's Guide to Installing Arch Linux on the Raspberry Pi 5

This guide documents what I did to get Arch Linux running on my Raspberry Pi 5. It's highly customized to fit my personal preferences: I use zsh instead of bash, nvim instead of nano, and I partition my drive with a swap partition. My / (root) and /home are on separate partitions.

Here's a screenshot of my Arch Linux installation running on my Raspberry Pi 5: https://github.com/hbthen3rd/dotfiles

You might not need to configure as many things as I did if you stick to a more generic Arch Linux installation (bash, nano, no swap partition, / and /home on the same partition, etc.).


Prerequisites

  • A generic Arch Linux ARM installation:

    • I daily drive an Apple Silicon MacBook (an M2 MacBook Air, to be exact).
    • Download and install VMware Fusion. The free version is sufficient; you don't need VMware Fusion Pro.
    • Download an Archboot aarch64 ISO. Pick the local/second-to-last ISO: archboot-{date}-{time}-{kernel-version}-aarch64-ARCH-local-aarch64.iso.
    • Create a virtual machine, boot from the Archboot aarch64 ISO, and install Arch Linux ARM.
    • If the latest Archboot aarch64 ISO doesn't work, try downloading an older version. Same deal—pick the local/second-to-last ISO. One of these older versions should work.
  • linux-rpi kernel version 6.126.17:

    • Support for Raspberry Pi 5 was added to the linux-rpi kernel starting with version 6.12.
    • At the time of writing, the latest linux-rpi kernel on the Arch Linux ARM repository is version 6.18.1-1. I spent three days trying to get my Raspberry Pi 5 to boot with the linux-rpi-6.18.1-1 kernel but couldn't get it to work—I don't know why.
    • After some googling, I found an older version of the linux-rpi kernel: version 6.17.6-1. My Raspberry Pi 5 booted immediately with this kernel. Again, I don't know why, but I'd already wasted three days on this.
    • Download the linux-rpi-6.17.6-1 kernel (or any version other than 6.18.1-1) onto your Arch Linux ARM installation (the virtual machine, in my case).
  • Install parted and arch-install-scripts on your Arch Linux ARM installation (the virtual machine):

    • We'll use parted to partition the microSD card.
    • We'll use genfstab, pacstrap, and arch-chroot from arch-install-scripts to create the Arch Linux ARM installation with the linux-rpi kernel.
  • Hardware: A microSD card, a microSD card reader, and a Raspberry Pi 5.


Creating the Arch Linux ARM Installation for the Raspberry Pi 5

Wipe and Partition the microSD Card

  1. Plug the microSD card into the generic Arch Linux ARM installation (the virtual machine).

  2. Find out which device the microSD card is listed under:

    lsblk

    Let's say my microSD card shows up as sda—the device path will be /dev/sda. Yours might be different; adjust accordingly.

Wipe the microSD Card

sudo wipefs --all /dev/sda
sudo sgdisk --zap-all /dev/sda

Partition the microSD Card

I'm going to partition my microSD card with the following allocation:

Partition Size Filesystem Mount Point
1 1 GB FAT32 /boot
2 4 GB linux-swap swap space
3 32 GB ext4 / (root)
4 Remaining space ext4 /home

This means I'll need to adjust my /boot/cmdline.txt file later to point the root partition to partition 3.

Alternatively, you can use a more standardized partition allocation:

Partition Size Filesystem Mount Point
1 512 MB FAT32 /boot
2 Remaining space ext4 / (root), also containing /home

If you go with this allocation, you won't need to update /boot/cmdline.txt, as the default cmdline.txt generated by the linux-rpi kernel expects the root partition to be partition 2.

To partition using my allocation:

sudo parted /dev/sda --script mklabel gpt
sudo parted /dev/sda --script mkpart primary fat32 1MiB 1025MiB
sudo parted /dev/sda --script set 1 boot on
sudo parted /dev/sda --script mkpart primary linux-swap 1025MiB 5121MiB
sudo parted /dev/sda --script mkpart primary ext4 5121MiB 37889MiB
sudo parted /dev/sda --script mkpart primary ext4 37889MiB 100%

Mount the Partitions and Install Arch Linux ARM

Mount the microSD Card

  1. Create and mount the / (root) partition. Since my root partition is partition 3, it's /dev/sda3. Adjust accordingly:

    sudo mkdir -p /mnt/pi
    sudo mount /dev/sda3 /mnt/pi
  2. Create and mount the /boot partition:

    sudo mkdir -p /mnt/pi/boot
    sudo mount /dev/sda1 /mnt/pi/boot
  3. Create and mount the /home partition (only if you created a separate partition for /home):

    sudo mkdir -p /mnt/pi/home
    sudo mount /dev/sda4 /mnt/pi/home
  4. Enable swap (only if you created a swap partition):

    sudo swapon /dev/sda2

Create the Arch Linux ARM Installation

Create an Arch Linux ARM installation with the Raspberry Pi kernel, firmware, and bootloader via pacstrap.

You only need the following packages: base base-devel linux-rpi firmware-raspberrypi raspberrypi-bootloader. However, for my setup, I'm including some additional packages that I use, particularly nvim and zsh. Customize to your liking:

sudo pacstrap -K /mnt/pi base base-devel linux-rpi firmware-raspberrypi raspberrypi-bootloader linux-firmware wireless-regdb zsh sudo neovim git wget curl less man-db man-pages networkmanager openssh

Generate and Configure fstab

  1. Generate the fstab file:

    genfstab -U /mnt/pi | sudo tee /mnt/pi/etc/fstab
  2. Edit the fstab file to remove the host system's swap partition and update device paths:

    sudo nvim /mnt/pi/etc/fstab

    Your fstab file might look something like this:

    # /dev/sda3
    UUID=xxxx-xxxx  /       ext4    rw,relatime     0 1
    
    # /dev/sda1
    UUID=xxxx-xxxx  /boot   vfat    rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro     0 2
    
    # /dev/sda4
    UUID=xxxx-xxxx  /home   ext4    rw,relatime     0 2
    
    # !! Notice how the following entry looks different from the rest?
    # !! It's under the /dev/nvme0n1 device instead of /dev/sda.
    # !! This is the host (virtual machine)'s swap partition.
    # !! Remove this entry (the next two lines):
    # /dev/nvme0n1p4 LABEL=SWAP
    UUID=xxxx-xxxx  none    swap    defaults        0 0
    
    # /dev/sda2
    UUID=xxxx-xxxx  none    swap    defaults        0 0
    
  3. Your microSD card might show up as /dev/sda in the virtual machine, but once you plug it into the Raspberry Pi 5, it will appear as /dev/mmcblk0 with different UUIDs. Replace all UUIDs with /dev/mmcblk0pX:

    # Partition 3 - root
    /dev/mmcblk0p3  /       ext4    rw,relatime     0 1
    
    # Partition 1 - boot
    /dev/mmcblk0p1  /boot   vfat    rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro     0 2
    
    # Partition 4 - home
    /dev/mmcblk0p4  /home   ext4    rw,relatime     0 2
    
    # Partition 2 - swap
    /dev/mmcblk0p2  none    swap    defaults        0 0
    
  4. Save and exit.


Downgrade the linux-rpi Kernel and Configure the Bootloader

Downgrade the Kernel

  1. Recall that we downloaded the linux-rpi-6.17.6-1 kernel (or any version older than 6.18.1-1 and newer than 6.12) in the Prerequisites step. Copy it to our Raspberry Pi installation:

    sudo cp ~/Downloads/linux-rpi-6.17.6-1-aarch64.pkg.tar.xz /mnt/pi/
  2. Enter chroot:

    sudo arch-chroot /mnt/pi
  3. Downgrade the kernel:

    pacman -U linux-rpi-6.17.6-1-aarch64.pkg.tar.xz
  4. Pin the kernel version in pacman to prevent accidental upgrades:

    nvim /etc/pacman.conf

    Uncomment the IgnorePkg line and modify it to:

    IgnorePkg = linux-rpi linux-rpi-headers
    
  5. Save and exit.

Configure the Bootloader

  1. Create vconsole.conf:

    touch /etc/vconsole.conf
  2. [Optional] This file can be blank. However, since I'm expecting a US keyboard in my virtual console, I'm setting that here. More info:

    nvim /etc/vconsole.conf
    KEYMAP=us
    
  3. Save and exit.

  4. Regenerate initramfs for the linux-rpi kernel:

    mkinitcpio -p linux-rpi
  5. [Optional] Clean up the kernel package file:

    rm linux-rpi-6.17.6-1-aarch64.pkg.tar.xz
  6. Adjust /boot/cmdline.txt to point to the root partition:

    As mentioned during the partitioning step, the linux-rpi kernel defaults to partition 2 for root. If your root partition is different (mine is partition 3), adjust it:

    nvim /boot/cmdline.txt

    Adjust the root= variable:

    root=/dev/mmcblk0p3 rw rootwait console=tty1 ...
    
  7. Save and exit.


Configure the Rest of the System

Set Hostname

echo "raspberrypi" > /etc/hostname

Edit the hosts File

nvim /etc/hosts

Add a third line so your hosts file looks like this:

127.0.0.1   localhost
::1         localhost
127.0.1.1   raspberrypi.localdomain raspberrypi

Save and exit.

Set Locale

nvim /etc/locale.gen

Find and uncomment the line with your locale. For me:

en_US.UTF-8 UTF-8

Save and exit, then run:

locale-gen
echo "LANG=en_US.UTF-8" > /etc/locale.conf

Set Timezone

I'm in Pacific Time (America/Los_Angeles). Adjust yours accordingly:

ln -sf /usr/share/zoneinfo/America/Los_Angeles /etc/localtime
hwclock --systohc

[Optional] Create a Wi-Fi Connection File

Since I have a keyboard, mouse, and monitor plugged into my Raspberry Pi, I usually connect to Wi-Fi after booting. However, if you're running headless, it's helpful to create a Wi-Fi connection file beforehand so your Raspberry Pi connects automatically and you can access it via SSH.

uuidgen
# This prints a UUID—make note of it
nvim /etc/NetworkManager/system-connections/MyHomeWifiName.nmconnection

Add the following content:

[connection]
id=MyHomeWifiName
uuid=<paste-generated-UUID-here>
type=wifi
interface-name=wlan0

[wifi]
mode=infrastructure
ssid=MyHomeWifiName

[wifi-security]
auth-alg=open
key-mgmt=wpa-psk
psk=MyHomeWifiPassword

[ipv4]
method=auto

[ipv6]
addr-gen-mode=default
method=auto

[proxy]

Save and exit, then set permissions:

chown root:root /etc/NetworkManager/system-connections/MyHomeWifiName.nmconnection
chmod 600 /etc/NetworkManager/system-connections/MyHomeWifiName.nmconnection

[Optional] Configure DNS

My ISP's default DNS server is unreliable, leading to pacman failures due to mismatched keys and wrong IP resolution from outdated DNS records. If you experience similar problems, I recommend changing your DNS server. I use Quad9 DNS servers with malware blocking, DNSSEC validation, and ECS enabled:

nvim /etc/resolv.conf

Replace the content with:

nameserver 9.9.9.11
nameserver 149.112.112.11

Save and exit.

Set Wireless Regulatory Domain

nvim /etc/conf.d/wireless-regdom

Uncomment the line with your wireless regulatory domain. For me:

WIRELESS_REGDOM="US"

Save and exit.

Enable Services

systemctl enable NetworkManager
systemctl enable sshd

Create Users and Configure sudo

Set Root Password

passwd

Create a User

I use zsh—adjust the -s parameter if you use bash or fish. I'm also adding the user to the wheel group for sudo access:

useradd -m -G wheel -c "My User Full Name" -s /usr/bin/zsh myusername
passwd myusername

Enable sudo for the wheel Group

EDITOR=nvim visudo

Find and uncomment the following line:

%wheel ALL=(ALL:ALL) ALL

Save and exit.


[Optional] Set Up yay for AUR and XDG Environment Variables

You can do this now or later after booting the Raspberry Pi.

Switch to the Newly Created User

su - myusername

Install yay

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

[Optional] Clean up the cloned repo:

cd ..
rm -rf yay

Set Up XDG Environment Variables

For zsh, XDG environment variables go in ~/.zshenv. For bash, use ~/.profile.

nvim ~/.zshenv

Add the following:

export XDG_CONFIG_HOME="$HOME/.config"
export XDG_DATA_HOME="$HOME/.local/share"
export XDG_CACHE_HOME="$HOME/.cache"
export XDG_STATE_HOME="$HOME/.local/state"

Save and exit, then exit the user's shell to return to the chroot shell.


Unmount and Clean Up

  1. Exit chroot to return to the host (virtual machine) shell.

  2. Disable the swap partition (if you created one):

    sudo swapoff /dev/sda2
  3. Unmount partitions in reverse order:

    sudo umount /mnt/pi/home
    sudo umount /mnt/pi/boot
    sudo umount /mnt/pi
  4. Remove the mount point:

    sudo rmdir /mnt/pi
  5. Sync and eject:

    sync
    sudo eject /dev/sda
  6. Unplug your microSD card from the virtual machine and insert it into your Raspberry Pi 5.


Booting into Arch Linux ARM on the Raspberry Pi 5

You might notice some error logs spilling over the TTY. Don't worry—these don't affect what you're typing (username, password, or commands). Just keep typing normally. Once you install a display server or desktop environment, these error logs won't bother you anymore.

Sign into the user account you created earlier. Ignore the error logs and keep typing normally.


Connect to Wi-Fi and Enable Network Time Synchronization

Connect to Wi-Fi

If you created a Wi-Fi connection file earlier, your Raspberry Pi should automatically connect to your Wi-Fi upon boot.

If it doesn't work or you didn't create one, connect via nmcli:

  1. Check if Wi-Fi is enabled:

    nmcli radio wifi
  2. If it shows "disabled", enable it:

    nmcli radio wifi on
  3. Scan for available networks:

    nmcli device wifi list
  4. Connect to your network:

    nmcli device wifi connect "YOUR_NETWORK_NAME" password "YOUR_PASSWORD"
  5. Verify the connection:

    nmcli connection show

NetworkManager will save this connection and automatically connect in the future.

Enable Network Time Synchronization

timedatectl set-ntp true

Fix the X.org Display Server

Previously, I used greetd + greetd-tuigreet for my login manager and sway as my desktop environment. These worked out of the box because:

  • greetd + greetd-tuigreet are purely TUI-based and don't use a display server (though the error logs still spill over the TTY).
  • sway uses Wayland, which automatically picks up the correct GPU device from the Raspberry Pi 5.

However, for my newer setup, I use lightdm + lightdm-gtk-greeter for my login manager and xfce4 as my desktop environment—all of which rely on xorg-server. This won't work out of the box.

Important: Do NOT enable the lightdm service before applying this fix. If you already have, switch to another TTY or SSH into your Raspberry Pi to apply the fix.

The problem: The Raspberry Pi 5 has two GPU devices:

  • /dev/dri/card0 — The 3D rendering engine only; no display outputs.
  • /dev/dri/card1 — The actual display controller with HDMI-A-1 and HDMI-A-2 outputs.

X.org tries to auto-detect and incorrectly chooses card0 as the display device. Since card0 has no display connectors, X.org crashes with a "no screens found" error.

The fix: Create a configuration file to tell X.org to use card1:

sudo nvim /etc/X11/xorg.conf.d/99-vc4.conf

Add the following:

Section "Device"
    Identifier "VC4"
    Driver "modesetting"
    Option "kmsdev" "/dev/dri/card1"
    Option "AccelMethod" "glamor"
    Option "PrimaryGPU" "true"
EndSection

Section "Screen"
    Identifier "Default Screen"
    Device "VC4"
EndSection

Section "ServerLayout"
    Identifier "Default Layout"
    Screen "Default Screen"
EndSection

Save and exit.


That's it! You should now have a working Arch Linux ARM installation on your Raspberry Pi 5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment