From 9f4e5feef0fa45a93edba99ebd4be6d100b4ec84 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Wed, 20 May 2026 21:29:40 -0400 Subject: [PATCH] Refactor ISO build for the package-backed install flow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ISO no longer carries a cp -r'd copy of the omarchy git checkout into /root/omarchy and the target /home/$user/.local/share/omarchy. Instead it builds omarchy-installer + omarchy-settings + omarchy + omarchy-limine from mounted source trees (${OMARCHY_INSTALLER_PATH:- ../omarchy-installer} and ${OMARCHY_PKGS_PATH:-../omarchy-pkgs}), drops them in the offline mirror, and pacstraps omarchy-installer during the target install — which deps-in the other three. - builder/build-omarchy-packages.sh: new. Builds the four packages inside the ISO build container using each PKGBUILD's OMARCHY_SRC override (introduced in Chunk 2). Creates a 'builder' user because makepkg refuses to run as root. Drops the resulting .pkg.tar.zst files into the offline-mirror directory. - builder/build-iso.sh: drop the git clone / -v omarchy mount path; call build-omarchy-packages.sh first; filter out the locally-built package names from the rest-of-mirror download so we don't try to fetch them from the network mirror. - configs/airootfs/root/.automated_script.sh: replace the install_omarchy cp-and-source dance with 'arch-chroot pacman -S omarchy-installer' followed by 'OMARCHY_INSTALL_MODE=offline omarchy-install'. Drop the big chown/chmod block that was setting up the cloned tree. use_omarchy_helpers extracts the installer's helpers/ tree directly from the offline-mirror's omarchy-installer-*.pkg.tar.zst so the live ISO has access to gum-styled logging before pacstrap. - bin/omarchy-iso-make: always mount omarchy-installer and omarchy-pkgs (paths configurable via OMARCHY_INSTALLER_PATH / OMARCHY_PKGS_PATH; default to ../omarchy-installer and ../omarchy-pkgs). --local-source is now a back-compat no-op. --- bin/omarchy-iso-make | 21 ++- builder/build-iso.sh | 109 +++++++-------- builder/build-omarchy-packages.sh | 72 ++++++++++ configs/airootfs/root/.automated_script.sh | 154 ++++++++------------- 4 files changed, 190 insertions(+), 166 deletions(-) create mode 100755 builder/build-omarchy-packages.sh diff --git a/bin/omarchy-iso-make b/bin/omarchy-iso-make index 0e2e79d..1d1f13a 100755 --- a/bin/omarchy-iso-make +++ b/bin/omarchy-iso-make @@ -16,7 +16,9 @@ while [[ $# -gt 0 ]]; do shift ;; --local-source) - LOCAL_SOURCE=1 + # Kept as a flag for back-compat (older callers passed it); the ISO + # build now always builds from local omarchy-installer + omarchy-pkgs + # checkouts. OMARCHY_MIRROR=edge shift ;; @@ -54,6 +56,16 @@ OMARCHY_INSTALLER_REPO="${OMARCHY_INSTALLER_REPO:-basecamp/omarchy}" OMARCHY_INSTALLER_REF="${OMARCHY_INSTALLER_REF:-master}" OMARCHY_MIRROR="${OMARCHY_MIRROR:-stable}" +# Source paths for the local package builds. The ISO builder pacstraps +# locally-built omarchy* packages from /omarchy-installer and /omarchy-pkgs, +# so these must point at checkouts of those repos. +OMARCHY_INSTALLER_PATH="${OMARCHY_INSTALLER_PATH:-$BUILD_ROOT/../omarchy-installer}" +OMARCHY_PKGS_PATH="${OMARCHY_PKGS_PATH:-$BUILD_ROOT/../omarchy-pkgs}" +[[ -d $OMARCHY_INSTALLER_PATH ]] || { echo "Error: omarchy-installer checkout not found at $OMARCHY_INSTALLER_PATH" >&2; exit 1; } +[[ -d $OMARCHY_PKGS_PATH ]] || { echo "Error: omarchy-pkgs checkout not found at $OMARCHY_PKGS_PATH" >&2; exit 1; } +OMARCHY_INSTALLER_PATH=$(realpath "$OMARCHY_INSTALLER_PATH") +OMARCHY_PKGS_PATH=$(realpath "$OMARCHY_PKGS_PATH") + DOCKER_ARGS=( --rm --privileged @@ -67,13 +79,10 @@ DOCKER_ARGS=( -v "$BUILD_ROOT/archiso:/archiso:ro" -v "$BUILD_ROOT/builder:/builder:ro" -v "$BUILD_ROOT/configs:/configs:ro" + -v "$OMARCHY_INSTALLER_PATH:/omarchy-installer:ro" + -v "$OMARCHY_PKGS_PATH:/omarchy-pkgs:ro" ) -# Use local source of Omarchy from $OMARCHY_PATH instead of git checkout -if [[ -n "${LOCAL_SOURCE-}" ]]; then - DOCKER_ARGS+=(-v "$OMARCHY_PATH:/omarchy:ro") -fi - # Use local pacman cache if you already have one on host to speed up repeat runs if [ -d "/var/cache/pacman/pkg" ]; then DOCKER_ARGS+=(-v "/var/cache/pacman/pkg:/var/cache/pacman/pkg") diff --git a/builder/build-iso.sh b/builder/build-iso.sh index 3680a8c..c8d728a 100755 --- a/builder/build-iso.sh +++ b/builder/build-iso.sh @@ -2,105 +2,90 @@ set -e -# Note that these are packages installed to the Arch container used to build the ISO. +# Packages installed into the Arch container used to build the ISO. pacman-key --init pacman --noconfirm -Sy archlinux-keyring pacman --noconfirm -Sy archiso git sudo base-devel jq grub -# Pre-import the omarchy signing key so pacman can verify packages without a keyserver lookup +# Pre-import the omarchy signing key (so pacman trusts our [omarchy] repo +# during the build without keyserver lookups). pacman-key --add /builder/omarchy.gpg pacman-key --lsign-key 40DFB630FF42BCFFB047046CF0134EE680CAC571 -# Install omarchy-keyring for package verification during build +# omarchy-keyring is needed inside the offline mirror too. pacman --config /configs/pacman-online-${OMARCHY_MIRROR}.conf --noconfirm -Sy omarchy-keyring pacman-key --populate omarchy -# Setup build locations -build_cache_dir="/var/cache" +# Build locations +build_cache_dir=/var/cache offline_mirror_dir="$build_cache_dir/airootfs/var/cache/omarchy/mirror/offline" -mkdir -p $build_cache_dir/ -mkdir -p $offline_mirror_dir/ +mkdir -p "$build_cache_dir" "$offline_mirror_dir" -# We base our ISO on the official arch ISO (releng) config -cp -r /archiso/configs/releng/* $build_cache_dir/ +# Seed from the official Arch releng profile. +cp -r /archiso/configs/releng/* "$build_cache_dir/" rm "$build_cache_dir/airootfs/etc/motd" -# Avoid using reflector for mirror identification as we are relying on the global CDN +# We rely on the global CDN; drop reflector. rm -rf "$build_cache_dir/airootfs/etc/systemd/system/multi-user.target.wants/reflector.service" rm -rf "$build_cache_dir/airootfs/etc/systemd/system/reflector.service.d" rm -rf "$build_cache_dir/airootfs/etc/xdg/reflector" -# Bring in our configs -cp -r /configs/* $build_cache_dir/ - -# Persist OMARCHY_MIRROR so it's available at install time +# Bring in our archiso profile additions. +cp -r /configs/* "$build_cache_dir/" echo "$OMARCHY_MIRROR" > "$build_cache_dir/airootfs/root/omarchy_mirror" -# Setup Omarchy itself -if [[ -d /omarchy ]]; then - cp -rp /omarchy "$build_cache_dir/airootfs/root/omarchy" -else - git clone -b $OMARCHY_INSTALLER_REF https://github.com/$OMARCHY_INSTALLER_REPO.git "$build_cache_dir/airootfs/root/omarchy" -fi +# Build omarchy* packages from the mounted source trees and drop them in the +# offline mirror. The .automated_script.sh later pacstraps omarchy-installer +# (which deps-in omarchy + omarchy-settings + omarchy-limine) from there. +bash /builder/build-omarchy-packages.sh "$offline_mirror_dir" -# Make log uploader available in the ISO too -mkdir -p "$build_cache_dir/airootfs/usr/local/bin/" -cp "$build_cache_dir/airootfs/root/omarchy/bin/omarchy-upload-log" "$build_cache_dir/airootfs/usr/local/bin/omarchy-upload-log" - -# Copy the Omarchy Plymouth theme to the ISO -mkdir -p "$build_cache_dir/airootfs/usr/share/plymouth/themes/omarchy" -cp -r "$build_cache_dir/airootfs/root/omarchy/default/plymouth/"* "$build_cache_dir/airootfs/usr/share/plymouth/themes/omarchy/" - -# Download and verify Node.js binary for offline installation +# Node.js binary for offline mise install. NODE_DIST_URL="https://nodejs.org/dist/latest" - -# Get checksums and parse filename and SHA NODE_SHASUMS=$(curl -fsSL "$NODE_DIST_URL/SHASUMS256.txt") NODE_FILENAME=$(echo "$NODE_SHASUMS" | grep "linux-x64.tar.gz" | awk '{print $2}') NODE_SHA=$(echo "$NODE_SHASUMS" | grep "linux-x64.tar.gz" | awk '{print $1}') - -# Download the tarball curl -fsSL "$NODE_DIST_URL/$NODE_FILENAME" -o "/tmp/$NODE_FILENAME" - -# Verify SHA256 checksum -echo "$NODE_SHA /tmp/$NODE_FILENAME" | sha256sum -c - || { - echo "ERROR: Node.js checksum verification failed!" - exit 1 -} - -# Copy to ISO +echo "$NODE_SHA /tmp/$NODE_FILENAME" | sha256sum -c - mkdir -p "$build_cache_dir/airootfs/opt/packages/" cp "/tmp/$NODE_FILENAME" "$build_cache_dir/airootfs/opt/packages/" -# Add our additional packages to packages.x86_64 +# Packages installed into the live ISO environment itself (NOT the target system). arch_packages=(linux-t2 git gum jq openssl plymouth tzupdate omarchy-keyring lvm2 cryptsetup parted) -printf '%s\n' "${arch_packages[@]}" >>"$build_cache_dir/packages.x86_64" +printf '%s\n' "${arch_packages[@]}" >> "$build_cache_dir/packages.x86_64" -# Build list of all the packages needed for the offline mirror -all_packages=($(cat "$build_cache_dir/packages.x86_64")) -all_packages+=($(grep -v '^#' "$build_cache_dir/airootfs/root/omarchy/install/omarchy-base.packages" | grep -v '^$')) -all_packages+=($(grep -v '^#' "$build_cache_dir/airootfs/root/omarchy/install/omarchy-other.packages" | grep -v '^$')) -all_packages+=($(grep -v '^#' /builder/archinstall.packages | grep -v '^$')) +# Build the offline mirror: everything pacstrap might want during the target +# install. The omarchy* packages we just built are already in the mirror; +# this pacman -Syw downloads the rest from the live network mirror. +declare -a all_packages +mapfile -t all_packages < <( + { + cat "$build_cache_dir/packages.x86_64" + grep -hv '^#\|^$' /omarchy-installer/install/omarchy-base.packages /omarchy-installer/install/omarchy-other.packages + grep -hv '^#\|^$' /builder/archinstall.packages + } | + # Filter out our locally-built packages (they're already in the mirror). + grep -vE '^(omarchy|omarchy-settings|omarchy-installer|omarchy-limine)$' | + sort -u +) -# Download all the packages to the offline mirror inside the ISO mkdir -p /tmp/offlinedb -pacman --config /configs/pacman-online-${OMARCHY_MIRROR}.conf --noconfirm -Syw "${all_packages[@]}" --cachedir $offline_mirror_dir/ --dbpath /tmp/offlinedb +pacman --config /configs/pacman-online-${OMARCHY_MIRROR}.conf --noconfirm -Syw \ + "${all_packages[@]}" --cachedir "$offline_mirror_dir/" --dbpath /tmp/offlinedb --needed + repo-add --new "$offline_mirror_dir/offline.db.tar.gz" "$offline_mirror_dir/"*.pkg.tar.zst -# Create a symlink to the offline mirror instead of duplicating it. -# mkarchiso needs packages at /var/cache/omarchy/mirror/offline in the container, -# but they're actually in $build_cache_dir/airootfs/var/cache/omarchy/mirror/offline +# mkarchiso expects the mirror at /var/cache/omarchy/mirror/offline inside the +# container (the airootfs path); symlink rather than duplicate. mkdir -p /var/cache/omarchy/mirror -ln -s "$offline_mirror_dir" "/var/cache/omarchy/mirror/offline" +ln -sf "$offline_mirror_dir" /var/cache/omarchy/mirror/offline -# Copy the offline pacman.conf to the ISO's /etc directory so the live environment uses our -# same config when booted. -cp $build_cache_dir/pacman-offline.conf "$build_cache_dir/airootfs/etc/pacman.conf" +# Live ISO uses the same offline pacman.conf. +cp "$build_cache_dir/pacman-offline.conf" "$build_cache_dir/airootfs/etc/pacman.conf" -# Finally, we assemble the entire ISO -mkarchiso -v -w "$build_cache_dir/work/" -o "/out/" "$build_cache_dir/" +# Build the ISO. +mkarchiso -v -w "$build_cache_dir/work/" -o /out/ "$build_cache_dir/" -# Fix ownership of output files to match host user -if [ -n "$HOST_UID" ] && [ -n "$HOST_GID" ]; then - chown -R "$HOST_UID:$HOST_GID" /out/ +# Match host UID/GID on output. +if [[ -n $HOST_UID && -n $HOST_GID ]]; then + chown -R "$HOST_UID:$HOST_GID" /out/ fi diff --git a/builder/build-omarchy-packages.sh b/builder/build-omarchy-packages.sh new file mode 100755 index 0000000..06389fa --- /dev/null +++ b/builder/build-omarchy-packages.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# Build omarchy + omarchy-settings + omarchy-installer + omarchy-limine from +# mounted source (/omarchy-installer + /omarchy-pkgs) and drop the .pkg.tar.zst +# files into the offline-mirror directory passed as $1. +# +# Run inside the ISO build container (build-iso.sh sources this). + +set -e + +offline_mirror_dir="$1" +if [[ -z $offline_mirror_dir ]]; then + echo "Usage: build-omarchy-packages.sh " >&2 + exit 1 +fi + +if [[ ! -d /omarchy-installer ]]; then + echo "ERROR: /omarchy-installer not mounted (pass --local-source or set OMARCHY_INSTALLER_PATH)" >&2 + exit 1 +fi +if [[ ! -d /omarchy-pkgs ]]; then + echo "ERROR: /omarchy-pkgs not mounted (set OMARCHY_PKGS_PATH or place ../omarchy-pkgs)" >&2 + exit 1 +fi + +work_dir=/tmp/omarchy-pkg-build +rm -rf "$work_dir" +mkdir -p "$work_dir" + +# makepkg refuses to run as root; create a builder user with passwordless +# sudo for pacman dep installation during the build. +if ! id builder &>/dev/null; then + useradd -m -s /bin/bash builder +fi +echo 'builder ALL=(ALL) NOPASSWD: /usr/bin/pacman' > /etc/sudoers.d/99-omarchy-pkg-builder +chmod 440 /etc/sudoers.d/99-omarchy-pkg-builder + +pacman -Sy --noconfirm + +# Order matters: omarchy depends on omarchy-settings/-installer which depend on +# the base packages; omarchy-installer depends on the others. Build leaves +# first so dependents can pacman -S them from /tmp once needed. We don't +# actually install during the build, so the order is mostly cosmetic — but +# keeping it stable helps logs. +packages=( + omarchy-limine + omarchy-settings + omarchy + omarchy-installer +) + +for pkg in "${packages[@]}"; do + echo "----------------------------------------" + echo "Building $pkg" + echo "----------------------------------------" + pkg_work="$work_dir/$pkg" + cp -a "/omarchy-pkgs/pkgbuilds/$pkg" "$pkg_work" + chown -R builder:builder "$pkg_work" + + su builder -c " + cd '$pkg_work' && + PKGDEST='$work_dir' \ + OMARCHY_SRC=/omarchy-installer \ + makepkg --noconfirm --skippgpcheck --skipchecksums -s -f + " +done + +mkdir -p "$offline_mirror_dir" +mv "$work_dir"/*.pkg.tar.zst "$offline_mirror_dir/" + +echo +echo "Built omarchy packages, placed in $offline_mirror_dir:" +ls "$offline_mirror_dir"/omarchy*.pkg.tar.zst | sed 's|^| |' diff --git a/configs/airootfs/root/.automated_script.sh b/configs/airootfs/root/.automated_script.sh index 7566803..2ba006e 100644 --- a/configs/airootfs/root/.automated_script.sh +++ b/configs/airootfs/root/.automated_script.sh @@ -2,11 +2,25 @@ set -euo pipefail use_omarchy_helpers() { - export OMARCHY_PATH="/root/omarchy" - export OMARCHY_INSTALL="/root/omarchy/install" - export OMARCHY_INSTALL_LOG_FILE="/var/log/omarchy-install.log" + # The omarchy-installer package isn't installed in the live ISO environment; + # only mounted as part of the offline mirror. Source the helpers we still + # need (gum styling, run_logged) from the package's install/ tree by + # pulling it out of the offline mirror tarball into /tmp. export OMARCHY_MIRROR="$(cat /root/omarchy_mirror)" - source /root/omarchy/install/helpers/all.sh + if [[ ! -d /tmp/omarchy-installer-iso ]]; then + local pkg + pkg=$(ls /var/cache/omarchy/mirror/offline/omarchy-installer-*.pkg.tar.zst 2>/dev/null | head -1) + if [[ -z $pkg ]]; then + echo "ERROR: omarchy-installer package not found in offline mirror" >&2 + exit 1 + fi + mkdir -p /tmp/omarchy-installer-iso + bsdtar -xf "$pkg" -C /tmp/omarchy-installer-iso usr/share/omarchy + fi + export OMARCHY_PATH=/tmp/omarchy-installer-iso/usr/share/omarchy + export OMARCHY_INSTALL=$OMARCHY_PATH/install + export OMARCHY_INSTALL_LOG_FILE=/var/log/omarchy-install.log + source "$OMARCHY_INSTALL/helpers/all.sh" } run_configurator() { @@ -21,10 +35,8 @@ install_arch() { echo touch /var/log/omarchy-install.log - start_log_output - # Set CURRENT_SCRIPT for the trap to display better when nothing is returned for some reason CURRENT_SCRIPT="install_base_system" install_base_system > >(sed -u 's/\x1b\[[0-9;]*[a-zA-Z]//g' >>/var/log/omarchy-install.log) 2>&1 unset CURRENT_SCRIPT @@ -32,39 +44,31 @@ 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" + # Install the omarchy meta-packages from the offline mirror into the target. + # omarchy-installer's depends pull in omarchy + omarchy-settings + omarchy-limine. + arch-chroot /mnt pacman -S --noconfirm --needed omarchy-installer + + # Run the installer's offline path. omarchy-install execs /usr/share/omarchy/ + # install.sh; OMARCHY_INSTALL_MODE=offline tells it to skip first-run-mode + # the right way for a chroot install. + chroot_run_as_user "OMARCHY_INSTALL_MODE=offline omarchy-install" configure_login_for_unencrypted_install - # Reboot if requested by installer if [[ -f /mnt/var/tmp/omarchy-install-completed ]]; then reboot fi } -# Set Tokyo Night color scheme for the terminal +# Tokyo Night palette so the live VT matches the installed look. set_tokyo_night_colors() { - if [[ $(tty) == "/dev/tty"* ]]; then - # Tokyo Night color palette - echo -en "\e]P01a1b26" # black (background) - echo -en "\e]P1f7768e" # red - echo -en "\e]P29ece6a" # green - echo -en "\e]P3e0af68" # yellow - echo -en "\e]P47aa2f7" # blue - echo -en "\e]P5bb9af7" # magenta - echo -en "\e]P67dcfff" # cyan - echo -en "\e]P7a9b1d6" # white - echo -en "\e]P8414868" # bright black - echo -en "\e]P9f7768e" # bright red - echo -en "\e]PA9ece6a" # bright green - echo -en "\e]PBe0af68" # bright yellow - echo -en "\e]PC7aa2f7" # bright blue - echo -en "\e]PDbb9af7" # bright magenta - echo -en "\e]PE7dcfff" # bright cyan - echo -en "\e]PFc0caf5" # bright white (foreground) - - # Set default foreground and background + if [[ $(tty) == /dev/tty* ]]; then + echo -en "\e]P01a1b26"; echo -en "\e]P1f7768e"; echo -en "\e]P29ece6a" + echo -en "\e]P3e0af68"; echo -en "\e]P47aa2f7"; echo -en "\e]P5bb9af7" + echo -en "\e]P67dcfff"; echo -en "\e]P7a9b1d6"; echo -en "\e]P8414868" + echo -en "\e]P9f7768e"; echo -en "\e]PA9ece6a"; echo -en "\e]PBe0af68" + echo -en "\e]PC7aa2f7"; echo -en "\e]PDbb9af7"; echo -en "\e]PE7dcfff" + echo -en "\e]PFc0caf5" echo -en "\033[0m" clear fi @@ -76,48 +80,28 @@ install_disk() { cleanup_install_disk() { local disk="$1" - - if [[ -z "$disk" || ! -b "$disk" ]]; then - echo "Could not determine install disk for cleanup" >&2 - return 1 - fi + [[ -n $disk && -b $disk ]] || { echo "Could not determine install disk for cleanup" >&2; return 1; } echo "Cleaning up existing holders on install disk: $disk" - - # Ensure that no mounts exist from past install attempts. findmnt -R /mnt >/dev/null && umount -R /mnt || true - # Turn off swap and unmount anything backed by the selected disk, including - # device-mapper children from a previous install. Active LVM/swap holders can - # prevent the kernel from re-reading the partition table after archinstall - # wipes and recreates it. while read -r dev; do - [[ -b "$dev" ]] || continue - + [[ -b $dev ]] || continue swapoff "$dev" 2>/dev/null || true - while read -r target; do - [[ -n "$target" ]] || continue - umount "$target" 2>/dev/null || true + [[ -n $target ]] && umount "$target" 2>/dev/null || true done < <(findmnt -rn -S "$dev" -o TARGET 2>/dev/null || true) done < <(lsblk -rnpo PATH "$disk") - # Deactivate any LVM volume groups whose physical volumes live on the selected - # disk. This is the common case when replacing Fedora/Alma/RHEL installs. while read -r dev type; do - [[ "$type" == "disk" || "$type" == "part" || "$type" == "crypt" ]] || continue - + [[ $type == disk || $type == part || $type == crypt ]] || continue while read -r vg; do - [[ -n "$vg" ]] || continue - vgchange -an "$vg" 2>/dev/null || true + [[ -n $vg ]] && vgchange -an "$vg" 2>/dev/null || true done < <(pvs --noheadings -o vg_name "$dev" 2>/dev/null | awk '{$1=$1; print}' | sort -u) done < <(lsblk -rnpo PATH,TYPE "$disk") - # Close any LUKS mappings stacked on the selected disk after filesystems and - # swap have been released. while read -r dev type; do - [[ "$type" == "crypt" ]] || continue - cryptsetup close "$dev" 2>/dev/null || true + [[ $type == crypt ]] && cryptsetup close "$dev" 2>/dev/null || true done < <(lsblk -rnpo PATH,TYPE "$disk") blockdev --flushbufs "$disk" 2>/dev/null || true @@ -126,31 +110,21 @@ cleanup_install_disk() { } install_base_system() { - # Initialize and populate the keyring pacman-key --init pacman-key --populate archlinux pacman-key --populate omarchy - - # Sync the offline database so pacman can find packages pacman -Sy --noconfirm cleanup_install_disk "$(install_disk)" - # Workarounds for archinstall 4.2 regressions under Python 3.14: - # 1. sync_log_to_install_medium: `self.target / absolute_logfile` drops - # self.target because the RHS is absolute, so Path.copy() raises EINVAL - # (source == target). - # 2. _add_limine_bootloader: `Path.copy(efi_dir_path)` raises IsADirectoryError - # because 3.14's Path.copy treats target as a literal path, not a directory - # (shutil.copy used to auto-append the source filename). + # archinstall 4.2 / Python 3.14 workarounds (matches upstream-main install + # behavior; carry forward until upstream lands the fixes). sed -i \ -e 's|logfile_target = self\.target / absolute_logfile$|logfile_target = self.target / absolute_logfile.relative_to("/")|' \ -e 's|(limine_path / file)\.copy(efi_dir_path)|(limine_path / file).copy(efi_dir_path / file)|' \ -e "s|(limine_path / 'limine-bios.sys')\.copy(boot_limine_path)|(limine_path / 'limine-bios.sys').copy(boot_limine_path / 'limine-bios.sys')|" \ /usr/lib/python3.14/site-packages/archinstall/lib/installer.py - # Install using files generated by the ./configurator - # Skip NTP and WKD sync since we're offline (keyring is pre-populated in ISO) archinstall \ --config user_configuration.json \ --creds user_credentials.json \ @@ -159,19 +133,18 @@ install_base_system() { --skip-wkd \ --skip-wifi-check - # After archinstall sets up the base system but before our installer runs, - # we need to ensure the offline pacman.conf is in place + # Use the offline pacman.conf for the target so it pulls from the bundled + # mirror, not from the network. cp /etc/pacman.conf /mnt/etc/pacman.conf - # Mount the offline mirror so it's accessible in the chroot - mkdir -p /mnt/var/cache/omarchy/mirror/offline + # Bind-mount the offline mirror + the /opt/packages tarballs into the target + # so chroot pacman / installer scripts can see them. + mkdir -p /mnt/var/cache/omarchy/mirror/offline /mnt/opt/packages mount --bind /var/cache/omarchy/mirror/offline /mnt/var/cache/omarchy/mirror/offline - - # Mount the packages dir so it's accessible in the chroot - mkdir -p /mnt/opt/packages mount --bind /opt/packages /mnt/opt/packages - # No need to ask for sudo during the installation (omarchy itself responsible for removing after install) + # Temporary passwordless sudo for the install user (cleaned up by + # omarchy's first-run flow). mkdir -p /mnt/etc/sudoers.d cat >/mnt/etc/sudoers.d/99-omarchy-installer </dev/null || true - find /mnt/home/$OMARCHY_USER/.local/share/omarchy/default/waybar -type f -name "*.sh" -exec chmod +x {} \; 2>/dev/null || true } configure_login_for_unencrypted_install() { @@ -197,12 +159,6 @@ configure_login_for_unencrypted_install() { return fi - # Unencrypted installs must stop at SDDM so the user password is entered - # before reaching the desktop. Omarchy's normal encrypted path may autologin - # because the disk password was already entered at boot. - # - # Keep the Omarchy SDDM theme and seed SDDM's last user/session state so - # first boot looks like the SDDM screen shown after logging out of Omarchy. mkdir -p /mnt/etc/sddm.conf.d rm -f /mnt/etc/sddm.conf.d/autologin.conf cat >/mnt/etc/sddm.conf.d/99-omarchy-login.conf </dev/null 2>&1 || true } -chroot_bash() { +# Run a bash command inside the chroot as the install user, with the env the +# offline installer expects. +chroot_run_as_user() { HOME=/home/$OMARCHY_USER \ - arch-chroot -u $OMARCHY_USER /mnt/ \ - env OMARCHY_CHROOT_INSTALL=1 \ + arch-chroot -u "$OMARCHY_USER" /mnt/ \ + env OMARCHY_INSTALL_MODE=offline \ OMARCHY_USER_NAME="$(