Fix nix single-user mode for live ISO and installer

- Store ownership: chown -R 1000:1000 at Docker build time (not runtime)
  so the live user can create lock files without flooding the tmpfs overlay
- nix.conf: add build-users-group= to force single-user mode and avoid
  daemon connection attempts (xbps nix-daemon v2.30.2 incompatible with
  pre-baked nix v2.34.6)
- profile.d: export NIX_REMOTE=local and NIXPKGS_ALLOW_UNFREE=1; wrap nix()
  to append --impure so flake installs work without extra flags
- Skel: add ~/.config/nixpkgs/config.nix with allowUnfree=true
- postinstall.sh: fix daemon socket path (/nix/var/nix/...), write
  ~/.config/nixpkgs/config.nix for installed user
- first-login.sh: add NIX_REMOTE=local alongside NIXPKGS_ALLOW_UNFREE=1
- Remove nix-daemon from live ISO services (wrong version for pre-baked client)
- Misc: bluetooth group, package list reorg, skip vscode install for niri profile

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
moze
2026-04-25 12:56:13 +00:00
parent 6d65f28844
commit 49d94bd2ac
11 changed files with 109 additions and 31 deletions

View File

@@ -7,7 +7,7 @@ HOSTNAME="xps9700"
USERNAME="moze" USERNAME="moze"
USER_FULLNAME="moze" USER_FULLNAME="moze"
USER_UID="1000" USER_UID="1000"
USER_GROUPS="wheel,docker,video,audio,input,plugdev,network,kvm,users" USER_GROUPS="wheel,docker,video,audio,input,plugdev,network,kvm,users,bluetooth"
DEFAULT_SHELL="/bin/bash" DEFAULT_SHELL="/bin/bash"
# ---------- Locale ---------- # ---------- Locale ----------

View File

