Creating an ArchLinux Live USB for Asahi Linux for M1/M2 Macs

I’m going to follow this up with better instructions + actual images built using GitHub Actions, but then following instructions will work for anything that can boot AsahiLinux.

If you have a newer device that is unsupported by the installer (such as 14" MacBook Pro 2023 M2 Max), you’ll need to do some additional steps to build firmware etc.

I use this to boot both a MacBook Air M1 2020 and MacBook Pro 2023 M2 Max.

Before you do anything, please ensure you have backups for everything on your device..

I’m going to assume you have installed ArchLinux before, but even if not, it’s fairly straight forward and is really nice as it doesn’t add layers of abstraction :-).

USB Notes/Rant

USB devices are the most messiest/inconsistent devices I’ve dealt with. Ensure you have tested that the device works well, and the speed is good. I recommend Blackmagic Disk Speed Test if using Mac.

I also highly recommend testing your USB-C cables. Data cables are different, and cost more to manufacture so we have a large amount of “charging only” cables.

I HIGHLY recommend using something like a NVME drive inside of a USB NVME enclosure, you can grab one for like <$30AUD which will do around 800Mb/s, and once the faster devices become cheaper you’ll get almost nvme speeds. Macbooks have really good USB ports from my testing and work great.

I also recommend reading Install Arch Linux on a removable medium on the ArchLinux wiki, as it has some tips around Minimizing disk access. I don’t recommend removing journaling for ext4 for AsahiLinux, as I’ve had cases where plugging in another USB device unmounts the USB.

Presetup

To run the follow steps, you’ll need a machine running ARM64 Linux, so if your machine is supported by AsahiLinux, just install the “Minimal Install”. I recommend around ~20-30GB for this.

Later I’ll provide images to create a bootable USB using a tool like balenaEtcher/RaspberryPiImager/good ol’ dd.

After you have created a USB Bootable device, you can just re-reun the Asahi Installer, and select “UEFI Only”. If you intend to only boot using USB, and not installing on the internal disk, you can have a very small partition size for this, I recommend >1GB, as the EFI partition is 500mb. Depends how much space you have.

Creating a USB-bootable device from Asahi Linux Minimal

This assumes you’re booted into Asahi Linux Minimal, what we’ll be doing is doing a typical Arch install, but on a USB.

I have all the disks listed as sdx, change to sda/sdb or whatever your USB is. I did this to prevent accidental wiping of disks :-).

  1. lsblk should show your USB Device as /dev/sda if it’s the only one plugged in, or sdb/sdc/etc.

  2. Upgrade all packages, install the needed packages and the latest asahi kernel: pacman --needed -Syu arch-install-scripts dosfstools e2fsprogs grub linux-asahi-edge gptfdisk gdisk

  3. Wipe the USB disk, this will remove all data.

sgdisk --clear /dev/sdx
wipefs -af /dev/sdx
  1. reboot, and ensure you select linux-asahi-edge from grub. When rebooted, uname -a should show linux-asahi-edge

  2. Partitioning the USB

!!THIS WILL WIPE YOUR DISK!!

I recommend using cfdisk or sfdisk when scripting, but if you want a handy/hacky/nasty one-liner…:

# Change 50G to how many gigabytes you need.
echo -e 'o\ny\nn\n\n\n+1G\nef00\nn\n\n\n+50G\n8300\nw\ny\n' | gdisk /dev/sdx

5a. Create the partitions:

We need to disable ^metadata_csum, which is what the asahi builder also does.

mkfs.vfat -F 32 "/dev/sdx1"
mkfs.ext4 -O '^metadata_csum' -F "/dev/sdx2"

5b. If you want to disable it for an existing device, ensuring it’s not mounted:

tune2fs -O "^metadata_csum" /dev/sdx2
  1. Mount the USB:
mkdir -p /mnt
# I like adding "-o noatime,commit=120", as it reduces the commit time to disk. Only use this for the install process though.
mount "/dev/sdx2" /mnt
mkdir -p /mnt/boot/grub /mnt/boot/efi
mount "/dev/sdx1" /mnt/boot/efi
  1. Now you can use pacstrap to install Arch. I like to use my USB as a recovery, as I do things that can break Asahi and use the USB to recover. Here are two different pacstraps, a super minimal one and one with some recommended packages to make your life a bit easier when recovering.

