feat: nomarchy-install — guided live-ISO installer (disko + mkFlake)
Ported from the previous iteration's installer (3bdfc35), adapted to the
mkFlake world. gum TUI: disk pick, optional LUKS2, user/hostname/timezone,
DMI → nixos-hardware autodetection (hardware-db.sh). disko partitions
GPT + 1 GiB ESP + BTRFS subvolumes; the generated machine flake lands at
~user/.nomarchy (one mkFlake call, /etc/nixos symlinks to it) and
nixos-install makes it bootable (UEFI/systemd-boot, v1 single disk).
Offline by construction: the target flake.lock is composed from the rev
the ISO was built from (compose-lock.py), `nix flake archive` seeds the
target store, and the ISO pre-builds the template system + desktop.
First boot lands themed: the HM generation is pre-activated in chroot.
mkFlake grows two things for this: hardwareProfile now also takes a list
(autodetection emits several common-* modules), and installed systems get
the standalone home-manager CLI from the pinned input. Unattended mode
(NOMARCHY_UNATTENDED=1 + env) documented in docs/TESTING.md §4.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
57
pkgs/nomarchy-install/compose-lock.py
Normal file
57
pkgs/nomarchy-install/compose-lock.py
Normal file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Compose a flake.lock for the freshly installed machine — offline.
|
||||
|
||||
The generated downstream flake has exactly one input, `nomarchy`. A normal
|
||||
`nix flake lock` would fetch it from its forge; on an offline install we
|
||||
already KNOW the answer: the live ISO was built from a specific nomarchy
|
||||
rev whose source (and all transitive inputs, via the ISO's pinned store
|
||||
paths) is on hand. So we write the lock nix would have written:
|
||||
|
||||
root ─▶ nomarchy (locked to the baked rev+narHash)
|
||||
└─▶ every node from nomarchy's own flake.lock, verbatim
|
||||
|
||||
Nix resolves locked inputs by narHash against the store before touching
|
||||
the network, so evaluation on the target works without connectivity.
|
||||
|
||||
Usage:
|
||||
compose-lock.py <nomarchy-flake.lock> <out> <locked-json> <original-json>
|
||||
|
||||
where <locked-json>/<original-json> are the flake-lock node fields for the
|
||||
nomarchy input (any input type — github, git, …), baked at package build.
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
||||
def main() -> None:
|
||||
src_lock, out, locked_json, original_json = sys.argv[1:5]
|
||||
|
||||
locked = json.loads(locked_json)
|
||||
if not locked.get("rev"):
|
||||
sys.exit("compose-lock: no rev in locked metadata (ISO built from a dirty tree?)")
|
||||
|
||||
with open(src_lock) as f:
|
||||
upstream = json.load(f)
|
||||
|
||||
nodes = dict(upstream["nodes"])
|
||||
# nomarchy's root node describes ITS inputs; that mapping becomes the
|
||||
# input set of the new `nomarchy` node.
|
||||
nomarchy_inputs = nodes.pop("root")["inputs"]
|
||||
if "nomarchy" in nodes:
|
||||
sys.exit("compose-lock: upstream lock already has a 'nomarchy' node")
|
||||
|
||||
nodes["nomarchy"] = {
|
||||
"inputs": nomarchy_inputs,
|
||||
"locked": locked,
|
||||
"original": json.loads(original_json),
|
||||
}
|
||||
nodes["root"] = {"inputs": {"nomarchy": "nomarchy"}}
|
||||
|
||||
with open(out, "w") as f:
|
||||
json.dump({"nodes": nodes, "root": "root", "version": 7}, f, indent=2)
|
||||
f.write("\n")
|
||||
print(f"compose-lock: wrote {out} (nomarchy @ {locked['rev'][:12]})")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user