Build a bootable qcow2 disk image of the unofficial Arch Linux aarch64 port from a Raspberry Pi or any aarch64 Linux system, for use with UTM on Apple Silicon Macs.
On your aarch64 Linux host, install:
pacman -S gptfdisk qemu-img arch-install-scripts dosfstools# Create an 8GB raw disk
dd if=/dev/zero of=arch-aarch64.raw bs=1M count=8192
# Two partitions: FAT32 for /boot (ESP), ext4 for /
sgdisk -o \
-n 1:0:+1G -t 1:ef00 -c 1:boot \
-n 2:0:0 -t 2:8300 -c 2:root \
arch-aarch64.raw
sudo losetup -fP arch-aarch64.raw
LOOP=$(losetup -j arch-aarch64.raw | cut -d: -f1)
sudo mkfs.fat -F32 ${LOOP}p1
sudo mkfs.ext4 ${LOOP}p2
# FAT32 at /boot — this is important!
# The kernel and initramfs land directly on the EFI partition when installed.
sudo mount ${LOOP}p2 /mnt
sudo mkdir -p /mnt/boot
sudo mount ${LOOP}p1 /mnt/bootCheck the tarballs directory for the latest version.
curl -LO https://arch-linux-repo.drzee.net/arch/tarballs/os/aarch64/archlinux-bootstrap-2026.03.15-aarch64.tar.zst
curl -LO https://arch-linux-repo.drzee.net/arch/tarballs/os/aarch64/archlinux-bootstrap-2026.03.15-aarch64.tar.zst.sig
# Verify signature
curl -sL https://arch-linux-repo.drzee.net/arch/extra/os/aarch64/public.key | gpg --import
gpg --verify archlinux-bootstrap-2026.03.15-aarch64.tar.zst.sig
# 'Good signature' is what matters here.
# If GPG also warns that the key is not certified or trusted,
# that's expected unless you've explicitly marked it as trusted
# in your personal keyring.
sudo tar xf archlinux-bootstrap-2026.03.15-aarch64.tar.zst -C /mnt --strip-components=1sudo arch-chroot /mnt
# Set up pacman keyring
pacman-key --init
pacman-key --populate archlinux
# Import the drzee signing key
curl -sL https://arch-linux-repo.drzee.net/arch/extra/os/aarch64/public.key -o /tmp/drzee.key
pacman-key --add /tmp/drzee.key
pacman-key --lsign-key 0CF25682E6BA0751
# Install base system + mainline kernel (not linux-rpi5 — this is a VM)
pacman -Syu
pacman -S base linux linux-firmware efibootmgr
# Set a root password — the bootstrap ships with root LOCKED
passwd
# mkinitcpio needs this file to exist
echo "KEYMAP=us" > /etc/vconsole.conf
# Build initramfs
mkinitcpio -P
# Install systemd-boot
bootctl install --esp-path=/boot
exit # leave chrootWrite the loader config from outside the chroot:
ROOT_UUID=$(sudo blkid -s UUID -o value ${LOOP}p2)
sudo tee /mnt/boot/loader/loader.conf << 'EOF'
default arch.conf
timeout 3
EOF
sudo mkdir -p /mnt/boot/loader/entries
sudo tee /mnt/boot/loader/entries/arch.conf << EOF
title Arch Linux (aarch64)
linux /vmlinuz-linux
initrd /initramfs-linux.img
options root=UUID=${ROOT_UUID} rw console=ttyAMA0 console=tty0
EOFsudo bash -c "sudo sh -c 'genfstab -U /mnt > /mnt/etc/fstab'"
sudo sudo umount -R /mnt
sudo losetup -d $LOOP
# Convert to qcow2 for UTM
qemu-img convert -f raw -O qcow2 -c arch-aarch64.raw arch-aarch64.qcow2
rm arch-aarch64.rawIn UTM: Virtualize → Other, skip the ISO, import the qcow2 as the drive, and set boot to UEFI.
Login: root with the password you set.
sync does not show a progress bar. The easiest rule is: wait for the command to return and only unplug after sudo umount -R /mnt finishes. If you want to watch writeback activity, you can run watch -n1 "grep -E 'Dirty|Writeback' /proc/meminfo" in another terminal and wait for the numbers to get close to zero.
UTM also supports booting without a bootloader. In the VM settings, point UTM directly at the kernel and initramfs files and pass boot arguments. You'll need to extract them from the image or download the linux package from drzee and unpack it.
- Don't use GRUB. Inside a chroot on a loop device,
grub-mkconfigproduced a config file full of null bytes. Even with a hand-written config, GRUB couldn't load the kernel from ext4 — it complained about "plain image kernel not supported." systemd-boot just works. - Mount FAT32 at
/boot, not/boot/efi. With/boot/efi, the kernel and initramfs end up on the ext4 root partition, and the bootloader can't find them. With/boot, pacman installs them directly where systemd-boot expects them. - The bootstrap has root locked. There's a
*in/etc/shadow. Not an empty password — no password works at all. You must runpasswdbefore rebooting or you'll be locked out. qemu-nbdandrmdon't mix. If you modify a qcow2 via nbd, make sure to disconnect cleanly before deleting anything. I corrupted an image this way and had to rebuild from scratch.