diff --git a/iso/README.md b/iso/README.md index e5cbb3d..087822e 100644 --- a/iso/README.md +++ b/iso/README.md @@ -34,6 +34,17 @@ The systemd service runs `flask --app app run --host 0.0.0.0 --port 5000` under mDNS is wired: `avahi-daemon` + `nss-mdns` come from `packages.extra`, the live ISO's hostname is `proksi`, and as soon as `systemd-networkd-wait-online` fires the installer is reachable at `http://proksi.local:5000`. The raw IP still shows on the console for fallback — some Windows clients need the Bonjour service for `.local` to resolve at all. +### archinstall is pinned + +The webinstaller imports archinstall internals and `furtka-webinstaller.service` sed-patches one of its files, so `build.sh` does not take whatever archinstall the Arch repos currently ship. It downloads the version in `ARCHINSTALL_PIN` from `archive.archlinux.org`, checks it against `ARCHINSTALL_SHA256`, and serves it from a local `[furtka-pinned]` repo listed before `[core]` in the build's `pacman.conf` (pacman takes a package from the first repo that has it). Only the build uses that repo; the live system's own `pacman.conf` is untouched. + +The build fails with "pinned archinstall … targets Python X, Arch now ships Y" once Arch moves to a new Python — the pinned package would install into a dead `site-packages`. To bump: + +1. Pick the new version from . +2. `curl -LO` the `.pkg.tar.zst`, `sha256sum` it, and update `ARCHINSTALL_PIN` + `ARCHINSTALL_SHA256` at the top of `build.sh`. +3. Check that `webinstaller/app.py:build_disk_config` still imports and that the `ExecStartPre` sed in `furtka-webinstaller.service` still matches (`journalctl -u furtka-webinstaller` on the live ISO). +4. Full VM install (UEFI and BIOS) before merging. + `build.sh` also deletes releng's `getty@tty1.service.d/autologin.conf`. With root auto-logged-in, tty1 belongs to a shell and `agetty --reload` can't redraw the banner, so the IP line was a snapshot of whatever DHCP had done by the time getty started. Without autologin tty1 sits at the login prompt showing the live banner; for a shell type `root` + Enter (releng's root has no password) — the banner says so. ## Test flow diff --git a/iso/build.sh b/iso/build.sh index 1587633..499ddab 100755 --- a/iso/build.sh +++ b/iso/build.sh @@ -27,7 +27,11 @@ fi # ---- inside the container from here on ---- echo "==> Syncing pacman, installing archiso" -pacman -Syu --noconfirm --needed archiso +pacman -Syu --noconfirm --needed archiso curl zstd + +# archinstall build the webinstaller is validated against (see pin step below). +ARCHINSTALL_PIN="4.4-1" +ARCHINSTALL_SHA256="6cb5da75c108ef2f5d25a7a20baf6c52cc927d5e06890dd10182e6eb4be815cb" PROFILE_SRC="/usr/share/archiso/configs/releng" PROFILE_WORK="/tmp/furtka-profile" @@ -43,6 +47,37 @@ cat "$SCRIPT_DIR/overlay/packages.extra" >> "$PROFILE_WORK/packages.x86_64" cat "$SCRIPT_DIR/overlay/profiledef.sh" >> "$PROFILE_WORK/profiledef.sh" +echo "==> Pinning archinstall ${ARCHINSTALL_PIN}" +# The webinstaller imports archinstall internals (build_disk_config) and +# sed-patches one of its files at service start, so a silent archinstall +# upgrade in the Arch repos can break every install with no change on our +# side. Serve the validated build from a local repo listed *before* [core]: +# pacman takes a package from the first repo that has it, whatever the +# version elsewhere. Bump deliberately: new version + sha256 below, rebuild, +# run the smoke VM (see iso/README.md). +PINNED_REPO="/tmp/furtka-pinned-repo" +rm -rf "$PINNED_REPO" && mkdir -p "$PINNED_REPO" +ARCHINSTALL_PKG="archinstall-${ARCHINSTALL_PIN}-any.pkg.tar.zst" +curl -fsSL --retry 3 -o "$PINNED_REPO/$ARCHINSTALL_PKG" \ + "https://archive.archlinux.org/packages/a/archinstall/$ARCHINSTALL_PKG" +echo "${ARCHINSTALL_SHA256} $PINNED_REPO/$ARCHINSTALL_PKG" | sha256sum -c - +# archinstall is an "any" package installed under /usr/lib/python3.X; after +# Arch moves to a new Python it would install into a dead directory. Fail +# the build with a clear message instead of shipping a broken installer. +pkg_py=$(tar --zstd -tf "$PINNED_REPO/$ARCHINSTALL_PKG" \ + | sed -n 's|^usr/lib/python\(3\.[0-9]*\)/.*|\1|p' | sort -u) +repo_py=$(pacman -Si python | awk -F': ' '/^Version/ {split($2, v, "."); print v[1] "." v[2]}') +if [ "$pkg_py" != "$repo_py" ]; then + echo "ERROR: pinned archinstall ${ARCHINSTALL_PIN} targets Python $pkg_py, Arch now ships $repo_py." >&2 + echo " Bump ARCHINSTALL_PIN/ARCHINSTALL_SHA256 in iso/build.sh (see iso/README.md)." >&2 + exit 1 +fi +repo-add -q "$PINNED_REPO/furtka-pinned.db.tar.gz" "$PINNED_REPO/$ARCHINSTALL_PKG" +# The sha256 above already pins the exact bytes. +sed -i "0,/^\[core\]/s||[furtka-pinned]\nSigLevel = Optional TrustAll\nServer = file://$PINNED_REPO\n\n[core]|" \ + "$PROFILE_WORK/pacman.conf" +grep -q '^\[furtka-pinned\]' "$PROFILE_WORK/pacman.conf" + cp -a "$SCRIPT_DIR/overlay/airootfs/." "$PROFILE_WORK/airootfs/" # releng auto-logs root in on tty1. That turns our /etc/issue banner into a