nix: Adopt Determinate Nix as the common Nix

Use Determinate Nix as `nix.package` for systems, homes and the
devshell, for its parallel evaluation and lazy trees. We only take the
package, not `determinate-nixd`: the daemon and `nix.conf` model are
unchanged and the Determinate NixOS module is not imported.

- Add the `determinate-nix` (`nix-src`) input, following our
  `nixpkgs-unstable`. FlakeHub's cache needs auth, so we build it
  ourselves and let it flow through Harmonia like everything else.
- `determinateOverlay` exposes it as `pkgs'.mine.determinate-nix`;
  `lib.my.c.nix.determinateSettings` (`lazy-trees`, `eval-cores = 0`)
  is merged into `nix.settings` and the devshell `nix.conf`.
- Switch CI to `DeterminateSystems/determinate-nix-action` so the
  runner itself evaluates with Determinate.
- Advertise the Harmonia cache via the flake's `nixConfig`, trusted
  without a prompt via `accept-flake-config` in the devshell, `.envrc`
  and CI only (boxes already trust it through `nix.settings`).
- Re-attach `pkgs`/`lib` to container and installer
  `nixosConfigurations` so Determinate's flake schemas can evaluate
  them (`nix flake check` otherwise fails with `attribute 'pkgs'
  missing`).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-03 21:07:02 +01:00
