Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 90 additions & 43 deletions Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -416,22 +423,48 @@ build-uki-iso:

WORKDIR /build
COPY --platform=linux/${ARCH} --keep-own +iso-image-rootfs/rootfs /build/image
# 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" ]
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 --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
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 \
--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 \
--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
RUN mv /iso/*.iso $ISO_NAME.iso
RUN mkdir -p /iso && \
mv /tmp/auroraboot/*.iso "/iso/$ISO_NAME.iso"
SAVE ARTIFACT /iso/*

iso:
Expand All @@ -457,7 +490,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
Expand Down Expand Up @@ -501,39 +539,48 @@ 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). --output/--override-name are inert for "dir:"
# sources: the ISO always lands at /tmp/auroraboot/kairos-<distro>-<ver>-
# core-<arch>-generic-v<kairos-ver>.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 --overlay-iso /overlay --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 --overlay-iso /overlay --arch amd64
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
RUN sha256sum "$ISO_NAME.iso" > "$ISO_NAME.iso.sha256"
SAVE ARTIFACT --keep-ts /iso/*

### UKI targets
Expand Down
39 changes: 31 additions & 8 deletions overlay/files-iso/boot/grub2/grub.cfg
Original file line number Diff line number Diff line change
@@ -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
}
Expand Down