From 7e830d6a281636d387585f203db77cbc05b85592 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 12 Jul 2026 10:55:43 -0700 Subject: [PATCH 1/5] Fix ISO boot finalization Archinstall unmounts the ESP before the Omarchy finalizer runs, leaving /boot empty in the target chroot. Mount it so Limine setup can access the generated configuration and EFI artifacts. The installed ESP uses root-only masks while finalization runs as the target user. Mount it temporarily with fmask=0022,dmask=0022 and verify the target user can traverse /boot; the installed fstab remains unchanged. Remove the fallback shell from the installer invocation so finalizer errors propagate instead of reporting a completed installation and rebooting a partially configured system. --- configs/airootfs/root/.automated_script.sh | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/configs/airootfs/root/.automated_script.sh b/configs/airootfs/root/.automated_script.sh index 7566803..1794eee 100644 --- a/configs/airootfs/root/.automated_script.sh +++ b/configs/airootfs/root/.automated_script.sh @@ -33,7 +33,7 @@ install_arch() { install_omarchy() { chroot_bash -lc "sudo pacman -S --noconfirm --needed gum" >/dev/null - chroot_bash -lc "source /home/$OMARCHY_USER/.local/share/omarchy/install.sh || bash" + chroot_bash -lc "source /home/$OMARCHY_USER/.local/share/omarchy/install.sh" configure_login_for_unencrypted_install @@ -159,6 +159,24 @@ install_base_system() { --skip-wkd \ --skip-wifi-check + # Archinstall unmounts the ESP when it finishes. Omarchy's boot finalizer + # needs the generated Limine config and EFI artifacts available under /boot. + if ! mountpoint -q /mnt/boot; then + arch-chroot /mnt mount /boot + fi + + # The installed fstab keeps the ESP root-only, but Omarchy finalization runs + # as the target user and must discover the Limine config before using sudo to + # replace it. Temporarily allow reads and directory traversal during install. + boot_device=$(findmnt -nro SOURCE --target /mnt/boot) + umount /mnt/boot + mount -t vfat -o rw,fmask=0022,dmask=0022 "$boot_device" /mnt/boot + + if ! arch-chroot -u "$OMARCHY_USER" /mnt test -x /boot; then + echo "Target user cannot access the mounted ESP" >&2 + return 1 + fi + # After archinstall sets up the base system but before our installer runs, # we need to ensure the offline pacman.conf is in place cp /etc/pacman.conf /mnt/etc/pacman.conf From 2ed796535d239cd19fb50077d8a76db1b27b7cc1 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 12 Jul 2026 17:04:05 -0700 Subject: [PATCH 2/5] Ensure we aren't sharing mirror caches between channels --- bin/omarchy-iso-make | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bin/omarchy-iso-make b/bin/omarchy-iso-make index 0e2e79d..3bb93cb 100755 --- a/bin/omarchy-iso-make +++ b/bin/omarchy-iso-make @@ -79,11 +79,10 @@ if [ -d "/var/cache/pacman/pkg" ]; then DOCKER_ARGS+=(-v "/var/cache/pacman/pkg:/var/cache/pacman/pkg") fi -# Mount the build cache directory where packages are downloaded +# Mount the build cache directory where packages are downloaded. Channels use +# different package snapshots and must never share an offline mirror cache. if [[ -z "$NO_CACHE" ]]; then - # using a dated dir on the host to refresh daily if building multiple times - BUILD_DATE=$(date +%Y-%m-%d) - OFFLINE_REPO_BUILD_CACHE_DIR="$HOME/.cache/omarchy/iso_${BUILD_DATE}/airootfs/var/cache/omarchy" + OFFLINE_REPO_BUILD_CACHE_DIR="$HOME/.cache/omarchy/iso_${OMARCHY_MIRROR}/airootfs/var/cache/omarchy" mkdir -p "$OFFLINE_REPO_BUILD_CACHE_DIR" # Mount to /var/cache/airootfs/var/cache/omarchy since that's where repo packages go in the ISO DOCKER_ARGS+=(-v "$OFFLINE_REPO_BUILD_CACHE_DIR:/var/cache/airootfs/var/cache/omarchy") From eadb1175604553a79d27956e33422a6098ecb65f Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 12 Jul 2026 17:59:13 -0700 Subject: [PATCH 3/5] Add --quattro as an option for iso creation --- README.md | 2 +- bin/omarchy-iso-make | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a8094dd..5a2b9c9 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ See the ISO link on [omarchy.org](https://omarchy.org). ## Creating the ISO -Run `./bin/omarchy-iso-make` and the output goes into `./release`. You can build from your local $OMARCHY_PATH for testing by using `--local-source` or from a checkout of the dev branch (instead of master) by using `--dev`. +Run `./bin/omarchy-iso-make` and the output goes into `./release`. You can build from your local `$OMARCHY_PATH` for testing with `--local-source`, from the dev branch with `--dev`, or from the quattro branch with `--quattro`. The dev and quattro builds use the edge package mirror. ### Environment Variables diff --git a/bin/omarchy-iso-make b/bin/omarchy-iso-make index 3bb93cb..349b971 100755 --- a/bin/omarchy-iso-make +++ b/bin/omarchy-iso-make @@ -25,6 +25,11 @@ while [[ $# -gt 0 ]]; do OMARCHY_MIRROR=edge shift ;; + --quattro) + OMARCHY_INSTALLER_REF=quattro + OMARCHY_MIRROR=edge + shift + ;; --rc) OMARCHY_MIRROR=rc OMARCHY_INSTALLER_REF=rc @@ -32,7 +37,7 @@ while [[ $# -gt 0 ]]; do ;; *) echo "Unknown option: $1" - echo "Usage: $0 [--no-cache] [--no-boot-offer] [--local-source] [--dev] [--rc]" + echo "Usage: $0 [--no-cache] [--no-boot-offer] [--local-source] [--dev] [--quattro] [--rc]" exit 1 ;; esac From 94c779d028dddc0343a28ebfa153de7f6b2ea778 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 13 Jul 2026 11:17:34 -0700 Subject: [PATCH 4/5] Fix QEMU display startup --- bin/omarchy-iso-boot | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/bin/omarchy-iso-boot b/bin/omarchy-iso-boot index 4cd7436..4081c47 100755 --- a/bin/omarchy-iso-boot +++ b/bin/omarchy-iso-boot @@ -20,6 +20,22 @@ fi omarchy-pkg-add qemu-full edk2-ovmf +if [[ -z ${WAYLAND_DISPLAY:-} && -z ${DISPLAY:-} ]]; then + while IFS='=' read -r name value; do + case "$name" in + WAYLAND_DISPLAY|DISPLAY|XAUTHORITY|XDG_SESSION_TYPE) + export "$name=$value" + ;; + esac + done < <(systemctl --user show-environment 2>/dev/null || true) +fi + +if [[ -z ${WAYLAND_DISPLAY:-} && -z ${DISPLAY:-} ]]; then + echo "Unable to find a graphical session for QEMU." >&2 + echo "Run omarchy-iso-boot from the Omarchy desktop session." >&2 + exit 1 +fi + DISK="/tmp/omarchy-iso-boot.qcow2" if [[ ! -f $DISK || $REUSE != "reuse" ]]; then qemu-img create -f qcow2 "$DISK" 40G @@ -37,8 +53,8 @@ qemu-system-x86_64 \ -device virtio-blk-pci,drive=drive0,bootindex=1 \ -drive file="$ISO",media=cdrom,if=none,format=raw,id=cdrom0 \ -device ide-cd,drive=cdrom0,bootindex=2 \ - -device virtio-vga-gl \ - -display gtk,gl=on \ + -device virtio-vga \ + -display gtk \ -usb -device usb-tablet \ -netdev user,id=net0,hostfwd=tcp::2222-:22 \ -device virtio-net-pci,netdev=net0 \ From abbd9eda34acc7dc60fc8e430f487ed59c535d9e Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 13 Jul 2026 16:06:41 -0700 Subject: [PATCH 5/5] Read signing key from 1pw --- README.md | 2 +- bin/omarchy-iso-sign | 46 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 5a2b9c9..d83ccd3 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Run `./bin/omarchy-iso-boot [release/omarchy.iso]`. ## Signing the ISO -Run `./bin/omarchy-iso-sign [gpg-user] [release/omarchy.iso]`. +Run `./bin/omarchy-iso-sign [release/omarchy.iso]`. The signing key is retrieved from the shared Omarchy vault with the 1Password CLI. ## Uploading the ISO diff --git a/bin/omarchy-iso-sign b/bin/omarchy-iso-sign index f852cbf..9d8865d 100755 --- a/bin/omarchy-iso-sign +++ b/bin/omarchy-iso-sign @@ -1,14 +1,48 @@ #!/bin/bash -if [ $# -eq 0 ]; then +set -euo pipefail + +if [[ $# -ne 1 ]]; then echo "usage: omarchy-iso-sign [release/omarchy.iso]" exit 1 fi -if ! pacman -Q gnupg >/dev/null; then - sudo pacman -S --noconfirm --needed --quiet gnupg - echo "You'll need to import key with: gpg --import path/to/signing-key.asc" +iso="$1" +key_ref="op://Shared/Omarchy GPG Private Key/omarchy-private.asc" + +if [[ ! -f $iso ]]; then + echo "ISO not found: $iso" >&2 + exit 1 fi -gnupg_user_key=$(gpg --list-secret-keys --keyid-format=long | awk '/^[[:space:]]/{print $1; exit}') -gpg --local-user "$gnupg_user_key" --output $1.sig --detach-sig $1 +if ! command -v op >/dev/null; then + echo "1Password CLI is required to retrieve the signing key." >&2 + exit 1 +fi + +if ! pacman -Q gnupg >/dev/null 2>&1; then + sudo pacman -S --noconfirm --needed --quiet gnupg +fi + +gnupg_home="$(mktemp -d)" +chmod 700 "$gnupg_home" +trap 'rm -rf "$gnupg_home"' EXIT + +op read "$key_ref" --account Omarchy | + gpg --batch --homedir "$gnupg_home" --import >/dev/null + +signing_key="$( + gpg --batch --homedir "$gnupg_home" --with-colons --list-secret-keys | + awk -F: '$1 == "fpr" { print $10; exit }' +)" + +if [[ -z $signing_key ]]; then + echo "No private signing key found in $key_ref" >&2 + exit 1 +fi + +gpg --batch --yes \ + --homedir "$gnupg_home" \ + --local-user "$signing_key" \ + --output "$iso.sig" \ + --detach-sig "$iso"