fix(install): bake dconf, seed main, name ISO, display modes (#123–#126)
Some checks failed
Check / eval (push) Has been cancelled

Batch of existing-bug fixes from Acer/XPS install findings:

- #123: HM pre-activate creates /run/user/$UID and prefers
  dbus-run-session so dconf no longer aborts the desktop bake
- #124: main-built ISOs seed ?ref=main; patch-template rewrites
  inputs.nomarchy.url from NOMARCHY_FLAKE_URL (was set but unused)
- #125: image.baseName → nomarchy-live-….iso (not nixos-live-…)
- #126: Display mode list sorted by pixel area; toast shows hyprctl
  size; TESTING notes QEMU fixed-window scaling illusion

Verified: V0 flake check, installer-safety, baseName eval, patch-template
flakeUrl rewrite, mode-sort fixture.
This commit is contained in:
2026-07-15 09:58:53 +01:00
parent 25e498a5ef
commit 748d4af414
13 changed files with 118 additions and 178 deletions

View File

@@ -110,7 +110,7 @@ Boot the full desktop from a USB stick or VM without installing anything:
```sh ```sh
nix build .#nixosConfigurations.nomarchy-live.config.system.build.isoImage nix build .#nixosConfigurations.nomarchy-live.config.system.build.isoImage
# → result/iso/*.iso — dd to a stick, or boot it in QEMU: # → result/iso/nomarchy-live-….iso — dd to a stick, or boot it in QEMU:
tools/test-live-iso.sh tools/test-live-iso.sh
``` ```

View File

@@ -31,150 +31,6 @@ post-boot sessions). Preserve separation: the installer bake failure and the
flake pin are different root causes even when they show up on the same machine. flake pin are different root causes even when they show up on the same machine.
(Terminal / Ghostty-on-Acer → shipped as Kitty-only, #95.) (Terminal / Ghostty-on-Acer → shipped as Kitty-only, #95.)
### 125. Live/install ISO artifact is still named `nixos-…`
**Observed:** a built live image lands as e.g.
`result/iso/nixos-live-26.05.20260710.8f0500b-x86_64-linux.iso` — users (and
USB writers) still see **NixOS**, not Nomarchy.
**Already branded elsewhere:** `isoImage.volumeID = "NOMARCHY_LIVE"`,
`isoImage.edition = "live"`, splash/GRUB theme, `system.nixos.distroName` /
`distroId = "nomarchy"` (os-release). The **filename** comes from
`image.baseName` / `image.fileName` (nixpkgs ISO module; formerly
`isoImage.isoBaseName` / `isoName`), which still default to the NixOS
template prefix.
**Fix direction:** set `image.baseName` (or the current nixpkgs equivalent)
to something like `nomarchy-live` in `hosts/live.nix` (and any install ISO
target if split later). Confirm boot menu strings / isolinux labels if they
still say NixOS after the rename. Guard: a cheap check or docs note that
`result/iso/nomarchy-*.iso` is the expected path (TESTING / README build
snippet).
**Pass:** `nix build …isoImage` produces a `nomarchy-…` ISO filename (not
`nixos-…`); volume label and user-facing boot branding stay Nomarchy.
### 126. Display resolution picker: choosing higher modes makes the image smaller (live VM)
**Observed (Bernardo, live ISO in a VM):** System Display resolution
picker — the **higher** the listed mode he picked, the **lower** the
on-screen resolution *appeared* (inverted / wrong mapping). Live session,
not necessarily install.
**Code path:** `modules/home/rofi.nix` `display)` — builds a mode list from
Hyprland tokens + `hyprctl monitors -j``.availableModes[]`, then
`sort -rV -u`, applies with
`hyprctl keyword monitor "$name,$mode,$pos,$scale"` and persists
`settings.monitors.$name`.
**Likely causes to separate:**
1. **Menu/sort bug** — labels or `sort -rV` on `WxH@R` strings dont match
what Hyprland applies (wrong mode string applied).
2. **QEMU/viewer scaling** — guest mode really increases while the host
window is fixed, so content *looks* smaller (not a Nomarchy bug; document).
3. **Scale factor interaction** — keeping current `.scale` while changing
mode on virtio-gpu yields surprising logical size.
**Fix direction:** reproduce in QEMU with `tools/test-live-iso.sh` (or
manual), log `hyprctl monitors -j` before/after each pick, assert applied
`width`/`height` match the chosen token. Fix sort/format if wrong; if pure
viewer scaling, tell the user and optionally show current mode from
`hyprctl` after apply. Prefer a permanent guard on mode-string formatting
if the bug is in our list/apply path.
**Pass:** picking `1920x1080@…` yields a monitor at 1920×1080 (hyprctl);
picking a lower mode yields lower; menu order is highest-first and honest.
If the only inversion is QEMU window chrome, document it in TESTING.md and
close with that finding — do not “fix” real hardware that was fine.
### 123. Installer HM pre-activate aborts on dconf / missing XDG_RUNTIME_DIR
**Seen on both machines** (Dell XPS 9350 and Acer M5-481T), same log shape at
the end of `nomarchy-install` after "✓ System installed":
```
— Baking the desktop —
Building the desktop generation...
▲ Desktop pre-activation failed (see /var/log/nomarchy-hm-preactivate.log
on the installed system); after first login run:
home-manager switch --flake ~/.nomarchy -b bak
Activating dconfSettings
dconf-CRITICAL **: Unable to create directory '/run/user/1001/dconf':
Permission denied. dconf will not work properly.
error: Could not connect: No such file or directory
```
Install still reports success and offers reboot — so first boot lands on a
**partial** Home Manager activation. That matches the post-boot pain Bernardo
had to fix by hand on both boxes: **GTK theme looking wrong** (Stylix/dconf
color-scheme never landed) and **missing nm-applet tray icon**
(`services.network-manager-applet` is on in `modules/home/default.nix`, but
only after a complete HM generation/activation). Do **not** file those as
separate product bugs until this bake succeeds; re-check them as acceptance
criteria of the fix.
**Root cause (code path):** `pkgs/nomarchy-install/nomarchy-install.sh`
"Baking the desktop" runs `$out/activate` via `runuser` inside `nixos-enter`.
There is no user session: `/run/user/$UID` is missing or unwritable, so the
dconf activation step dies and the scripted activate aborts mid-way. #83
already surfaces the recovery one-liner; the *bake itself* is what is broken.
**Fix direction:** before `runuser … activate`, create a private runtime dir
the target user owns (`mkdir -p /run/user/$UID && chown`, export
`XDG_RUNTIME_DIR`), and/or give activate a session bus if dconf still needs
one. Prefer making pre-activate succeed over papering over dconf. Keep the
existing failure hint for genuine failures.
**Pass:** a `tools/test-install.sh` (or equivalent) run ends with
"Desktop pre-activated — first boot is fully themed", **not** the dconf
CRITICAL; `/var/log/nomarchy-hm-preactivate.log` is absent or clean; first
graphical login has Stylix GTK theming + nm-applet in the tray **without** a
manual `home-manager switch`. V3: same on at least one of the two boxes that
regressed (HARDWARE-QUEUE).
### 124. Install seeds `?ref=v1` while writing main-era config (and v1 lags hard)
**Seen on Acer after install** (and inherent in every current install):
- ISO was built from **main**.
- Generated `~/.nomarchy/flake.nix` still has
`inputs.nomarchy.url = "…?ref=v1"` (`templates/downstream/flake.nix` +
`flake.nix` `flakeUrl` / `originalNode.ref = "v1"`).
- Installer **also** writes live `nomarchy.hardware.*` lines into
`system.nix` (`patch-template.py` — e.g. `nomarchy.hardware.intel.enable`).
- `v1` is far behind main (hundreds of commits; currently lacks the modern
`nomarchy.hardware` surface). After a pull / lock re-resolve to the forge,
rebuild dies with:
```
error: The option 'nomarchy.hardware' does not exist.
… intel = { enable = true; };
Did you mean 'nomarchy.services' or 'nomarchy.system'?
```
So a main-built ISO writes config that **only main understands**, then points
the machine at a release branch that does not have those options. Offline
compose-lock papers over first boot (path-locked to the ISO store), but the
first intentional update re-resolves to ancient v1 and the machine breaks.
**Product tension:** the standing branch model is "downstreams pin `v1`"
(ROADMAP / CONVENTIONS) — correct once `v1` is a real release pointer. While
`v1` lags development this hard, **installs from a main ISO must not leave
users on that lagging ref**.
**Fix direction (pick one and document):** (a) ISO build injects the ref the
image was built from (`main` or `v1`) into the template + `flakeUrl`; (b) pin
`original` to the exact ISO `rev` and only advance on explicit
`nomarchy-pull`; (c) stop writing options that do not exist on the pinned
ref (worse — loses hardware enablement). Prefer (a) or (b).
**Pass:** a machine installed from a main-built ISO has a flake whose nomarchy
input evaluates the same option surface the installer wrote (no
`nomarchy.hardware does not exist` on `nomarchy-rebuild` / first pull policy
as documented); a release ISO built from `v1` still pins `v1`. Guard: install
safety / template check that written options ⊆ pinned module surface, or that
the seeded ref matches the ISO source ref.
### 94. Live ISO/install: no default browser observed ### 94. Live ISO/install: no default browser observed
**Progress 2026-07-13:** installed path VERIFIED at V1 — the exact HM **Progress 2026-07-13:** installed path VERIFIED at V1 — the exact HM

View File

@@ -427,24 +427,18 @@ the **T14s** (webcam case).
template installs). Firefox is deliberately absent; its absence is template installs). Firefox is deliberately absent; its absence is
correct, not a miss. correct, not a miss.
- [ ] **#123 install bake: first boot fully themed without manual HM switch** - [ ] **#123 install bake: first boot fully themed without manual HM switch**
after a fix for the dconf / XDG_RUNTIME_DIR abort lands, re-install re-install from a main ISO (this commit+) on **either** the Acer
(or re-run bake) on **either** the Acer M5-481T or the Dell XPS 9350. M5-481T or the Dell XPS 9350. **Pass:** install ends with "Desktop
**Pass:** install ends with "Desktop pre-activated", no pre-activated", no `dconf-CRITICAL` in
`dconf-CRITICAL` / `Permission denied` in
`/var/log/nomarchy-hm-preactivate.log`, first graphical login has `/var/log/nomarchy-hm-preactivate.log`, first graphical login has
coherent Stylix GTK theming **and** nm-applet in the Waybar tray Stylix GTK + nm-applet **without** hand `home-manager switch`.
**without** running `home-manager switch` by hand. **Fail** = still
need the recovery one-liner, or GTK/nm-applet still wrong until a
manual switch (then the bake is still incomplete).
- [ ] **#95 Kitty-only terminal on Acer M5-481T** — after rebuild/install - [ ] **#95 Kitty-only terminal on Acer M5-481T** — after rebuild/install
from main: SUPER+Return opens **themed Kitty**; System Doctor opens from main: SUPER+Return opens **themed Kitty**; System Doctor opens
a floating classed Kitty window. No Ghostty on PATH required. a floating classed Kitty window. No Ghostty on PATH required.
- [ ] **#124 flake pin after main-ISO install** — on a machine installed - [ ] **#124 flake pin after main-ISO install** — installed machines
from a **main-built** ISO (post-fix): `~/.nomarchy/flake.nix` `~/.nomarchy/flake.nix` has `?ref=main` (not lagging v1). **Pass:**
nomarchy input must not re-resolve to a lagging `v1` that lacks `nomarchy-rebuild` does not die with
options the installer wrote. **Pass:** `nomarchy-rebuild` (and a `The option 'nomarchy.hardware' does not exist`.
deliberate pull policy as documented by the fix) does **not** die
with `The option 'nomarchy.hardware' does not exist`.
## AMD dev box only ## AMD dev box only
- [ ] **#118 smartd still runs where drives DO have SMART** (this commit) — the - [ ] **#118 smartd still runs where drives DO have SMART** (this commit) — the

