feat: bake everything into live ISO — no first-login script
Instead of downloading at first login, everything is ready at boot:
- iso/build-live-iso.sh:
* apply-live-settings.sh XDG autostart applies theme/wallpaper/terminal
via gsettings at first Cinnamon login (reliable vs dconf binary format)
* /etc/environment: XDG_DATA_DIRS includes nix profile so Cinnamon menu
shows pre-baked nix apps immediately
* /etc/profile.d/nix-prebaked.sh: PATH setup for terminal sessions
* first-login.sh kept at /usr/local/libexec but NOT autostarted (manual
use for Claude/NVM installs)
* NIX_PACKAGES_PREBAKE passed to Docker build
- iso/_inner-build-live.sh:
* Pre-bake nix packages inside Docker before mklive.sh; copy /nix store
into squashfs overlay; set /etc/skel/.nix-profile → store profile path
* Cached at /cache/nix-prebake (keyed by package list md5)
- iso/Dockerfile: add rsync (needed by nix prebake)
- packages.live-desktop.list: add vscode + chromium (XBPS, no download)
This commit is contained in:
@@ -114,6 +114,10 @@ gtk-engine-murrine
|
||||
dconf
|
||||
dconf-editor
|
||||
|
||||
# --- code editors / dev tools ---
|
||||
vscode
|
||||
chromium
|
||||
|
||||
# --- media / utilities ---
|
||||
vlc
|
||||
flameshot
|
||||
|
||||
@@ -10,7 +10,7 @@ ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
bash git curl ca-certificates xz-utils tar patch python3 \
|
||||
mtools xorriso squashfs-tools dosfstools e2fsprogs \
|
||||
kmod dconf-cli \
|
||||
kmod dconf-cli rsync \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# xbps-static is downloaded into /cache by the host script and added to PATH
|
||||
|
||||
@@ -38,6 +38,66 @@ 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
|
||||
curl -fsSL https://nixos.org/nix/install | sh -s -- --no-daemon --no-channel-add
|
||||
# shellcheck disable=SC1091
|
||||
. /root/.nix-profile/etc/profile.d/nix.sh
|
||||
|
||||
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
|
||||
|
||||
@@ -485,21 +485,88 @@ Extensions=any;
|
||||
Dependencies=/usr/local/bin/code-open;
|
||||
EOF
|
||||
|
||||
# ── 3f) first-login autostart + profile.d for the live user ─────────────
|
||||
# ── 3f) Live session baked-in configuration ──────────────────────────────
|
||||
# No first-login script. Everything is baked in at build time.
|
||||
# The apply-settings script runs once at first Cinnamon login to apply
|
||||
# gsettings (100% reliable vs dconf system-db binary format variations).
|
||||
install -d -m 0755 "$INCLUDE_DIR/usr/local/libexec"
|
||||
install -d -m 0755 "$INCLUDE_DIR/etc/xdg/autostart"
|
||||
|
||||
# Keep first-login.sh available for MANUAL use (Claude, NVM installs) but
|
||||
# do NOT autostart it. User can run it from a terminal if needed.
|
||||
if [[ -r "$OVERLAY/first-login.sh" ]]; then
|
||||
install -d -m 0755 "$INCLUDE_DIR/usr/local/libexec"
|
||||
install -m 0755 "$OVERLAY/first-login.sh" "$INCLUDE_DIR/usr/local/libexec/first-login.sh"
|
||||
cat > "$INCLUDE_DIR/etc/xdg/autostart/void-live-first-login.desktop" <<EOF
|
||||
fi
|
||||
|
||||
# apply-settings.sh: runs once at first Cinnamon login, applies theme/wallpaper/
|
||||
# terminal via gsettings (writes to user dconf db — always works).
|
||||
cat > "$INCLUDE_DIR/usr/local/libexec/apply-live-settings.sh" <<EOF
|
||||
#!/bin/bash
|
||||
# Baked live-session settings. Runs once at first Cinnamon login.
|
||||
DONE="\$HOME/.void-live-settings-done"
|
||||
[[ -f "\$DONE" ]] && exit 0
|
||||
|
||||
# Wait for D-Bus session bus (LightDM autologin starts it, be safe)
|
||||
for _i in \$(seq 15); do
|
||||
[[ -n "\${DBUS_SESSION_BUS_ADDRESS:-}" ]] && break
|
||||
eval "\$(dbus-launch --sh-syntax 2>/dev/null)" || true
|
||||
sleep 0.3
|
||||
done
|
||||
|
||||
# GTK / Cinnamon DE theme
|
||||
gsettings set org.cinnamon.desktop.interface gtk-theme '${GTK_THEME}'
|
||||
gsettings set org.cinnamon.desktop.interface icon-theme '${ICON_THEME}'
|
||||
gsettings set org.gnome.desktop.interface cursor-theme '${CURSOR_THEME}'
|
||||
gsettings set org.cinnamon.theme name '${GTK_THEME}'
|
||||
|
||||
# Wallpaper (first .jpg found in the backgrounds dir)
|
||||
_WP=\$(ls /usr/share/backgrounds/void-installer/*.jpg 2>/dev/null | head -1 || echo '')
|
||||
[[ -n "\$_WP" ]] && gsettings set org.cinnamon.desktop.background picture-uri "file://\$_WP"
|
||||
[[ -n "\$_WP" ]] && gsettings set org.gnome.desktop.background picture-uri "file://\$_WP"
|
||||
|
||||
# Default terminal
|
||||
gsettings set org.cinnamon.desktop.default-applications.terminal exec '${DEFAULT_TERMINAL:-alacritty}'
|
||||
gsettings set org.cinnamon.desktop.default-applications.terminal exec-arg '-e'
|
||||
gsettings set org.gnome.desktop.default-applications.terminal exec '${DEFAULT_TERMINAL:-alacritty}'
|
||||
gsettings set org.gnome.desktop.default-applications.terminal exec-arg '-e'
|
||||
|
||||
# Keyboard layout (Swiss French)
|
||||
gsettings set org.gnome.desktop.input-sources sources "[('xkb', '${KEYMAP:-ch+fr_nodeadkeys}')]"
|
||||
|
||||
touch "\$DONE"
|
||||
EOF
|
||||
chmod 0755 "$INCLUDE_DIR/usr/local/libexec/apply-live-settings.sh"
|
||||
|
||||
cat > "$INCLUDE_DIR/etc/xdg/autostart/void-live-settings.desktop" <<'DESK'
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Void Live First-Login Setup
|
||||
Exec=/usr/local/libexec/first-login.sh
|
||||
Name=Void Live Apply Settings
|
||||
Exec=/usr/local/libexec/apply-live-settings.sh
|
||||
NoDisplay=true
|
||||
X-GNOME-Autostart-enabled=true
|
||||
OnlyShowIn=X-Cinnamon;
|
||||
EOF
|
||||
DESK
|
||||
|
||||
# /etc/environment: XDG_DATA_DIRS includes the pre-baked nix profile so that
|
||||
# Cinnamon's app menu picks up .desktop files from the nix store without
|
||||
# requiring any PATH tricks in the graphical session.
|
||||
cat > "$INCLUDE_DIR/etc/environment" <<'ENVEOF'
|
||||
XDG_DATA_DIRS=/home/live/.nix-profile/share:/usr/local/share:/usr/share
|
||||
ENVEOF
|
||||
|
||||
# /etc/profile.d: PATH for interactive terminals (alacritty, etc.)
|
||||
install -d -m 0755 "$INCLUDE_DIR/etc/profile.d"
|
||||
cat > "$INCLUDE_DIR/etc/profile.d/nix-prebaked.sh" <<'NIXEOF'
|
||||
# Pre-baked nix profile — set up PATH for interactive shells.
|
||||
if [[ -d "${HOME:-}/.nix-profile/bin" ]]; then
|
||||
case ":$PATH:" in
|
||||
*":$HOME/.nix-profile/bin:"*) ;;
|
||||
*) export PATH="$HOME/.nix-profile/bin:$PATH" ;;
|
||||
esac
|
||||
fi
|
||||
NIXEOF
|
||||
|
||||
|
||||
|
||||
# ── 3f-ins) Void Linux installer in live image ───────────────────────────
|
||||
# install.sh uses INSTALLER_DIR=$(dirname $0)/lib for its libraries, so we
|
||||
@@ -552,41 +619,30 @@ StartupNotify=true
|
||||
DESKEOF
|
||||
|
||||
install -d -m 0755 "$INCLUDE_DIR/etc/profile.d"
|
||||
cat > "$INCLUDE_DIR/etc/profile.d/local-bin.sh" <<'EOF'
|
||||
cat >> "$INCLUDE_DIR/etc/profile.d/nix-prebaked.sh" <<'EOF'
|
||||
case ":$PATH:" in
|
||||
*":$HOME/.local/bin:"*) ;;
|
||||
*) export PATH="$HOME/.local/bin:$PATH" ;;
|
||||
esac
|
||||
EOF
|
||||
|
||||
# ── 3f-bis) Nix user packages list for first-login.sh ───────────────────
|
||||
# Write NIX_USER_PACKAGES (from install.conf) as a plain list so
|
||||
# first-login.sh can read it without sourcing install.conf.
|
||||
# nix-packages.list: kept so first-login.sh can still be run manually
|
||||
install -d -m 0755 "$INCLUDE_DIR/usr/local/libexec"
|
||||
{
|
||||
for pkg in "${NIX_USER_PACKAGES[@]}"; do
|
||||
echo "$pkg"
|
||||
done
|
||||
for pkg in "${NIX_USER_PACKAGES[@]}"; do echo "$pkg"; done
|
||||
} > "$INCLUDE_DIR/usr/local/libexec/nix-packages.list"
|
||||
# Also set the env var so first-login.sh knows where to find it.
|
||||
cat > "$INCLUDE_DIR/etc/profile.d/nix-packages-path.sh" <<'EOF'
|
||||
export NIX_PACKAGES_FILE=/usr/local/libexec/nix-packages.list
|
||||
EOF
|
||||
|
||||
# ── 3g) Live-session skel: pre-wire .bash_profile for first-login ────────
|
||||
# ── 3g) Skel: .bash_profile sources .bashrc only (no first-login autorun) ──
|
||||
install -d -m 0755 "$INCLUDE_DIR/etc/skel"
|
||||
cat > "$INCLUDE_DIR/etc/skel/.bash_profile" <<'EOF'
|
||||
# Source .bashrc for interactive login shells.
|
||||
[[ -f ~/.bashrc ]] && . ~/.bashrc
|
||||
|
||||
# Auto-run user environment setup on first interactive login.
|
||||
if [[ -z "$_FIRST_LOGIN_RAN" && -x /usr/local/libexec/first-login.sh \
|
||||
&& ! -f "$HOME/.first-login-done" ]]; then
|
||||
export _FIRST_LOGIN_RAN=1
|
||||
/usr/local/libexec/first-login.sh 2>&1 | tee -a "$HOME/.first-login.log"
|
||||
fi
|
||||
EOF
|
||||
|
||||
|
||||
# 4) build Docker image
|
||||
echo ">>> building docker image $DOCKER_IMAGE"
|
||||
if "$DOCKER" buildx version >/dev/null 2>&1; then
|
||||
@@ -618,6 +674,7 @@ echo ">>> running mklive.sh inside docker — output: $OUT_ISO"
|
||||
-e OUT_ISO_REL="${OUT_ISO#$PROJECT_DIR/}" \
|
||||
-e BOOT_CMDLINE="${BOOT_CMDLINE:-}" \
|
||||
-e INCLUDE_DIR_REL="${INCLUDE_DIR#$PROJECT_DIR/}" \
|
||||
-e NIX_PACKAGES_PREBAKE="${NIX_USER_PACKAGES[*]}" \
|
||||
-e HOST_UID="$(id -u)" \
|
||||
-e HOST_GID="$(id -g)" \
|
||||
"$DOCKER_IMAGE" \
|
||||
|
||||
Reference in New Issue
Block a user