From 30ae82c5fd0ff2a3b0e0de7d46ffeeab29ac9016 Mon Sep 17 00:00:00 2001 From: mozempk Date: Thu, 23 Apr 2026 09:32:39 +0200 Subject: [PATCH] feat: add installer to live ISO; skip nix pkgs if <4GB free in /nix - iso/build-live-iso.sh: copy install.sh+lib/ to /usr/local/lib/void-installer/, config+profiles to /usr/local/share/installer/, bake secrets.env as /etc/installer-secrets.env, add 'Install Void Linux' .desktop launcher (opens alacritty+sudo), create /usr/local/bin/void-install wrapper - installer/first-login.sh: skip nix profile add when /nix has <4GB free (live tmpfs overlay fills up with ~3-4GB of nix packages); packages are installed on first login after the system is installed instead --- installer/first-login.sh | 64 +++++++++++++++++++++++----------------- iso/build-live-iso.sh | 50 +++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 27 deletions(-) diff --git a/installer/first-login.sh b/installer/first-login.sh index 3126931..0914496 100644 --- a/installer/first-login.sh +++ b/installer/first-login.sh @@ -35,41 +35,51 @@ fi # --- Nix user packages (google-chrome, spotify, discord, etc.) --- # Present when running from the live ISO (written by build-live-iso.sh). # In the installed system the packages come from first-boot-nix.sh instead. +# NOTE: nix packages are intentionally skipped in the live session — they +# can total 3-4 GB which exceeds the tmpfs overlay on typical hardware. +# They will be installed on the first login after the system is installed. NIX_PACKAGES_FILE="${NIX_PACKAGES_FILE:-/usr/local/libexec/nix-packages.list}" if [[ -r "$NIX_PACKAGES_FILE" ]] && command -v nix >/dev/null 2>&1; then - echo "==> installing nix user packages from $NIX_PACKAGES_FILE" + remaining=$(df -k /nix 2>/dev/null | awk 'NR==2{print $4}') + # Require at least 4GB free in /nix before attempting package install + if [[ -n "$remaining" && "$remaining" -lt 4194304 ]]; then + echo "==> skipping nix packages in live session (only ${remaining}KB free in /nix)" + echo " packages will be installed on first login after installation" + else + echo "==> installing nix user packages from $NIX_PACKAGES_FILE" - # Source nix profile.d scripts so PATH and env are set. - for f in /etc/profile.d/nix*.sh; do - # shellcheck disable=SC1090 - [[ -r "$f" ]] && . "$f" - done + # Source nix profile.d scripts so PATH and env are set. + for f in /etc/profile.d/nix*.sh; do + # shellcheck disable=SC1090 + [[ -r "$f" ]] && . "$f" + done - # Guard: nix-env --switch-profile creates a circular symlink when given - # ~/.nix-profile as the target (it points to itself). Remove it so - # 'nix profile add' can initialise a clean profile. - if [[ -L "$HOME/.nix-profile" ]]; then - _target=$(readlink "$HOME/.nix-profile") - if [[ "$_target" == ".nix-profile" || "$_target" == "$HOME/.nix-profile" ]]; then - echo " removing circular .nix-profile symlink" - rm -f "$HOME/.nix-profile" + # Guard: nix-env --switch-profile creates a circular symlink when given + # ~/.nix-profile as the target (it points to itself). Remove it so + # 'nix profile add' can initialise a clean profile. + if [[ -L "$HOME/.nix-profile" ]]; then + _target=$(readlink "$HOME/.nix-profile") + if [[ "$_target" == ".nix-profile" || "$_target" == "$HOME/.nix-profile" ]]; then + echo " removing circular .nix-profile symlink" + rm -f "$HOME/.nix-profile" + fi + unset _target fi - unset _target - fi - # D-Bus session is available when autostarted from Cinnamon. - if [[ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]]; then - eval "$(dbus-launch --sh-syntax 2>/dev/null)" || true - fi + # D-Bus session is available when autostarted from Cinnamon. + if [[ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]]; then + eval "$(dbus-launch --sh-syntax 2>/dev/null)" || true + fi - export NIXPKGS_ALLOW_UNFREE=1 + export NIXPKGS_ALLOW_UNFREE=1 - mapfile -t pkgs < <(grep -vE '^\s*(#|$)' "$NIX_PACKAGES_FILE") - if [[ ${#pkgs[@]} -gt 0 ]]; then - echo " packages: ${pkgs[*]}" - # 'nix profile install' is deprecated as of nix 2.x — use 'nix profile add' - nix profile add --impure "${pkgs[@]}" 2>&1 || { - echo "!! nix profile add failed (partial install may have succeeded)"; } + mapfile -t pkgs < <(grep -vE '^\s*(#|$)' "$NIX_PACKAGES_FILE") + if [[ ${#pkgs[@]} -gt 0 ]]; then + echo " packages: ${pkgs[*]}" + # 'nix profile install' is deprecated as of nix 2.x — use 'nix profile add' + nix profile add --impure "${pkgs[@]}" 2>&1 || { + echo "!! nix profile add failed (partial install may have succeeded)"; } + fi fi fi diff --git a/iso/build-live-iso.sh b/iso/build-live-iso.sh index db5a6cb..fe00d3d 100755 --- a/iso/build-live-iso.sh +++ b/iso/build-live-iso.sh @@ -501,6 +501,56 @@ OnlyShowIn=X-Cinnamon; EOF fi +# ── 3f-ins) Void Linux installer in live image ─────────────────────────── +# install.sh uses INSTALLER_DIR=$(dirname $0)/lib for its libraries, so we +# keep the script and lib/ together under /usr/local/lib/void-installer/. +# SHARE_DIR (/usr/local/share/installer) holds config, packages, profiles. +install -d -m 0755 "$INCLUDE_DIR/usr/local/lib/void-installer/lib" +install -d -m 0755 "$INCLUDE_DIR/usr/local/share/installer" +install -m 0755 "$PROJECT_DIR/installer/install.sh" "$INCLUDE_DIR/usr/local/lib/void-installer/install.sh" +for f in "$PROJECT_DIR/installer/lib/"*.sh; do + install -m 0755 "$f" "$INCLUDE_DIR/usr/local/lib/void-installer/lib/$(basename "$f")" +done +# Config and packages — read by install.sh via SHARE_DIR +install -m 0644 "$PROJECT_DIR/config/install.conf" "$INCLUDE_DIR/usr/local/share/installer/install.conf" +install -m 0644 "$PROJECT_DIR/installer/packages.list" "$INCLUDE_DIR/usr/local/share/installer/packages.list" +# Profiles directory (profile.conf + per-profile packages.list) +if [[ -d "$PROJECT_DIR/config/profiles" ]]; then + cp -r "$PROJECT_DIR/config/profiles" "$INCLUDE_DIR/usr/local/share/installer/profiles" +fi +# Thin wrapper so the user can type `void-install` from anywhere +install -d -m 0755 "$INCLUDE_DIR/usr/local/bin" +cat > "$INCLUDE_DIR/usr/local/bin/void-install" <<'WRAPEOF' +#!/bin/sh +exec /usr/local/lib/void-installer/install.sh "$@" +WRAPEOF +chmod 0755 "$INCLUDE_DIR/usr/local/bin/void-install" +# Secrets: read from secrets.env at build time, baked as /etc/installer-secrets.env +# (the file is .gitignored; if absent the installer prompts interactively) +_SECRETS_SRC="${SECRETS_ENV:-$PROJECT_DIR/secrets.env}" +if [[ -r "$_SECRETS_SRC" ]]; then + install -d -m 0755 "$INCLUDE_DIR/etc" + install -m 0600 "$_SECRETS_SRC" "$INCLUDE_DIR/etc/installer-secrets.env" + echo " baked installer secrets from $_SECRETS_SRC" +else + echo " WARNING: no secrets.env found — installer will prompt for passwords at runtime" +fi +# Desktop launcher — opens alacritty running void-install as root (live user +# has passwordless sudo configured by mklive). +install -d -m 0755 "$INCLUDE_DIR/usr/share/applications" +cat > "$INCLUDE_DIR/usr/share/applications/void-installer.desktop" <<'DESKEOF' +[Desktop Entry] +Version=1.0 +Type=Application +Name=Install Void Linux +Comment=Install Void Linux to this machine +Exec=alacritty --title "Void Linux Installer" -e sudo /usr/local/bin/void-install +Icon=system-software-install +Terminal=false +Categories=System; +StartupNotify=true +DESKEOF + install -d -m 0755 "$INCLUDE_DIR/etc/profile.d" cat > "$INCLUDE_DIR/etc/profile.d/local-bin.sh" <<'EOF' case ":$PATH:" in