Until our Raspberry Pi 5 is fully supported by Arch Linux ARM we can get it running by "... removing U-Boot and replacing the mainline kernel with a directly booting kernel from the Raspberry Pi foundation". --source
This guide boots an encrypted root Arch Linux ARM on an SSD connected to a Raspberry Pi 5. The root partition is automatically unlocked from a key file on a USB key or you can enter the password with a keyboard. While it's not covered here, adding unlock via SSH should be the same as any other Arch install. Hopefully.
If you're looking for a guide to install to a SD card instead of the SSD you could try the incomplete notes section at the end of this file to build on a host that's not a Pi.
Tested with ArchLinuxARM-rpi-aarch64-latest.tar.gz
from 2024-03-27.
These excellent guides:
- Arch Linux ARM on a Raspberry Pi 5 Model B
- Pi Encrypted Boot with Remote SSH (Raspberry Pi OS Lite)
- Raspberry Pi 5
- SD card
- NVMe connected via PCIe (tested with Pimoroni NVMe Base)
- SSD (tested with Solidigm P44 Pro, 512GB)
- USB key (to hold the encrypted root key file)
We'll need Raspberry Pi OS Lite installed on the SD card to kick things off. They have a great install guide. I used the Raspberry Pi Imager so I could click buttons and add my public SSH key to the image easily.
Boot the Pi from the SD card and connect via SSH.
Run the following commands as root.
sudo su -
We'll need to change the boot order to boot from NVMe and you can learn all about NVMe SSD booting from Jeff. Thanks Jeff.
My preferred order is 0xf461
which corresponds to (and is read from right to left):
- 1 First, SD card (which will only used to rescue the system in the future - otherwise you'll have to disconnect the SSD to boot from an SD card)
- 6 Second, NVMe
- 4 Third, USB
Edit EEPROM:
rpi-eeprom-config --edit
BOOT_ORDER=0xf461
PCIE_PROBE=1
(Optional) For the lowest power state on halt because my Pi doesn't have a HAT and doesn't use GPIO pins:
POWER_OFF_ON_HALT=1
WAKE_ON_GPIO=0
Install required packages:
apt update
apt install libarchive-tools cryptsetup curl
# cryptsetup for luks encryption
# libarchive-tools for bsdtar
# curl for ... curl
Download Arch Linux ARM:
curl -L -o alarm.tar.gz 'http://os.archlinuxarm.org/os/ArchLinuxARM-rpi-aarch64-latest.tar.gz'
curl -L -o alarm.tar.gz.sig 'http://os.archlinuxarm.org/os/ArchLinuxARM-rpi-aarch64-latest.tar.gz.sig'
Verify file signature:
gpg --keyserver 'hkp://keyserver.ubuntu.com' --keyserver-options auto-key-retrieve --verify 'alarm.tar.gz.sig'
Mount the USB key and create a key file. My USB key already formatted as ext4:
mkdir -p /media/usb/
mount /dev/sda1 /media/usb/
dd bs=512 count=4 if=/dev/random of=/media/usb/unlock.key iflag=fullblock
Partition the target SSD with 2 partitions (Arch's install guide has a section on partitioning):
- 512MiB boot:
/dev/nvme0n1p1
- Remaining space for root:
/dev/nvme0n1p2
Format boot device:
mkfs.vfat -F 32 /dev/nvme0n1p1
Decide on your --pbkdf-*
parameters:
By default cryptsetup will benchmark your host and use a memory-hard PBKDF algorithm that can require up to 4GB of RAM. If these settings exceed your Raspberry Pi's available RAM, it will make it impossible to unlock the partition. To work around this, set the --pbkdf-memory and --pbkdf-parallel arguments so when you multiply them, the result is less than your Pi's total RAM. --source
Setup luks and format root partition:
cryptsetup luksFormat --pbkdf-memory=1024000 --pbkdf-parallel=1 /dev/nvme0n1p2
cryptsetup luksAddKey /dev/nvme0n1p2 /media/usb/unlock.key
cryptsetup --key-file /media/usb/unlock.key open --type luks /dev/nvme0n1p2 root
mkfs.ext4 -m 1 /dev/mapper/root
Make a note of these device's UUID, we'll need them later (the SD card, mmcblk0
, can be ignored):
lsblk -f
# NAME FSTYPE UUID
# nvme0n1
# ├─nvme0n1p1
# │ vfat aaaa-aaaa <- boot
# └─nvme0n1p2
# crypto bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb <- encrypted root
# └─root ext4 cccccccc-cccc-cccc-cccc-cccccccccccc <- unlocked root
# sda
# └─sda1 ext4 dddddddd-dddd-dddd-dddd-dddddddddddd <- usb key
You can copy this text and fill it out unless your super power is memorizing UUIDs:
aaaa-aaaa = boot =
bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb = encrypted root =
cccccccc-cccc-cccc-cccc-cccccccccccc = unlocked root =
dddddddd-dddd-dddd-dddd-dddddddddddd = usb key =
Mount root device:
mount /dev/mapper/root /mnt/
Extract Arch Linux ARM's files:
bsdtar -xpf alarm.tar.gz -C /mnt/
Mount boot:
mount /dev/nvme0n1p1 /mnt/boot
Setup the chroot:
mount -t proc none /mnt/proc/
mount -t sysfs none /mnt/sys/
mount -o bind /dev /mnt/dev/
mount -o bind /dev/pts /mnt/dev/pts/
mkdir -p /mnt/run/systemd/resolve/
touch /mnt/run/systemd/resolve/resolv.conf
mount --bind /etc/resolv.conf /mnt/run/systemd/resolve/resolv.conf
Enter the chroot:
LANG=C chroot /mnt/ /bin/bash
Normal Arch init things (see the Pi 4 install guide):
pacman-key --init
pacman-key --populate archlinuxarm
Update the system and swap kernels:
pacman -R linux-aarch64 uboot-raspberrypi
pacman -Syu --overwrite "/boot/*" linux-rpi-16k
# Some packages provide hints on actions to take and you'll have to decide which ones need attention.
# mkinitcpio probably failed, we'll fix that soon.
Update your localization otherwise mkinitcpio fails:
vi /etc/locale.gen
# enable C.UTF-8
# enable your locale
vi /etc/locale.conf
LANG=<your locale>
Generate locales:
locale-gen
You might as well update your time zone while you're here:
ln -sf /usr/share/zoneinfo/Region/City /etc/localtime
Update mkinitcpio hooks:
vi /etc/mkinitcpio.conf
# Update HOOKS to add encrypt.
# Update HOOKS to remove kms (my Pi froze on boot with it enabled).
# Update HOOKS to remove microcode (not supported on this platform).
# Maybe update MODULES if your usb key uses a file system that isn't ext4.
HOOKS=(base udev autodetect modconf keyboard keymap consolefont block encrypt filesystems fsck)
Update fstab:
vi /etc/fstab
# <file system> <dir> <type> <options> <dump> <pass>
UUID=cccccccc-cccc-cccc-cccc-cccccccccccc / ext4 rw,relatime 0 1
UUID=aaaa-aaaa /boot vfat rw,relatime 0 0
Update linux command line by replacing root=/dev/mmcblk0p2
:
vi /boot/cmdline.txt
# Replace root=/dev/mmcblk0p2 with this (and update the cryptkey file system parameter, ext4, to the file system of your usb key):
cryptdevice=UUID=bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb:root cryptkey=UUID=dddddddd-dddd-dddd-dddd-dddddddddddd:ext4:/unlock.key root=/dev/mapper/root
Your full command line should look something like this:
cryptdevice=UUID=bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb:root cryptkey=UUID=dddddddd-dddd-dddd-dddd-dddddddddddd:ext4:/unlock.key root=/dev/mapper/root rw rootwait console=serial0,115200 console=tty1 fsck.repair=yes
(Optional) Update Pi's configuration:
vi /boot/config.txt
# I'll be disabling things I don't need:
# - vc4-kms-v3d (try disable this if your Pi freezes on boot)
# - wifi
# - bluetooth
If you're looking to unlock using SSH, now is the time.
Run mkinitcpio:
mkinitcpio -P
# You should see: Initcpio image generation successful
# Without this image your Pi won't boot.
Add your public SSH key to root:
mkdir -p /root/.ssh && chmod 0700 /root/.ssh
echo "ssh-ed25519 [...]" | tee /root/.ssh/authorized_keys
chmod 0600 /root/.ssh/authorized_keys
(Optional) My Pi will be headless so I'll remove the default user that has an obvious password and disable root's password because I'll only be connecting via SSH:
userdel -r alarm
usermod -p '!' root
(Optional) Periodic pacman cache cleaner:
pacman -S pacman-contrib
systemctl enable paccache.timer
(Optional) Update your hostname:
vi /etc/hostname
Exit the chroot:
sync
history -c && exit
Power off the Pi which is easier than unmounting all the file systems by hand:
poweroff
Real life steps:
- Remove power
- Remove the SD card
- Apply power
- Wait
- Connect to your Pi using SSH as root
Enjoy!
"When Arch Linux ARM starts supporting the Pi 5, the Pi Foundation’s kernel can be replaced with the mainline kernel by running:
pacman -Syu linux-aarch64 uboot-raspberrypi
There will be warning that those packages conflict with package
linux-rpi
and whether you want it replaced. If you do,linux-rpi
will be removed before installing the new packages. After that, your Arch Linux ARM installation should be the same as the official Arch Linux ARM Raspberry Pi image that supports the Pi 5."
--source
Unfortunately, plugging the Pi into a monitor and looking at the screen is the easiest debug method.
You might need to wait slightly longer for the Pi to boot due to unlocking the root partition.
Still nothing?
Power off, insert the SD card into the Pi, boot and SSH. Unlock and mount partitions then enter the chroot and start pressing buttons. Double check your UUID's and cmdline.txt
. Perhaps you missed the UUID=
when referencing the disk?
Maybe you'll need to remove the kms
minitcpio HOOKS. Maybe you'll need to disable vc4-kms-v3d
in the config.txt
.
You can build the Arch Linux ARM image on a Arch host computer, like x86_64 or in a VM (basic image, QCOW2). You can probably use other linux distro's with the right packages installed.
Install packages required for the chroot:
pacman -S qemu-user-static qemu-user-static-binfmt arch-install-scripts
Create files to temporarily hold the file systems:
fallocate -l 512MiB pi-boot
fallocate -l 4GiB pi-root
Mount the files as devices:
losetup -f pi-boot
losetup -f pi-root
Check which file was assigned to which loop device:
losetup -l
From there you can install to the loop devices.
You can transfer your boot and root partitions from the loop devices to a real device using:
rsync --archive --hard-links --acls --xattrs --one-file-system --numeric-ids --info="progress2" /mnt/src//* /mnt/dest/