fix(deploy): make the live ISO boot cleanly

Fresh live boots hit a cascade of activation/unit failures because live.nix
shared installed-system config that assumes persistent state:

- bitspire-env chowned /var/lib/bitspire/.env to bitspire:bitspire in the
  default activation order, before `users` runs, so on a fresh boot (no .env
  yet) it failed with 'invalid user'. Move to the attrset form with
  deps=["users"]. (Installed systems skip the block since .env exists.)
- swapDevices=/var/swapfile lives in the live tmpfs and fails to init —
  replace with zramSwap for the low-RAM models' OOM cushion.
- wg0 needs a provisioned key the live boot lacks; it failed and dragged
  network-setup down. Drop the interface on live.
- display-reset runs `xrandr --output eDP-1`, but the Sintra drives HDMI-1
  (no eDP-1) — gate the service off for sintra.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-06-29 23:47:31 +02:00
commit b2099c7d48

View file

@ -172,8 +172,15 @@ in
}; };
}; };
# Install the .env on first boot # Install the .env on first boot. Attrset form with deps=["users"] so the
system.activationScripts.bitspire-env = '' # chown runs AFTER the bitspire user is created. Otherwise on a fresh live
# boot (where /var/lib/bitspire/.env doesn't exist yet) the chown runs in the
# default activation order — before `users` — and fails with
# "chown: invalid user: 'bitspire:bitspire'". The installed system skips this
# block because its .env already exists, which is why only live boots tripped.
system.activationScripts.bitspire-env = {
deps = [ "users" ];
text = ''
mkdir -p /var/lib/bitspire mkdir -p /var/lib/bitspire
if [ ! -f /var/lib/bitspire/.env ]; then if [ ! -f /var/lib/bitspire/.env ]; then
cp ${envTemplate} /var/lib/bitspire/.env cp ${envTemplate} /var/lib/bitspire/.env
@ -181,10 +188,13 @@ in
chown bitspire:bitspire /var/lib/bitspire/.env chown bitspire:bitspire /var/lib/bitspire/.env
fi fi
''; '';
};
# Reset display output after X starts (required for kexec boots where # Reset display output after X starts (required for kexec boots where
# the GPU wasn't reinitialized by BIOS firmware) # the GPU wasn't reinitialized by BIOS firmware). Only the eDP-panel models
systemd.services.display-reset = { # (Douro/Tejo) have an eDP-1 output; the Sintra drives HDMI-1, so the
# `xrandr --output eDP-1` here just errors out — skip it there.
systemd.services.display-reset = lib.mkIf (machineModel != "sintra") {
description = "Reset eDP display output"; description = "Reset eDP display output";
after = [ "display-manager.service" ]; after = [ "display-manager.service" ];
requires = [ "display-manager.service" ]; requires = [ "display-manager.service" ];
@ -198,12 +208,17 @@ in
}; };
}; };
# Swap file — Douro/Tejo have only 2GB RAM; without swap the system # Low-RAM models (Douro/Tejo, 2GB) need a swap cushion or they hard-freeze
# hard-freezes under memory pressure instead of gracefully OOM-killing. # under memory pressure. The live system is RAM-rooted, so a /var/swapfile
swapDevices = [{ # lives in tmpfs — pointless, and its init fails on a fresh boot. Use
device = "/var/swapfile"; # compressed RAM swap (zram) instead; no on-disk file required.
size = 1024; # MB zramSwap.enable = true;
}];
# The wg0 VPN tunnel (declared in configuration.nix) needs a provisioned key
# at /var/lib/wireguard/wg0.key, which a fresh live boot doesn't have — it
# fails and drags network-setup down with it. A live test image doesn't need
# the VPN, so drop the interface entirely.
networking.wireguard.interfaces = lib.mkForce { };
# Clean /tmp on boot to prevent stale Nix build artifacts from filling disk # Clean /tmp on boot to prevent stale Nix build artifacts from filling disk
boot.tmp.cleanOnBoot = true; boot.tmp.cleanOnBoot = true;