diff --git a/common.nix b/common.nix index 72e36c5..7f501be 100644 --- a/common.nix +++ b/common.nix @@ -9,6 +9,22 @@ let # 146%. Plain `-L` output there; the other hosts can afford the pretty one. buildLog = lib.optionalString (!isMacbook) " --log-format internal-json 2>&1 | nom --json"; + + flake = "git+https://forg.gregersen.it/rope/nixos"; + + post = "nvd diff $OLD_SYSTEM /run/current-system && (command -v record-update &>/dev/null && record-update $OLD_SYSTEM /run/current-system || true)"; + + # The server evaluates and builds for itself. + localUpdate = "bash -c 'set -o pipefail && OLD_SYSTEM=$(readlink /run/current-system) && sudo nixos-rebuild switch $@ --refresh --flake ${flake} -L${buildLog} && ${post}' --"; + + # The clients offload the *evaluation* too, not just the build. nixos-rebuild + # always evaluates on the machine it runs on (--build-host ships the + # derivation, not the expression), so the only way to move eval off a client + # is to run nix on the server over SSH and hand the resulting closure to + # --store-path, which skips eval and build entirely. Same lantian substituter + # as services/prebuild.nix, and --out-link keeps a gc root on the server so + # `clean` there can't reap the closure mid-copy. + remoteUpdate = "bash -c 'set -o pipefail && OLD_SYSTEM=$(readlink /run/current-system) && NEW=$(sudo ssh fred@nordhammer.it \"nix build --refresh --print-out-paths --out-link prebuild-${config.networking.hostName} --option extra-substituters https://attic.xuyh0120.win/lantian --option extra-trusted-public-keys lantian:EeAUQ+W+6r7EtwnmYjeVwx5kOGEBpjlBfPlzGlTNvHc= ${flake}#nixosConfigurations.${config.networking.hostName}.config.system.build.toplevel\") && sudo nix copy --from ssh://fred@nordhammer.it $NEW && sudo nixos-rebuild switch --store-path $NEW && ${post}'"; in { imports = [ @@ -122,7 +138,10 @@ in # Shell aliases (work in both bash and fish) environment.shellAliases = { - update = "bash -c 'set -o pipefail && OLD_SYSTEM=$(readlink /run/current-system) && sudo nixos-rebuild switch $@ --refresh --flake git+https://forg.gregersen.it/rope/nixos -L${buildLog} && nvd diff $OLD_SYSTEM /run/current-system && (command -v record-update &>/dev/null && record-update $OLD_SYSTEM /run/current-system || true)' --"; + update = + if config.networking.hostName == "FredOS-Mediaserver" + then localUpdate + else remoteUpdate; clean = "sudo nix-collect-garbage -d"; # Throw away the VM's disk first so every run is a real first boot — # greeter, Plasma first-run, the lot. Builds into ./result in $PWD. diff --git a/services/prebuild.nix b/services/prebuild.nix index 527ef75..44fcb41 100644 --- a/services/prebuild.nix +++ b/services/prebuild.nix @@ -3,8 +3,9 @@ # Both laptops/desktops offload builds to this host (nix.buildMachines in # common.nix), and the Macbook can't build at all (max-jobs = 0). Realising # their toplevels here ahead of time turns `update` on those machines into a -# pure copy: the offloaded build finds the path already in this store and just -# ships it back over SSH. +# pure copy: the client's `update` alias re-runs this exact nix build over SSH +# (so eval happens here too, against a warm eval cache), finds the path already +# realised, and only copies the closure back. # # --out-link doubles as the gc root, so `clean` doesn't reap the closures # before the other machines ever ask for them.