You can also checkout the packages AsahiLinux for Arch installs on the asahi-alarm-builder repository.

7a. Super minimal:

pacstrap -c /mnt arch-install-scripts base dhcpcd dosfstools e2fsprogs grub iwd neovim reiserfsprogs rsync asahi-configs asahi-fwextract asahi-meta asahi-scripts asahilinux-keyring linux-asahi linux-asahi-edge uboot-asahi openssh

7b. Semi-minimal, with some useful packages:

  • brightnessctl (control backlight, etc)
  • bmon (seeing how much bandwidth you’re using)
  • asahi packages
  • rustup
  • screen/tmux
  • bash-completion
  • zsh/zsh completions
  • file system tools such as btrfs-progs, dosfstools e2fsprogs gptfdisk gdisk
  • dbus-broker, which is faster.
pacstrap -c /mnt acl alsa-ucm-conf alsa-ucm-conf-asahi arch-install-scripts archlinux-keyring archlinuxarm-keyring argon2 asahi-configs asahi-fwextract asahi-meta asahi-scripts asahilinux-keyring attr audit autoconf automake axel base base-devel bash bash-completion bat binutils bison bluez-libs bmon brightnessctl brotli btrfs-progs bzip2 ca-certificates ca-certificates-mozilla ca-certificates-utils clang cmake compiler-rt confuse coreutils cppdap cpupower cryptsetup curl db db5.3 dbus dbus-broker debugedit device-mapper dhcpcd diffutils dnssec-anchors dosfstools duktape e2fsprogs efibootmgr efivar ell expat fakeroot fd file filesystem findutils flex fzf gawk gc gcc gcc-libs gdbm gdisk gettext git glib2 glibc gmp gnupg gnutls gpgme gpm gptfdisk grep groff grub guile gzip hicolor-icon-theme hiredis htop http-parser hwdata iana-etc icu inetutils iproute2 iptables iputils iwd jansson json-c jsoncpp kbd keyutils kmod krb5 ldns less libarchive libassuan libbpf libcap libcap-ng libdaemon libedit libelf libevent libffi libgcrypt libgit2 libgpg-error libidn2 libinih libisl libksba libldap libluv libmm-glib libmnl libmpc libndp libnetfilter_conntrack libnewt libnfnetlink libnftnl libnghttp2 libnl libnm libnsl libp11-kit libpcap libpgm libpsl libsasl libseccomp libsecret libsodium libssh2 libsysprof-capture libtasn1 libteam libtermkey libtirpc libtool libunistring liburcu libutempter libuv libverto libvterm libxcrypt libxml2 licenses linux-api-headers linux-asahi linux-asahi-edge llvm-libs lm_sensors luajit lz4 lzfse lzo m1n1 m4 make mkinitcpio mkinitcpio-busybox mobile-broadband-provider-info mpfr msgpack-c nano ncurses neovim nettle networkmanager npth nspr nss oniguruma openssh openssl p11-kit pacman pacman-mirrorlist pam pambase patch pciutils pcre pcre2 pcsclite perl perl-error perl-mailtools perl-timedate pinentry pkgconf polkit popt procps-ng psmisc python readline reiserfsprogs rhash ripgrep rsync rustup screen sed shadow slang sqlite sudo systemd systemd-libs systemd-sysvcompat tar texinfo tmux tpm2-tss tree-sitter tzdata uboot-asahi unibilium util-linux util-linux-libs vim vim-runtime wget which wpa_supplicant xfsprogs xxhash xz zeromq zlib zsh zsh-completions zstd
  1. Copy across pacman mirror/config from the existing install:
cp -aR /etc/pacman* /mnt/etc/
  1. Edit /mnt/etc/mkinitcpio.conf (use something like nano/vim) 9a. Edit the line MODULES= to be:
MODULES=(ext4 btrfs usbhid xhci_hcd)

9b. Edit the line HOOKS= to be (adding asahi):

HOOKS=(base asahi udev autodetect modconf kms keyboard keymap consolefont block filesystems fsck)

9c. Add the following lines at the end to ensure you’re using zstd compression, which saves space on disk for the kernel:

