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.).
-
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-rpikernel version6.12–6.17:- Support for Raspberry Pi 5 was added to the
linux-rpikernel starting with version6.12. - At the time of writing, the latest
linux-rpikernel on the Arch Linux ARM repository is version6.18.1-1. I spent three days trying to get my Raspberry Pi 5 to boot with thelinux-rpi-6.18.1-1kernel but couldn't get it to work—I don't know why. - After some googling, I found an older version of the
linux-rpikernel: version6.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-1kernel (or any version other than6.18.1-1) onto your Arch Linux ARM installation (the virtual machine, in my case).
- Support for Raspberry Pi 5 was added to the
-
Install
partedandarch-install-scriptson your Arch Linux ARM installation (the virtual machine):- We'll use
partedto partition the microSD card. - We'll use
genfstab,pacstrap, andarch-chrootfromarch-install-scriptsto create the Arch Linux ARM installation with thelinux-rpikernel.
- We'll use
-
Hardware: A microSD card, a microSD card reader, and a Raspberry Pi 5.
-
Plug the microSD card into the generic Arch Linux ARM installation (the virtual machine).
-
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.
sudo wipefs --all /dev/sda
sudo sgdisk --zap-all /dev/sdaI'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%-
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
-
Create and mount the
/bootpartition:sudo mkdir -p /mnt/pi/boot sudo mount /dev/sda1 /mnt/pi/boot
-
Create and mount the
/homepartition (only if you created a separate partition for/home):sudo mkdir -p /mnt/pi/home sudo mount /dev/sda4 /mnt/pi/home
-
Enable swap (only if you created a swap partition):
sudo swapon /dev/sda2
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 the fstab file:
genfstab -U /mnt/pi | sudo tee /mnt/pi/etc/fstab -
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 -
Your microSD card might show up as
/dev/sdain the virtual machine, but once you plug it into the Raspberry Pi 5, it will appear as/dev/mmcblk0with 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 -
Save and exit.
-
Recall that we downloaded the
linux-rpi-6.17.6-1kernel (or any version older than6.18.1-1and newer than6.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/ -
Enter chroot:
sudo arch-chroot /mnt/pi
-
Downgrade the kernel:
pacman -U linux-rpi-6.17.6-1-aarch64.pkg.tar.xz
-
Pin the kernel version in
pacmanto prevent accidental upgrades:nvim /etc/pacman.conf
Uncomment the
IgnorePkgline and modify it to:IgnorePkg = linux-rpi linux-rpi-headers -
Save and exit.
-
Create
vconsole.conf:touch /etc/vconsole.conf
-
[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:
- https://man.archlinux.org/man/vconsole.conf.5
- https://wiki.archlinux.org/title/Linux_console/Keyboard_configuration
- https://wiki.archlinux.org/title/Installation_guide#Set_the_console_keyboard_layout_and_font
nvim /etc/vconsole.conf
KEYMAP=us -
Save and exit.
-
Regenerate
initramfsfor thelinux-rpikernel:mkinitcpio -p linux-rpi
-
[Optional] Clean up the kernel package file:
rm linux-rpi-6.17.6-1-aarch64.pkg.tar.xz
-
Adjust
/boot/cmdline.txtto point to the root partition:As mentioned during the partitioning step, the
linux-rpikernel 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 ... -
Save and exit.
echo "raspberrypi" > /etc/hostnamenvim /etc/hostsAdd 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.
nvim /etc/locale.genFind 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.confI'm in Pacific Time (America/Los_Angeles). Adjust yours accordingly:
ln -sf /usr/share/zoneinfo/America/Los_Angeles /etc/localtime
hwclock --systohcSince 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.nmconnectionAdd 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.nmconnectionMy 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.confReplace the content with:
nameserver 9.9.9.11
nameserver 149.112.112.11
Save and exit.
nvim /etc/conf.d/wireless-regdomUncomment the line with your wireless regulatory domain. For me:
WIRELESS_REGDOM="US"
Save and exit.
systemctl enable NetworkManager
systemctl enable sshdpasswdI 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 myusernameEDITOR=nvim visudoFind and uncomment the following line:
%wheel ALL=(ALL:ALL) ALL
Save and exit.
You can do this now or later after booting the Raspberry Pi.
su - myusernamecd /tmp
git clone https://aur.archlinux.org/yay.git
cd yay
makepkg -si[Optional] Clean up the cloned repo:
cd ..
rm -rf yayFor zsh, XDG environment variables go in ~/.zshenv. For bash, use ~/.profile.
nvim ~/.zshenvAdd 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.
-
Exit chroot to return to the host (virtual machine) shell.
-
Disable the swap partition (if you created one):
sudo swapoff /dev/sda2
-
Unmount partitions in reverse order:
sudo umount /mnt/pi/home sudo umount /mnt/pi/boot sudo umount /mnt/pi
-
Remove the mount point:
sudo rmdir /mnt/pi
-
Sync and eject:
sync sudo eject /dev/sda
-
Unplug your microSD card from the virtual machine and insert it into your 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.
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:
-
Check if Wi-Fi is enabled:
nmcli radio wifi
-
If it shows "disabled", enable it:
nmcli radio wifi on
-
Scan for available networks:
nmcli device wifi list
-
Connect to your network:
nmcli device wifi connect "YOUR_NETWORK_NAME" password "YOUR_PASSWORD"
-
Verify the connection:
nmcli connection show
NetworkManager will save this connection and automatically connect in the future.
timedatectl set-ntp truePreviously, I used greetd + greetd-tuigreet for my login manager and sway as my desktop environment. These worked out of the box because:
greetd+greetd-tuigreetare purely TUI-based and don't use a display server (though the error logs still spill over the TTY).swayuses 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.confAdd 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.