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:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,6 +13,7 @@ authorized_keys
|
|||||||
|
|
||||||
# ── Generated build staging (build-iso.sh populates this at build time) ─
|
# ── Generated build staging (build-iso.sh populates this at build time) ─
|
||||||
build/includes/
|
build/includes/
|
||||||
|
build/live-includes/
|
||||||
build/first-login.sh
|
build/first-login.sh
|
||||||
|
|
||||||
# ── Build artifacts ────────────────────────────────────────────────────
|
# ── Build artifacts ────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ base-system
|
|||||||
linux
|
linux
|
||||||
linux-firmware
|
linux-firmware
|
||||||
linux-firmware-network
|
linux-firmware-network
|
||||||
intel-ucode
|
|
||||||
dracut
|
dracut
|
||||||
|
|
||||||
# --- core userspace ---
|
# --- core userspace ---
|
||||||
@@ -61,15 +60,20 @@ xorg-fonts
|
|||||||
xorg-input-drivers
|
xorg-input-drivers
|
||||||
xf86-input-libinput
|
xf86-input-libinput
|
||||||
xf86-video-intel
|
xf86-video-intel
|
||||||
|
xf86-video-fbdev
|
||||||
|
xf86-video-vesa
|
||||||
mesa-dri
|
mesa-dri
|
||||||
mesa-vulkan-intel
|
mesa-vulkan-intel
|
||||||
intel-video-accel
|
intel-video-accel
|
||||||
vulkan-loader
|
vulkan-loader
|
||||||
|
pciutils
|
||||||
|
|
||||||
# --- nvidia (PRIME offload) ---
|
# --- nvidia (PRIME offload, from nonfree repo) ---
|
||||||
|
# Installed so live-setup.sh can detect and configure PRIME at boot.
|
||||||
nvidia
|
nvidia
|
||||||
nvidia-libs-32bit
|
nvidia-libs
|
||||||
nvidia-vaapi-driver
|
nvidia-vaapi-driver
|
||||||
|
# nvidia-vaapi-driver
|
||||||
|
|
||||||
# --- desktop ---
|
# --- desktop ---
|
||||||
cinnamon
|
cinnamon
|
||||||
|
|||||||
206
docs/LIVE_ISO.md
Normal file
206
docs/LIVE_ISO.md
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
# Live ISO Build — Findings & Architecture Notes
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The live ISO boots directly into a Cinnamon desktop session as user `live` with no password prompt. It is designed for hardware testing on XPS 9700 and serves as the installer delivery vehicle.
|
||||||
|
|
||||||
|
Builder: `iso/build-live-iso.sh` (host) → Docker container running `iso/_inner-build-live.sh` → `void-mklive/mklive.sh`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Boot + Session Startup
|
||||||
|
|
||||||
|
### Kernel Cmdline
|
||||||
|
```
|
||||||
|
live.user=live console=tty0 console=ttyS0,115200
|
||||||
|
```
|
||||||
|
The `live.user=live` parameter is consumed by the vmklive dracut hook (`adduser.sh`) which creates the user inside the initramfs and sets password `voidlinux`.
|
||||||
|
|
||||||
|
### runit Stage 2 Override
|
||||||
|
We override `/etc/runit/2` to run `/etc/runit/live-setup.sh` before handing off to `runsvdir`. The script:
|
||||||
|
1. Adds extra groups (`plugdev input network docker`) to the live user
|
||||||
|
2. Writes `/etc/sudoers.d/live` (full passwordless sudo)
|
||||||
|
3. Configures `/etc/nix/nix.conf` (daemon mode, `trusted-users = root live`)
|
||||||
|
4. Auto-detects GPU and writes `/etc/X11/xorg.conf.d/20-gpu.conf`
|
||||||
|
|
||||||
|
After live-setup.sh, stage 2 mirrors the real `runit-void` exactly:
|
||||||
|
```sh
|
||||||
|
runsvchdir "${runlevel}"
|
||||||
|
ln -sf /etc/runit/runsvdir/current /run/runit/runsvdir/current
|
||||||
|
exec runsvdir -P /run/runit/runsvdir/current
|
||||||
|
```
|
||||||
|
|
||||||
|
### Services (runsvdir/default symlinks in overlay)
|
||||||
|
Enabled at build time via symlinks in `build/live-includes/etc/runit/runsvdir/default/`:
|
||||||
|
- `dbus`
|
||||||
|
- `NetworkManager`
|
||||||
|
- `lightdm`
|
||||||
|
- `nix-daemon`
|
||||||
|
|
||||||
|
> **Note:** Do NOT use mklive.sh's `-S` flag for service enable — it is not supported by the version used. Services must be wired via runsvdir symlinks in the include overlay.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## LightDM Autologin
|
||||||
|
|
||||||
|
### Critical: `lightdm-session` does not exist on Void Linux
|
||||||
|
The Void `lightdm` 1.32 package does **not** ship the `lightdm-session` binary. The default LightDM behaviour of spawning `lightdm-session` causes the session to crash immediately (exit code 1 in ~20ms) with no error message.
|
||||||
|
|
||||||
|
**Fix:** Set `session-wrapper=/etc/lightdm/Xsession` in `lightdm.conf`. The `/etc/lightdm/Xsession` wrapper **is** provided by the Void lightdm package and correctly sources `/etc/profile` → `/etc/profile.d/`.
|
||||||
|
|
||||||
|
### `greeter-env=` and `session-env=` are not supported
|
||||||
|
These options are silently ignored in LightDM 1.32 on Void. To propagate environment variables to the session use `/etc/profile.d/` scripts instead.
|
||||||
|
|
||||||
|
### lightdm.conf autologin lines must be commented
|
||||||
|
The vmklive dracut hook `display-manager-autologin.sh` uses `sed` to uncomment lines. The autologin lines in `lightdm.conf` must be present but commented out — the hook finds them by regex and uncomments them at boot.
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Seat:*]
|
||||||
|
#autologin-user=
|
||||||
|
#autologin-user-timeout=0
|
||||||
|
#autologin-session=
|
||||||
|
#user-session=
|
||||||
|
session-wrapper=/etc/lightdm/Xsession
|
||||||
|
greeter-session=lightdm-gtk-greeter
|
||||||
|
```
|
||||||
|
|
||||||
|
The `/etc/lightdm/.session` file (content: `cinnamon`) is read by the hook to set the session name.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## GPU Auto-Detection
|
||||||
|
|
||||||
|
`live-setup.sh` runs `lspci` at boot and writes `/etc/X11/xorg.conf.d/20-gpu.conf`:
|
||||||
|
|
||||||
|
| Detected | Xorg Config | Extra |
|
||||||
|
|----------|-------------|-------|
|
||||||
|
| Virtual (virtio/VMware/QEMU/VirtualBox) | `modesetting`, `AccelMethod none` | `LIBGL_ALWAYS_SOFTWARE=1` in `/etc/profile.d/live-env.sh` |
|
||||||
|
| NVIDIA + proprietary driver (`nvidia_drv.so`) | PRIME offload: Intel `modesetting` + NVIDIA `nvidia` | No software GL |
|
||||||
|
| NVIDIA without proprietary driver | `modesetting` | — |
|
||||||
|
| Intel / AMD / other | `modesetting` | — |
|
||||||
|
|
||||||
|
`LIBGL_ALWAYS_SOFTWARE=1` is set via `/etc/profile.d/live-env.sh`, not via `session-env=` (unsupported).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Nix Integration
|
||||||
|
|
||||||
|
### Daemon mode (not single-user)
|
||||||
|
The Void `nix` xbps package ships `nix-daemon` with a runit service at `/etc/sv/nix-daemon`. The daemon puts its socket at:
|
||||||
|
```
|
||||||
|
/var/nix/daemon-socket/socket
|
||||||
|
```
|
||||||
|
|
||||||
|
We use daemon mode (not single-user) because `/nix/store` stays root-owned. The live user is granted trust via `nix.conf`:
|
||||||
|
```
|
||||||
|
experimental-features = nix-command flakes
|
||||||
|
sandbox = false
|
||||||
|
auto-optimise-store = true
|
||||||
|
trusted-users = root live
|
||||||
|
```
|
||||||
|
|
||||||
|
`sandbox = false` is required because the live system has no `nixbld` users and no user namespaces in the dracut initramfs environment.
|
||||||
|
|
||||||
|
### Package list
|
||||||
|
`/usr/local/libexec/nix-packages.list` is written at ISO build time from `NIX_USER_PACKAGES` in `config/install.conf`. At first login, `first-login.sh` reads this file and runs `nix profile install --impure` with `NIXPKGS_ALLOW_UNFREE=1`.
|
||||||
|
|
||||||
|
Current packages:
|
||||||
|
- `nixpkgs#google-chrome`
|
||||||
|
- `nixpkgs#spotify`
|
||||||
|
- `nixpkgs#discord`
|
||||||
|
- `nixpkgs#localsend`
|
||||||
|
- `nixpkgs#mission-center`
|
||||||
|
|
||||||
|
### postinstall.sh socket path (installed system)
|
||||||
|
In the **installed system** (not live), `installer/lib/postinstall.sh` polls for the nix-daemon socket. The correct path is:
|
||||||
|
```
|
||||||
|
/var/nix/daemon-socket/socket
|
||||||
|
```
|
||||||
|
Not `/nix/var/nix/daemon-socket/socket` (upstream Nix default) — Void's package uses `/var/nix/`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## dconf / Theme
|
||||||
|
|
||||||
|
The Gruvbox-Dark GTK theme and Cinnamon dconf settings are pre-applied via a system-db. The dconf binary database must be compiled at **ISO build time**, not at runtime.
|
||||||
|
|
||||||
|
### Build-time compilation
|
||||||
|
`iso/_inner-build-live.sh` runs inside the Debian Docker container. The Dockerfile installs `dconf-cli` for this step. The correct Debian `dconf-cli` API is:
|
||||||
|
```sh
|
||||||
|
dconf compile <output_binary_db> <input_keyfile_dir>
|
||||||
|
# e.g.:
|
||||||
|
dconf compile build/live-includes/etc/dconf/db/local \
|
||||||
|
build/live-includes/etc/dconf/db/local.d
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** `dconf update <path>` does not work in Debian's `dconf-cli` — it only updates the user's own db. `dconf compile` is the correct tool for building a system-db binary.
|
||||||
|
|
||||||
|
### dconf profile
|
||||||
|
`/etc/dconf/profile/user` must point to the system-db:
|
||||||
|
```
|
||||||
|
user-db:user
|
||||||
|
system-db:local
|
||||||
|
```
|
||||||
|
Without this file, the compiled system-db is ignored and Cinnamon shows a black wallpaper with default GTK theme.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## First-Login Setup (`installer/first-login.sh`)
|
||||||
|
|
||||||
|
Runs once via XDG autostart (`~/.config/autostart/void-live-first-login.desktop`) when Cinnamon first loads. Installs:
|
||||||
|
|
||||||
|
1. **Claude Code** — official installer from `https://claude.ai/install.sh`
|
||||||
|
2. **Nix user packages** — from `/usr/local/libexec/nix-packages.list`
|
||||||
|
3. **NVM + Node LTS**
|
||||||
|
4. **VS Code extensions** — from `/etc/installer-vscode-extensions.txt`
|
||||||
|
|
||||||
|
Idempotent: creates `~/.first-login-done` on success. Logs to `~/.first-login.log`.
|
||||||
|
|
||||||
|
The script does NOT use `set -u` because `nvm.sh` references unbound variables.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Build Pipeline
|
||||||
|
|
||||||
|
```
|
||||||
|
iso/build-live-iso.sh (host — stages overlay, builds Docker image if needed)
|
||||||
|
└─ Docker: void-installer-builder:latest
|
||||||
|
└─ iso/_inner-build-live.sh
|
||||||
|
├─ dconf compile (pre-bakes system-db)
|
||||||
|
└─ void-mklive/mklive.sh -a x86_64 -r <repo> -I <include_dir> ...
|
||||||
|
└─ squashfs + GRUB + ISO 9660
|
||||||
|
```
|
||||||
|
|
||||||
|
Output: `out/void-live-stable.iso` (~2.9 GB)
|
||||||
|
|
||||||
|
### Build artifacts that must NOT be committed
|
||||||
|
- `build/live-includes/` — generated staging tree (hundreds of binary assets)
|
||||||
|
- `out/` — ISO output
|
||||||
|
- `cache/` — cloned void-mklive, xbps package cache
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## QEMU Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp /usr/share/OVMF/OVMF_VARS.fd out/OVMF_VARS.live.fd
|
||||||
|
qemu-system-x86_64 -name void-live-test -machine q35,accel=kvm:tcg -cpu max \
|
||||||
|
-m 4096 -smp 4 \
|
||||||
|
-drive "if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE.fd" \
|
||||||
|
-drive "if=pflash,format=raw,file=out/OVMF_VARS.live.fd" \
|
||||||
|
-cdrom out/void-live-stable.iso -boot order=d,menu=off \
|
||||||
|
-netdev user,id=n0 -device virtio-net-pci,netdev=n0 \
|
||||||
|
-serial "unix:out/live-serial.sock,server,nowait" \
|
||||||
|
-monitor "unix:out/qemu-monitor.sock,server,nowait" \
|
||||||
|
-device virtio-vga -display gtk,gl=off &
|
||||||
|
```
|
||||||
|
|
||||||
|
Serial console access (root shell for diagnostics):
|
||||||
|
```python
|
||||||
|
import socket, time
|
||||||
|
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
|
s.connect('out/live-serial.sock')
|
||||||
|
# send commands, read output
|
||||||
|
```
|
||||||
|
|
||||||
|
GPU in QEMU: `virtio-vga` is detected as virtual → `modesetting + LIBGL_ALWAYS_SOFTWARE=1`.
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# First-login one-shot setup for the user.
|
# First-login one-shot setup for the user.
|
||||||
# Installs Claude Code (official) + NVM + node LTS + vscode extensions.
|
# Installs: Claude Code, NVM + node LTS, VS Code extensions,
|
||||||
|
# and (if NIX_PACKAGES_FILE is present) nix user packages
|
||||||
|
# (google-chrome, spotify, discord, localsend, mission-center).
|
||||||
# Idempotent: creates ~/.first-login-done marker on success.
|
# Idempotent: creates ~/.first-login-done marker on success.
|
||||||
|
|
||||||
# NOTE: do NOT use `set -u` here — nvm.sh references unbound vars.
|
# NOTE: do NOT use `set -u` here — nvm.sh references unbound vars.
|
||||||
@@ -19,8 +21,7 @@ if ! getent hosts github.com >/dev/null 2>&1; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --- Claude Code (official native installer) — runs FIRST so failures in
|
# --- Claude Code (official native installer) ---
|
||||||
# downstream NVM/node/etc. don't block claude installation. ---
|
|
||||||
mkdir -p "$HOME/.local/bin"
|
mkdir -p "$HOME/.local/bin"
|
||||||
export PATH="$HOME/.local/bin:$PATH"
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
if ! command -v claude >/dev/null 2>&1 && [[ ! -x "$HOME/.local/bin/claude" ]]; then
|
if ! command -v claude >/dev/null 2>&1 && [[ ! -x "$HOME/.local/bin/claude" ]]; then
|
||||||
@@ -29,6 +30,39 @@ if ! command -v claude >/dev/null 2>&1 && [[ ! -x "$HOME/.local/bin/claude" ]];
|
|||||||
echo "!! claude install failed"; }
|
echo "!! claude install failed"; }
|
||||||
fi
|
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.
|
||||||
|
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"
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Initialise per-user nix profile if needed.
|
||||||
|
if [[ ! -d "$HOME/.nix-profile" ]]; then
|
||||||
|
nix-env --switch-profile "$HOME/.nix-profile" 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
|
||||||
|
|
||||||
|
mapfile -t pkgs < <(grep -vE '^\s*(#|$)' "$NIX_PACKAGES_FILE")
|
||||||
|
if [[ ${#pkgs[@]} -gt 0 ]]; then
|
||||||
|
echo " packages: ${pkgs[*]}"
|
||||||
|
nix profile install --impure "${pkgs[@]}" 2>&1 || {
|
||||||
|
echo "!! nix profile install failed (partial install may have succeeded)"; }
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# --- NVM (best effort; nvm.sh has unbound vars so isolate it) ---
|
# --- NVM (best effort; nvm.sh has unbound vars so isolate it) ---
|
||||||
if [[ ! -s "$HOME/.nvm/nvm.sh" ]]; then
|
if [[ ! -s "$HOME/.nvm/nvm.sh" ]]; then
|
||||||
echo "==> installing NVM"
|
echo "==> installing NVM"
|
||||||
@@ -39,7 +73,6 @@ fi
|
|||||||
|
|
||||||
if [[ -s "$HOME/.nvm/nvm.sh" ]]; then
|
if [[ -s "$HOME/.nvm/nvm.sh" ]]; then
|
||||||
export NVM_DIR="$HOME/.nvm"
|
export NVM_DIR="$HOME/.nvm"
|
||||||
# nvm.sh trips `set -u` on STABLE/PROVIDED_VERSION; isolate in subshell.
|
|
||||||
(
|
(
|
||||||
set +u
|
set +u
|
||||||
# shellcheck disable=SC1091
|
# shellcheck disable=SC1091
|
||||||
@@ -51,8 +84,6 @@ if [[ -s "$HOME/.nvm/nvm.sh" ]]; then
|
|||||||
nvm use --lts >/dev/null 2>&1 || true
|
nvm use --lts >/dev/null 2>&1 || true
|
||||||
) || true
|
) || true
|
||||||
|
|
||||||
# Symlink the resulting node/npm into ~/.local/bin so they're on PATH
|
|
||||||
# for non-nvm shells.
|
|
||||||
NODE_BIN_DIR="$(ls -d "$HOME"/.nvm/versions/node/v*/bin 2>/dev/null | sort -V | tail -1)"
|
NODE_BIN_DIR="$(ls -d "$HOME"/.nvm/versions/node/v*/bin 2>/dev/null | sort -V | tail -1)"
|
||||||
if [[ -n "$NODE_BIN_DIR" && -d "$NODE_BIN_DIR" ]]; then
|
if [[ -n "$NODE_BIN_DIR" && -d "$NODE_BIN_DIR" ]]; then
|
||||||
for bin in node npm npx; do
|
for bin in node npm npx; do
|
||||||
|
|||||||
@@ -206,14 +206,13 @@ mark=/var/lib/first-boot-nix.done
|
|||||||
[[ -f "\$mark" ]] && exit 0
|
[[ -f "\$mark" ]] && exit 0
|
||||||
|
|
||||||
# Wait for nix-daemon to be available.
|
# Wait for nix-daemon to be available.
|
||||||
# The Void package puts the socket at /var/nix/daemon-socket/nix-daemon.sock
|
# The Void xbps nix package puts the socket at /var/nix/daemon-socket/socket.
|
||||||
# (NOT /nix/var/nix/...).
|
for _ in \$(seq 1 60); do
|
||||||
for _ in \$(seq 1 30); do
|
[[ -S /var/nix/daemon-socket/socket ]] && break
|
||||||
[[ -S /var/nix/daemon-socket/nix-daemon.sock ]] && break
|
sleep 2
|
||||||
sleep 1
|
|
||||||
done
|
done
|
||||||
|
|
||||||
if [[ ! -S /var/nix/daemon-socket/nix-daemon.sock ]]; then
|
if [[ ! -S /var/nix/daemon-socket/socket ]]; then
|
||||||
echo "nix-daemon not available; aborting first-boot nix install" >&2
|
echo "nix-daemon not available; aborting first-boot nix install" >&2
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ ENV DEBIAN_FRONTEND=noninteractive
|
|||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
bash git curl ca-certificates xz-utils tar patch python3 \
|
bash git curl ca-certificates xz-utils tar patch python3 \
|
||||||
mtools xorriso squashfs-tools dosfstools e2fsprogs \
|
mtools xorriso squashfs-tools dosfstools e2fsprogs \
|
||||||
kmod \
|
kmod dconf-cli \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# xbps-static is downloaded into /cache by the host script and added to PATH
|
# xbps-static is downloaded into /cache by the host script and added to PATH
|
||||||
|
|||||||
@@ -28,10 +28,12 @@ command -v xbps-install.static >/dev/null \
|
|||||||
mkdir -p "$(dirname "$OUT_ISO")"
|
mkdir -p "$(dirname "$OUT_ISO")"
|
||||||
|
|
||||||
# Compile dconf system-db inside the include dir so it ships compiled.
|
# Compile dconf system-db inside the include dir so it ships compiled.
|
||||||
|
# Debian's dconf-cli provides 'dconf compile <output_db> <keyfile_dir>'.
|
||||||
if command -v dconf >/dev/null 2>&1 && [[ -d "$INCLUDE_DIR/etc/dconf/db/local.d" ]]; then
|
if command -v dconf >/dev/null 2>&1 && [[ -d "$INCLUDE_DIR/etc/dconf/db/local.d" ]]; then
|
||||||
DCONF_PROFILE_PATH="$INCLUDE_DIR/etc/dconf/profile" \
|
dconf compile "$INCLUDE_DIR/etc/dconf/db/local" \
|
||||||
DCONF_SYSTEM_DB_PATH="$INCLUDE_DIR/etc/dconf/db" \
|
"$INCLUDE_DIR/etc/dconf/db/local.d" 2>/dev/null \
|
||||||
dconf update "$INCLUDE_DIR/etc/dconf/db" 2>/dev/null || true
|
&& echo "dconf: compiled system-db/local" \
|
||||||
|
|| echo "dconf: compile failed (non-fatal)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "$MKLIVE_DIR"
|
cd "$MKLIVE_DIR"
|
||||||
@@ -52,6 +54,7 @@ trap _cleanup_mklive_builds EXIT
|
|||||||
./mklive.sh \
|
./mklive.sh \
|
||||||
-a "$ARCH" \
|
-a "$ARCH" \
|
||||||
-r "$REPO_URL" \
|
-r "$REPO_URL" \
|
||||||
|
-r "${REPO_URL%/current}/current/nonfree" \
|
||||||
-c "$CACHE_DIR/xbps-live-pkgs" \
|
-c "$CACHE_DIR/xbps-live-pkgs" \
|
||||||
-H "$CACHE_DIR/xbps-host-pkgs" \
|
-H "$CACHE_DIR/xbps-host-pkgs" \
|
||||||
-k "$KEYMAP" \
|
-k "$KEYMAP" \
|
||||||
|
|||||||
@@ -70,57 +70,201 @@ rm -rf "$INCLUDE_DIR"
|
|||||||
mkdir -p "$INCLUDE_DIR"
|
mkdir -p "$INCLUDE_DIR"
|
||||||
|
|
||||||
# ── 3a) live user account ───────────────────────────────────────────────
|
# ── 3a) live user account ───────────────────────────────────────────────
|
||||||
# Create user 'live' with no password in the live image.
|
# The vmklive dracut hook (adduser.sh) creates the live user in initramfs
|
||||||
# mklive populates /etc/passwd at install time — we drop a post-install hook
|
# using the live.user= kernel cmdline parameter (added to BOOT_CMDLINE below).
|
||||||
# via the live init that calls useradd. We use an install.conf.d override
|
# We add extra groups and sudo via /etc/runit/2 override (after pivot_root).
|
||||||
# that mklive will source, plus an rc.local-style runit oneshot.
|
|
||||||
install -d -m 0755 "$INCLUDE_DIR/etc"
|
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.
|
# GPU detection + extra group setup — runs from our runit/2 override below.
|
||||||
install -d -m 0755 "$INCLUDE_DIR/etc/runit/runsvdir/default"
|
install -d -m 0755 "$INCLUDE_DIR/etc/runit"
|
||||||
install -d -m 0755 "$INCLUDE_DIR/etc/sv/live-user-setup"
|
cat > "$INCLUDE_DIR/etc/runit/live-setup.sh" <<'SV_EOF'
|
||||||
cat > "$INCLUDE_DIR/etc/sv/live-user-setup/run" <<'SV_EOF'
|
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Create the 'live' user (no password) and set up home directory.
|
# Runs from /etc/runit/2 before any service starts.
|
||||||
# Runs once; removes itself from default runsvdir on completion.
|
# 1. Ensures live user has all needed groups.
|
||||||
set -e
|
# 2. Generates /etc/X11/xorg.conf.d/20-gpu.conf based on detected hardware.
|
||||||
if ! id live >/dev/null 2>&1; then
|
|
||||||
useradd -m -s /bin/bash -G wheel,audio,video,plugdev,input,network,docker live
|
LIVE_USER="${USERNAME:-live}"
|
||||||
passwd -d live
|
[ -f /etc/default/live.conf ] && . /etc/default/live.conf
|
||||||
install -d -m 0700 /home/live/.ssh
|
LIVE_USER="${USERNAME:-live}"
|
||||||
# Apply skel dotfiles
|
|
||||||
if [ -d /etc/skel ]; then
|
# Extra groups (dracut only adds audio,video,wheel)
|
||||||
cp -a /etc/skel/. /home/live/ 2>/dev/null || true
|
for g in plugdev input network docker; do
|
||||||
fi
|
groupadd -f "$g" 2>/dev/null || true
|
||||||
chown -R live:live /home/live
|
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
|
fi
|
||||||
# Enable sudoers entry for live
|
NIXSH
|
||||||
if ! grep -q '^live ' /etc/sudoers 2>/dev/null; then
|
chmod 0644 /etc/profile.d/nix-live.sh
|
||||||
echo 'live ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers
|
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
|
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
|
SV_EOF
|
||||||
chmod 0755 "$INCLUDE_DIR/etc/sv/live-user-setup/run"
|
chmod 0755 "$INCLUDE_DIR/etc/runit/live-setup.sh"
|
||||||
ln -sf /etc/sv/live-user-setup "$INCLUDE_DIR/etc/runit/runsvdir/default/live-user-setup"
|
|
||||||
|
# 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 ───────────────────────────────────────────────
|
# ── 3b) LightDM autologin ───────────────────────────────────────────────
|
||||||
install -d -m 0755 "$INCLUDE_DIR/etc/lightdm"
|
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:*]
|
[Seat:*]
|
||||||
autologin-user=${LIVE_USER}
|
#autologin-user=
|
||||||
autologin-user-timeout=0
|
#autologin-user-timeout=0
|
||||||
user-session=cinnamon
|
#autologin-session=
|
||||||
|
#user-session=
|
||||||
|
session-wrapper=/etc/lightdm/Xsession
|
||||||
greeter-session=lightdm-gtk-greeter
|
greeter-session=lightdm-gtk-greeter
|
||||||
EOF
|
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"
|
install -d -m 0755 "$INCLUDE_DIR/etc/runit/runsvdir/default"
|
||||||
# Enable NetworkManager, lightdm, pipewire and dbus for the live session.
|
# Enable services for the live session.
|
||||||
for svc in dbus NetworkManager lightdm; do
|
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
|
ln -sf "/etc/sv/$svc" "$INCLUDE_DIR/etc/runit/runsvdir/default/$svc" 2>/dev/null || true
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -285,6 +429,20 @@ case ":$PATH:" in
|
|||||||
esac
|
esac
|
||||||
EOF
|
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 ────────
|
# ── 3g) Live-session skel: pre-wire .bash_profile for first-login ────────
|
||||||
install -d -m 0755 "$INCLUDE_DIR/etc/skel"
|
install -d -m 0755 "$INCLUDE_DIR/etc/skel"
|
||||||
cat > "$INCLUDE_DIR/etc/skel/.bash_profile" <<'EOF'
|
cat > "$INCLUDE_DIR/etc/skel/.bash_profile" <<'EOF'
|
||||||
@@ -313,6 +471,9 @@ ISO_PKGS=$(grep -vE '^\s*(#|$)' \
|
|||||||
| tr '\n' ' ')
|
| tr '\n' ' ')
|
||||||
TS="$(date -u +%Y%m%d)"
|
TS="$(date -u +%Y%m%d)"
|
||||||
OUT_ISO="${OUTPUT_ISO:-$OUT_DIR/void-live-stable-${TS}.iso}"
|
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"
|
echo ">>> running mklive.sh inside docker — output: $OUT_ISO"
|
||||||
"$DOCKER" run --rm --privileged \
|
"$DOCKER" run --rm --privileged \
|
||||||
|
|||||||
Reference in New Issue
Block a user