COMPRESSION="zstd"
COMPRESSION_OPTIONS=(-T0 -3)
  1. Generate the fstab file:
genfstab -U /mnt >> /mnt/etc/fstab
  1. Edit /mnt/etc/fstab (use something like nano/vim), to be similar to the below (DO NOT CHANGE THE UUID):
UUID=   /           ext4        rw,noatime  0 1
UUID= /boot/efi vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro    0 2

You should just need to change the / mountpoint to use noatime, and ensure you don’t have commit= or barrier=0 etc, as this can lead to data corruption issues for USBs.

  1. Enter chroot: arch-chroot /mnt

  2. Minimal recommended configuration: 13a. Set a password:

passwd

13b. Change locale to en_US.UTF-8, if you want another language, you can add it to /etc/locale.conf.

# Ensure we have UTF8
echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen && echo LANG=en_US.UTF-8 > /etc/locale.conf && export LANG=en_US.UTF-8

13c. Ensure we have the keys setup:

pacman-key --init
pacman-key --populate archlinuxarm asahilinux
  1. Ensure everything is mounted: mount -a

  2. Rebuild mkinitcpio:

mkinitcpio -P

At this point, I also recommend changing grub for your first boot to be verbose, incase there are any issues. This allows easier debugging and figuring out WTF is going on. a. Edit /etc/default/grub b. Change the GRUB_CMDLINE_LINUX_DEFAULT= line to be GRUB_CMDLINE_LINUX_DEFAULT=loglevel=7" Once everything works, you can change this back to the default options loglevel=3 quiet.

  1. Install grub:
grub-mkconfig -o /boot/grub/grub.cfg
grub-install --removable

Now you can do what you would normally do if you know Arch (installing packages, enabling services, configuring networking/bluetooth, etc). Here is what I usually do for a live USB. Some of these are opinionated/my own personal preference, so pick and choose the ones you like.

# Disable logging when a command has a space at the start.
echo 'HISTIGNORE="&:[ \t]*:*[Pp][Aa][Ss][Ss][Ww][Oo][Rr][Dd]*"' > /root/.bashrc && source ~/.bashrc

# Change to your desired hostname
echo asahirecovery > /etc/hostname

# Change to your desired hostname
cat <<EOT >> /etc/hosts
127.0.0.1 localhost asahirecovery
EOT

# ntp time server configuration
cat <<EOT > /etc/systemd/timesyncd.conf
[Time]
NTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org
FallbackNTP=0.pool.ntp.org 1.pool.ntp.org 0.fr.pool.ntp.org
EOT

# remove sleep, which I want for a live USB. If you dont want this, skip.
cat <<EOT > /etc/systemd/sleep.conf
[Sleep]
AllowSuspend=no
AllowHibernation=no
AllowSuspendThenHibernate=no
AllowHybridSleep=no
EOT

# Enable sshd, timesynced, networkmanager, iwd on boot.
systemctl enable sshd systemd-timesyncd.service NetworkManager iwd.service
# If you use dbus-broker :
# systemctl enable dbus-broker

# This disables userdbd, and systemd-homed which pollutes the logs.
# I don't use systemd-resolved systemd-networkd on the Live USB, nothing against them, I use it on other systems :).
systemctl disable systemd-homed systemd-userdbd.service systemd-userdbd.socket systemd-resolved systemd-networkd
systemctl mask  systemd-homed systemd-userdbd.service systemd-userdbd.socket  systemd-resolved systemd-networkd

Once you’re done:

  1. Exit the chroot: exit

  2. Sync disks: sync

  3. Unmount the disks:

umount -R /mnt
  1. Double check you’re synced, and run fsck to ensure there are no errors..
sync
fsck /dev/sdx2

Now you can reboot if

Once you see the Asahi logo, start hammering that esc key. Once you are able to type lines, type the following:

usb start
usb reset

Sometimes it might say usb start not found, type it again. It’s because escape sometimes breaks the first key.

You should then see that your USB shows. If it doesn’t, try replugging it or using a different port on your Mac.

Then to boot the USB:

run bootcmd_usb0

Once you do all this, you can wipe the install if you want and use a UEFI install instead.