#!/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 inside the include dir so it ships compiled. # Debian's dconf-cli provides 'dconf compile '. if command -v dconf >/dev/null 2>&1 && [[ -d "$INCLUDE_DIR/etc/dconf/db/local.d" ]]; then dconf compile "$INCLUDE_DIR/etc/dconf/db/local" \ "$INCLUDE_DIR/etc/dconf/db/local.d" 2>/dev/null \ && echo "dconf: compiled system-db/local" \ || echo "dconf: compile failed (non-fatal)" fi 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 install --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:-}" \ -o "$OUT_ISO" chown "$(stat -c '%u:%g' "$PROJECT_DIR")" "$OUT_ISO" "${OUT_ISO}".* 2>/dev/null || true