Files
os-build/scripts/configure-system.sh
Blake Ridgway 0ea8b713dd 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).
2026-08-21 20:24:09 -05:00

127 lines
6.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────────────
# Arcline OS — in-chroot system configuration
#
# scripts/configure-system.sh <edition>
#
# This script is executed INSIDE the chroot (build-rootfs.sh copies it in and
# runs it via chroot). It turns a raw debootstrap tree into an Arcline system:
# hostname, locale, kernel cmdline, enabled/masked services, optional live-boot,
# optional Arcline toolchain install, optional upstream repos (grafana/loki).
#
# It is idempotent and safe to re-run.
# ─────────────────────────────────────────────────────────────────────────────
set -euo pipefail
EDITION="${1:?usage: configure-system.sh <edition>}"
DISTRO_NAME="${DISTRO_NAME:-Arcline OS}"
VERSION="${VERSION:-0.1.0}"
RELEASE_NAME="${RELEASE_NAME:-arclines}"
LOCK_ROOT="${ARCLINE_LOCK_ROOT:-0}"
EXTRA_REPOS="${ARCLINE_EXTRA_REPOS:-0}"
# Absolute path of the edition dir on the host is injected by build-rootfs.sh.
EDIR="${ARCLINE_EDITION_DIR:?ARCLINE_EDITION_DIR must be set}"
log() { printf '\033[1;34m[arcline:chroot]\033[0m %s\n' "$*"; }
warn() { printf '\033[1;33m[arcline:chroot]\033[0m %s\n' "$*" >&2; }
# Read a flat YAML list (key: then indented "- item" lines). Keys may be
# nested under a section (e.g. services: → enabled:).
yaml_list() {
awk -v key="$2" '
$0 ~ "^[[:space:]]*" key ":" { insec=1; next }
insec && /^[[:space:]]*-/ { sub(/^[[:space:]]*-[[:space:]]*/, ""); print; next }
insec && !/^[[:space:]]*-/ && !/^[[:space:]]*$/ { exit }
' "$1"
}
# ── identity ────────────────────────────────────────────────────────────────
echo "$RELEASE_NAME" > /etc/hostname
cat > /etc/arcline-release <<EOF
$DISTRO_NAME $VERSION ($RELEASE_NAME)
Edition: $EDITION
Debian base: $(. /etc/os-release && echo "$PRETTY_NAME")
EOF
ln -sf /etc/arcline-release /etc/os-release-arcline
# ── locale / timezone ───────────────────────────────────────────────────────
sed -i 's/^# *en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen
locale-gen >/dev/null 2>&1 || true
echo "LANG=en_US.UTF-8" > /etc/default/locale
ln -sf /usr/share/zoneinfo/UTC /etc/localtime
# ── kernel cmdline (used when this rootfs is installed to disk) ─────────────
KCMD="$(tr '\n' ' ' < "$EDIR/kernel.cmdline" | sed 's/ */ /g; s/^ *//; s/ *$//')"
cat > /etc/default/grub <<EOF
GRUB_DEFAULT=0
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$DISTRO_NAME"
GRUB_CMDLINE_LINUX_DEFAULT="$KCMD"
GRUB_CMDLINE_LINUX=""
GRUB_DISABLE_OS_PROBER=false
EOF
# ── systemd services ────────────────────────────────────────────────────────
META="$EDIR/metadata.yaml"
while IFS= read -r svc; do
[[ -n "$svc" ]] && systemctl enable "$svc" 2>/dev/null || true
done < <(yaml_list "$META" "enabled" || true)
while IFS= read -r svc; do
[[ -n "$svc" ]] && systemctl mask "$svc" 2>/dev/null || true
done < <(yaml_list "$META" "masked" || true)
# Graphical boot: when a display manager (sddm) is enabled, boot straight to
# the graphical login instead of a tty. Without this the desktop is installed
# but the system still boots to multi-user.
if yaml_list "$META" "enabled" | grep -qx "sddm"; then
systemctl set-default graphical.target
log "graphical boot: default target set to graphical.target (sddm)"
fi
# Zero-telemetry: apt's automatic update calls are masked in metadata; also
# ensure no package telemetry survives.
rm -f /var/log/apt/*.log /var/cache/apt/archives/*.deb
# ── Arcline toolchain (host-built .debs) ────────────────────────────────────
if [[ -d /arcline-debs ]] && ls /arcline-debs/*.deb >/dev/null 2>&1; then
log "installing Arcline toolchain packages"
export DEBIAN_FRONTEND=noninteractive
apt-get install -y /arcline-debs/*.deb 2>/dev/null \
|| dpkg -i /arcline-debs/*.deb 2>/dev/null \
|| warn "toolchain install incomplete (fix with: apt-get -f install)"
fi
# ── observability services (vendor debs from toolchain/build-vendor.sh) ─────
# Only enabled when their binaries actually landed in the image.
for svc_bin_unit in \
"/usr/sbin/grafana-server:grafana-server" \
"/usr/bin/loki:loki" \
"/usr/bin/promtail:promtail"; do
bin="${svc_bin_unit%%:*}"
unit="${svc_bin_unit##*:}"
if [[ -x "$bin" ]]; then
systemctl enable "$unit" 2>/dev/null || true
log "observability: enabled $unit ($bin present)"
fi
done
# ── optional upstream repos (grafana, loki) ─────────────────────────────────
if [[ "$EXTRA_REPOS" == "1" ]]; then
log "adding upstream observability repos (grafana, loki)"
install -d /usr/share/keyrings
curl -fsSL https://apt.grafana.com/gpg.key -o /usr/share/keyrings/grafana.asc 2>/dev/null || warn "grafana key fetch failed"
echo "deb [signed-by=/usr/share/keyrings/grafana.asc] https://apt.grafana.com stable main" > /etc/apt/sources.list.d/grafana.list
# Loki ships as a static binary tarball; the packaging lives in toolchain/.
# (No-op here; documented in docs/observability.md.)
fi
# ── root account policy ─────────────────────────────────────────────────────
if [[ "$LOCK_ROOT" == "1" ]]; then
passwd -l root
log "root account locked (sudo/ssh-key access only)"
fi
log "configure-system.sh complete for edition '$EDITION'"