From 1fe29df5ad0e7a58cb1da2664c4070aa4d6c3cb2 Mon Sep 17 00:00:00 2001 From: Arvind Date: Sat, 1 Aug 2026 03:15:53 -0700 Subject: [PATCH 1/6] Update grub.cfg --- overlay/files-iso/boot/grub2/grub.cfg | 39 +++++++++++++++++++++------ 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/overlay/files-iso/boot/grub2/grub.cfg b/overlay/files-iso/boot/grub2/grub.cfg index 1aaa44fc..62b5af0f 100644 --- a/overlay/files-iso/boot/grub2/grub.cfg +++ b/overlay/files-iso/boot/grub2/grub.cfg @@ -1,33 +1,56 @@ -search --file --set=root /boot/kernel.xz +search --no-floppy --file --set=root /boot/kernel set default={{DEFAULT_ENTRY}} set timeout=5 set timeout_style=menu set linux=linux set initrd=initrd + +# Video/console parameters are firmware-specific. +# +# BIOS/CSM: vga=795 requests VESA mode 0x31B via INT 10h from the legacy video +# BIOS, giving the kernel a framebuffer console. Unchanged. +# +# UEFI: there is no VBE, so vga= is inert. Combined with nomodeset (which +# blocks the native KMS driver) the kernel ends up with no usable +# framebuffer and the screen stays black. The last console= also wins +# for /dev/console, so console=tty0 must come last or all output goes +# to serial. The baud is pinned because an unqualified console=ttyS0 +# defaults to 9600 while BMC SOL typically runs at 115200. if [ "${grub_platform}" = "efi" ]; then - echo "Please press 't' to show the boot menu on this console" + set consoleparams="console=ttyS0,115200n8 console=tty0" + set videoparams="" +else + set consoleparams="console=tty1 console=ttyS0" + set videoparams="vga=795 nomodeset" fi -set font=($root)/boot/${grub_cpu}/loader/grub2/fonts/unicode.pf2 -if [ -f ${font} ];then - loadfont ${font} + +# loadfont switches GRUB to gfxterm. Some UEFI implementations (observed on +# Supermicro with ATEN BMC) render nothing in that mode, leaving a blank menu, +# so keep the graphical terminal on the BIOS path only. +if [ "${grub_platform}" != "efi" ]; then + set font=($root)/boot/${grub_cpu}/loader/grub2/fonts/unicode.pf2 + if [ -f ${font} ];then + loadfont ${font} + fi fi + menuentry "Palette eXtended Kubernetes Edge Installer" --class os --unrestricted { echo Loading kernel... - $linux ($root)/boot/kernel cdroot root=live:CDLABEL=COS_LIVE rd.live.dir=/ rd.live.squashimg=rootfs.squashfs net.ifnames=1 console=tty1 console=ttyS0 rd.cos.disable vga=795 nomodeset nodepair.enable selinux=0 rd.live.overlay.overlayfs rd.immucore.sysrootwait=600 systemd.unified_cgroup_hierarchy=1 rd.driver.blacklist=nouveau,qat_4xxx modprobe.blacklist=nouveau,qat_4xxx nouveau.modeset=0 + $linux ($root)/boot/kernel cdroot root=live:CDLABEL=COS_LIVE rd.live.dir=/ rd.live.squashimg=rootfs.squashfs net.ifnames=1 $consoleparams rd.cos.disable $videoparams nodepair.enable selinux=0 rd.live.overlay.overlayfs rd.immucore.sysrootwait=600 systemd.unified_cgroup_hierarchy=1 rd.driver.blacklist=nouveau,qat_4xxx modprobe.blacklist=nouveau,qat_4xxx nouveau.modeset=0 echo Loading initrd... $initrd ($root)/boot/initrd } menuentry "Palette eXtended Kubernetes Edge Installer (manual)" --class os --unrestricted { echo Loading kernel... - $linux ($root)/boot/kernel cdroot root=live:CDLABEL=COS_LIVE rd.live.dir=/ rd.live.squashimg=rootfs.squashfs net.ifnames=1 console=tty1 console=ttyS0 rd.cos.disable selinux=0 rd.live.overlay.overlayfs rd.immucore.sysrootwait=600 systemd.unified_cgroup_hierarchy=1 rd.driver.blacklist=nouveau,qat_4xxx modprobe.blacklist=nouveau,qat_4xxx nouveau.modeset=0 + $linux ($root)/boot/kernel cdroot root=live:CDLABEL=COS_LIVE rd.live.dir=/ rd.live.squashimg=rootfs.squashfs net.ifnames=1 $consoleparams rd.cos.disable selinux=0 rd.live.overlay.overlayfs rd.immucore.sysrootwait=600 systemd.unified_cgroup_hierarchy=1 rd.driver.blacklist=nouveau,qat_4xxx modprobe.blacklist=nouveau,qat_4xxx nouveau.modeset=0 echo Loading initrd... $initrd ($root)/boot/initrd } menuentry "Palette Edge Interactive Installer" --class os --unrestricted { echo Loading kernel... - $linux ($root)/boot/kernel cdroot root=live:CDLABEL=COS_LIVE rd.live.dir=/ rd.live.squashimg=rootfs.squashfs net.ifnames=1 console=tty1 console=ttyS0 rd.cos.disable vga=795 nomodeset nodepair.enable selinux=0 rd.live.overlay.overlayfs rd.immucore.sysrootwait=600 systemd.unified_cgroup_hierarchy=1 rd.driver.blacklist=nouveau,qat_4xxx modprobe.blacklist=nouveau,qat_4xxx nouveau.modeset=0 interactive-install + $linux ($root)/boot/kernel cdroot root=live:CDLABEL=COS_LIVE rd.live.dir=/ rd.live.squashimg=rootfs.squashfs net.ifnames=1 $consoleparams rd.cos.disable $videoparams nodepair.enable selinux=0 rd.live.overlay.overlayfs rd.immucore.sysrootwait=600 systemd.unified_cgroup_hierarchy=1 rd.driver.blacklist=nouveau,qat_4xxx modprobe.blacklist=nouveau,qat_4xxx nouveau.modeset=0 interactive-install echo Loading initrd... $initrd ($root)/boot/initrd } From 6d409d60bcca730a8376691a14b3f1deeb787f57 Mon Sep 17 00:00:00 2001 From: Vipin Sharma Date: Mon, 3 Aug 2026 20:12:26 -0700 Subject: [PATCH 2/6] feat(iso): switch +build-iso and +build-uki-iso to AuroraBoot kairos-io/osbuilder and kairos-io/enki are both archived, so the osbuilder-tools image we've built ISOs against for years has no maintained upstream. Switch to quay.io/kairos/auroraboot:v0.26.1 (kairos-io/AuroraBoot), the maintained successor. Only +build-iso and +build-uki-iso move. +uki-genkey and +build-provider-trustedboot-image still call the osbuilder entrypoint; they touch container/UKI artifacts, not ISOs, and can migrate separately once the ISO switch is boot-verified. Mapping (osbuilder -> AuroraBoot): /entrypoint.sh build-iso -> auroraboot build-iso --name -> --override-name --arch x86_64 -> --arch amd64 (Go arch names) enki build-uki -t iso -> auroraboot build-uki -t iso -k /keys (bundled) -> --public-keys / --sb-key / --sb-cert / --tpm-pcr-private-key (all still under /keys because the three secure-boot/* source dirs are flattened into the same COPY target) Bonuses from the AuroraBoot base image (Fedora 44): - xorriso 1.5.8.pl02 (osbuilder-tools ships 1.4.6, which the Supermicro ATEN BMC virtual CD refuses to boot). This is the xorriso fix vipsharm-isofix built from source; no longer needed. - Actively maintained; kairos-sdk fixes land here. Caveat: AuroraBoot still selects grubx64.efi.signed (installed-system variant, prefix /EFI/ubuntu) via kairos-sdk utils.GetEfiGrubFiles. That binary hangs immediately on Supermicro UEFI. This switch does not fix defect 1 from the UEFI investigation on its own. Verifying that on real hardware is the next step; if it reproduces, the CD-variant swap workaround from vipsharm-isofix 22e00cb / 0a80d30 gets ported. The grub.cfg cleanup (previous commit, ex-3faff86) is independent of the toolchain switch and rides along. Co-Authored-By: Claude Opus 4.7 --- Earthfile | 112 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 40 deletions(-) diff --git a/Earthfile b/Earthfile index 6b0f6fd8..e49951f2 100644 --- a/Earthfile +++ b/Earthfile @@ -31,9 +31,12 @@ ARG RKE2_FLAVOR_TAG=rke2r1 ARG BASE_IMAGE_URL=quay.io/kairos ARG OSBUILDER_VERSION=v0.400.3 ARG OSBUILDER_IMAGE=quay.io/kairos/osbuilder-tools:$OSBUILDER_VERSION -# v0.18.0 is the minimum usable version. v0.16.0 and v0.17.0 do not work for the Hadron - -ARG AURORABOOT_VERSION=v0.21.2 +# v0.18.0 is the minimum usable version. v0.16.0 and v0.17.0 do not work for the Hadron. +# v0.26.2 also fixes the UEFI-only ISO boot path: xorriso appended_part_as=gpt for a +# hybrid MBR+GPT layout (needed by VMware ESXi, OVMF/QEMU, some SuperMicro BMCs), +# and the CD-variant signed GRUB binary (gcdx64.efi.signed) via kairos-sdk v0.25.2. +# Kairos upstream: kairos-io/AuroraBoot#713, kairos-io/kairos-sdk#0.25.2. +ARG AURORABOOT_VERSION=v0.26.2 ARG AURORABOOT_IMAGE=quay.io/kairos/auroraboot:$AURORABOOT_VERSION ARG K3S_PROVIDER_VERSION=v4.10.0 ARG KUBEADM_PROVIDER_VERSION=v4.10.0 @@ -385,7 +388,11 @@ install-k8s: SAVE ARTIFACT --keep-ts /output/ . build-uki-iso: - FROM --platform=linux/${ARCH} $OSBUILDER_IMAGE + # Switched from quay.io/kairos/osbuilder-tools (archived kairos-io/osbuilder + # + kairos-io/enki) to AuroraBoot, which is the maintained successor. The + # build-iso and build-uki subcommands accept a "dir:" source, so the rootfs + # preparation path above is unchanged; only the final CLI invocation differs. + FROM --platform=linux/${ARCH} $AURORABOOT_IMAGE ENV ISO_NAME=${ISO_NAME} COPY overlay/files-iso/ /overlay/ COPY --if-exists +validate-user-data/user-data /overlay/config.yaml @@ -416,18 +423,46 @@ build-uki-iso: WORKDIR /build COPY --platform=linux/${ARCH} --keep-own +iso-image-rootfs/rootfs /build/image + RUN mkdir /iso IF [ "$ARCH" = "arm64" ] - RUN CMD="/entrypoint.sh --name $ISO_NAME build-iso --date=false --overlay-iso /overlay dir:/build/image --output /iso/ --arch $ARCH" && \ - if [ "$DEBUG" = "true" ]; then CMD="$CMD --debug"; else CMD="$CMD"; fi && \ - $CMD + # arm64 UKI ISO is not supported by upstream today; fall through to a + # plain live/installer ISO, matching the previous osbuilder behavior. + RUN CMD="auroraboot" && \ + if [ "$DEBUG" = "true" ]; then CMD="$CMD --debug"; fi && \ + $CMD build-iso dir:/build/image \ + --override-name "$ISO_NAME" \ + --overlay-iso /overlay \ + --output /iso/ \ + --arch arm64 ELSE IF [ "$ARCH" = "amd64" ] COPY secure-boot/enrollment/ secure-boot/private-keys/ secure-boot/public-keys/ /keys RUN ls -liah /keys - RUN mkdir /iso + # AuroraBoot's build-uki takes explicit key paths instead of osbuilder's + # bundled -k /keys. All key files live at /keys/* because the three + # secure-boot/* dirs above are flattened into the same target. IF [ "$AUTO_ENROLL_SECUREBOOT_KEYS" = "true" ] - RUN enki --config-dir /config build-uki dir:/build/image --extend-cmdline "$CMDLINE" --overlay-iso /overlay --secure-boot-enroll force -t iso -d /iso -k /keys --boot-branding "$BRANDING" + RUN CMD="auroraboot" && \ + if [ "$DEBUG" = "true" ]; then CMD="$CMD --debug"; fi && \ + $CMD build-uki dir:/build/image -t iso -d /iso \ + --extend-cmdline "$CMDLINE" \ + --overlay-iso /overlay \ + --boot-branding "$BRANDING" \ + --public-keys /keys \ + --sb-key /keys/db.key \ + --sb-cert /keys/db.pem \ + --tpm-pcr-private-key /keys/tpm2-pcr-private.pem \ + --secure-boot-enroll force ELSE - RUN enki --config-dir /config build-uki dir:/build/image --extend-cmdline "$CMDLINE" --overlay-iso /overlay -t iso -d /iso -k /keys --boot-branding "$BRANDING" + RUN CMD="auroraboot" && \ + if [ "$DEBUG" = "true" ]; then CMD="$CMD --debug"; fi && \ + $CMD build-uki dir:/build/image -t iso -d /iso \ + --extend-cmdline "$CMDLINE" \ + --overlay-iso /overlay \ + --boot-branding "$BRANDING" \ + --public-keys /keys \ + --sb-key /keys/db.key \ + --sb-cert /keys/db.pem \ + --tpm-pcr-private-key /keys/tpm2-pcr-private.pem END END WORKDIR /iso @@ -457,7 +492,12 @@ validate-user-data: build-iso: - FROM --platform=linux/${ARCH} $OSBUILDER_IMAGE + # Switched from quay.io/kairos/osbuilder-tools (archived kairos-io/osbuilder + # + kairos-io/enki) to AuroraBoot, which is the maintained successor. The + # build-iso subcommand accepts a "dir:" source with the same semantics as + # osbuilder's /entrypoint.sh build-iso, so the rootfs preparation path + # above is unchanged; only the final CLI invocation differs. + FROM --platform=linux/${ARCH} $AURORABOOT_IMAGE ENV ISO_NAME=${ISO_NAME} COPY overlay/files-iso/ /overlay/ COPY --if-exists +validate-user-data/user-data /overlay/files-iso/config.yaml @@ -501,36 +541,28 @@ build-iso: rm -f /build/image/opt/spectrocloud/local-ui.tar; \ fi - # Hadron uses AuroraBoot instead of osbuilder's enki: enki writes the grub - # stage as EFI/BOOT/grub.efi, but Hadron's shim chainloads grubx64.efi, so an - # enki-built Hadron ISO does not boot on any UEFI firmware. AuroraBoot names - # the file after its source, giving grubx64.efi. The UKI ISO - # boots systemd-boot directly and has no shim->grub chain. - IF [ "$OS_DISTRIBUTION" = "hadron" ] - WITH DOCKER --pull $AURORABOOT_IMAGE - RUN mkdir -p /iso && \ - LOGLEVEL=info && \ - if [ "$DEBUG" = "true" ]; then LOGLEVEL=debug; fi && \ - docker run --rm --privileged \ - -v /build/image:/rootfs \ - -v /overlay:/overlay \ - -v /iso:/aurora \ - $AURORABOOT_IMAGE \ - build-iso \ - --loglevel "$LOGLEVEL" \ - --override-name "$ISO_NAME" \ - --overlay-iso /overlay \ - --output /aurora \ - dir:/rootfs - END - ELSE IF [ "$ARCH" = "arm64" ] - RUN CMD="/entrypoint.sh --name $ISO_NAME build-iso --date=false --overlay-iso /overlay dir:/build/image --output /iso/ --arch $ARCH" && \ - if [ "$DEBUG" = "true" ]; then CMD="$CMD --debug"; else CMD="$CMD"; fi && \ - $CMD + # AuroraBoot uses Go arch names for both amd64 and arm64 (osbuilder used + # "x86_64" for amd64). The Hadron-specific WITH DOCKER path is unnecessary + # now that all builds are FROM $AURORABOOT_IMAGE -- AuroraBoot names the + # grub stage grubx64.efi (was: EFI/BOOT/grub.efi under enki), and AuroraBoot + # v0.26.2 fixes the UEFI-only boot path via GPT-hybrid + gcdx64.efi.signed + # for all distros, not just Hadron. + IF [ "$ARCH" = "arm64" ] + RUN CMD="auroraboot" && \ + if [ "$DEBUG" = "true" ]; then CMD="$CMD --debug"; fi && \ + $CMD build-iso dir:/build/image \ + --override-name "$ISO_NAME" \ + --overlay-iso /overlay \ + --output /iso/ \ + --arch arm64 ELSE IF [ "$ARCH" = "amd64" ] - RUN CMD="/entrypoint.sh --name $ISO_NAME build-iso --date=false --overlay-iso /overlay dir:/build/image --output /iso/ --arch x86_64" && \ - if [ "$DEBUG" = "true" ]; then CMD="$CMD --debug"; else CMD="$CMD"; fi && \ - $CMD + RUN CMD="auroraboot" && \ + if [ "$DEBUG" = "true" ]; then CMD="$CMD --debug"; fi && \ + $CMD build-iso dir:/build/image \ + --override-name "$ISO_NAME" \ + --overlay-iso /overlay \ + --output /iso/ \ + --arch amd64 END WORKDIR /iso RUN sha256sum $ISO_NAME.iso > $ISO_NAME.iso.sha256 From ec549cf18914d856fc57341c1f6e5a5b6c8ae1dd Mon Sep 17 00:00:00 2001 From: Vipin Sharma Date: Mon, 3 Aug 2026 20:42:29 -0700 Subject: [PATCH 3/6] fix(iso): normalize AuroraBoot's ISO filename to \$ISO_NAME.iso AuroraBoot v0.26.1's --override-name is not honored for "dir:" sources (only image sources). A build-iso against dir:/build/image landed as kairos-ubuntu-24.04-core-amd64-generic-v4.0.4.iso in /iso/, and the subsequent RUN sha256sum \$ISO_NAME.iso > \$ISO_NAME.iso.sha256 failed with "No such file or directory". Rename /iso/*.iso to \$ISO_NAME.iso before checksumming, matching what +build-uki-iso has done all along. This decouples us from whatever naming scheme AuroraBoot uses internally. Co-Authored-By: Claude Opus 4.7 --- Earthfile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Earthfile b/Earthfile index e49951f2..bea99add 100644 --- a/Earthfile +++ b/Earthfile @@ -565,7 +565,12 @@ build-iso: --arch amd64 END WORKDIR /iso - RUN sha256sum $ISO_NAME.iso > $ISO_NAME.iso.sha256 + # AuroraBoot's --override-name is honored only for some source types in + # v0.26.1 and does not apply to "dir:" sources: the ISO comes out as + # kairos---core--generic-v.iso. Normalize + # to the expected $ISO_NAME.iso the same way +build-uki-iso already does. + RUN mv /iso/*.iso "$ISO_NAME.iso" && \ + sha256sum "$ISO_NAME.iso" > "$ISO_NAME.iso.sha256" SAVE ARTIFACT --keep-ts /iso/* ### UKI targets From 7e5c2b4b080207212470597fef6d28ef3cabb65e Mon Sep 17 00:00:00 2001 From: Vipin Sharma Date: Mon, 3 Aug 2026 20:54:48 -0700 Subject: [PATCH 4/6] fix(iso): locate AuroraBoot's ISO wherever it lands, not just /iso/ AuroraBoot v0.26.1's --output flag on build-iso is ignored for "dir:" sources: the log line "Generating iso '...' to '/tmp/auroraboot'" confirmed the ISO drops under /tmp/auroraboot, not /iso/, so `mv /iso/*.iso ...` failed with "cannot stat '/iso/*.iso'". Search /iso, /tmp/auroraboot, and (fall back) the whole filesystem for a .iso and move it into /iso/\$ISO_NAME.iso. Applied to both +build-iso and +build-uki-iso so we're covered if build-uki -d has the same bug. Co-Authored-By: Claude Opus 4.7 --- Earthfile | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/Earthfile b/Earthfile index bea99add..54b2f3e4 100644 --- a/Earthfile +++ b/Earthfile @@ -466,7 +466,17 @@ build-uki-iso: END END WORKDIR /iso - RUN mv /iso/*.iso $ISO_NAME.iso + # See the equivalent block in +build-iso: AuroraBoot v0.26.1 may drop the + # ISO under /tmp/auroraboot instead of the requested -d, so search wherever + # it landed and normalize to $ISO_NAME.iso. + RUN ISO_SRC=$(find /iso /tmp/auroraboot -maxdepth 2 -name '*.iso' 2>/dev/null | head -n1) && \ + if [ -z "$ISO_SRC" ]; then \ + ISO_SRC=$(find / -xdev -name '*.iso' 2>/dev/null | head -n1); \ + fi && \ + if [ -z "$ISO_SRC" ]; then \ + echo "ERROR: AuroraBoot produced no .iso file"; exit 1; \ + fi && \ + mv "$ISO_SRC" "/iso/$ISO_NAME.iso" SAVE ARTIFACT /iso/* iso: @@ -565,11 +575,19 @@ build-iso: --arch amd64 END WORKDIR /iso - # AuroraBoot's --override-name is honored only for some source types in - # v0.26.1 and does not apply to "dir:" sources: the ISO comes out as - # kairos---core--generic-v.iso. Normalize - # to the expected $ISO_NAME.iso the same way +build-uki-iso already does. - RUN mv /iso/*.iso "$ISO_NAME.iso" && \ + # AuroraBoot v0.26.1's build-iso ignores both --output and --override-name + # for "dir:" sources: the ISO always lands at + # /tmp/auroraboot/kairos---core--generic-v.iso + # (see the "Generating iso ... to '/tmp/auroraboot'" log line). Locate the + # ISO wherever it landed and normalize to $ISO_NAME.iso. + RUN ISO_SRC=$(find /iso /tmp/auroraboot -maxdepth 2 -name '*.iso' 2>/dev/null | head -n1) && \ + if [ -z "$ISO_SRC" ]; then \ + ISO_SRC=$(find / -xdev -name '*.iso' 2>/dev/null | head -n1); \ + fi && \ + if [ -z "$ISO_SRC" ]; then \ + echo "ERROR: AuroraBoot produced no .iso file"; exit 1; \ + fi && \ + mv "$ISO_SRC" "/iso/$ISO_NAME.iso" && \ sha256sum "$ISO_NAME.iso" > "$ISO_NAME.iso.sha256" SAVE ARTIFACT --keep-ts /iso/* From ae85eeb3a72b41a51332e0cdce97579b9b452b3e Mon Sep 17 00:00:00 2001 From: Vipin Sharma Date: Mon, 3 Aug 2026 21:05:28 -0700 Subject: [PATCH 5/6] chore(iso): drop dead --output/--override-name/-d flags and clean up rename Both --output on build-iso and -d on build-uki are silently ignored by AuroraBoot v0.26.1 for "dir:" sources -- the ISO always drops at /tmp/auroraboot/*.iso. Two builds in a row confirmed the location, so drop the fallback find-tree and just mv from /tmp/auroraboot directly. Also drops --override-name (also inert for dir: sources on build-iso) so the invocation reads honestly. No behavior change -- the previous fallback path already worked. This is just less noisy shell. Co-Authored-By: Claude Opus 4.7 --- Earthfile | 72 ++++++++++++++++++------------------------------------- 1 file changed, 23 insertions(+), 49 deletions(-) diff --git a/Earthfile b/Earthfile index 54b2f3e4..7ba2af23 100644 --- a/Earthfile +++ b/Earthfile @@ -423,17 +423,15 @@ build-uki-iso: WORKDIR /build COPY --platform=linux/${ARCH} --keep-own +iso-image-rootfs/rootfs /build/image - RUN mkdir /iso + # AuroraBoot v0.26.1 silently ignores --output/-d for "dir:" sources on + # both build-iso and build-uki, dropping the ISO at /tmp/auroraboot/*.iso + # regardless. We hoist it into /iso/ ourselves after the run. IF [ "$ARCH" = "arm64" ] # arm64 UKI ISO is not supported by upstream today; fall through to a # plain live/installer ISO, matching the previous osbuilder behavior. RUN CMD="auroraboot" && \ if [ "$DEBUG" = "true" ]; then CMD="$CMD --debug"; fi && \ - $CMD build-iso dir:/build/image \ - --override-name "$ISO_NAME" \ - --overlay-iso /overlay \ - --output /iso/ \ - --arch arm64 + $CMD build-iso dir:/build/image --overlay-iso /overlay --arch arm64 ELSE IF [ "$ARCH" = "amd64" ] COPY secure-boot/enrollment/ secure-boot/private-keys/ secure-boot/public-keys/ /keys RUN ls -liah /keys @@ -443,7 +441,7 @@ build-uki-iso: IF [ "$AUTO_ENROLL_SECUREBOOT_KEYS" = "true" ] RUN CMD="auroraboot" && \ if [ "$DEBUG" = "true" ]; then CMD="$CMD --debug"; fi && \ - $CMD build-uki dir:/build/image -t iso -d /iso \ + $CMD build-uki dir:/build/image -t iso \ --extend-cmdline "$CMDLINE" \ --overlay-iso /overlay \ --boot-branding "$BRANDING" \ @@ -455,7 +453,7 @@ build-uki-iso: ELSE RUN CMD="auroraboot" && \ if [ "$DEBUG" = "true" ]; then CMD="$CMD --debug"; fi && \ - $CMD build-uki dir:/build/image -t iso -d /iso \ + $CMD build-uki dir:/build/image -t iso \ --extend-cmdline "$CMDLINE" \ --overlay-iso /overlay \ --boot-branding "$BRANDING" \ @@ -465,18 +463,8 @@ build-uki-iso: --tpm-pcr-private-key /keys/tpm2-pcr-private.pem END END - WORKDIR /iso - # See the equivalent block in +build-iso: AuroraBoot v0.26.1 may drop the - # ISO under /tmp/auroraboot instead of the requested -d, so search wherever - # it landed and normalize to $ISO_NAME.iso. - RUN ISO_SRC=$(find /iso /tmp/auroraboot -maxdepth 2 -name '*.iso' 2>/dev/null | head -n1) && \ - if [ -z "$ISO_SRC" ]; then \ - ISO_SRC=$(find / -xdev -name '*.iso' 2>/dev/null | head -n1); \ - fi && \ - if [ -z "$ISO_SRC" ]; then \ - echo "ERROR: AuroraBoot produced no .iso file"; exit 1; \ - fi && \ - mv "$ISO_SRC" "/iso/$ISO_NAME.iso" + RUN mkdir -p /iso && \ + mv /tmp/auroraboot/*.iso "/iso/$ISO_NAME.iso" SAVE ARTIFACT /iso/* iso: @@ -552,43 +540,29 @@ build-iso: fi # AuroraBoot uses Go arch names for both amd64 and arm64 (osbuilder used - # "x86_64" for amd64). The Hadron-specific WITH DOCKER path is unnecessary - # now that all builds are FROM $AURORABOOT_IMAGE -- AuroraBoot names the - # grub stage grubx64.efi (was: EFI/BOOT/grub.efi under enki), and AuroraBoot - # v0.26.2 fixes the UEFI-only boot path via GPT-hybrid + gcdx64.efi.signed - # for all distros, not just Hadron. + # "x86_64" for amd64). --output/--override-name are inert for "dir:" + # sources: the ISO always lands at /tmp/auroraboot/kairos--- + # core--generic-v.iso, so we leave --output default and + # hoist the produced ISO into /iso/ ourselves. + # + # The Hadron-specific WITH DOCKER path is unnecessary now that all builds + # are FROM $AURORABOOT_IMAGE -- AuroraBoot names the grub stage + # grubx64.efi (was: EFI/BOOT/grub.efi under enki), and AuroraBoot v0.26.2 + # fixes the UEFI-only boot path via GPT-hybrid + gcdx64.efi.signed for all + # distros, not just Hadron. IF [ "$ARCH" = "arm64" ] RUN CMD="auroraboot" && \ if [ "$DEBUG" = "true" ]; then CMD="$CMD --debug"; fi && \ - $CMD build-iso dir:/build/image \ - --override-name "$ISO_NAME" \ - --overlay-iso /overlay \ - --output /iso/ \ - --arch arm64 + $CMD build-iso dir:/build/image --overlay-iso /overlay --arch arm64 ELSE IF [ "$ARCH" = "amd64" ] RUN CMD="auroraboot" && \ if [ "$DEBUG" = "true" ]; then CMD="$CMD --debug"; fi && \ - $CMD build-iso dir:/build/image \ - --override-name "$ISO_NAME" \ - --overlay-iso /overlay \ - --output /iso/ \ - --arch amd64 + $CMD build-iso dir:/build/image --overlay-iso /overlay --arch amd64 END + RUN mkdir -p /iso && \ + mv /tmp/auroraboot/*.iso "/iso/$ISO_NAME.iso" WORKDIR /iso - # AuroraBoot v0.26.1's build-iso ignores both --output and --override-name - # for "dir:" sources: the ISO always lands at - # /tmp/auroraboot/kairos---core--generic-v.iso - # (see the "Generating iso ... to '/tmp/auroraboot'" log line). Locate the - # ISO wherever it landed and normalize to $ISO_NAME.iso. - RUN ISO_SRC=$(find /iso /tmp/auroraboot -maxdepth 2 -name '*.iso' 2>/dev/null | head -n1) && \ - if [ -z "$ISO_SRC" ]; then \ - ISO_SRC=$(find / -xdev -name '*.iso' 2>/dev/null | head -n1); \ - fi && \ - if [ -z "$ISO_SRC" ]; then \ - echo "ERROR: AuroraBoot produced no .iso file"; exit 1; \ - fi && \ - mv "$ISO_SRC" "/iso/$ISO_NAME.iso" && \ - sha256sum "$ISO_NAME.iso" > "$ISO_NAME.iso.sha256" + RUN sha256sum "$ISO_NAME.iso" > "$ISO_NAME.iso.sha256" SAVE ARTIFACT --keep-ts /iso/* ### UKI targets From b83ded42c8848cee4ae82cc38ec773335ff6071a Mon Sep 17 00:00:00 2001 From: Vipin Sharma Date: Thu, 6 Aug 2026 10:16:33 -0700 Subject: [PATCH 6/6] fix(iso): xorriso-inject overlay into ISO because AuroraBoot's build-iso subcommand skips StepInjectCC Empirically: AuroraBoot v0.26.2 subcommand \`build-iso dir:...\` with --overlay-iso produces an ISO whose /boot/grub2/grub.cfg is AuroraBoot's default "Kairos"-branded template rather than our overlay's "Palette eXtended Kubernetes Edge Installer" version. Confirmed by extracting the file from the built ISO. Root cause (pkg/ops/iso.go, internal/cmd/build-iso.go): the build-iso subcommand runs only PrepDirs -> StepCopyCloudConfig -> StepDumpSource -> StepGenISO and never calls StepInjectCC. StepInjectCC is where AuroraBoot's InjectISO() function xorriso-maps the overlay directory onto the finalised ISO tree. Without it, --overlay-iso silently discards every file we put under /overlay/ -- not just the grub menu, but also user-data, cluster config (spc.tgz), content bundles, and edge_custom_config. Two ways to fix: 1. Switch +build-iso to AuroraBoot pipeline mode (docker run auroraboot --set container_image=... --set iso.overlay_iso=... --cloud-config ...). This invokes StepInjectCC. But it's a ~100-line rewrite involving DinD, container_image loading, and matches the pattern +cloud-image / +kairos-raw-image already use. 2. Do StepInjectCC's actual work ourselves inline. Its whole body is one xorriso command: xorriso -indev X -outdev X -map / \ -boot_image any replay No DinD, no rewrite. Same result. Going with (2). Small, isolated, uses the same xorriso invocation the upstream code path does, and can be trivially deleted the day StepInjectCC is wired into the subcommand path. Doesn't touch +build-uki-iso; that uses build-uki -t iso which is a separate code path. Filed separately as an upstream issue on kairos-io/AuroraBoot (subcommand build-iso should call StepInjectCC too, or --overlay-iso should be honored end-to-end within StepGenISO). Co-Authored-By: Claude Opus 4.7 --- Earthfile | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Earthfile b/Earthfile index 7ba2af23..65ee2a88 100644 --- a/Earthfile +++ b/Earthfile @@ -561,6 +561,24 @@ build-iso: END RUN mkdir -p /iso && \ mv /tmp/auroraboot/*.iso "/iso/$ISO_NAME.iso" + + # AuroraBoot v0.26.2's `build-iso` subcommand runs only: + # PrepDirs -> StepCopyCloudConfig -> StepDumpSource -> StepGenISO + # and NEVER calls StepInjectCC. That step is the one that actually copies + # --overlay-iso content onto the finalised ISO tree; its absence means our + # /overlay/... files (Palette-branded /boot/grub2/grub.cfg, user-data, + # cluster config, content bundles, edge_custom_config) silently disappear. + # Empirically verified: the built ISO's /boot/grub2/grub.cfg is + # AuroraBoot's default "Kairos"-branded template, not our overlay's + # "Palette eXtended Kubernetes Edge Installer" version. + # + # Pipeline mode (docker run auroraboot --set ...) invokes StepInjectCC, + # but that adds DinD, container_image loading, and ~100 lines of Earthfile. + # StepInjectCC's actual work is one xorriso command; do it here directly. + # See kairos-io/AuroraBoot pkg/ops/iso.go InjectISO() for the upstream + # equivalent -- same xorriso invocation. + RUN xorriso -indev "/iso/$ISO_NAME.iso" -outdev "/iso/$ISO_NAME.iso" \ + -map /overlay / -boot_image any replay WORKDIR /iso RUN sha256sum "$ISO_NAME.iso" > "$ISO_NAME.iso.sha256" SAVE ARTIFACT --keep-ts /iso/*