feat(install): copy templates/downstream and patch install values
All checks were successful
Check / eval (push) Successful in 3m4s
All checks were successful
Check / eval (push) Successful in 3m4s
Make the downstream template the single source of truth for machine flakes: nomarchy-install copies flake/system/home/theme-state and patch-template.py only fills hostname, user, keyboard, detected hardware, snapper, resume, and password. Install and flake-init users now share the same commented opt-ins and starter home.packages. Also: BACKLOG boreal-as-default proposal; installer audit notes; HARDWARE.md from prior work if uncommitted.
This commit is contained in:
@@ -330,21 +330,14 @@ rm -f "$LUKS_KEY_PATH" "$disko_log"
|
||||
success "Disk partitioned and mounted at /mnt"
|
||||
|
||||
# Hibernation plumbing: the swapfile's physical offset goes into the
|
||||
# kernel cmdline. Deactivate swap first so nixos-generate-config doesn't
|
||||
# also emit a swapDevices entry (we write our own, with resume wiring).
|
||||
RESUME_CONFIG=""
|
||||
# kernel cmdline (patched into system.nix). Deactivate swap first so
|
||||
# nixos-generate-config doesn't also emit a swapDevices entry.
|
||||
resume_offset=""
|
||||
root_uuid=""
|
||||
if [[ "$SWAP_GB" != "0" ]]; then
|
||||
swapoff -a 2>/dev/null || true
|
||||
resume_offset=$(btrfs inspect-internal map-swapfile -r /mnt/swap/swapfile)
|
||||
root_uuid=$(findmnt -no UUID /mnt)
|
||||
RESUME_CONFIG=$(cat <<NIX
|
||||
|
||||
# Swapfile (hibernation-ready: resume points into it).
|
||||
swapDevices = [{ device = "/swap/swapfile"; }];
|
||||
boot.resumeDevice = "/dev/disk/by-uuid/$root_uuid";
|
||||
boot.kernelParams = [ "resume_offset=$resume_offset" ];
|
||||
NIX
|
||||
)
|
||||
success "Swapfile created (resume offset $resume_offset)"
|
||||
fi
|
||||
|
||||
@@ -358,183 +351,75 @@ nixos-generate-config --root /mnt
|
||||
mv /mnt/etc/nixos/hardware-configuration.nix "$FLAKE_DIR/"
|
||||
rm -rf /mnt/etc/nixos
|
||||
|
||||
cp "$SHARE/template/theme-state.json" "$FLAKE_DIR/"
|
||||
# templates/downstream is the single source of truth (same files as
|
||||
# `nix flake init -t`). Copy, then patch install-time values only.
|
||||
cp "$SHARE/template/flake.nix" \
|
||||
"$SHARE/template/system.nix" \
|
||||
"$SHARE/template/home.nix" \
|
||||
"$SHARE/template/theme-state.json" \
|
||||
"$FLAKE_DIR/"
|
||||
|
||||
# home.nix is generated (not copied from the template) so the chosen
|
||||
# keyboard layout reaches the Hyprland session — standalone HM cannot
|
||||
# read system.nix.
|
||||
cat > "$FLAKE_DIR/home.nix" <<EOF
|
||||
# Your user environment. The Nomarchy desktop (Hyprland, Waybar,
|
||||
# Ghostty, theming engine, Stylix) comes from homeModules.nomarchy;
|
||||
# tune it via the nomarchy.* options, add your own packages and
|
||||
# programs below.
|
||||
{ pkgs, ... }:
|
||||
# Detected hardware → flags for the patcher (safe defaults active).
|
||||
has_intel=false; has_amd=false; has_fp=false
|
||||
intel_guc_off=false; has_camera_ir=false
|
||||
if [[ ${#HW_NOMARCHY[@]} -gt 0 ]]; then
|
||||
for nm in "${HW_NOMARCHY[@]}"; do
|
||||
case "$nm" in
|
||||
hardware.intel.enable=true) has_intel=true ;;
|
||||
hardware.intel.guc=false) intel_guc_off=true ;;
|
||||
hardware.amd.enable=true) has_amd=true ;;
|
||||
hardware.fingerprint.enable=true) has_fp=true ;;
|
||||
hardware.camera.hideIrSensor=true) has_camera_ir=true ;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
is_laptop=false
|
||||
[[ " ${HW_PROFILES[*]:-} " == *" common-pc-laptop "* ]] && is_laptop=true
|
||||
thermald=false
|
||||
[[ $is_laptop == true ]] && grep -q GenuineIntel /proc/cpuinfo 2>/dev/null && thermald=true
|
||||
|
||||
{
|
||||
# Keyboard for the desktop session; console + LUKS prompt get the
|
||||
# same layout from system.nix (xkb + console.useXkbConfig).
|
||||
nomarchy.keyboard.layout = "$KB_LAYOUT";
|
||||
nomarchy.keyboard.variant = "$KB_VARIANT";
|
||||
|
||||
# Examples:
|
||||
# nomarchy.terminal = "kitty"; # swap the default terminal
|
||||
# nomarchy.waybar.enable = false; # bring your own bar
|
||||
# nomarchy.stylix.enable = false; # opt out of GTK/Qt theming
|
||||
|
||||
home.packages = with pkgs; [
|
||||
# firefox
|
||||
];
|
||||
}
|
||||
EOF
|
||||
|
||||
hw_nix=""
|
||||
# JSON for patch-template.py (stdin). Hardware profiles as a JSON array.
|
||||
hw_json="["
|
||||
first=1
|
||||
for p in "${HW_PROFILES[@]:-}"; do
|
||||
[[ -n "$p" ]] && hw_nix+=" \"$p\""
|
||||
[[ -z "$p" ]] && continue
|
||||
if [[ $first -eq 1 ]]; then first=0; else hw_json+=","; fi
|
||||
hw_json+=$(printf '%s' "$p" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip("\n")))')
|
||||
done
|
||||
hw_json+="]"
|
||||
|
||||
cat > "$FLAKE_DIR/flake.nix" <<EOF
|
||||
resume_json="null"
|
||||
root_uuid_json="null"
|
||||
if [[ -n "$resume_offset" && "$SWAP_GB" != "0" ]]; then
|
||||
resume_json=$(printf '%s' "$resume_offset" | python3 -c 'import json,sys; print(json.dumps(int(sys.stdin.read().strip())))')
|
||||
root_uuid_json=$(printf '%s' "$root_uuid" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip("\n")))')
|
||||
fi
|
||||
|
||||
python3 "$SHARE/patch-template.py" "$FLAKE_DIR" <<PYJSON
|
||||
{
|
||||
description = "$HOSTNAME_ — my Nomarchy machine";
|
||||
|
||||
# The only input. nixpkgs, home-manager etc. come pinned through it —
|
||||
# tested together upstream. Generated by nomarchy-install; your machine
|
||||
# lives in system.nix and home.nix, this file is never hand-edited.
|
||||
inputs.nomarchy.url = "${NOMARCHY_FLAKE_URL}";
|
||||
|
||||
outputs = { nomarchy, ... }:
|
||||
nomarchy.lib.mkFlake {
|
||||
src = ./.;
|
||||
username = "$USERNAME";
|
||||
hardwareProfile = [$hw_nix ];
|
||||
};
|
||||
"hostname": $(printf '%s' "$HOSTNAME_" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip("\n")))'),
|
||||
"username": $(printf '%s' "$USERNAME" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip("\n")))'),
|
||||
"timezone": $(printf '%s' "$TIMEZONE" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip("\n")))'),
|
||||
"locale": $(printf '%s' "$LOCALE" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip("\n")))'),
|
||||
"keyboardLayout": $(printf '%s' "$KB_LAYOUT" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip("\n")))'),
|
||||
"keyboardVariant": $(printf '%s' "$KB_VARIANT" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip("\n")))'),
|
||||
"hashedPassword": $(printf '%s' "$HASHED_PASSWORD" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().rstrip("\n")))'),
|
||||
"autoLogin": $([[ $WITH_LUKS == true ]] && echo true || echo false),
|
||||
"laptop": $is_laptop,
|
||||
"thermald": $thermald,
|
||||
"hardwareProfiles": $hw_json,
|
||||
"hardware": {
|
||||
"intel": $has_intel,
|
||||
"intelGucOff": $intel_guc_off,
|
||||
"amd": $has_amd,
|
||||
"fingerprint": $has_fp,
|
||||
"cameraIr": $has_camera_ir,
|
||||
"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,
|
||||
"rootUuid": $root_uuid_json
|
||||
}
|
||||
EOF
|
||||
|
||||
AUTOLOGIN_CONFIG=""
|
||||
if [[ $WITH_LUKS == true ]]; then
|
||||
AUTOLOGIN_CONFIG=$(cat <<NIX
|
||||
|
||||
# The LUKS passphrase already gates this machine — skip the second
|
||||
# password prompt and boot straight into the desktop.
|
||||
nomarchy.system.greeter.autoLogin = "$USERNAME";
|
||||
NIX
|
||||
)
|
||||
fi
|
||||
|
||||
# Laptop power: power-profiles-daemon ships by default; mark this a laptop
|
||||
# so battery-only features apply, and enable thermald on Intel. Keyed off
|
||||
# the same battery probe that chose the common-pc-laptop hardware profile.
|
||||
POWER_CONFIG=""
|
||||
if [[ " ${HW_PROFILES[*]:-} " == *" common-pc-laptop "* ]]; then
|
||||
power_lines=" # Laptop power management (power-profiles-daemon + menu/Waybar
|
||||
# switcher). Uncomment to stop charging at 80% to extend battery life.
|
||||
nomarchy.system.power.laptop = true;
|
||||
# nomarchy.system.power.batteryChargeLimit = 80;"
|
||||
if grep -q GenuineIntel /proc/cpuinfo 2>/dev/null; then
|
||||
power_lines+="
|
||||
nomarchy.system.power.thermal.enable = true; # thermald (Intel)"
|
||||
fi
|
||||
POWER_CONFIG=$(cat <<NIX
|
||||
|
||||
$power_lines
|
||||
NIX
|
||||
)
|
||||
fi
|
||||
|
||||
# Hardware enablement (nomarchy.hardware.*): what hardware-db.sh detected
|
||||
# above the nixos-hardware commons. Safe defaults active; the heavier or
|
||||
# experimental opt-ins written commented for the user to flip on.
|
||||
HARDWARE_CONFIG=""
|
||||
if [[ ${#HW_NOMARCHY[@]} -gt 0 || -n "$NPU_VENDOR" ]]; then
|
||||
has_intel=0; has_amd=0; has_fp=0; intel_guc_off=0; has_camera_ir=0
|
||||
if [[ ${#HW_NOMARCHY[@]} -gt 0 ]]; then
|
||||
for nm in "${HW_NOMARCHY[@]}"; do
|
||||
case "$nm" in
|
||||
hardware.intel.enable=true) has_intel=1 ;;
|
||||
hardware.intel.guc=false) intel_guc_off=1 ;;
|
||||
hardware.amd.enable=true) has_amd=1 ;;
|
||||
hardware.fingerprint.enable=true) has_fp=1 ;;
|
||||
hardware.camera.hideIrSensor=true) has_camera_ir=1 ;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
hw_lines=" # Hardware enablement (auto-detected). Safe defaults are active;
|
||||
# the heavier opt-ins are commented — uncomment to turn them on."
|
||||
if [[ $has_intel -eq 1 ]]; then
|
||||
hw_lines+="
|
||||
nomarchy.hardware.intel.enable = true; # GuC/HuC firmware (i915.enable_guc=3)"
|
||||
if [[ $intel_guc_off -eq 1 ]]; then
|
||||
hw_lines+="
|
||||
nomarchy.hardware.intel.guc = false; # GPU on the xe driver → GuC is default-on"
|
||||
fi
|
||||
hw_lines+="
|
||||
# nomarchy.hardware.intel.computeRuntime = true; # OpenCL/oneVPL GPU compute (opt-in)"
|
||||
fi
|
||||
if [[ $has_amd -eq 1 ]]; then
|
||||
hw_lines+="
|
||||
nomarchy.hardware.amd.enable = true; # amd-pstate EPP + radeonsi VA-API
|
||||
# nomarchy.hardware.amd.rocm.enable = true; # ROCm GPU compute (multi-GB, opt-in)
|
||||
# nomarchy.hardware.amd.rocm.gfxOverride = \"\"; # e.g. \"11.0.0\" for an unlisted iGPU"
|
||||
fi
|
||||
if [[ $has_fp -eq 1 ]]; then
|
||||
hw_lines+="
|
||||
nomarchy.hardware.fingerprint.enable = true; # fprintd (enroll: fprintd-enroll)
|
||||
# nomarchy.hardware.fingerprint.pam = true; # use it for login + sudo (opt-in)"
|
||||
fi
|
||||
if [[ $has_camera_ir -eq 1 ]]; then
|
||||
hw_lines+="
|
||||
nomarchy.hardware.camera.hideIrSensor = true; # dual-sensor webcam: hide the IR node (color cam only)"
|
||||
fi
|
||||
if [[ -n "$NPU_VENDOR" ]]; then
|
||||
hw_lines+="
|
||||
# nomarchy.hardware.npu.enable = true; # $NPU_VENDOR NPU driver (experimental; userspace runtime BYO)
|
||||
# nomarchy.hardware.latestKernel = true; # newest kernel if the NPU driver isn't in the shipped one"
|
||||
fi
|
||||
HARDWARE_CONFIG=$(cat <<NIX
|
||||
|
||||
$hw_lines
|
||||
NIX
|
||||
)
|
||||
fi
|
||||
|
||||
# initialHashedPassword is safe to template: mkpasswd's alphabet is
|
||||
# [a-zA-Z0-9./$] — no Nix string metacharacters.
|
||||
cat > "$FLAKE_DIR/system.nix" <<EOF
|
||||
# Your machine: hostname, users, services. The distro itself comes from
|
||||
# Nomarchy (via flake.nix); override its defaults here with plain NixOS
|
||||
# options, or the nomarchy.system.* toggles.
|
||||
{ pkgs, username, ... }:
|
||||
|
||||
{
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
|
||||
networking.hostName = "$HOSTNAME_";
|
||||
time.timeZone = "$TIMEZONE";
|
||||
i18n.defaultLocale = "$LOCALE";
|
||||
|
||||
# One keyboard layout everywhere: xkb is the source of truth, and the
|
||||
# distro defaults (console.useXkbConfig + the systemd initrd, set in
|
||||
# the nomarchy module) derive the virtual console and the LUKS
|
||||
# passphrase prompt from it — so only the chosen layout is written here.
|
||||
# The Hyprland session reads the same layout from nomarchy.keyboard.* in
|
||||
# home.nix.
|
||||
services.xserver.xkb.layout = "$KB_LAYOUT";
|
||||
services.xserver.xkb.variant = "$KB_VARIANT";
|
||||
|
||||
# Your login user — \`username\` flows in from flake.nix automatically.
|
||||
users.users.\${username} = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" "networkmanager" "video" "input" ];
|
||||
initialHashedPassword = "$HASHED_PASSWORD";
|
||||
};
|
||||
$AUTOLOGIN_CONFIG$POWER_CONFIG$HARDWARE_CONFIG$RESUME_CONFIG
|
||||
# Hourly/daily BTRFS timeline snapshots + nixos-rebuild-snap.
|
||||
nomarchy.system.snapper.enable = true;
|
||||
|
||||
system.stateVersion = "26.05";
|
||||
}
|
||||
EOF
|
||||
PYJSON
|
||||
|
||||
# The flake.lock: composed offline — nomarchy is path-locked to the very
|
||||
# source the ISO carries (original stays the forge URL, so a later
|
||||
|
||||
Reference in New Issue
Block a user