From bef7be01b8540039b855f9d5a8c946bdbcba3ce1 Mon Sep 17 00:00:00 2001 From: Bernardo Magri Date: Sat, 2 May 2026 12:24:12 +0100 Subject: [PATCH] fix(installer): wire HM as a NixOS module, move env-update to system layer The post-install standalone HM activation kept failing in new ways (daemon access, git ownership, missing PATH on first boot). Wire HM as a NixOS module in the generated flake instead, so first-boot dotfiles are activated by `nixos-install` itself with proper system context. The standalone `homeConfigurations.` is kept alongside for fast iteration via `nomarchy-env-update`. Also: - Drop the chroot HM activation block from the installer entirely. - Move `nomarchy-env-update` from `features/scripts/utils/` to `core/system/scripts/` so it ships in `nomarchy-system-scripts` and exists on a freshly-installed system regardless of HM state. - Set system-wide git `safe.directory` for /etc/nixos and the impermanence-relocated /persist/etc/nixos so the user-mode HM run doesn't trip on the root-owned flake repo. Co-Authored-By: Claude Opus 4.7 --- core/system/scripts.nix | 9 +++ .../system/scripts}/nomarchy-env-update | 14 ++-- installer/install.sh | 77 +++++++------------ 3 files changed, 43 insertions(+), 57 deletions(-) rename {features/scripts/utils => core/system/scripts}/nomarchy-env-update (60%) mode change 100644 => 100755 diff --git a/core/system/scripts.nix b/core/system/scripts.nix index a4c610a..7ed306d 100644 --- a/core/system/scripts.nix +++ b/core/system/scripts.nix @@ -2,4 +2,13 @@ { environment.systemPackages = [ pkgs.nomarchy-system-scripts ]; + + # /etc/nixos is owned by root, but `nomarchy-env-update` (and `nix + # flake` invocations) run as the user and shell out to git. Without + # this, git refuses with "dubious ownership in repository" and HM + # evaluation fails. Mark both the standard and impermanence-relocated + # paths as safe at the system level so every user is covered. + programs.git.config = { + safe.directory = [ "/etc/nixos" "/persist/etc/nixos" ]; + }; } diff --git a/features/scripts/utils/nomarchy-env-update b/core/system/scripts/nomarchy-env-update old mode 100644 new mode 100755 similarity index 60% rename from features/scripts/utils/nomarchy-env-update rename to core/system/scripts/nomarchy-env-update index 9e3e207..57624ec --- a/features/scripts/utils/nomarchy-env-update +++ b/core/system/scripts/nomarchy-env-update @@ -1,12 +1,13 @@ #!/usr/bin/env bash # Nomarchy Environment Update Script -# 1. Runs the pre-flight state migration -# 2. Applies user-level Home Manager changes (Standalone) +# Standalone Home Manager iteration path. Use this for fast dotfile and +# theme changes that don't need a full system rebuild. For first-boot +# dotfiles and any system-level change, the NixOS module activation +# from `sudo nixos-rebuild switch` is the source of truth. set -e -# Detect the repository location if [ -f "/etc/nixos/flake.nix" ]; then REPO_DIR="/etc/nixos" elif [ -f "/etc/nomarchy/flake.nix" ]; then @@ -16,19 +17,16 @@ else exit 1 fi -# Use the pre-flight migration script to ensure the state is synced before evaluation if command -v nomarchy-preflight-migration >/dev/null 2>&1; then nomarchy-preflight-migration fi -# Apply Home Manager changes from the local flake (Standalone). -# On a freshly-installed system where the installer's HM activation failed, -# `home-manager` won't be on PATH yet — fall back to `nix run` so this -# script can recover the install instead of erroring on a missing binary. echo "Applying user-level changes from $REPO_DIR#$USER..." if command -v home-manager >/dev/null 2>&1; then home-manager switch --flake "$REPO_DIR#$USER" --impure else + # Bootstrap path: HM hasn't put `home-manager` on PATH yet (e.g. running + # straight after a partial install). Pull it from the flake registry. nix --extra-experimental-features 'nix-command flakes' \ run 'home-manager/release-25.11' \ -- switch --flake "$REPO_DIR#$USER" --impure diff --git a/installer/install.sh b/installer/install.sh index e4dde6d..873abe1 100755 --- a/installer/install.sh +++ b/installer/install.sh @@ -1256,47 +1256,10 @@ execute_installation() { nixos-install --flake "/mnt/etc/nixos#$HOSTNAME" --no-root-passwd success "Nomarchy installed" - # 9.8 Activate Home Manager for $USERNAME inside the new system so the - # user's first login already has Nomarchy's dotfiles. `home-manager - # switch` must run as the target user with a real \$HOME *and* a - # \$USER env var pointing at them — home-manager's activation script - # bails with "running as root" if \$USER is still root, even when the - # uid has been switched. `runuser -l` runs a login shell, which sets - # HOME, USER, LOGNAME, and SHELL from the user database; plain - # `runuser -u … -- env HOME=…` switches uid only and leaves \$USER - # as root, which is what landed the dotfiles in /root previously. - info "Activating Home Manager for $USERNAME..." - # `nixos-enter` chroots without starting systemd, so nix-daemon isn't - # running. A user-level `nix run` would then fall back to single-user - # mode and try to write /nix/var/nix/db directly — which root owns in - # the multi-user store, so it fails with "big.lock: Permission denied". - # Launch the daemon manually for the duration of the activation. - if nixos-enter --root /mnt -- bash -c " - set -e - install -d -o '$USERNAME' -g users -m 0755 '/home/$USERNAME' - - # /etc/nixos is a git repo owned by root (we init it as root above). - # When HM runs as the user, nix invokes git, which refuses with - # 'dubious ownership' unless the path is marked safe system-wide. - git config --system --add safe.directory /etc/nixos || true - git config --system --add safe.directory /persist/etc/nixos || true - - /run/current-system/sw/bin/nix-daemon --daemon & - DAEMON_PID=\$! - trap 'kill \$DAEMON_PID 2>/dev/null || true' EXIT - - for _ in \$(seq 1 50); do - [ -S /nix/var/nix/daemon-socket/socket ] && break - sleep 0.1 - done - - runuser -l '$USERNAME' -c \"NIX_REMOTE=daemon nix --extra-experimental-features 'nix-command flakes' run 'home-manager/release-25.11' -- switch --flake '/etc/nixos#$USERNAME' --impure\" - "; then - success "Home Manager activated" - else - error "Home Manager activation failed (non-fatal)." - info "Run \`nomarchy-env-update\` after the first login to retry." - fi + # 9.8 (Removed) Standalone Home Manager activation in a chroot. + # HM is now wired as a NixOS module in the generated flake, so + # `nixos-install` above already activated the user's dotfiles as part + # of system activation. No chroot dance required. # 9.9 Pre-flight: catch evaluation errors in the freshly-installed # configuration *now*, while we can still fix them with `vi`, instead of @@ -1432,11 +1395,15 @@ generate_flake_config() { }; # Two-track Nomarchy workflow: - # * System changes → sudo nixos-rebuild switch --flake /etc/nixos#$HOSTNAME - # * Dotfiles/themes → nomarchy-env-update (home-manager switch, no rebuild) + # * System + dotfiles (full) → sudo nixos-rebuild switch --flake /etc/nixos#$HOSTNAME + # * Dotfiles only (fast iter) → nomarchy-env-update (standalone home-manager switch) # - # Both consume the same \`pkgs\` below so overlays and allowUnfree stay in - # sync across the two paths. + # Home Manager is wired both ways: + # - As a NixOS module under \`nixosConfigurations.$HOSTNAME\` so first boot + # after install already has dotfiles in place and every nixos-rebuild + # reconciles them. This is what makes the install actually usable. + # - As a standalone \`homeConfigurations.$USERNAME\` so theme switches and + # dotfile iteration don't require a full system rebuild. outputs = { self, nomarchy, ... }@inputs: let inherit (nomarchy.inputs) nixpkgs home-manager; @@ -1459,12 +1426,24 @@ generate_flake_config() { ./hardware-selection.nix nomarchy.nixosModules.system ./system.nix + + home-manager.nixosModules.home-manager + { + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + home-manager.backupFileExtension = "hm-bak"; + home-manager.extraSpecialArgs = { inputs = nomarchy.inputs; }; + home-manager.users.$USERNAME = { + imports = [ nomarchy.nixosModules.home ./home.nix ]; + home.stateVersion = "25.11"; + }; + } ]; }; # Standalone Home Manager — \`home-manager switch --flake /etc/nixos#$USERNAME\` - # (which is what \`nomarchy-env-update\` runs). Kept separate from the - # NixOS config so dotfile/theme iterations don't rebuild the system. + # (which is what \`nomarchy-env-update\` runs). Kept alongside the NixOS + # module above so dotfile/theme iterations can skip a full system rebuild. homeConfigurations.$USERNAME = home-manager.lib.homeManagerConfiguration { inherit pkgs; extraSpecialArgs = { inputs = nomarchy.inputs; }; @@ -1721,8 +1700,8 @@ finish() { echo " 4. Your configuration lives at /etc/nixos/" echo "" echo "Rebuild commands:" - echo " • System: sudo nixos-rebuild switch --flake /etc/nixos#$HOSTNAME" - echo " • Dotfiles: nomarchy-env-update (runs home-manager switch)" + echo " • System + dotfiles: sudo nixos-rebuild switch --flake /etc/nixos#$HOSTNAME" + echo " • Dotfiles only: nomarchy-env-update (fast standalone home-manager switch)" echo "" echo "Tip: run 'nomarchy-themes-prebuild' once to pre-cache every theme" echo " variant. Theme switches after that are instant (no rebuild)."