feat: live ISO — nix daemon mode, autologin fix, GPU detection, app stack
- Switch nix from single-user to daemon mode (trusted-users = root live); Void socket at /var/nix/daemon-socket/socket confirmed - Fix lightdm autologin: use session-wrapper=/etc/lightdm/Xsession (Void lightdm 1.32 has no lightdm-session binary) - Fix session env: LIBGL_ALWAYS_SOFTWARE=1 via profile.d (session-env= is unsupported in this lightdm version) - GPU auto-detection at boot: VIRT→software GL, NVIDIA PRIME offload, Intel/AMD/generic→modesetting - Add nix-daemon to live runsvdir/default; remove unsupported -S mklive flag - first-login.sh: install Claude Code + nix user packages (google-chrome, spotify, discord, localsend, mission-center) + NVM/node + VS Code exts - build-live-iso.sh: write nix-packages.list from NIX_USER_PACKAGES - postinstall.sh: fix nix-daemon socket path to /var/nix/daemon-socket/socket - Dockerfile: add dconf-cli for build-time dconf compile - _inner-build-live.sh: use correct 'dconf compile' API (not 'dconf update') - .gitignore: add build/live-includes/ (generated staging tree) - docs/LIVE_ISO.md: document all findings, gotchas and architecture
This commit is contained in:
@@ -70,57 +70,201 @@ rm -rf "$INCLUDE_DIR"
|
||||
mkdir -p "$INCLUDE_DIR"
|
||||
|
||||
# ── 3a) live user account ───────────────────────────────────────────────
|
||||
# Create user 'live' with no password in the live image.
|
||||
# mklive populates /etc/passwd at install time — we drop a post-install hook
|
||||
# via the live init that calls useradd. We use an install.conf.d override
|
||||
# that mklive will source, plus an rc.local-style runit oneshot.
|
||||
# The vmklive dracut hook (adduser.sh) creates the live user in initramfs
|
||||
# using the live.user= kernel cmdline parameter (added to BOOT_CMDLINE below).
|
||||
# We add extra groups and sudo via /etc/runit/2 override (after pivot_root).
|
||||
install -d -m 0755 "$INCLUDE_DIR/etc"
|
||||
cat > "$INCLUDE_DIR/etc/passwd-live" <<EOF
|
||||
# placeholder replaced at build time by _inner-build-live.sh
|
||||
EOF
|
||||
|
||||
# rc.local equivalent: runit oneshot that creates the live user on first boot.
|
||||
install -d -m 0755 "$INCLUDE_DIR/etc/runit/runsvdir/default"
|
||||
install -d -m 0755 "$INCLUDE_DIR/etc/sv/live-user-setup"
|
||||
cat > "$INCLUDE_DIR/etc/sv/live-user-setup/run" <<'SV_EOF'
|
||||
# GPU detection + extra group setup — runs from our runit/2 override below.
|
||||
install -d -m 0755 "$INCLUDE_DIR/etc/runit"
|
||||
cat > "$INCLUDE_DIR/etc/runit/live-setup.sh" <<'SV_EOF'
|
||||
#!/bin/sh
|
||||
# Create the 'live' user (no password) and set up home directory.
|
||||
# Runs once; removes itself from default runsvdir on completion.
|
||||
set -e
|
||||
if ! id live >/dev/null 2>&1; then
|
||||
useradd -m -s /bin/bash -G wheel,audio,video,plugdev,input,network,docker live
|
||||
passwd -d live
|
||||
install -d -m 0700 /home/live/.ssh
|
||||
# Apply skel dotfiles
|
||||
if [ -d /etc/skel ]; then
|
||||
cp -a /etc/skel/. /home/live/ 2>/dev/null || true
|
||||
fi
|
||||
chown -R live:live /home/live
|
||||
# Runs from /etc/runit/2 before any service starts.
|
||||
# 1. Ensures live user has all needed groups.
|
||||
# 2. Generates /etc/X11/xorg.conf.d/20-gpu.conf based on detected hardware.
|
||||
|
||||
LIVE_USER="${USERNAME:-live}"
|
||||
[ -f /etc/default/live.conf ] && . /etc/default/live.conf
|
||||
LIVE_USER="${USERNAME:-live}"
|
||||
|
||||
# Extra groups (dracut only adds audio,video,wheel)
|
||||
for g in plugdev input network docker; do
|
||||
groupadd -f "$g" 2>/dev/null || true
|
||||
usermod -aG "$g" "$LIVE_USER" 2>/dev/null || true
|
||||
done
|
||||
install -d -m 0755 /etc/sudoers.d
|
||||
printf '%s ALL=(ALL) NOPASSWD: ALL\n' "$LIVE_USER" > /etc/sudoers.d/live
|
||||
chmod 0440 /etc/sudoers.d/live
|
||||
|
||||
# ── Nix daemon-mode setup ───────────────────────────────────────────────
|
||||
# Void's xbps nix package ships nix-daemon + a runit service at /etc/sv/nix-daemon
|
||||
# and puts the socket at /var/nix/daemon-socket/socket.
|
||||
# We configure the daemon to trust the live user so 'nix profile install'
|
||||
# works without root and without owning /nix/store.
|
||||
if [ -x /usr/bin/nix ]; then
|
||||
install -d -m 0755 /etc/nix
|
||||
cat > /etc/nix/nix.conf <<NIXCONF
|
||||
experimental-features = nix-command flakes
|
||||
sandbox = false
|
||||
auto-optimise-store = true
|
||||
trusted-users = root $LIVE_USER
|
||||
NIXCONF
|
||||
# Ensure nix.sh profile.d sets PATH for installed nix packages.
|
||||
# The Void nix package ships /etc/profile.d/nix.sh; we just supplement it.
|
||||
cat > /etc/profile.d/nix-live.sh <<'NIXSH'
|
||||
# Add nix user-profile bin to PATH
|
||||
if [ -d "$HOME/.nix-profile/bin" ]; then
|
||||
export PATH="$HOME/.nix-profile/bin:$PATH"
|
||||
fi
|
||||
# Enable sudoers entry for live
|
||||
if ! grep -q '^live ' /etc/sudoers 2>/dev/null; then
|
||||
echo 'live ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers
|
||||
NIXSH
|
||||
chmod 0644 /etc/profile.d/nix-live.sh
|
||||
echo "live-setup: nix daemon mode configured (trusted-users = $LIVE_USER)"
|
||||
fi
|
||||
|
||||
# ── D-Bus session socket for the live user's login session ───────────────
|
||||
# dbus-launch is called by lightdm-session / Xsession automatically.
|
||||
# Ensure dbus system bus is accessible (needed by nix and Cinnamon).
|
||||
# The dbus runit service is enabled in runsvdir/default; no extra setup needed.
|
||||
|
||||
# ── GPU / Xorg driver detection ──────────────────────────────────────────
|
||||
mkdir -p /etc/X11/xorg.conf.d
|
||||
|
||||
# Detect GPU via PCI
|
||||
HAS_NVIDIA=0
|
||||
HAS_INTEL=0
|
||||
HAS_AMD=0
|
||||
IS_VIRT=0
|
||||
|
||||
if command -v lspci >/dev/null 2>&1; then
|
||||
lspci_out=$(lspci 2>/dev/null)
|
||||
echo "$lspci_out" | grep -qi 'NVIDIA' && HAS_NVIDIA=1
|
||||
echo "$lspci_out" | grep -qiE 'Intel.*VGA|VGA.*Intel|Intel.*Integrated' && HAS_INTEL=1
|
||||
echo "$lspci_out" | grep -qiE 'AMD.*VGA|VGA.*AMD|ATI.*VGA|Radeon' && HAS_AMD=1
|
||||
echo "$lspci_out" | grep -qiE 'virtio|VMware|QEMU|VirtualBox|bochs' && IS_VIRT=1
|
||||
fi
|
||||
|
||||
if [ $IS_VIRT -eq 1 ]; then
|
||||
# Virtual machine: force modesetting, disable accel, use software GL
|
||||
cat > /etc/X11/xorg.conf.d/20-gpu.conf <<'EOF'
|
||||
Section "Device"
|
||||
Identifier "GPU"
|
||||
Driver "modesetting"
|
||||
Option "AccelMethod" "none"
|
||||
EndSection
|
||||
EOF
|
||||
# Xsession sources /etc/profile which sources /etc/profile.d/ — so this
|
||||
# env var reaches the cinnamon session (LightDM's session-env is not
|
||||
# supported in the Void-packaged lightdm 1.32).
|
||||
echo 'export LIBGL_ALWAYS_SOFTWARE=1' > /etc/profile.d/live-env.sh
|
||||
chmod 0644 /etc/profile.d/live-env.sh
|
||||
echo "live-setup: VIRT detected — modesetting (no accel), software GL"
|
||||
elif [ $HAS_NVIDIA -eq 1 ] && [ -e /usr/lib/xorg/modules/drivers/nvidia_drv.so ]; then
|
||||
# NVIDIA PRIME (Intel iGPU primary + NVIDIA render offload)
|
||||
# Real hardware — ensure software GL is NOT forced
|
||||
rm -f /etc/profile.d/live-env.sh
|
||||
INTEL_BUSID=$(lspci | grep -iE 'VGA.*Intel|Intel.*VGA' | head -1 | \
|
||||
awk '{print $1}' | awk -F'[.:]' '{printf "PCI:%d:%d:%d", strtonum("0x"$1), strtonum("0x"$2), strtonum("0x"$3)}')
|
||||
NVIDIA_BUSID=$(lspci | grep -i NVIDIA | head -1 | \
|
||||
awk '{print $1}' | awk -F'[.:]' '{printf "PCI:%d:%d:%d", strtonum("0x"$1), strtonum("0x"$2), strtonum("0x"$3)}')
|
||||
cat > /etc/X11/xorg.conf.d/20-gpu.conf <<EOF
|
||||
Section "ServerLayout"
|
||||
Identifier "layout"
|
||||
Option "AllowNVIDIAGPUScreens"
|
||||
EndSection
|
||||
Section "Device"
|
||||
Identifier "Intel"
|
||||
Driver "modesetting"
|
||||
BusID "${INTEL_BUSID:-PCI:0:2:0}"
|
||||
EndSection
|
||||
Section "Device"
|
||||
Identifier "NVIDIA"
|
||||
Driver "nvidia"
|
||||
BusID "${NVIDIA_BUSID:-PCI:1:0:0}"
|
||||
Option "AllowEmptyInitialConfiguration"
|
||||
EndSection
|
||||
EOF
|
||||
echo "live-setup: NVIDIA PRIME detected (Intel=${INTEL_BUSID} NVIDIA=${NVIDIA_BUSID})"
|
||||
elif [ $HAS_NVIDIA -eq 1 ]; then
|
||||
# NVIDIA present but no proprietary driver — use modesetting
|
||||
rm -f /etc/profile.d/live-env.sh
|
||||
cat > /etc/X11/xorg.conf.d/20-gpu.conf <<'EOF'
|
||||
Section "Device"
|
||||
Identifier "GPU"
|
||||
Driver "modesetting"
|
||||
EndSection
|
||||
EOF
|
||||
echo "live-setup: NVIDIA detected but no proprietary driver — modesetting"
|
||||
else
|
||||
# Intel / AMD / generic — modesetting
|
||||
rm -f /etc/profile.d/live-env.sh
|
||||
cat > /etc/X11/xorg.conf.d/20-gpu.conf <<'EOF'
|
||||
Section "Device"
|
||||
Identifier "GPU"
|
||||
Driver "modesetting"
|
||||
EndSection
|
||||
EOF
|
||||
echo "live-setup: Generic/Intel/AMD — modesetting"
|
||||
fi
|
||||
# Remove self from runsvdir so it doesn't restart
|
||||
rm -f /etc/runit/runsvdir/default/live-user-setup
|
||||
sv stop live-user-setup 2>/dev/null || true
|
||||
SV_EOF
|
||||
chmod 0755 "$INCLUDE_DIR/etc/sv/live-user-setup/run"
|
||||
ln -sf /etc/sv/live-user-setup "$INCLUDE_DIR/etc/runit/runsvdir/default/live-user-setup"
|
||||
chmod 0755 "$INCLUDE_DIR/etc/runit/live-setup.sh"
|
||||
|
||||
# Override /etc/runit/2 — mirrors real runit-void stage 2 but runs live-setup.sh first.
|
||||
# Real runit-void/2: runsvchdir default → runsvdir /run/runit/runsvdir/current
|
||||
cat > "$INCLUDE_DIR/etc/runit/2" <<'SV_EOF'
|
||||
#!/bin/sh
|
||||
PATH=/usr/bin:/usr/sbin
|
||||
|
||||
# Live session setup: extra groups, sudo, GPU/Xorg detection
|
||||
[ -x /etc/runit/live-setup.sh ] && /etc/runit/live-setup.sh
|
||||
|
||||
# Mirror real runit-void stage 2: select runlevel from cmdline (default: default)
|
||||
runlevel=default
|
||||
for arg in $(cat /proc/cmdline); do
|
||||
if [ -d /etc/runit/runsvdir/"$arg" ]; then
|
||||
runlevel="$arg"
|
||||
fi
|
||||
done
|
||||
|
||||
[ -x /etc/rc.local ] && /etc/rc.local
|
||||
|
||||
runsvchdir "${runlevel}"
|
||||
mkdir -p /run/runit/runsvdir
|
||||
ln -sf /etc/runit/runsvdir/current /run/runit/runsvdir/current
|
||||
|
||||
exec env - PATH=$PATH \
|
||||
runsvdir -P /run/runit/runsvdir/current \
|
||||
'log: ...........................................................................................................................................................................................................................................................................................................................................................................................................'
|
||||
SV_EOF
|
||||
chmod 0755 "$INCLUDE_DIR/etc/runit/2"
|
||||
|
||||
install -d -m 0755 "$INCLUDE_DIR/etc/runit/runsvdir/default"
|
||||
|
||||
# ── 3b) LightDM autologin ───────────────────────────────────────────────
|
||||
install -d -m 0755 "$INCLUDE_DIR/etc/lightdm"
|
||||
cat > "$INCLUDE_DIR/etc/lightdm/lightdm.conf" <<EOF
|
||||
# .session file: read by the vmklive dracut hook (display-manager-autologin.sh)
|
||||
# to configure LightDM autologin session.
|
||||
echo 'cinnamon' > "$INCLUDE_DIR/etc/lightdm/.session"
|
||||
# lightdm.conf: autologin lines MUST be commented so the dracut
|
||||
# display-manager-autologin.sh hook can sed-uncomment them.
|
||||
cat > "$INCLUDE_DIR/etc/lightdm/lightdm.conf" <<'EOF'
|
||||
[Seat:*]
|
||||
autologin-user=${LIVE_USER}
|
||||
autologin-user-timeout=0
|
||||
user-session=cinnamon
|
||||
#autologin-user=
|
||||
#autologin-user-timeout=0
|
||||
#autologin-session=
|
||||
#user-session=
|
||||
session-wrapper=/etc/lightdm/Xsession
|
||||
greeter-session=lightdm-gtk-greeter
|
||||
EOF
|
||||
# NOTE: session-wrapper=/etc/lightdm/Xsession is required on Void Linux —
|
||||
# LightDM defaults to 'lightdm-session' which is NOT provided by the Void
|
||||
# lightdm package. The /etc/lightdm/Xsession wrapper is installed by the
|
||||
# lightdm package and sources /etc/profile (and therefore /etc/profile.d/)
|
||||
# so LIBGL_ALWAYS_SOFTWARE=1 placed there by live-setup.sh is propagated to
|
||||
# the cinnamon session.
|
||||
|
||||
install -d -m 0755 "$INCLUDE_DIR/etc/runit/runsvdir/default"
|
||||
# Enable NetworkManager, lightdm, pipewire and dbus for the live session.
|
||||
for svc in dbus NetworkManager lightdm; do
|
||||
# Enable services for the live session.
|
||||
for svc in dbus NetworkManager lightdm nix-daemon; do
|
||||
ln -sf "/etc/sv/$svc" "$INCLUDE_DIR/etc/runit/runsvdir/default/$svc" 2>/dev/null || true
|
||||
done
|
||||
|
||||
@@ -285,6 +429,20 @@ case ":$PATH:" in
|
||||
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.
|
||||
install -d -m 0755 "$INCLUDE_DIR/usr/local/libexec"
|
||||
{
|
||||
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 ────────
|
||||
install -d -m 0755 "$INCLUDE_DIR/etc/skel"
|
||||
cat > "$INCLUDE_DIR/etc/skel/.bash_profile" <<'EOF'
|
||||
@@ -313,6 +471,9 @@ ISO_PKGS=$(grep -vE '^\s*(#|$)' \
|
||||
| tr '\n' ' ')
|
||||
TS="$(date -u +%Y%m%d)"
|
||||
OUT_ISO="${OUTPUT_ISO:-$OUT_DIR/void-live-stable-${TS}.iso}"
|
||||
# live.user=live → vmklive dracut hook creates user 'live' (default would be 'anon')
|
||||
# console=ttyS0 → serial output for QEMU/real hardware debugging
|
||||
BOOT_CMDLINE="${BOOT_CMDLINE:-live.user=${LIVE_USER} console=tty0 console=ttyS0,115200}"
|
||||
|
||||
echo ">>> running mklive.sh inside docker — output: $OUT_ISO"
|
||||
"$DOCKER" run --rm --privileged \
|
||||
|
||||
Reference in New Issue
Block a user