design: cache is signed by harmonia; producers need no key
1 files changed,  +13, -6
M DESIGN.md
+13, -6
 1@@ -518,16 +518,23 @@ mx99 limits builds (`maxJobs = 1`, a build slice with `MemoryMax`, low
 2 app.
 3 
 4 Binary cache: the CI host's own `/nix/store` is the cache, served read-only by
 5-`harmonia` behind Caddy (authenticated: store paths reveal host layout, even
 6-though they hold no secrets). Producers push signed paths with
 7-`nix copy --to ssh-ng://<ci host>`, from a `post-build-hook` where useful:
 8+`harmonia` behind Caddy (basic auth, one shared netrc: store paths reveal host
 9+layout, even though they hold no secrets). Harmonia signs what it serves, so
10+producers need no key: they push with `nix copy --to ssh-ng://root@<ci host>`
11+(root over SSH, as deploys do); outputs a remote builder returns to the CI
12+host's store arrive without any push:
13 
14 - the dev machine (64 GB RAM) builds x86_64 closures, which `ci run` there and
15   the runner evaluate to identical store paths, so the runner substitutes
16   instead of building;
17-- mx99 pushes what it builds for aarch64;
18-- every fleet host and the runner list the cache in `substituters` and its
19-  public key in `trusted-public-keys`; the `ci` user needs no extra trust.
20+- aarch64 builds the runner sends to mx99 come back into the CI host's store by
21+  themselves; builds mx99 does on its own (staging previews) can be pushed too;
22+- every other fleet host lists the cache in `substituters` (after
23+  cache.nixos.org), its public key in `trusted-public-keys` and the netrc in
24+  `netrc-file`, with `fallback` and a short `connect-timeout` so an outage costs
25+  time, not deploys; the `ci` user needs no extra trust. Implemented in
26+  `servers`: `modules/nix-cache.nix`, `roles/ci/cache.nix`, `just cache-push`,
27+  `ci-cache-pin`.
28 
29 The cache is not a repository of project state (the runner pushes nothing to
30 repos): losing it only costs rebuild time. GC on the CI host (`min-free` /