View File

@@ -19,6 +19,20 @@ Template:
--- ---
## 2026-07-15 — Fix batch #123#126 (install bake, flake ref, ISO name, display)
- **Task:** Fix-only NOW batch: #123 dconf pre-activate, #124 main flake
seed, #125 ISO filename, #126 display mode list.
- **Did:** (123) pre-activate creates `/run/user/$UID` + prefers
`dbus-run-session -- activate`. (124) seed `?ref=main`; patch-template
rewrites `inputs.nomarchy.url` from NOMARCHY_FLAKE_URL (was unused);
template default main. (125) `image.baseName` → nomarchy-live-….iso.
(126) sort modes by pixel area; toast shows hyprctl size; TESTING QEMU note.
- **Verified:** V0 flake check; installer-safety; `image.baseName` eval
`nomarchy-live-…`; patch-template flakeUrl rewrite; mode sort unit fixture.
- **Pending:** V3 reinstall on Acer/XPS (#123/#124); optional full
`test-install.sh` V2 when time allows.
- **Next suggestion:** #112 disk-picker fd0, or V2 test-install for #123.
## 2026-07-15 — File #125 ISO name + #126 display resolution invert (no code) ## 2026-07-15 — File #125 ISO name + #126 display resolution invert (no code)
- **Task:** Bernardo: (1) installer ISO still named nixos; (2) live VM - **Task:** Bernardo: (1) installer ISO still named nixos; (2) live VM
Display picker — higher modes made the screen look lower-res. Display picker — higher modes made the screen look lower-res.

View File

@@ -137,6 +137,19 @@ iteration would otherwise rediscover.
without a hierarchy pass. without a hierarchy pass.
## Gotchas (cost a debugging session once) ## Gotchas (cost a debugging session once)
- **Installer HM pre-activate needs XDG_RUNTIME_DIR (+ session bus) (#123):**
`runuser … activate` inside `nixos-enter` has no user session. Without
`mkdir -p /run/user/$UID` owned by the install user and
`XDG_RUNTIME_DIR` (prefer `dbus-run-session -- activate`), dconf dies
with Permission denied and the bake aborts mid-way — first boot looks
unthemed / missing nm-applet even though the system installed.
- **ISO filename is `image.baseName` (#125):** volumeID alone does not rename
`result/iso/…`; force `image.baseName` to `nomarchy-…` or the artifact
stays `nixos-live-….iso`.
- **Install flake ref must match the ISO branch (#124):** while `v1` lags
`main`, seed `?ref=main` (and compose-lock original) from main-built ISOs;
`NOMARCHY_FLAKE_URL` must actually rewrite `inputs.nomarchy.url` (was set
but unused until #124).
- Gum `filter` returns unmatched typed text by default; catalog-only pickers - Gum `filter` returns unmatched typed text by default; catalog-only pickers
require `--strict` plus an independent exact-membership validation boundary. require `--strict` plus an independent exact-membership validation boundary.
- Waybar `layer: top` renders above **even real-fullscreen windows** — the - Waybar `layer: top` renders above **even real-fullscreen windows** — the

View File

@@ -404,6 +404,13 @@ Design/decision records and a running log of shipped work (items marked
decision rather than a drive-by. Proved to fail: dropping snapshot makes it decision rather than a drive-by. Proved to fail: dropping snapshot makes it
name the missing entry. **V3 pending** — that the apps *launch* needs real name the missing entry. **V3 pending** — that the apps *launch* needs real
hardware (HARDWARE-QUEUE, Acer M5-481T). hardware (HARDWARE-QUEUE, Acer M5-481T).
- ✓ **Install fix batch (#123#126):** (123) HM pre-activate creates
`/run/user/$UID` + `dbus-run-session` so dconf no longer aborts the bake;
(124) main-built ISOs seed `?ref=main` and installer actually rewrites
`inputs.nomarchy.url` from `NOMARCHY_FLAKE_URL` (was set but unused);
(125) `image.baseName` → `nomarchy-live-….iso`; (126) Display mode list
sorted by pixel area + toast reports hyprctl size; TESTING notes QEMU
fixed-window scaling. V3: reinstall on Acer/XPS for #123.
- ✓ **Kitty is the only terminal (#95 complete):** Ghosttys OpenGL 4.3 floor - ✓ **Kitty is the only terminal (#95 complete):** Ghosttys OpenGL 4.3 floor
broke SUPER+Return (and classed doctor/calendar windows) on Ivy Bridge broke SUPER+Return (and classed doctor/calendar windows) on Ivy Bridge
HD 4000 (Acer M5-481T). Maintaining two terminals was pure complexity. HD 4000 (Acer M5-481T). Maintaining two terminals was pure complexity.

View File

@@ -122,6 +122,11 @@ Hyprland's headless backend otherwise aborts in a VM-only zero-output state.
script's qemu flags; on real hardware check `journalctl -b -u greetd`. script's qemu flags; on real hardware check `journalctl -b -u greetd`.
- **Tiny resolution**: the live config forces `monitor = ,highres,auto,1`; - **Tiny resolution**: the live config forces `monitor = ,highres,auto,1`;
if QEMU still picks 1024×768, resize the window — Hyprland follows. if QEMU still picks 1024×768, resize the window — Hyprland follows.
- **Display menu + QEMU**: System Display mode list is sorted by **pixel
area** (highest first). After a pick, the toast shows hyprctls reported
size. In a **fixed-size** QEMU/viewer window, a higher guest mode still
*looks* smaller (more pixels in the same window) — that is viewer scaling,
not an inverted apply. Trust hyprctl / the toast numbers.
- **First theme switch is the slowest**: it evaluates the flake on a RAM - **First theme switch is the slowest**: it evaluates the flake on a RAM
disk. Subsequent switches reuse the eval cache. disk. Subsequent switches reuse the eval cache.

View File

@@ -51,16 +51,17 @@
(nixpkgs.lib.concatStringsSep "\n" (nixpkgs.lib.concatStringsSep "\n"
(builtins.attrNames nixos-hardware.nixosModules)); (builtins.attrNames nixos-hardware.nixosModules));
nixpkgsPath = nixpkgs.outPath; nixpkgsPath = nixpkgs.outPath;
# Branch model: `main` is the development default; `v1` is the # Branch model: `main` is development; `v1` is the release pointer
# release pointer — the stable line for the NixOS 26.05 rewrite, # (advanced to main after human QA). Installs from a *main-built* ISO
# advanced to main once a batch is tested (rolling, no tags). A # must seed `?ref=main` — seeding v1 while it lags hundreds of
# future major bump would become `v2`. Installed machines track # commits left machines with installer-written `nomarchy.hardware.*`
# `?ref=v1` on `nix flake update`, not the forge's default branch. # that v1 does not have (#124). When cutting a release ISO from the
flakeUrl = "git+${gitUrl}?ref=v1"; # v1 pointer, change both of these to "v1".
flakeUrl = "git+${gitUrl}?ref=main";
# Future updates re-resolve from the forge (original); the install # Future updates re-resolve from the forge (original); the install
# itself resolves from the ISO store (locked = path) — fully # itself resolves from the ISO store (locked = path) — fully
# offline, even from a dirty-tree ISO. # offline, even from a dirty-tree ISO.
originalNode = { type = "git"; url = gitUrl; ref = "v1"; }; originalNode = { type = "git"; url = gitUrl; ref = "main"; };
lockedNode = { lockedNode = {
type = "path"; type = "path";
path = self.outPath; path = self.outPath;

View File

@@ -2,7 +2,7 @@
# without touching the disk. The live session bundles nomarchy-install # without touching the disk. The live session bundles nomarchy-install
# (gum + disko + mkFlake) for a real install; this target also lets you # (gum + disko + mkFlake) for a real install; this target also lets you
# test the distro end-to-end on real hardware before committing to disk. # test the distro end-to-end on real hardware before committing to disk.
{ lib, pkgs, username, nomarchySrc, ... }: { lib, pkgs, config, username, nomarchySrc, ... }:
let let
# ISO boot branding: the Nomarchy monogram recolored to the palette accent, # ISO boot branding: the Nomarchy monogram recolored to the palette accent,
@@ -84,6 +84,11 @@ in
isoImage.edition = lib.mkForce "live"; isoImage.edition = lib.mkForce "live";
isoImage.splashImage = isoSplash; # isolinux / BIOS isoImage.splashImage = isoSplash; # isolinux / BIOS
isoImage.grubTheme = nomarchyGrubTheme; # GRUB / UEFI isoImage.grubTheme = nomarchyGrubTheme; # GRUB / UEFI
# Filename: nixpkgs defaults image.baseName to "nixos-<edition>-…". Force
# nomarchy so result/iso/ is nomarchy-live-….iso, not nixos-live-….iso (#125).
image.baseName = lib.mkForce (
"nomarchy-${config.isoImage.edition}-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}"
);
# The minimal-CD profile slims the image for a CONSOLE installer; this # The minimal-CD profile slims the image for a CONSOLE installer; this
# ISO is the desktop, so re-enable what it strips. Above all # ISO is the desktop, so re-enable what it strips. Above all

View File

@@ -643,26 +643,38 @@ ${themeRows}
fi fi
[ -n "$name" ] || exit 0 [ -n "$name" ] || exit 0
# Pick a mode: a few Hyprland resolution tokens, then the output's # Pick a mode: Hyprland tokens, then advertised modes sorted by
# advertised modes (rounded refresh rate, deduped, highest first). The # pixel area (highest first). Do NOT use sort -rV on "WxH@R"
# prompt shows the current mode. # version sort is not geometric and mis-orders common modes (#126).
cur=$(printf '%s' "$mons" | jq -r --arg n "$name" \ cur=$(printf '%s' "$mons" | jq -r --arg n "$name" \
'.[]|select(.name==$n)|"\(.width)x\(.height)@\(.refreshRate|round)"') '.[]|select(.name==$n)|"\(.width)x\(.height)@\(.refreshRate|round)"')
mode=$( { mode=$( {
printf 'preferred\nhighres\nhighrr\n' printf 'preferred\nhighres\nhighrr\n'
printf '%s' "$mons" | jq -r --arg n "$name" '.[]|select(.name==$n)|.availableModes[]' \ printf '%s' "$mons" | jq -r --arg n "$name" '.[]|select(.name==$n)|.availableModes[]' \
| sed 's/Hz$//' | awk -F@ '{ printf "%s@%d\n", $1, $2 + 0.5 }' | sort -rV -u | sed 's/Hz$//' \
| awk -F'[@x]' '
NF >= 2 {
w=$1+0; h=$2+0; r=($3==""?0:$3+0);
printf "%d\t%dx%d@%d\n", w*h, w, h, r
}' \
| sort -t$'\t' -k1,1nr -k2,2 \
| cut -f2- \
| awk 'NF && !seen[$0]++'
printf '%s\n' "$BACK" printf '%s\n' "$BACK"
} | rofi_menu -p "$name (now $cur)" ) || exit 0 } | rofi_menu -p "$name (now $cur)" ) || exit 0
[ "$mode" = "$BACK" ] && exec "$0" "$modeBack" [ "$mode" = "$BACK" ] && exec "$0" "$modeBack"
[ -n "$mode" ] || exit 0 [ -n "$mode" ] || exit 0
# Apply live (keep the output's current position + scale), then persist. # Apply live (keep the output's current position + scale), then persist.
# Notify with hyprctl-reported size so a QEMU fixed window that
# *looks* smaller at higher modes is not mistaken for an invert (#126).
pos=$(printf '%s' "$mons" | jq -r --arg n "$name" '.[]|select(.name==$n)|"\(.x)x\(.y)"') pos=$(printf '%s' "$mons" | jq -r --arg n "$name" '.[]|select(.name==$n)|"\(.x)x\(.y)"')
scale=$(printf '%s' "$mons" | jq -r --arg n "$name" '.[]|select(.name==$n)|.scale') scale=$(printf '%s' "$mons" | jq -r --arg n "$name" '.[]|select(.name==$n)|.scale')
if hyprctl keyword monitor "$name,$mode,$pos,$scale" >/dev/null 2>&1; then if hyprctl keyword monitor "$name,$mode,$pos,$scale" >/dev/null 2>&1; then
nomarchy-theme-sync --quiet set "settings.monitors.$name" "$mode" --no-switch nomarchy-theme-sync --quiet set "settings.monitors.$name" "$mode" --no-switch
notify-send "Display" "$name $mode" got=$(hyprctl monitors -j | jq -r --arg n "$name" \
'.[]|select(.name==$n)|"\(.width)x\(.height)@\(.refreshRate|round)"')
notify-send "Display" "$name $mode (now ${got:-?})"
else else
notify-send "Display" "Could not set $name to $mode." notify-send "Display" "Could not set $name to $mode."
fi ;; fi ;;

View File

@@ -621,7 +621,8 @@ python3 "$SHARE/patch-template.py" "$FLAKE_DIR" <<PYJSON
"npu": $(if [[ -n "$NPU_VENDOR" ]]; then printf '%s' "$NPU_VENDOR" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip("\n")))'; else echo null; fi) "npu": $(if [[ -n "$NPU_VENDOR" ]]; then printf '%s' "$NPU_VENDOR" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip("\n")))'; else echo null; fi)
}, },
"resumeOffset": $resume_json, "resumeOffset": $resume_json,
"rootUuid": $root_uuid_json "rootUuid": $root_uuid_json,
"flakeUrl": $(printf '%s' "${NOMARCHY_FLAKE_URL:?NOMARCHY_FLAKE_URL unset}" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip("\n")))')
} }
PYJSON PYJSON
@@ -771,10 +772,28 @@ nix-daemon &
daemon_pid=\$! daemon_pid=\$!
trap 'kill \$daemon_pid 2>/dev/null || true' EXIT trap 'kill \$daemon_pid 2>/dev/null || true' EXIT
sleep 2 sleep 2
# Pre-activate has no graphical session: without XDG_RUNTIME_DIR, HM's
# dconfSettings step dies ("Unable to create directory /run/user/UID/dconf:
# Permission denied") and the rest of activation never runs — first boot
# then lands half-themed (#123). Create a private runtime dir the target
# user owns, and wrap activate in a session bus (dconf needs one).
uid=$USER_UID
install -d -o "$USERNAME" -g users -m 700 "/run/user/\$uid"
# BACKUP_EXT: collisions can't abort the activation (a stray # BACKUP_EXT: collisions can't abort the activation (a stray
# autogenerated config gets moved aside instead). # autogenerated config gets moved aside instead).
runuser -u "$USERNAME" -- bash -lc \ if command -v dbus-run-session >/dev/null 2>&1; then
"USER=$USERNAME HOME=/home/$USERNAME NIX_REMOTE=daemon HOME_MANAGER_BACKUP_EXT=bak \$out/activate" runuser -u "$USERNAME" -- env \
USER="$USERNAME" HOME="/home/$USERNAME" \
XDG_RUNTIME_DIR="/run/user/\$uid" \
NIX_REMOTE=daemon HOME_MANAGER_BACKUP_EXT=bak \
dbus-run-session -- "\$out/activate"
else
runuser -u "$USERNAME" -- env \
USER="$USERNAME" HOME="/home/$USERNAME" \
XDG_RUNTIME_DIR="/run/user/\$uid" \
NIX_REMOTE=daemon HOME_MANAGER_BACKUP_EXT=bak \
"\$out/activate"
fi
EOF EOF
# NOMARCHY_TEST_FORCE_HM_FAIL=1 — unattended harness only (#54 V2): take # NOMARCHY_TEST_FORCE_HM_FAIL=1 — unattended harness only (#54 V2): take
# the failure arm so the durable recovery hint is exercised without a # the failure arm so the durable recovery hint is exercised without a

View File

@@ -57,6 +57,17 @@ def patch_flake(text: str, v: dict) -> str:
f'username = "{nix_str(v["username"])}"; # <- your login name', f'username = "{nix_str(v["username"])}"; # <- your login name',
"flake username", "flake username",
) )
# ISO build bakes the ref it was built from (main vs v1). Must match the
# option surface the installer writes into system.nix (#124).
if v.get("flakeUrl"):
text, n = re.subn(
r'inputs\.nomarchy\.url = "[^"]*";',
f'inputs.nomarchy.url = "{nix_str(v["flakeUrl"])}";',
text,
count=1,
)
if n != 1:
sys.exit("patch-template: could not patch inputs.nomarchy.url")
profiles = v.get("hardwareProfiles") or [] profiles = v.get("hardwareProfiles") or []
if profiles: if profiles:
items = " ".join(f'"{nix_str(p)}"' for p in profiles) items = " ".join(f'"{nix_str(p)}"' for p in profiles)

View File

@@ -4,9 +4,12 @@
# The only input. nixpkgs, home-manager etc. come pinned through it — # The only input. nixpkgs, home-manager etc. come pinned through it —
# tested together upstream. This file is written once (by you or the # tested together upstream. This file is written once (by you or the
# installer) and never hand-edited afterwards; your machine lives in # installer) and never hand-edited afterwards; your machine lives in
# system.nix and home.nix. v1 is the release branch. # system.nix and home.nix.
# Installer copies this template and patches username + hardwareProfile. # Development tip is `main`. Release consumers pin `?ref=v1` once that
inputs.nomarchy.url = "git+https://git.bemagri.xyz/bernardo/nomarchy.git?ref=v1"; # pointer is current (installer overwrites this URL from the ISO build).
# Installer copies this template and patches username + hardwareProfile
# + the nomarchy input URL.
inputs.nomarchy.url = "git+https://git.bemagri.xyz/bernardo/nomarchy.git?ref=main";
outputs = { nomarchy, ... }: outputs = { nomarchy, ... }:
nomarchy.lib.mkFlake { nomarchy.lib.mkFlake {