Files
os-build/scripts/build-iso.sh
Blake Ridgway 3a17504dd0 feat: add MOK-based secure boot signing
- scripts/secureboot/gen-keys.sh: generates a Machine Owner Key pair
  (MOK.priv / MOK.pem / MOK.der) for self-signing the boot chain.
- scripts/secureboot/sign-image.sh: signs kernels and EFI binaries
  (already-signed files skipped) with sbsign.
- arcline-mok-enroll.service (+ script): one-time MOK enrollment at first
  boot via mokutil; no-ops when no key was shipped.
- build-iso.sh: ARCLINE_SIGN=1 signs the live boot chain and ships the
  public MOK in the image. Smoke test now asserts the enroll unit exists.
2026-08-21 13:33:17 -05:00

92 lines
4.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────────────
# Arcline OS — live ISO builder
#
# scripts/build-iso.sh <edition>
#
# Wraps a rootfs into a hybrid (BIOS+UEFI) live ISO:
# 1. ensure the rootfs exists (build it with live-boot support if needed)
# 2. stage kernel + initramfs + squashfs in isofiles/live
# 3. write the grub boot config (live-boot: boot=live)
# 4. grub-mkrescue → build/artifacts/arcline-<edition>-<version>-<arch>.iso
#
# Requires root for the rootfs stage; the ISO assembly itself runs unprivileged.
# ─────────────────────────────────────────────────────────────────────────────
set -euo pipefail
source "$(dirname "${BASH_SOURCE[0]}")/common.sh"
EDITION="${1:?usage: build-iso.sh <edition>}"
validate_edition "$EDITION"
ROOTFS="$ROOTFS_DIR/$EDITION"
ISOFILES="$IMAGE_DIR/$EDITION/isofiles"
ARTIFACT="$ARTIFACT_DIR/arcline-$EDITION-$VERSION-$ARCH.iso"
# ── 1. rootfs ───────────────────────────────────────────────────────────────
if [[ ! -d "$ROOTFS" ]]; then
log "rootfs missing — building with live-boot support"
ARCLINE_LIVE=1 "$ROOT/scripts/build-rootfs.sh" "$EDITION"
fi
# live-boot must be present in the rootfs for the ISO to boot
if [[ ! -d "$ROOTFS/lib/live" && ! -d "$ROOTFS/usr/lib/live" ]]; then
warn "rootfs has no live-boot support; rebuilding with ARCLINE_LIVE=1"
ARCLINE_LIVE=1 "$ROOT/scripts/build-rootfs.sh" "$EDITION"
fi
# ── 2. stage files ──────────────────────────────────────────────────────────
log "staging ISO files for edition '$EDITION'"
rm -rf "$ISOFILES"
mkdir -p "$ISOFILES/live" "$ISOFILES/boot/grub"
KERNEL="$(find "$ROOTFS/boot" -maxdepth 1 -name 'vmlinuz-*' | sort -V | tail -1)"
INITRD="$(find "$ROOTFS/boot" -maxdepth 1 -name 'initrd.img-*' | sort -V | tail -1)"
[[ -n "$KERNEL" && -n "$INITRD" ]] || die "kernel or initramfs not found in rootfs"
cp -L "$KERNEL" "$ISOFILES/live/vmlinuz"
cp -L "$INITRD" "$ISOFILES/live/initrd.img"
# ── 2b. secure boot (optional: ARCLINE_SIGN=1 + a MOK keypair) ──────────────
if [[ "${ARCLINE_SIGN:-0}" == "1" ]]; then
log "secure boot: signing boot chain and shipping MOK in the live image"
[[ -f "$BUILD_DIR/keys/MOK.der" ]] || die "ARCLINE_SIGN=1 but no MOK keypair — run: scripts/secureboot/gen-keys.sh"
mkdir -p "$ROOTFS/etc/arcline"
cp "$BUILD_DIR/keys/MOK.der" "$ROOTFS/etc/arcline/MOK.der"
"$ROOT/scripts/secureboot/sign-image.sh" "$ROOTFS" --keydir "$BUILD_DIR/keys"
"$ROOT/scripts/secureboot/sign-image.sh" "$ISOFILES" --keydir "$BUILD_DIR/keys"
fi
log "compressing rootfs → squashfs (this takes a while)"
# The squashfs is the live root. Keep it complete — offline man pages and
# docs are a product promise (see the landing page), so nothing is excluded.
mksquashfs "$ROOTFS" "$ISOFILES/live/arcline.squashfs" -noappend -comp zstd -Xcompression-level 15 2>/dev/null || \
mksquashfs "$ROOTFS" "$ISOFILES/live/arcline.squashfs" -noappend -comp xz
# ── 3. grub boot config ─────────────────────────────────────────────────────
log "writing grub config"
KCMD="$(tr '\n' ' ' < "$(edition_dir "$EDITION")/kernel.cmdline" | sed 's/ */ /g')"
cat > "$ISOFILES/boot/grub/grub.cfg" <<EOF
set timeout=5
set default=0
menuentry "Arcline $EDITION ($VERSION)" {
linux /live/vmlinuz boot=live config quiet $KCMD
initrd /live/initrd.img
}
menuentry "Arcline $EDITION ($VERSION) — safe mode (no mitigations)" {
linux /live/vmlinuz boot=live config quiet nomodeset
initrd /live/initrd.img
}
EOF
# ── 4. assemble ─────────────────────────────────────────────────────────────
log "assembling ISO with grub-mkrescue"
command -v grub-mkrescue >/dev/null || die "grub-mkrescue not found (run scripts/check-host-deps.sh --install)"
mkdir -p "$ARTIFACT_DIR"
grub-mkrescue -o "$ARTIFACT" "$ISOFILES" -- \
-volume-label "ARCLINE_${EDITION^^}" 2>/dev/null || \
grub-mkrescue -o "$ARTIFACT" "$ISOFILES"
log "ISO artifact: $ARTIFACT"
sha256sum "$ARTIFACT" | tee "$ARTIFACT.sha256"