ci: trust niri.cachix.org substituter in flake-check workflow (ADR-028)#59
Merged
Conversation
Companion to slice 3b.5 (#57). Slice 3b.5 added niri.cachix.org to nix.settings in modules/core/nixos/niri.nix — that configures the substituter on deployed systems *after* `nh os switch`. CI's nix daemon reads its own config from cachix/install-nix-action's extra_nix_config, which (until this commit) did not include niri.cachix.org. Without this trust in CI, flake-check source-builds niri on the x86_64-linux matrix entry when any host imports the desktop-env bundle, and the source build hits the in-flight nixpkgs Rust crate fetcher 403 cascade (rust-lang/crates.io#13482, NixOS/nixpkgs#512735). Slice 3d (next) is the first commit that imports the bundle into a host, so this trust must land first. Implementation: - Adds `extra-substituters = https://niri.cachix.org` and the matching `extra-trusted-public-keys` line to the workflow's extra_nix_config. - Uses the `extra-` prefix so it appends to install-nix-action's defaults rather than replacing them (cache.nixos.org is preserved). - `accept-flake-config = false` is preserved unchanged — transitive flake inputs still cannot silently mutate config; only this operator-owned line adds new trust. The whitelist principle is intact. Cross-arch note: niri.cachix.org serves x86_64-linux only. flake-check builds every host's system.build.toplevel including the aarch64 nixos-vm host, but nixos-vm does not import the niri module, so the aarch64 matrix entry lists the substituter but never queries it. Header comment updated to remove the prior "binary-cache config in a follow-up workflow tweak" placeholder and replace with the rationale + source-of-key + cross-arch reasoning. Peer-reviewed (8 checkpoints: extra- semantics, block-scalar format, key byte-match against modules/core/nixos/niri.nix, whitelist preservation, YAML indent, actionlint compatibility, cross-arch correctness, concurrency). Per ADR-028 §Implementation slice 3 (amendment).
dannyfaris
added a commit
that referenced
this pull request
May 28, 2026
First commit that imports the slice-3 desktop bundles into a real host. Two-line addition to hosts/metis/default.nix: - modules/core/nixos/bundles/desktop-env.nix added to `imports` (alongside bundles/remote-access.nix). - home/core/nixos/bundles/desktop-env.nix added to hostContext.extraHomeModules (after the shared theming bundle, before standalones). This is the integration test for the four merged slice-3 PRs: - #42 (3a) — flake inputs - #44 (3b) — system bundle scaffold (niri + greetd + fonts + DMS bridge) - #55 (3c) — home bundle scaffold (niri binds + foot + DMS) - #57 (3b.5) — niri.cachix.org substituter in nix.settings …plus the CI-side half currently in flight at #59 (extra_nix_config in flake-check workflow). This branch is stacked on desktop-env/ci-niri-cache-trust so the CI workflow trust is in place when CI evaluates this PR. Closure delta on metis (expected): niri (from niri.cachix.org), greetd + tuigreet, Quickshell + Qt6 + matugen + DMS deps, xdg-desktop-portal-gnome, polkit-kde-agent-1, gnome-keyring, Inter, Noto Color Emoji, foot. No regression expected on mercury or nixos-vm — neither imports the bundles. Local build verification not possible — dbf is not in nix's trusted-users, so runtime substituter additions are rejected. The integration test fires in CI where the GH Actions runner is trusted and the workflow already declares extra-substituters via #59 (which this branch inherits). No `nh os switch` here; that's slice 5. Peer-reviewed (8 checkpoints: bundle placement, no auto-discovery, closure delta sanity, eval-without-cache, CI matrix arch scoping, CI ordering / branch base, merge-order safety, edge cases including HM module order, Stylix font conflicts, pre-commit hooks). Per ADR-028 §Implementation slice 3.
5 tasks
dannyfaris
added a commit
that referenced
this pull request
May 28, 2026
First commit that imports the slice-3 desktop bundles into a real host. Two-line addition to hosts/metis/default.nix: - modules/core/nixos/bundles/desktop-env.nix added to `imports` (alongside bundles/remote-access.nix). - home/core/nixos/bundles/desktop-env.nix added to hostContext.extraHomeModules (after the shared theming bundle, before standalones). This is the integration test for the four merged slice-3 PRs: - #42 (3a) — flake inputs - #44 (3b) — system bundle scaffold (niri + greetd + fonts + DMS bridge) - #55 (3c) — home bundle scaffold (niri binds + foot + DMS) - #57 (3b.5) — niri.cachix.org substituter in nix.settings …plus the CI-side half currently in flight at #59 (extra_nix_config in flake-check workflow). This branch is stacked on desktop-env/ci-niri-cache-trust so the CI workflow trust is in place when CI evaluates this PR. Closure delta on metis (expected): niri (from niri.cachix.org), greetd + tuigreet, Quickshell + Qt6 + matugen + DMS deps, xdg-desktop-portal-gnome, polkit-kde-agent-1, gnome-keyring, Inter, Noto Color Emoji, foot. No regression expected on mercury or nixos-vm — neither imports the bundles. Local build verification not possible — dbf is not in nix's trusted-users, so runtime substituter additions are rejected. The integration test fires in CI where the GH Actions runner is trusted and the workflow already declares extra-substituters via #59 (which this branch inherits). No `nh os switch` here; that's slice 5. Peer-reviewed (8 checkpoints: bundle placement, no auto-discovery, closure delta sanity, eval-without-cache, CI matrix arch scoping, CI ordering / branch base, merge-order safety, edge cases including HM module order, Stylix font conflicts, pre-commit hooks). Per ADR-028 §Implementation slice 3.
6 tasks
dannyfaris
added a commit
that referenced
this pull request
May 28, 2026
… font size, DMS dynamic-theming off) (#63) Three pre-activation hardening edits across the desktop-env module set. Co-motivated: each is needed before slice 5 (first activation on metis) can run cleanly, but none belongs in the slice 5 PR itself (that one records the activation outcome). Single commit, three files. modules/core/nixos/niri.nix Add `systemd.user.services.niri.enableDefaultPath = false;`. niri-session imports the user-manager PATH at session start; the NixOS default would otherwise inject a stripped PATH on niri.service that shadows it, breaking binary resolution for niri-spawned helpers. nixpkgs's own niri module sets this verbatim at nixos/modules/programs/wayland/niri.nix:51; niri-flake's nixosModule does not. Required companion when launching niri-session via greetd. modules/core/nixos/desktop-fonts.nix Add `stylix.fonts.sizes.terminal = 11;`. foot 1.15.0 changed `dpi-aware` from `auto` to `no`, which Stylix's foot target adopts verbatim. Under that default, `:size=N` (points) is multiplied by the compositor scale rather than the monitor DPI; on a scale-1 output the historical sizing reads smaller. 11pt approximates the prior visual size; operator may retune in slice 5. home/core/nixos/dms.nix Add `programs.dank-material-shell.enableDynamicTheming = false;` at the top level (NOT under `.settings.` — verified against DMS upstream `distro/nix/options.nix:58`). Load-bearing for the Stylix-decoupling decision (ADR-028 §History 2026-05-29): this is the single gate in DMS's `distro/nix/common.nix:19` (`++ lib.optional cfg.enableDynamicTheming pkgs.matugen`) that pulls matugen into the closure. With it false, matugen is absent from build and runtime and cannot stomp the GTK/Qt files Stylix's gtk/qt targets already manage. Header comment rewritten: drop the "slice 4 (issue #34) owns the customThemeFile" paragraph (slice 4 deferred indefinitely); add a decoupling note pointing to ADR-028 §History 2026-05-29; reframe the Q10 TODO (enableKeybinds + includes.enable overlap warning) to "next iteration on the niri/DMS interface" rather than "revisit at slice 4". Verified: - All three files parse + treefmt clean + nix flake check --no-build succeeds. - Slice 3b.5's substituter whitelist (niri-flake.cache.enable = false + nix.settings entries in niri.nix) survives the niri.nix edit. - All four DMS option-path references use the correct top-level `programs.dank-material-shell.enableDynamicTheming` (peer review caught the path during planning; this commit applies the fix). - No matugen reference remains in the nix sources outside the dms.nix comment that documents the gate. - Bundles + hosts/metis/default.nix untouched. Local build (`nix build .#nixosConfigurations.metis...`) source-builds niri locally and hits the in-flight crates.io 403 cascade because the operator's user is not in nix's trusted-users — same constraint hit during slice 3d. CI is the real integration test (the workflow has extra-substituters for niri.cachix.org per #59 on main). Peer-reviewed; three non-blocking nits surfaced + agreed with operator (comment phrasing fixed; attribute order + TODO cross-reference left as-is). Per ADR-028 §Implementation slice 5 prep (post-§History 2026-05-29).
3 tasks
dannyfaris
added a commit
that referenced
this pull request
May 28, 2026
… cold runs (#61) Inserts a cache-nix-action@v7 step between cachix/install-nix-action and nix flake check. Per-arch cache key keyed on hashFiles('flake.lock') so lockfile bumps invalidate cleanly; per-arch restore-prefix lets PR branches restore from default-branch entries (the squash-auto-merge flow seeds each new entry). Amortises the non-niri portion of metis's desktop closure across cold CI runs: Quickshell + Qt6 + DMS (dms-shell) + xwayland-satellite + foot + greetd transitive deps. niri itself comes from niri.cachix.org via the extra-substituters trust added in #59 and doesn't need this; matugen is suppressed via DMS's enableDynamicTheming = false (ADR-028 §History 2026-05-29 / PR #63) so it also doesn't enter the closure. Configuration choices (all per #61's spec verbatim): - @v7 — current major tag (released 2026-01-08); inputs unchanged from v6; matches the floating-major-tag convention used by the other steps in this workflow. - primary-key on hashFiles('flake.lock'); restore-prefixes-first-match per-arch so PR branches fall back to the latest default-branch entry. - gc-max-store-size-linux: 5G — two arch entries fit exactly under GH's 10 GB/repo default cap. Follow-up tracked on #61: revisit after the first two runs if entries land smaller. - 7-day last-accessed purge with primary-key pinned. Hardening edits folded into this commit after PR #66's first CI attempt failed with HTTP 404 on api.github.com tarball endpoints (both arches, ~12s each): 1. Explicit `github_access_token: ${{ secrets.GITHUB_TOKEN }}` on the cachix/install-nix-action step. v31's docs claim GITHUB_TOKEN-from-env auto-pickup, but the symptom (HTTP 404 on unauthenticated api.github.com calls — what GitHub returns to anonymous clients past the 60 req/hr limit) suggests the auto-pickup didn't apply in our environment. The empty-restore on cache-nix-action's first run exposed this: every flake input had to fetch from GitHub. Setting the token explicitly makes the auth deterministic. 2. Top-level `permissions: contents: read` block. Defense-in-depth scope-pin on the workflow's token. The workflow only needs to read repo contents (checkout clones; Nix fetches public flake inputs); explicit-over-implicit per CLAUDE.md's whitelist > blanket stance applied to the token surface. No interaction with the `github_access_token` input — different layer. Why cache-nix-action and not Cachix-hosted / FlakeHub / Attic: one-operator project; matched-to-scale tooling; no extra trust delegations beyond GitHub itself. Triggers to revisit (hit rate <60%, second source-built dep, routine aarch64 source builds) are documented in #61's body. Peer-reviewed twice — once for the original cache-nix-action step (12 checkpoints; clean), once for the hardening amend (8 checkpoints; clean with two non-blocking nits surfaced + agreed with operator: comment phrasing left as-is, permissions block folded into this amend). Closes #61.
6 tasks
dannyfaris
added a commit
that referenced
this pull request
May 31, 2026
#151) Amortise the non-niri half of the desktop closure (Quickshell, Qt6, matugen, DMS, xwayland-satellite, foot and transitive deps) that a fresh GH Actions runner otherwise rebuilds every cold run. Output-cache storage (actions/cache-shaped), orthogonal to the niri.cachix.org substituter trust lines (#59). Keyed on os × arch × flake.lock hash; PR branches restore from the os×arch prefix seeded on main. GC to 5G before save keeps both arch entries under the 10 GB per-repo limit; a 7-day last-accessed purge sweeps dead prefixes without evicting the run's own primary key. cache-nix-action chosen over Cachix/FlakeHub/Attic per the issue's trust-delegation reasoning; revisit only if hit rate stays below ~60% over a month or a second major source-built dep arrives. https://claude.ai/code/session_01R9nbBuTjy2rkiMYJ6NJ1G1 Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Companion to slice 3b.5 (#57). Slice 3b.5 added
niri.cachix.orgtonix.settingsinmodules/core/nixos/niri.nix— that configures the substituter on deployed systems afternh os switch. CI's nix daemon reads its config fromcachix/install-nix-action'sextra_nix_config, which (until this commit) didn't include niri.cachix.org.Without this trust in CI,
flake-checksource-builds niri on the x86_64-linux matrix entry when any host imports the desktop-env bundle, and the source build hits the in-flight nixpkgs Rust crate fetcher 403 cascade (rust-lang/crates.io#13482, NixOS/nixpkgs#512735). Slice 3d is the first commit that imports the bundle into a host, so this trust must land first.Changes
extra-substituters = https://niri.cachix.organd the matchingextra-trusted-public-keysline to the workflow'sextra_nix_config.extra-prefix so it appends toinstall-nix-action's defaults rather than replacing them (cache.nixos.orgpreserved).accept-flake-config = falsepreserved unchanged — transitive flake inputs still cannot silently mutate config; only this operator-owned line adds new trust. The whitelist principle is intact.extra_nix_configto record the rationale, source-of-key, and the cross-arch reasoning.Cross-arch note
niri.cachix.orgserves x86_64-linux only.flake-checkbuilds every host'ssystem.build.toplevelincluding the aarch64nixos-vmhost, butnixos-vmdoes not import the niri module — so the aarch64 matrix entry lists the substituter but never queries it. Harmless on aarch64.Why this is a separate PR from #57
PR #57 was opened with auto-merge enabled and the substituter-trust amendment was originally drafted as an amend + force-push on that branch. PR #57 auto-merged before the amend went out, so the CI workflow half lands as its own PR. Same content the peer review approved; just different commit shape.
Peer review
Reviewed against 8 checkpoints:
extra-prefix correctly appends (pernix.conf(5)).|format is whatinstall-nix-action@v31expects.modules/core/nixos/niri.nix:51and niri-flake's flake.nix lines 480–481.accept-flake-config = falsepreserved.actionlintcompatibility — pre-commit confirms.extra_nix_configapplied per-step at runner startup; cancellation safe.Test plan
actionlintpre-commit pass.Refs: #33, #57, ADR-028.
🤖 Generated with Claude Code