Files
void-installer/iso/_inner-build-live.sh
2026-04-25 13:23:49 +02:00

166 lines
7.5 KiB
Bash
Executable File

#!/bin/bash
# Runs INSIDE the docker container (as root). Invoked by iso/build-live-iso.sh.
# Expects the project bind-mounted at /work and the cache at /cache.
#
# Required env (set by build-live-iso.sh):
# ARCH, REPO_URL, KEYMAP, LOCALE, ISO_PKGS, ISO_TITLE, OUT_ISO_REL,
# INCLUDE_DIR_REL
set -Eeuo pipefail
: "${ARCH:?}"; : "${REPO_URL:?}"; : "${KEYMAP:?}"; : "${LOCALE:?}"
: "${ISO_PKGS:?}"; : "${ISO_TITLE:?}"; : "${OUT_ISO_REL:?}"
: "${INCLUDE_DIR_REL:?}"
CACHE_DIR=/cache
PROJECT_DIR=/work
MKLIVE_DIR="$CACHE_DIR/void-mklive"
INCLUDE_DIR="$PROJECT_DIR/$INCLUDE_DIR_REL"
OUT_ISO="$PROJECT_DIR/$OUT_ISO_REL"
export PATH="$CACHE_DIR/xbps-static/usr/bin:$PATH"
[[ -d "$MKLIVE_DIR" ]] || { echo "ERROR: $MKLIVE_DIR missing"; exit 1; }
[[ -d "$INCLUDE_DIR" ]] || { echo "ERROR: $INCLUDE_DIR missing"; exit 1; }
command -v xbps-install.static >/dev/null \
|| { echo "ERROR: xbps-install.static not on PATH"; exit 1; }
mkdir -p "$(dirname "$OUT_ISO")"
# Compile dconf system-db using Void's own dconf binary (inside the Void
# rootfs chroot via mklive's -x postsetup hook). This guarantees the GVDB
# binary is produced by the exact same dconf/glib version that runs on the
# live system — no cross-distro format mismatch possible.
# (We do NOT pre-compile with Debian's dconf here; that caused silent failures
# when the GVDB format differed between the host and Void's glib.)
_DCONF_POSTSETUP="$(mktemp -p "$MKLIVE_DIR" postsetup-dconf.XXXXX.sh)"
cat > "$_DCONF_POSTSETUP" <<'PSEOF'
#!/bin/bash
# Postsetup script: compile dconf system-db AND user skel db with Void's own binary.
ROOTFS="$1"
if [[ -x "$ROOTFS/usr/bin/dconf" ]] && [[ -d "$ROOTFS/etc/dconf/db/local.d" ]]; then
# 1. Compile system-db (read by all users via /etc/dconf/profile/user)
chroot "$ROOTFS" dconf compile /etc/dconf/db/local /etc/dconf/db/local.d \
&& echo "postsetup: system-db compiled ($(chroot "$ROOTFS" dconf --version 2>/dev/null))" \
|| echo "postsetup: system-db compile failed (non-fatal)"
# 2. Compile a USER dconf db directly into /etc/skel/.config/dconf/user.
# dracut's adduser.sh copies skel → /home/live on first boot, so the live
# user starts with the keyboard in their OWN user db — no dependency on
# dconf profile/system-db loading order.
mkdir -p "$ROOTFS/etc/skel/.config/dconf"
chroot "$ROOTFS" dconf compile /etc/skel/.config/dconf/user /etc/dconf/db/local.d \
&& echo "postsetup: skel user dconf db compiled" \
|| echo "postsetup: skel user dconf db compile failed (non-fatal)"
else
echo "postsetup: dconf or keyfile dir not found in rootfs — skipping dconf compile"
fi
PSEOF
chmod +x "$_DCONF_POSTSETUP"
cd "$MKLIVE_DIR"
# ── Pre-bake nix packages ────────────────────────────────────────────────
# Install the nix user packages inside the Docker container and bake the
# resulting /nix store directly into the squashfs overlay. The live session
# then boots with all apps already present — no network downloads needed.
#
# The store is cached at /cache/nix-prebake; only rebuilt when the package
# list changes (checked via an md5 key file).
if [[ -n "${NIX_PACKAGES_PREBAKE:-}" ]]; then
echo ">>> pre-baking nix packages"
read -r -a _NIX_PKGS <<< "$NIX_PACKAGES_PREBAKE"
_NIX_CACHE="$CACHE_DIR/nix-prebake"
_CACHE_KEY="$_NIX_CACHE/.done.$(printf '%s\n' "${_NIX_PKGS[@]}" | sort | md5sum | cut -c1-8)"
mkdir -p "$_NIX_CACHE"
if [[ -f "$_CACHE_KEY" ]] && [[ -d "$_NIX_CACHE/store" ]] && [[ -f "$_NIX_CACHE/.profile-path" ]]; then
echo " restoring cached nix store ($(du -sh "$_NIX_CACHE/store" 2>/dev/null | cut -f1))"
mkdir -p /nix
rsync -a "$_NIX_CACHE/" /nix/ 2>&1 | tail -1
else
echo " installing nix (single-user, no-daemon)..."
rm -rf /nix ~/.nix-profile ~/.nix-defexpr ~/.nix-channels
# Pre-create /nix as root so the installer doesn't try 'sudo mkdir'
# (sudo isn't installed in this Docker container).
mkdir -m 0755 -p /nix
# Disable build-users-group so nix doesn't complain about missing nixbld group.
export NIX_CONFIG="build-users-group = "
curl -fsSL https://nixos.org/nix/install | \
NIX_INSTALLER_TRUST_INSTALLER=1 sh -s -- --no-daemon --no-channel-add
# shellcheck disable=SC1091
. /root/.nix-profile/etc/profile.d/nix.sh 2>/dev/null || true
# Explicitly add nix to PATH in case the profile script didn't export it
export PATH="/root/.nix-profile/bin:/nix/var/nix/profiles/default/bin:$PATH"
export NIXPKGS_ALLOW_UNFREE=1
echo " nix profile install: ${_NIX_PKGS[*]}"
nix profile add --extra-experimental-features "nix-command flakes" \
--impure "${_NIX_PKGS[@]}" 2>&1
# Save the profile store path so we can restore from cache next time
readlink -f /root/.nix-profile > "$_NIX_CACHE/.profile-path"
# Cache the full /nix store
rsync -a /nix/ "$_NIX_CACHE/" 2>&1 | tail -1
touch "$_CACHE_KEY"
echo " cached nix store: $(du -sh "$_NIX_CACHE/store" 2>/dev/null | cut -f1)"
fi
# Stage the nix store into the squashfs overlay
echo " staging /nix into overlay ($(du -sh /nix/store 2>/dev/null | cut -f1))"
mkdir -p "$INCLUDE_DIR/nix"
rsync -a /nix/ "$INCLUDE_DIR/nix/" 2>&1 | tail -1
# /etc/skel/.nix-profile → the pre-baked store profile path.
# dracut's adduser.sh runs 'useradd -m' which copies skel → /home/live,
# so the live user gets a ready nix profile from the squashfs store.
_STORE_PROFILE=$(cat "$_NIX_CACHE/.profile-path" 2>/dev/null \
|| readlink -f /root/.nix-profile 2>/dev/null || echo "")
if [[ -n "$_STORE_PROFILE" && -d "$_STORE_PROFILE" ]]; then
mkdir -p "$INCLUDE_DIR/etc/skel"
ln -sf "$_STORE_PROFILE" "$INCLUDE_DIR/etc/skel/.nix-profile"
echo " skel/.nix-profile → $_STORE_PROFILE"
else
echo " WARNING: could not determine nix store profile path"
fi
fi
# ── end nix prebake ──────────────────────────────────────────────────────
_cleanup_mklive_builds() {
local d sub
for d in "$MKLIVE_DIR"/mklive-build.*/; do
[[ -d "$d" ]] || continue
for sub in tmp-rootfs/sys tmp-rootfs/proc tmp-rootfs/dev tmp-rootfs/run \
image/rootfs/sys image/rootfs/proc image/rootfs/dev image/rootfs/run; do
[[ -d "$d$sub" ]] && umount -R --lazy "$d$sub" 2>/dev/null || true
done
rm -rf "$d" 2>/dev/null || true
done
}
trap _cleanup_mklive_builds EXIT
./mklive.sh \
-a "$ARCH" \
-r "$REPO_URL" \
-r "${REPO_URL%/current}/current/nonfree" \
-c "$CACHE_DIR/xbps-live-pkgs" \
-H "$CACHE_DIR/xbps-host-pkgs" \
-k "$KEYMAP" \
-l "$LOCALE" \
-T "$ISO_TITLE" \
-p "$ISO_PKGS" \
-I "$INCLUDE_DIR" \
-C "${BOOT_CMDLINE:-}" \
-x "$_DCONF_POSTSETUP" \
-o "$OUT_ISO"
# ownership of OUT_ISO is fixed unconditionally below with the include dir
# Fix ownership of include dir so the host user can clean up without sudo.
# u+rwX: sets read+write on all, execute only on directories (capital X).
chmod -R u+rwX "$INCLUDE_DIR" 2>/dev/null || true
chown -R "${HOST_UID:-1000}:${HOST_GID:-1000}" "$INCLUDE_DIR" 2>/dev/null || true
chown -R "${HOST_UID:-1000}:${HOST_GID:-1000}" "$OUT_ISO" "${OUT_ISO}".* 2>/dev/null || true