parent 1ca978baf4
commit 7fe3c8186c
10 changed files with 208 additions and 16 deletions
+3 -1
View File
@@ -1,2 +1,4 @@
watch_file devshell/{default,commands,install,vm-tasks}.nix watch_file devshell/{default,commands,install,vm-tasks}.nix
use flake # --accept-flake-config trusts the flake's nixConfig (our Harmonia cache) non-interactively, so
# direnv doesn't stall on the trust prompt.
use flake . --accept-flake-config
+10 -5
View File
@@ -10,17 +10,22 @@ jobs:
runs-on: ubuntu-26.04 runs-on: ubuntu-26.04
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
- uses: cachix/install-nix-action@v31 - uses: DeterminateSystems/determinate-nix-action@v3
with: with:
# Gitea will supply a token in GITHUB_TOKEN, which this action will # Gitea will supply a token in GITHUB_TOKEN, which this action passes to
# try to pass to Nix when downloading from GitHub # Nix (as access-tokens) when downloading from GitHub
github_access_token: ${{ secrets.GH_PULL_TOKEN }} github-token: ${{ secrets.GH_PULL_TOKEN }}
extra_nix_config: | extra-conf: |
# Make sure we're using sandbox # Make sure we're using sandbox
sandbox-fallback = false sandbox-fallback = false
# Big C++ projects fill up memory... # Big C++ projects fill up memory...
cores = 6 cores = 6
# Determinate performance features
lazy-trees = true
eval-cores = 0
accept-flake-config = true
extra-substituters = https://nix-cache.nul.ie extra-substituters = https://nix-cache.nul.ie
extra-trusted-public-keys = nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4= extra-trusted-public-keys = nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4=
+4 -1
View File
@@ -12,6 +12,9 @@ in
NIX_USER_CONF_FILES = toString (pkgs.writeText "nix.conf" NIX_USER_CONF_FILES = toString (pkgs.writeText "nix.conf"
'' ''
experimental-features = nix-command flakes ca-derivations experimental-features = nix-command flakes ca-derivations
lazy-trees = true
eval-cores = 0
accept-flake-config = true
connect-timeout = 5 connect-timeout = 5
fallback = true fallback = true
${lib.my.c.nix.cache.conf} ${lib.my.c.nix.cache.conf}
@@ -22,7 +25,7 @@ in
packages = with pkgs; [ packages = with pkgs; [
coreutils coreutils
nixVersions.stable determinate-nix
rage rage
wireguard-tools wireguard-tools
(pkgs.writeShellScriptBin "deploy" '' (pkgs.writeShellScriptBin "deploy" ''
+1 -1
View File
@@ -29,7 +29,7 @@ let
coreutils coreutils
gnugrep gnugrep
openssh openssh
nixVersions.stable determinate-nix
jq jq
]; ];
text = text =
+29 -2
View File
@@ -110,6 +110,31 @@ VM's unix sockets from `/run/vms/<vm>/` on `<host>` over SSH):
| `vm-monitor <host> <vm>` | QEMU monitor socket in `minicom`. | | `vm-monitor <host> <vm>` | QEMU monitor socket in `minicom`. |
| `vm-viewer <host> <vm>` | SPICE display in `virt-viewer` (not on Darwin). | | `vm-viewer <host> <vm>` | SPICE display in `virt-viewer` (not on Darwin). |
## Nix implementation
Every context uses **Determinate Nix** as its `nix.package`, for its performance features
(parallel evaluation and lazy trees) — not `determinate-nixd`; the daemon and `nix.conf` model
are unchanged, and the Determinate NixOS module is deliberately not imported.
- **Input and package.** The [`determinate-nix`](../flake.nix) input is the `nix-src` flake
(`flakehub.com/f/DeterminateSystems/nix-src`), with `nixpkgs.follows = "nixpkgs-unstable"`. We
build it ourselves against our pinned nixpkgs — FlakeHub's own cache needs authentication, so
there is nothing to gain from leaving it unpinned — and it then flows through the Harmonia cache
like everything else. `determinateOverlay` exposes it under the stable attr `determinate-nix`,
added to both the devshell `pkgs'` and the config `configPkgs'` overlay lists, so systems, homes
and the devshell all resolve the same package (`pkgs'.mine.determinate-nix`).
- **Settings.** `lib.my.c.nix.determinateSettings` (`lazy-trees`, `eval-cores = 0`) is merged into
`nix.settings` for systems and homes and into the devshell's `nix.conf`. These keys are only
understood by the Determinate binary.
- **Consumers follow automatically.** Everything that shells out to Nix references
`config.nix.package` (deploy-rs, containers, `build`, netboot, Harmonia), so they inherit
Determinate without further change.
- **`accept-flake-config`.** Set true only in the devshell `nix.conf`, `.envrc` (as
`--accept-flake-config`, for direnv) and CI — the contexts that build this flake — so its
`nixConfig` (the Harmonia cache) is trusted without an interactive prompt. It is deliberately not
set system-wide: boxes already trust that cache via `nix.settings`, so a global setting would only
blanket-trust every flake's `nixConfig` for no gain.
## Secrets ## Secrets
Secrets are age-encrypted files in [`secrets/`](../secrets), managed with **ragenix** (a fork Secrets are age-encrypted files in [`secrets/`](../secrets), managed with **ragenix** (a fork
@@ -152,8 +177,10 @@ GitHub/Gitea Actions workflows live in [`.gitea/workflows/`](../.gitea/workflows
### `ci.yaml` ### `ci.yaml`
On pushes to `master`, this runs `nix flake check --no-build`, then builds every attribute of On pushes to `master`, this installs Determinate Nix on the runner (via
`.#ci.x86_64-linux`: systems as `system-<name>`, homes as `home-<name>` (with `@` changed to `DeterminateSystems/determinate-nix-action`, configured with the same performance settings and
Harmonia substituter as the boxes), runs `nix flake check --no-build`, then builds every attribute
of `.#ci.x86_64-linux`: systems as `system-<name>`, homes as `home-<name>` (with `@` changed to
`-at-`), packages as `package-<name>`, and the development `shell`. Each result is pushed to the `-at-`), packages as `package-<name>`, and the development `shell`. Each result is pushed to the
Harmonia cache with [`ci/push-to-cache.sh`](../ci/push-to-cache.sh). Harmonia cache with [`ci/push-to-cache.sh`](../ci/push-to-cache.sh).
Generated
+116
View File
@@ -163,6 +163,29 @@
"type": "github" "type": "github"
} }
}, },
"determinate-nix": {
"inputs": {
"flake-parts": "flake-parts",
"git-hooks-nix": "git-hooks-nix",
"nixpkgs": [
"nixpkgs-unstable"
],
"nixpkgs-23-11": "nixpkgs-23-11",
"nixpkgs-regression": "nixpkgs-regression"
},
"locked": {
"lastModified": 1785428605,
"narHash": "sha256-wfaiSRLM1wDb4MV+NEzbyheK9Y03/oe56NR2I84UF7E=",
"rev": "0ff46631f69584c9f76792cae595ea253bd482c3",
"revCount": 26288,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/DeterminateSystems/nix-src/3.21.9/019fb409-4d6e-7243-8a88-23ceee2520e9/source.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://flakehub.com/f/DeterminateSystems/nix-src/%2A"
}
},
"devshell": { "devshell": {
"inputs": { "inputs": {
"flake-utils": "flake-utils", "flake-utils": "flake-utils",
@@ -256,6 +279,42 @@
"type": "github" "type": "github"
} }
}, },
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"determinate-nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1748821116,
"narHash": "sha256-F82+gS044J1APL0n4hH50GYdPRv/5JWm34oCJYmVKdE=",
"rev": "49f0870db23e8c1ca0b5259734a02cd9e1e371a1",
"revCount": 377,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/hercules-ci/flake-parts/0.1.377%2Brev-49f0870db23e8c1ca0b5259734a02cd9e1e371a1/01972f28-554a-73f8-91f4-d488cc502f08/source.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://flakehub.com/f/hercules-ci/flake-parts/0.1"
}
},
"flake-utils": { "flake-utils": {
"inputs": { "inputs": {
"systems": "systems" "systems": "systems"
@@ -460,6 +519,30 @@
"type": "github" "type": "github"
} }
}, },
"git-hooks-nix": {
"inputs": {
"flake-compat": "flake-compat_2",
"gitignore": [
"determinate-nix"
],
"nixpkgs": [
"determinate-nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1747372754,
"narHash": "sha256-2Y53NGIX2vxfie1rOW0Qb86vjRZ7ngizoo+bnXU9D9k=",
"rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46",
"revCount": 1026,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/cachix/git-hooks.nix/0.1.1026%2Brev-80479b6ec16fefd9c1db3ea13aeb038c60530f46/0196d79a-1b35-7b8e-a021-c894fb62163d/source.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://flakehub.com/f/cachix/git-hooks.nix/0.1.941"
}
},
"harmonia": { "harmonia": {
"inputs": { "inputs": {
"crane": "crane", "crane": "crane",
@@ -655,6 +738,22 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-23-11": {
"locked": {
"lastModified": 1717159533,
"narHash": "sha256-oamiKNfr2MS6yH64rUn99mIZjc45nGJlj9eGth/3Xuw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446",
"type": "github"
}
},
"nixpkgs-mine": { "nixpkgs-mine": {
"locked": { "locked": {
"lastModified": 1781356656, "lastModified": 1781356656,
@@ -687,6 +786,22 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-regression": {
"locked": {
"lastModified": 1643052045,
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
}
},
"nixpkgs-stable": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1780902259, "lastModified": 1780902259,
@@ -847,6 +962,7 @@
"borgthin": "borgthin", "borgthin": "borgthin",
"copyparty": "copyparty", "copyparty": "copyparty",
"deploy-rs": "deploy-rs", "deploy-rs": "deploy-rs",
"determinate-nix": "determinate-nix",
"devshell": "devshell_3", "devshell": "devshell_3",
"flake-utils": "flake-utils_6", "flake-utils": "flake-utils_6",
"harmonia": "harmonia", "harmonia": "harmonia",
+33 -1
View File
@@ -1,6 +1,19 @@
{ {
description = "System configs"; description = "System configs";
# Offer our Harmonia cache when building the flake itself, so `nix develop` / `nix build` don't
# rebuild from source. Nix reads `nixConfig` before the flake evaluates and rejects any computed
# value (imports/thunks), so these must stay literal — keep them in sync with `lib.my.c.nix.cache`.
# Consumers must trust these (accept-flake-config / a trusted user) for them to take effect.
nixConfig = {
extra-substituters = [
"https://nix-cache.nul.ie"
];
extra-trusted-public-keys = [
"nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4="
];
};
inputs = { inputs = {
flake-utils.url = "github:numtide/flake-utils"; flake-utils.url = "github:numtide/flake-utils";
# libnet.url = "github:reo101/nix-lib-net"; # libnet.url = "github:reo101/nix-lib-net";
@@ -21,6 +34,12 @@
home-manager-stable.url = "home-manager/release-26.05"; home-manager-stable.url = "home-manager/release-26.05";
home-manager-stable.inputs.nixpkgs.follows = "nixpkgs-stable"; home-manager-stable.inputs.nixpkgs.follows = "nixpkgs-stable";
# Determinate Nix, used as the common Nix implementation across systems, homes, the devshell and
# CI (see lib.my.c.nix). We build it ourselves against our pinned nixpkgs (FlakeHub's cache needs
# auth), so it flows through our own Harmonia cache like everything else.
determinate-nix.url = "https://flakehub.com/f/DeterminateSystems/nix-src/*";
determinate-nix.inputs.nixpkgs.follows = "nixpkgs-unstable";
# Stuff used by the flake for build / deployment # Stuff used by the flake for build / deployment
# ragenix.url = "github:yaxitech/ragenix"; # ragenix.url = "github:yaxitech/ragenix";
ragenix.url = "github:devplayer0/ragenix/add-rekey-one-flag"; ragenix.url = "github:devplayer0/ragenix/add-rekey-one-flag";
@@ -83,6 +102,11 @@
}; };
pkgsLibOverlay = final: prev: { lib = prev.lib.extend libOverlay; }; pkgsLibOverlay = final: prev: { lib = prev.lib.extend libOverlay; };
myPkgsOverlay = final: prev: import ./pkgs { lib = final.lib; pkgs = prev; }; myPkgsOverlay = final: prev: import ./pkgs { lib = final.lib; pkgs = prev; };
# Exposes Determinate Nix under a stable attr name so systems, homes and the devshell all
# resolve the exact same package (referenced as `pkgs'.mine.determinate-nix` in configs).
determinateOverlay = final: prev: {
determinate-nix = inputs.determinate-nix.packages.${prev.stdenv.hostPlatform.system}.default;
};
# Override the flake-level lib since we're going to use it for non-config specific stuff # Override the flake-level lib since we're going to use it for non-config specific stuff
pkgsFlakes = mapAttrs (_: pkgsFlake: pkgsFlake // { lib = pkgsFlake.lib.extend libOverlay; }) { pkgsFlakes = mapAttrs (_: pkgsFlake: pkgsFlake // { lib = pkgsFlake.lib.extend libOverlay; }) {
@@ -111,6 +135,7 @@
pkgsLibOverlay pkgsLibOverlay
myPkgsOverlay myPkgsOverlay
determinateOverlay
inputs.devshell.overlays.default inputs.devshell.overlays.default
inputs.ragenix.overlays.default inputs.ragenix.overlays.default
inputs.deploy-rs.overlays.default inputs.deploy-rs.overlays.default
@@ -126,6 +151,7 @@
pkgsLibOverlay pkgsLibOverlay
myPkgsOverlay myPkgsOverlay
determinateOverlay
]; ];
config = { config = {
@@ -187,7 +213,13 @@
nixosModules = nixfiles.config.nixos.modules; nixosModules = nixfiles.config.nixos.modules;
homeModules = nixfiles.config.home-manager.modules; homeModules = nixfiles.config.home-manager.modules;
nixosConfigurations = mapAttrs (_: s: s.rendered) nixfiles.config.nixos.systems; # Containers and the installer override `rendered` with a bare `extendModules` config
# (`my.asContainer` / `my.asISO`) that lacks the `pkgs`/`lib` attrs `eval-config` exposes on a
# normal system. Determinate Nix's flake schemas read `machine.pkgs.stdenv.system` for every
# `nixosConfigurations` entry, so re-attach them from the full system eval (`configuration`).
nixosConfigurations = mapAttrs
(_: s: s.rendered // { inherit (s.configuration) pkgs lib; })
nixfiles.config.nixos.systems;
homeConfigurations = mapAttrs (_: s: s.configuration) nixfiles.config.home-manager.homes; homeConfigurations = mapAttrs (_: s: s.configuration) nixfiles.config.home-manager.homes;
deploy = nixfiles.config.deploy-rs.rendered; deploy = nixfiles.config.deploy-rs.rendered;
+3 -3
View File
@@ -50,7 +50,7 @@ in
}; };
nix = { nix = {
settings = with lib.my.c.nix; { settings = with lib.my.c.nix; determinateSettings // {
experimental-features = [ "nix-command" "flakes" "ca-derivations" ]; experimental-features = [ "nix-command" "flakes" "ca-derivations" ];
max-jobs = mkDefault "auto"; max-jobs = mkDefault "auto";
@@ -256,13 +256,13 @@ in
ssh.authKeys.files = [ lib.my.c.sshKeyFiles.me ]; ssh.authKeys.files = [ lib.my.c.sshKeyFiles.me ];
}; };
nix.package = pkgs.nix; nix.package = pkgs'.mine.determinate-nix;
fonts.fontconfig.enable = true; fonts.fontconfig.enable = true;
home = { home = {
packages = with pkgs; [ packages = with pkgs; [
pkgs'.mine.nix pkgs'.mine.determinate-nix
]; ];
# Without this, we are at the mercy of whatever version of nix is in $PATH... # Without this, we are at the mercy of whatever version of nix is in $PATH...
+7
View File
@@ -111,6 +111,13 @@ rec {
extra-trusted-public-keys = ${concatStringsSep " " keys} extra-trusted-public-keys = ${concatStringsSep " " keys}
''; '';
}; };
# Determinate-specific settings enabling its performance features. Only understood by the
# Determinate Nix binary, so they must not be emitted for a base-Nix package.
determinateSettings = {
lazy-trees = true;
eval-cores = 0;
};
}; };
pubDomain = "nul.ie"; pubDomain = "nul.ie";
+2 -2
View File
@@ -50,9 +50,9 @@ in
}; };
nix = { nix = {
package = pkgs'.mine.nix; package = pkgs'.mine.determinate-nix;
channel.enable = false; channel.enable = false;
settings = with lib.my.c.nix; { settings = with lib.my.c.nix; determinateSettings // {
trusted-users = [ "@wheel" ]; trusted-users = [ "@wheel" ];
experimental-features = [ "nix-command" "flakes" "ca-derivations" ]; experimental-features = [ "nix-command" "flakes" "ca-derivations" ];
extra-substituters = cache.substituters; extra-substituters = cache.substituters;