feat: graphical installer in the live ISO
The ISO now boots straight into a GTK installer instead of dropping to a tty. Structure: - installer/arcline-installer: small GTK3 (Python) frontend that drives scripts/deploy-disk.sh — pick a disk, choose boot mode, type the device path to confirm, watch the deploy log, reboot. Pure helper logic is tested against lsblk (lowercase keys, pseudo-devices filtered). - scripts/build-live.sh: builds build/rootfs/<edition>-live by cloning the CLEAN rootfs and layering on live-boot, a minimal X session (Xorg + openbox), the installer, and the deploy tooling under /usr/lib/arcline (deploy-disk.sh + btrfs/init.sh + edition fstabs, laid out so the scripts' own path resolution works unchanged). - overlays/live/: arcline-installer.service + session script that start Xorg on vt1 (with -allow-root) and run the installer as the X client. - build-iso.sh: builds the live rootfs for the squashfs AND stages the clean rootfs archive into isofiles/install/ — the installer deploys the clean archive, so what's installed is the hardened system, never the live session with the installer in it. - Refactor: ARCLINE_LIVE handling removed from build-rootfs.sh and configure-system.sh (now lives entirely in build-live.sh). - validate.sh now checks overlays shell scripts + installer python. - docs updated (building.md, architecture.md, installer/README.md).
This commit is contained in:
@@ -1,14 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Arcline OS — live ISO builder
|
||||
# Arcline OS — live ISO builder (with graphical installer)
|
||||
#
|
||||
# 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
|
||||
# Produces a hybrid (BIOS+UEFI) live ISO that boots straight into the Arcline
|
||||
# graphical installer:
|
||||
# 1. ensure the CLEAN rootfs exists (what the installer deploys)
|
||||
# 2. build-live.sh → build/rootfs/<edition>-live (live-boot + X + installer)
|
||||
# 3. stage kernel + initramfs + squashfs in isofiles/live, and the clean
|
||||
# rootfs archive in isofiles/install (the installer's install source)
|
||||
# 4. write the grub boot config (live-boot: boot=live)
|
||||
# 5. grub-mkrescue → build/artifacts/arcline-<edition>-<version>-<arch>.iso
|
||||
#
|
||||
# Requires root for the rootfs stage; the ISO assembly itself runs unprivileged.
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
@@ -18,48 +21,54 @@ source "$(dirname "${BASH_SOURCE[0]}")/common.sh"
|
||||
EDITION="${1:?usage: build-iso.sh <edition>}"
|
||||
validate_edition "$EDITION"
|
||||
|
||||
ROOTFS="$ROOTFS_DIR/$EDITION"
|
||||
CLEAN="$ROOTFS_DIR/$EDITION"
|
||||
LIVE_ROOT="$ROOTFS_DIR/$EDITION-live"
|
||||
INSTALL_ARC="$ARTIFACT_DIR/arcline-$EDITION-$VERSION-$ARCH.tar.xz"
|
||||
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"
|
||||
# ── 1. rootfs(es) ───────────────────────────────────────────────────────────
|
||||
# The ISO is a live session (built on top of the clean rootfs) and carries the
|
||||
# CLEAN rootfs archive as the install source for the graphical installer.
|
||||
if [[ ! -d "$CLEAN" ]]; then
|
||||
log "clean rootfs missing — building it first"
|
||||
"$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"
|
||||
if [[ ! -f "$INSTALL_ARC" ]]; then
|
||||
log "clean rootfs archive missing — building it first"
|
||||
"$ROOT/scripts/build-rootfs.sh" "$EDITION"
|
||||
fi
|
||||
"$ROOT/scripts/build-live.sh" "$EDITION"
|
||||
|
||||
# ── 2. stage files ──────────────────────────────────────────────────────────
|
||||
log "staging ISO files for edition '$EDITION'"
|
||||
rm -rf "$ISOFILES"
|
||||
mkdir -p "$ISOFILES/live" "$ISOFILES/boot/grub"
|
||||
mkdir -p "$ISOFILES/live" "$ISOFILES/boot/grub" "$ISOFILES/install"
|
||||
|
||||
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"
|
||||
KERNEL="$(find "$LIVE_ROOT/boot" -maxdepth 1 -name 'vmlinuz-*' | sort -V | tail -1)"
|
||||
INITRD="$(find "$LIVE_ROOT/boot" -maxdepth 1 -name 'initrd.img-*' | sort -V | tail -1)"
|
||||
[[ -n "$KERNEL" && -n "$INITRD" ]] || die "kernel or initramfs not found in live rootfs"
|
||||
cp -L "$KERNEL" "$ISOFILES/live/vmlinuz"
|
||||
cp -L "$INITRD" "$ISOFILES/live/initrd.img"
|
||||
|
||||
# the clean (installed-system) rootfs is what the installer deploys
|
||||
cp "$INSTALL_ARC" "$ISOFILES/install/arcline-$EDITION.tar.xz"
|
||||
|
||||
# ── 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"
|
||||
mkdir -p "$LIVE_ROOT/etc/arcline"
|
||||
cp "$BUILD_DIR/keys/MOK.der" "$LIVE_ROOT/etc/arcline/MOK.der"
|
||||
"$ROOT/scripts/secureboot/sign-image.sh" "$LIVE_ROOT" --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
|
||||
log "compressing live rootfs → squashfs (this takes a while)"
|
||||
# The squashfs is the live session root. Keep it complete — offline man pages
|
||||
# and docs are a product promise (see the landing page), so nothing is excluded.
|
||||
mksquashfs "$LIVE_ROOT" "$ISOFILES/live/arcline.squashfs" -noappend -comp zstd -Xcompression-level 15 2>/dev/null || \
|
||||
mksquashfs "$LIVE_ROOT" "$ISOFILES/live/arcline.squashfs" -noappend -comp xz
|
||||
|
||||
# ── 3. grub boot config ─────────────────────────────────────────────────────
|
||||
log "writing grub config"
|
||||
|
||||
97
scripts/build-live.sh
Executable file
97
scripts/build-live.sh
Executable file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env bash
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Arcline OS — live-session rootfs builder
|
||||
#
|
||||
# scripts/build-live.sh <edition>
|
||||
#
|
||||
# Creates build/rootfs/<edition>-live: a bootable live-session rootfs used by
|
||||
# the ISO. It starts from the CLEAN installed-system rootfs (so what you
|
||||
# install is exactly what you booted), clones it, and layers on:
|
||||
#
|
||||
# - live-boot / live-config / live-tools (boot the squashfs)
|
||||
# - a minimal X session (Xorg + openbox) for the graphical installer
|
||||
# - the Arcline graphical installer (installer/arcline-installer)
|
||||
# - the deploy tooling it needs (deploy-disk.sh + btrfs/init.sh + fstabs)
|
||||
#
|
||||
# The live rootfs itself is never what gets installed — the installer deploys
|
||||
# the clean rootfs archive (staged into the ISO by build-iso.sh).
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
set -euo pipefail
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/common.sh"
|
||||
|
||||
EDITION="${1:?usage: build-live.sh <edition>}"
|
||||
validate_edition "$EDITION"
|
||||
require_root "$0" "$@"
|
||||
|
||||
CLEAN="$ROOTFS_DIR/$EDITION"
|
||||
LIVE_ROOT="$ROOTFS_DIR/$EDITION-live"
|
||||
|
||||
# ── 1. ensure the clean rootfs ──────────────────────────────────────────────
|
||||
if [[ ! -d "$CLEAN" ]]; then
|
||||
log "clean rootfs missing — building it first"
|
||||
"$ROOT/scripts/build-rootfs.sh" "$EDITION"
|
||||
fi
|
||||
|
||||
log "═══ building live session rootfs for $EDITION ═══"
|
||||
rm -rf "$LIVE_ROOT"
|
||||
cp -a "$CLEAN" "$LIVE_ROOT"
|
||||
|
||||
# ── chroot helpers ──────────────────────────────────────────────────────────
|
||||
mount_pseudo() {
|
||||
mount --bind /dev "$LIVE_ROOT/dev"
|
||||
mount --bind /proc "$LIVE_ROOT/proc"
|
||||
mount --bind /sys "$LIVE_ROOT/sys"
|
||||
mount --bind /dev/pts "$LIVE_ROOT/dev/pts" 2>/dev/null || true
|
||||
}
|
||||
unmount_pseudo() {
|
||||
umount -l "$LIVE_ROOT/dev/pts" 2>/dev/null || true
|
||||
umount -l "$LIVE_ROOT/sys" 2>/dev/null || true
|
||||
umount -l "$LIVE_ROOT/proc" 2>/dev/null || true
|
||||
umount -l "$LIVE_ROOT/dev" 2>/dev/null || true
|
||||
}
|
||||
trap 'unmount_pseudo' EXIT
|
||||
chroot_run() { chroot "$LIVE_ROOT" /bin/bash -c "$*"; }
|
||||
|
||||
# ── 2. install live session packages ────────────────────────────────────────
|
||||
log "[1/4] installing live-boot + X + installer dependencies"
|
||||
mount_pseudo
|
||||
chroot_run "export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -qq
|
||||
apt-get install -y --no-install-recommends \
|
||||
live-boot live-config-systemd live-tools \
|
||||
xserver-xorg xinit x11-xserver-utils openbox \
|
||||
python3-gi gir1.2-gtk-3.0 gdisk parted dosfstools \
|
||||
| tee /tmp/live-packages.log"
|
||||
|
||||
# ── 3. ship the graphical installer + deploy tooling ────────────────────────
|
||||
log "[2/4] installing installer + deploy tooling"
|
||||
install -Dm0755 "$ROOT/installer/arcline-installer" "$LIVE_ROOT/usr/local/bin/arcline-installer"
|
||||
|
||||
# The installer drives deploy-disk.sh; mirror the repo layout under
|
||||
# /usr/lib/arcline so common.sh's ROOT resolution works unchanged.
|
||||
install -Dm0755 "$ROOT/scripts/common.sh" "$LIVE_ROOT/usr/lib/arcline/scripts/common.sh"
|
||||
install -Dm0755 "$ROOT/scripts/deploy-disk.sh" "$LIVE_ROOT/usr/lib/arcline/scripts/deploy-disk.sh"
|
||||
install -Dm0755 "$ROOT/scripts/apply-fstab.sh" "$LIVE_ROOT/usr/lib/arcline/scripts/apply-fstab.sh"
|
||||
install -Dm0755 "$ROOT/btrfs/init.sh" "$LIVE_ROOT/usr/lib/arcline/btrfs/init.sh"
|
||||
for e in "${EDITIONS[@]}"; do
|
||||
install -Dm0644 "$ROOT/editions/$e/fstab" "$LIVE_ROOT/usr/lib/arcline/editions/$e/fstab"
|
||||
done
|
||||
|
||||
# ── 4. live overlay (session autostart) + service wiring ────────────────────
|
||||
log "[3/4] applying live overlay"
|
||||
cp -a "$ROOT/overlays/live/." "$LIVE_ROOT/"
|
||||
|
||||
chroot_run "systemctl enable arcline-installer.service 2>/dev/null || true
|
||||
systemctl mask sddm 2>/dev/null || true
|
||||
systemctl set-default multi-user.target 2>/dev/null || true"
|
||||
|
||||
# the live session is disposable; give it a fresh identity
|
||||
echo "arclines-live" > "$LIVE_ROOT/etc/hostname"
|
||||
rm -f "$LIVE_ROOT/etc/machine-id"
|
||||
: > "$LIVE_ROOT/etc/machine-id"
|
||||
|
||||
log "[4/4] cleaning live rootfs"
|
||||
chroot_run "apt-get clean 2>/dev/null; rm -rf /var/lib/apt/lists/* /var/cache/apt/* /tmp/* /root/.bash_history"
|
||||
unmount_pseudo
|
||||
|
||||
log "live rootfs ready: $LIVE_ROOT"
|
||||
@@ -40,7 +40,6 @@ esac
|
||||
EDIR="$(edition_dir "$EDITION")"
|
||||
ROOTFS="$ROOTFS_DIR/$EDITION"
|
||||
ARTIFACT="$ARTIFACT_DIR/arcline-$EDITION-$VERSION-$ARCH.tar.xz"
|
||||
LIVE="${ARCLINE_LIVE:-0}"
|
||||
|
||||
mkdir -p "$ROOTFS_DIR" "$LOG_DIR" "$ARTIFACT_DIR"
|
||||
rm -rf "$ROOTFS" "$ARTIFACT"
|
||||
@@ -135,7 +134,7 @@ case "$ARCLINE_TOOLCHAIN" in
|
||||
esac
|
||||
|
||||
mount_pseudo
|
||||
chroot_run "ARCLINE_EDITION_DIR='/root/arcline-edition' ARCLINE_LIVE='$LIVE' ARCLINE_LOCK_ROOT='${ARCLINE_LOCK_ROOT:-0}' ARCLINE_EXTRA_REPOS='${ARCLINE_EXTRA_REPOS:-0}' /root/configure-system.sh '$EDITION'"
|
||||
chroot_run "ARCLINE_EDITION_DIR='/root/arcline-edition' ARCLINE_LOCK_ROOT='${ARCLINE_LOCK_ROOT:-0}' ARCLINE_EXTRA_REPOS='${ARCLINE_EXTRA_REPOS:-0}' /root/configure-system.sh '$EDITION'"
|
||||
rm -f "$ROOTFS/root/configure-system.sh"
|
||||
rm -rf "$ROOTFS/root/arcline-edition" "$ROOTFS/arcline-debs"
|
||||
unmount_pseudo
|
||||
|
||||
@@ -17,7 +17,6 @@ EDITION="${1:?usage: configure-system.sh <edition>}"
|
||||
DISTRO_NAME="${DISTRO_NAME:-Arcline OS}"
|
||||
VERSION="${VERSION:-0.1.0}"
|
||||
RELEASE_NAME="${RELEASE_NAME:-arclines}"
|
||||
LIVE="${ARCLINE_LIVE:-0}"
|
||||
LOCK_ROOT="${ARCLINE_LOCK_ROOT:-0}"
|
||||
EXTRA_REPOS="${ARCLINE_EXTRA_REPOS:-0}"
|
||||
|
||||
@@ -85,13 +84,6 @@ fi
|
||||
# ensure no package telemetry survives.
|
||||
rm -f /var/log/apt/*.log /var/cache/apt/archives/*.deb
|
||||
|
||||
# ── live-boot (ISO builds) ──────────────────────────────────────────────────
|
||||
if [[ "$LIVE" == "1" ]]; then
|
||||
log "installing live-boot support"
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get install -y --no-install-recommends live-boot live-config-systemd live-tools || warn "live-boot install failed"
|
||||
fi
|
||||
|
||||
# ── Arcline toolchain (host-built .debs) ────────────────────────────────────
|
||||
if [[ -d /arcline-debs ]] && ls /arcline-debs/*.deb >/dev/null 2>&1; then
|
||||
log "installing Arcline toolchain packages"
|
||||
|
||||
@@ -21,8 +21,15 @@ while IFS= read -r -d '' s; do
|
||||
if ! bash -n "$s"; then
|
||||
note_fail "syntax error in $s"
|
||||
fi
|
||||
done < <(find "$ROOT/scripts" "$ROOT/btrfs" "$ROOT/toolchain" "$ROOT/tests" \
|
||||
-name '*.sh' -type f -print0 2>/dev/null)
|
||||
done < <(find "$ROOT/scripts" "$ROOT/btrfs" "$ROOT/toolchain" "$ROOT/tests" "$ROOT/overlays" \
|
||||
-type f \( -name '*.sh' -o -name 'arcline-installer-session' \) -print0 2>/dev/null)
|
||||
|
||||
log "validating installer (python syntax)…"
|
||||
if command -v python3 >/dev/null 2>&1; then
|
||||
python3 -m py_compile "$ROOT/installer/arcline-installer" 2>/dev/null \
|
||||
|| note_fail "python syntax error in installer/arcline-installer"
|
||||
rm -rf "$ROOT/installer/__pycache__"
|
||||
fi
|
||||
|
||||
log "validating editions…"
|
||||
for e in "${EDITIONS[@]}"; do
|
||||
|
||||
Reference in New Issue
Block a user