- 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.
92 lines
4.7 KiB
Bash
Executable File
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"
|