@@ -47,10 +47,8 @@ prefer-no-csd
spawn-at-startup "swaybg" "-i" "/usr/share/backgrounds/void-installer/pxfuel.jpg" spawn-at-startup "swaybg" "-i" "/usr/share/backgrounds/void-installer/pxfuel.jpg"
spawn-at-startup "mako" spawn-at-startup "mako"
spawn-at-startup "nm-applet" "--indicator"
spawn-at-startup "blueman-applet"
spawn-at-startup "/usr/libexec/polkit-gnome-authentication-agent-1" spawn-at-startup "/usr/libexec/polkit-gnome-authentication-agent-1"
spawn-at-startup "noctalia-shell" spawn-at-startup "sh" "-c" "i=0; while [ \$i -lt 30 ] && ! dbus-send --system --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.GetNameOwner string:org.bluez >/dev/null 2>&1; do sleep 1; i=\$((i+1)); done; exec noctalia-shell"
cursor { cursor {
xcursor-theme "Bibata-Modern-Ice" xcursor-theme "Bibata-Modern-Ice"

View File

@@ -110,10 +110,12 @@ gvfs-smb
file-roller file-roller
gnome-keyring gnome-keyring
seahorse seahorse
network-manager-applet
blueman blueman
bluez bluez
# --- bluetooth audio ---
bluez-alsa
# --- display manager --- # --- display manager ---
# niri can be launched directly via TTY (`niri-session`) or via a wayland-aware # niri can be launched directly via TTY (`niri-session`) or via a wayland-aware
# greeter. We use greetd + tuigreet — lighter than lightdm under wayland. # greeter. We use greetd + tuigreet — lighter than lightdm under wayland.
@@ -170,9 +172,6 @@ system-config-printer
sane sane
simple-scan simple-scan
# --- bluetooth audio ---
bluez-alsa
# --- backups / snapshots --- # --- backups / snapshots ---
timeshift timeshift
grub-btrfs grub-btrfs

View File

@@ -89,8 +89,8 @@ brightnessctl
ImageMagick ImageMagick
python3 python3
upower upower
power-profiles-daemon
wl-clipboard wl-clipboard
network-manager-applet
# --- XDG portals --- # --- XDG portals ---
xdg-desktop-portal xdg-desktop-portal
@@ -98,7 +98,7 @@ xdg-desktop-portal-gnome
xdg-utils xdg-utils
xdg-user-dirs xdg-user-dirs
# --- nix (for prebaked packages — spotify, discord, vscode, fastfetch, etc.) --- # --- nix (for prebaked packages — spotify, discord, google-chrome, vscode, fastfetch, etc.) ---
nix nix
# --- noctalia-shell (from noctalia third-party XBPS repo) --- # --- noctalia-shell (from noctalia third-party XBPS repo) ---

View File

@@ -2,7 +2,7 @@
# First-login one-shot setup for the user. # First-login one-shot setup for the user.
# Installs: Claude Code, NVM + node LTS, VS Code extensions, # Installs: Claude Code, NVM + node LTS, VS Code extensions,
# and (if NIX_PACKAGES_FILE is present) nix user packages # and (if NIX_PACKAGES_FILE is present) nix user packages
# (google-chrome, spotify, discord, localsend, mission-center). # (google-chrome, spotify, discord, localsend, mission-center, vscode).
# 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.
@@ -23,16 +23,17 @@ if ! curl -fsSL --max-time 3 --connect-timeout 3 -o /dev/null https://api.github
exit 0 exit 0
fi fi
# --- Claude Code (official native installer) ---
mkdir -p "$HOME/.local/bin" mkdir -p "$HOME/.local/bin"
export PATH="$HOME/.local/bin:$PATH" export PATH="$HOME/.local/bin:$PATH"
# --- Claude Code (official native installer) ---
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
echo "==> installing Claude Code via official installer" echo "==> installing Claude Code via official installer"
curl -fsSL https://claude.ai/install.sh | bash || { curl -fsSL https://claude.ai/install.sh | bash || {
echo "!! claude install failed"; } echo "!! claude install failed"; }
fi fi
# --- Nix user packages (google-chrome, spotify, discord, etc.) --- # --- Nix user packages (google-chrome, spotify, discord, vscode, etc.) ---
# Present when running from the live ISO (written by build-live-iso.sh). # 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. # In the installed system the packages come from first-boot-nix.sh instead.
# NOTE: nix packages are intentionally skipped in the live session — they # NOTE: nix packages are intentionally skipped in the live session — they
@@ -72,6 +73,7 @@ if [[ -r "$NIX_PACKAGES_FILE" ]] && command -v nix >/dev/null 2>&1; then
fi fi
export NIXPKGS_ALLOW_UNFREE=1 export NIXPKGS_ALLOW_UNFREE=1
export NIX_REMOTE=local
mapfile -t pkgs < <(grep -vE '^\s*(#|$)' "$NIX_PACKAGES_FILE") mapfile -t pkgs < <(grep -vE '^\s*(#|$)' "$NIX_PACKAGES_FILE")
if [[ ${#pkgs[@]} -gt 0 ]]; then if [[ ${#pkgs[@]} -gt 0 ]]; then

View File

@@ -98,7 +98,7 @@ main() {
configure_nvidia_prime configure_nvidia_prime
configure_zram configure_zram
configure_nix configure_nix
install_vscode_real [[ "${DESKTOP:-cinnamon}" != "niri" ]] && install_vscode_real
install_customizations install_customizations
enable_services enable_services
install_grub install_grub

View File

@@ -206,13 +206,12 @@ 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 xbps nix package puts the socket at /var/nix/daemon-socket/socket.
for _ in \$(seq 1 60); do for _ in \$(seq 1 60); do
[[ -S /var/nix/daemon-socket/socket ]] && break [[ -S /nix/var/nix/daemon-socket/socket ]] && break
sleep 2 sleep 2
done done
if [[ ! -S /var/nix/daemon-socket/socket ]]; then if [[ ! -S /nix/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
@@ -230,6 +229,12 @@ touch "\$mark"
EOF EOF
chmod 0755 "$TARGET/usr/local/libexec/first-boot-nix.sh" chmod 0755 "$TARGET/usr/local/libexec/first-boot-nix.sh"
# Persistent nixpkgs config so the installed user can install unfree packages
# without needing to export NIXPKGS_ALLOW_UNFREE=1 every time.
install -d -m 0755 "$TARGET/home/$USERNAME/.config/nixpkgs"
echo '{ allowUnfree = true; }' > "$TARGET/home/$USERNAME/.config/nixpkgs/config.nix"
run_chroot "chown -R $USERNAME:$USERNAME /home/$USERNAME/.config/nixpkgs"
# runit one-shot service. # runit one-shot service.
install -d -m 0755 "$TARGET/etc/sv/first-boot-nix" install -d -m 0755 "$TARGET/etc/sv/first-boot-nix"
cat > "$TARGET/etc/sv/first-boot-nix/run" <<'EOF' cat > "$TARGET/etc/sv/first-boot-nix/run" <<'EOF'
@@ -312,10 +317,8 @@ enable_services() {
local enabled=( local enabled=(
dbus dbus
NetworkManager NetworkManager
lightdm
polkitd polkitd
docker docker
bluetoothd
acpid acpid
tlp tlp
elogind elogind
@@ -326,6 +329,14 @@ enable_services() {
cupsd cupsd
cups-browsed cups-browsed
) )
# Display manager: greetd for wayland/niri, lightdm for cinnamon.
if [[ "${DESKTOP:-cinnamon}" == "niri" ]]; then
enabled+=(greetd bluetoothd)
else
enabled+=(lightdm bluetoothd)
fi
[[ "${SSHD_ENABLE:-no}" == "yes" ]] && enabled+=(sshd) [[ "${SSHD_ENABLE:-no}" == "yes" ]] && enabled+=(sshd)
for svc in "${enabled[@]}"; do for svc in "${enabled[@]}"; do

View File

@@ -112,6 +112,8 @@ if [[ -n "${NIX_PACKAGES_PREBAKE:-}" ]]; then
echo " staging /nix into overlay ($(du -sh /nix/store 2>/dev/null | cut -f1))" echo " staging /nix into overlay ($(du -sh /nix/store 2>/dev/null | cut -f1))"
mkdir -p "$INCLUDE_DIR/nix" mkdir -p "$INCLUDE_DIR/nix"
rsync -a /nix/ "$INCLUDE_DIR/nix/" 2>&1 | tail -1 rsync -a /nix/ "$INCLUDE_DIR/nix/" 2>&1 | tail -1
# Single-user nix: the live user (uid 1000) must own the store to create lock files and new paths.
chown -R 1000:1000 "$INCLUDE_DIR/nix"
# /etc/skel/.nix-profile → the pre-baked store profile path. # /etc/skel/.nix-profile → the pre-baked store profile path.
# dracut's adduser.sh runs 'useradd -m' which copies skel → /home/live, # dracut's adduser.sh runs 'useradd -m' which copies skel → /home/live,

View File

@@ -73,6 +73,8 @@ if [[ -n "${NIX_PACKAGES_PREBAKE:-}" ]]; then
echo " staging /nix into overlay ($(du -sh /nix/store 2>/dev/null | cut -f1))" echo " staging /nix into overlay ($(du -sh /nix/store 2>/dev/null | cut -f1))"
mkdir -p "$INCLUDE_DIR/nix" mkdir -p "$INCLUDE_DIR/nix"
rsync -a /nix/ "$INCLUDE_DIR/nix/" 2>&1 | tail -1 rsync -a /nix/ "$INCLUDE_DIR/nix/" 2>&1 | tail -1
# Single-user nix: the live user (uid 1000) must own the store to create lock files and new paths.
chown -R 1000:1000 "$INCLUDE_DIR/nix"
_STORE_PROFILE=$(cat "$_NIX_CACHE/.profile-path" 2>/dev/null \ _STORE_PROFILE=$(cat "$_NIX_CACHE/.profile-path" 2>/dev/null \
|| readlink -f /root/.nix-profile 2>/dev/null || echo "") || readlink -f /root/.nix-profile 2>/dev/null || echo "")
@@ -113,9 +115,10 @@ for ua in ("curl/8.0", "xbps/0.59.2", "Mozilla/5.0 (X11; Linux x86_64)"):
data = urllib.request.urlopen(req, timeout=15).read() data = urllib.request.urlopen(req, timeout=15).read()
tf = tarfile.open(fileobj=io.BytesIO(data)) tf = tarfile.open(fileobj=io.BytesIO(data))
idx = plistlib.loads(tf.extractfile("index.plist").read()) idx = plistlib.loads(tf.extractfile("index.plist").read())
for pkgver, meta in idx.items(): # index.plist keys are package names; pkgver field holds the versioned name
if isinstance(meta, dict) and meta.get("pkgname") in want: for pkgname, meta in idx.items():
found[meta["pkgname"]] = pkgver if isinstance(meta, dict) and pkgname in want:
found[pkgname] = meta.get("pkgver", pkgname)
if len(found) >= len(want): if len(found) >= len(want):
break break
except Exception: except Exception:

View File

@@ -90,7 +90,7 @@ LIVE_USER="${USERNAME:-live}"
LIVE_USER="${USERNAME:-live}" LIVE_USER="${USERNAME:-live}"
# Extra groups (dracut only adds audio,video,wheel) # Extra groups (dracut only adds audio,video,wheel)
for g in plugdev input network docker; do for g in plugdev input network docker bluetooth; do
groupadd -f "$g" 2>/dev/null || true groupadd -f "$g" 2>/dev/null || true
usermod -aG "$g" "$LIVE_USER" 2>/dev/null || true usermod -aG "$g" "$LIVE_USER" 2>/dev/null || true
done done
@@ -107,6 +107,7 @@ if [ -x /usr/bin/nix ]; then
install -d -m 0755 /etc/nix install -d -m 0755 /etc/nix
cat > /etc/nix/nix.conf <<NIXCONF cat > /etc/nix/nix.conf <<NIXCONF
experimental-features = nix-command flakes experimental-features = nix-command flakes
build-users-group =
sandbox = false sandbox = false
auto-optimise-store = true auto-optimise-store = true
trusted-users = root $LIVE_USER trusted-users = root $LIVE_USER
@@ -288,7 +289,7 @@ EOF
install -d -m 0755 "$INCLUDE_DIR/etc/runit/runsvdir/default" install -d -m 0755 "$INCLUDE_DIR/etc/runit/runsvdir/default"
# Enable services for the live session. # Enable services for the live session.
for svc in dbus NetworkManager lightdm nix-daemon; do for svc in dbus NetworkManager lightdm bluetoothd; 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
@@ -570,6 +571,13 @@ if [[ -d "${HOME:-}/.nix-profile/bin" ]]; then
*) export PATH="$HOME/.nix-profile/bin:$PATH" ;; *) export PATH="$HOME/.nix-profile/bin:$PATH" ;;
esac esac
fi fi
export NIXPKGS_ALLOW_UNFREE=1
# Pre-baked nix is single-user (no daemon) — bypass daemon connection attempt
export NIX_REMOTE=local
# Flake commands ignore NIXPKGS_ALLOW_UNFREE unless --impure is passed.
# Wrap nix so interactive installs work without extra flags.
nix() { command nix "$@" --impure; }
export -f nix
NIXEOF NIXEOF
@@ -641,6 +649,10 @@ cat > "$INCLUDE_DIR/etc/profile.d/nix-packages-path.sh" <<'EOF'
export NIX_PACKAGES_FILE=/usr/local/libexec/nix-packages.list export NIX_PACKAGES_FILE=/usr/local/libexec/nix-packages.list
EOF EOF
# nixpkgs config: allow unfree packages for all users
install -d -m 0755 "$INCLUDE_DIR/etc/skel/.config/nixpkgs"
echo '{ allowUnfree = true; }' > "$INCLUDE_DIR/etc/skel/.config/nixpkgs/config.nix"
# ── 3g) Skel: .bash_profile sources .bashrc only (no first-login autorun) ── # ── 3g) Skel: .bash_profile sources .bashrc only (no first-login autorun) ──
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'

View File

@@ -119,7 +119,7 @@ LIVE_USER="${USERNAME:-live}"
LIVE_USER="${LIVE_USER:-live}" LIVE_USER="${LIVE_USER:-live}"
# Extra groups (dracut only adds audio,video,wheel) # Extra groups (dracut only adds audio,video,wheel)
for g in plugdev input network video audio _seatd; do for g in plugdev input network video audio _seatd bluetooth; do
groupadd -f "$g" 2>/dev/null || true groupadd -f "$g" 2>/dev/null || true
usermod -aG "$g" "$LIVE_USER" 2>/dev/null || true usermod -aG "$g" "$LIVE_USER" 2>/dev/null || true
done done
@@ -145,6 +145,7 @@ XDG_RUN="/run/user/$(id -u "$LIVE_USER" 2>/dev/null || echo 1000)"
install -d -m 0700 "$XDG_RUN" 2>/dev/null || true install -d -m 0700 "$XDG_RUN" 2>/dev/null || true
chown "$LIVE_USER" "$XDG_RUN" 2>/dev/null || true chown "$LIVE_USER" "$XDG_RUN" 2>/dev/null || true
# Start elogind here, once, before runsvdir brings up greetd. # Start elogind here, once, before runsvdir brings up greetd.
# Runit does NOT supervise it — this avoids cgroup-race restart spam. # Runit does NOT supervise it — this avoids cgroup-race restart spam.
# We wait until dbus is available (dbus service starts first in runsvdir), # We wait until dbus is available (dbus service starts first in runsvdir),
@@ -209,7 +210,7 @@ sleep 3
EOF EOF
chmod 0755 "$INCLUDE_DIR/etc/sv/elogind/finish" chmod 0755 "$INCLUDE_DIR/etc/sv/elogind/finish"
for svc in dbus elogind NetworkManager sshd; do for svc in dbus elogind NetworkManager bluetoothd sshd; do
ln -sf "/etc/sv/$svc" "$INCLUDE_DIR/etc/runit/runsvdir/default/$svc" ln -sf "/etc/sv/$svc" "$INCLUDE_DIR/etc/runit/runsvdir/default/$svc"
done done
@@ -237,6 +238,13 @@ if [[ -d "${HOME:-}/.nix-profile/bin" ]]; then
*) export PATH="$HOME/.nix-profile/bin:$PATH" ;; *) export PATH="$HOME/.nix-profile/bin:$PATH" ;;
esac esac
fi fi
export NIXPKGS_ALLOW_UNFREE=1
# Pre-baked nix is single-user (no daemon) — bypass daemon connection attempt
export NIX_REMOTE=local
# Flake commands ignore NIXPKGS_ALLOW_UNFREE unless --impure is passed.
# Wrap nix so interactive installs work without extra flags.
nix() { command nix "$@" --impure; }
export -f nix
EOF EOF
chmod 0644 "$INCLUDE_DIR/etc/profile.d/nix-prebaked.sh" chmod 0644 "$INCLUDE_DIR/etc/profile.d/nix-prebaked.sh"
@@ -244,6 +252,7 @@ chmod 0644 "$INCLUDE_DIR/etc/profile.d/nix-prebaked.sh"
install -d -m 0755 "$INCLUDE_DIR/etc/nix" install -d -m 0755 "$INCLUDE_DIR/etc/nix"
cat > "$INCLUDE_DIR/etc/nix/nix.conf" <<EOF cat > "$INCLUDE_DIR/etc/nix/nix.conf" <<EOF
experimental-features = nix-command flakes experimental-features = nix-command flakes
build-users-group =
sandbox = false sandbox = false
auto-optimise-store = true auto-optimise-store = true
trusted-users = root ${LIVE_USER} trusted-users = root ${LIVE_USER}
@@ -251,6 +260,10 @@ max-jobs = 2
http-connections = 10 http-connections = 10
EOF EOF
# nixpkgs config: allow unfree packages for all users
install -d -m 0755 "$INCLUDE_DIR/etc/skel/.config/nixpkgs"
echo '{ allowUnfree = true; }' > "$INCLUDE_DIR/etc/skel/.config/nixpkgs/config.nix"
# ── 3e) niri config.kdl in /etc/skel ─────────────────────────────────── # ── 3e) niri config.kdl in /etc/skel ───────────────────────────────────
# dracut's adduser.sh copies skel → /home/live, so the live user gets a # dracut's adduser.sh copies skel → /home/live, so the live user gets a
# ready niri config without any first-boot setup step. # ready niri config without any first-boot setup step.
@@ -314,15 +327,17 @@ spawn-at-startup "pipewire"
spawn-at-startup "pipewire-pulse" spawn-at-startup "pipewire-pulse"
spawn-at-startup "wireplumber" spawn-at-startup "wireplumber"
// Background, notifications, network, bluetooth, auth // Background, notifications and auth
spawn-at-startup "swaybg" "-i" "/usr/share/backgrounds/void-installer/pxfuel.jpg" "-m" "fill" spawn-at-startup "swaybg" "-i" "/usr/share/backgrounds/void-installer/pxfuel.jpg" "-m" "fill"
spawn-at-startup "mako" spawn-at-startup "mako"
spawn-at-startup "nm-applet" "--indicator"
spawn-at-startup "blueman-applet"
spawn-at-startup "/usr/libexec/polkit-gnome-authentication-agent-1" spawn-at-startup "/usr/libexec/polkit-gnome-authentication-agent-1"
// noctalia-shell (Quickshell-based Wayland shell) // noctalia-shell — wait for org.bluez before launching so the BT module
spawn-at-startup "quickshell" "-c" "noctalia-shell" // initialises correctly (bluetoothd may not be on D-Bus yet at this point).
spawn-at-startup "sh" "-c" "i=0; while [ \$i -lt 30 ] && ! dbus-send --system --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.GetNameOwner string:org.bluez >/dev/null 2>&1; do sleep 1; i=\$((i+1)); done; exec quickshell -c noctalia-shell"
// First-login setup: installs Claude Code (and NVM) once, then closes
spawn-at-startup "sh" "-c" "[ -f ~/.first-login-done ] || alacritty -T 'Void Setup' -e /usr/local/libexec/first-login.sh"
binds { binds {
Mod+T { spawn "alacritty"; } Mod+T { spawn "alacritty"; }
@@ -408,6 +423,28 @@ if [[ -d "$BIBATA_SRC" ]]; then
echo " cursor: Bibata-Modern-Ice" echo " cursor: Bibata-Modern-Ice"
fi fi
# first-login.sh — deployed by _deploy_first_login() to the installed system.
[[ -r "$PROJECT_DIR/installer/first-login.sh" ]] && \
install -m 0755 "$PROJECT_DIR/installer/first-login.sh" "$OVERLAY/first-login.sh"
# Claude Code config + auth tokens from host (deployed to the installed system).
CLAUDE_SRC="${CLAUDE_SRC:-$HOME/.claude}"
[[ -d "$CLAUDE_SRC" ]] && { cp -a "$CLAUDE_SRC" "$OVERLAY/claude"; echo " claude: ~/.claude bundled"; }
[[ -r "${HOME}/.claude.json" ]] && install -m 0600 "${HOME}/.claude.json" "$OVERLAY/claude.json"
# VS Code user config + extension list from host.
VSCODE_SRC="${VSCODE_USER_SRC:-$HOME/.config/Code/User}"
install -d -m 0755 "$OVERLAY/vscode-user"
if [[ -d "$VSCODE_SRC" ]]; then
for f in settings.json keybindings.json; do
[[ -r "$VSCODE_SRC/$f" ]] && install -m 0644 "$VSCODE_SRC/$f" "$OVERLAY/vscode-user/$f"
done
[[ -d "$VSCODE_SRC/snippets" ]] && cp -a "$VSCODE_SRC/snippets" "$OVERLAY/vscode-user/snippets"
command -v code >/dev/null 2>&1 && \
code --list-extensions > "$OVERLAY/vscode-extensions.txt" 2>/dev/null || true
echo " vscode-user: staged from $VSCODE_SRC"
fi
# Copy wallpapers and assets into usr/share (rootfs overlay) # Copy wallpapers and assets into usr/share (rootfs overlay)
install -d -m 0755 "$INCLUDE_DIR/usr/share/backgrounds/void-installer" install -d -m 0755 "$INCLUDE_DIR/usr/share/backgrounds/void-installer"
cp -a "$OVERLAY/wallpapers"/. "$INCLUDE_DIR/usr/share/backgrounds/void-installer/" 2>/dev/null || true cp -a "$OVERLAY/wallpapers"/. "$INCLUDE_DIR/usr/share/backgrounds/void-installer/" 2>/dev/null || true
@@ -488,6 +525,20 @@ exec /usr/local/lib/void-installer/install.sh "$@"
WRAPEOF WRAPEOF
chmod 0755 "$INCLUDE_DIR/usr/local/bin/void-install" chmod 0755 "$INCLUDE_DIR/usr/local/bin/void-install"
# first-login.sh at /usr/local/libexec: available in the live session and
# deployed by _deploy_first_login() to the installed system via the overlay.
install -d -m 0755 "$INCLUDE_DIR/usr/local/libexec"
install -m 0755 "$PROJECT_DIR/installer/first-login.sh" \
"$INCLUDE_DIR/usr/local/libexec/first-login.sh"
# nix-packages.list: tells first-login.sh which nix packages to install.
# In the live session these are already prebaked; in the installed system the
# first-boot-nix runit service handles them, so this is informational only.
{
printf '# Nix user packages\n'
printf '%s\n' "${NIX_USER_PACKAGES[@]}"
} > "$INCLUDE_DIR/usr/local/libexec/nix-packages.list"
_SECRETS_SRC="${SECRETS_ENV:-$PROJECT_DIR/secrets.env}" _SECRETS_SRC="${SECRETS_ENV:-$PROJECT_DIR/secrets.env}"
if [[ -r "$_SECRETS_SRC" ]]; then if [[ -r "$_SECRETS_SRC" ]]; then
install -d -m 0755 "$INCLUDE_DIR/etc" install -d -m 0755 "$INCLUDE_DIR/etc"