The Nix binary cache protocol, in Haskell.
nix-base32, NAR archives, narinfo, store paths, and Ed25519 signing - with an optional WAI cache server. A pure core; IO is confined to the storage and server boundaries.
build-depends: nova-cacheimport NovaCache.Hash (hashBytes, formatNixHash)
import qualified Data.ByteString as BS
-- Hash file contents into sha256:<nix-base32>
hash <- formatNixHash . hashBytes <$> BS.readFile pathimport NovaCache.NarInfo (parseNarInfo)
import NovaCache.Signing (parseSecretKey, sign)
-- Parse a narinfo and sign it
case (parseNarInfo raw, parseSecretKey "mykey:base64...") of
(Right ni, Right sk) -> print (sign sk ni) -- Right "mykey:<base64 sig>"
_ -> error "parse failed"import NovaCache.Validate (validateFull)
-- Validate an upload: fields + NAR hash + file hash + signatures.
-- Pure, and every error is collected rather than failing on the first.
case validateFull publicKey ni narBytes fileBytes of
Right () -> accept
Left errs -> reject errscabal run --flag server nova-cache-server -- --port 5000 --store ./nix-cacheThe protocol itself lives in the NovaCache.Server library module as a WAI
Application, so any operator can embed the cache in their own server with
their own root page; the bundled executable is one such embedding.
| Variable | Description |
|---|---|
PORT |
Listen port (default: 5000; also --port) |
HOST |
Bind host (default: all interfaces; also --host) |
NIX_CACHE_DIR |
Store directory (default: ./nix-cache) |
CACHE_API_KEY |
Bearer token required for PUT. The server refuses to start without it unless --allow-open-writes is passed. |
SIGNING_KEY_FILE |
Ed25519 secret key file for server-side narinfo signing |
LOG_REQUESTS |
Set to 0 to disable request logging |
| Method | Path | Description |
|---|---|---|
GET |
/ |
Landing page: live stats and the cache public key |
GET |
/nix-cache-info |
Cache metadata |
GET |
/narinfo-hashes |
All cached narinfo hashes, newline-delimited (authenticated) |
GET |
/<hash>.narinfo |
Fetch a narinfo |
GET |
/nar/<file> |
Fetch a NAR (streamed from disk) |
PUT |
/<hash>.narinfo |
Upload a narinfo (authenticated, validated) |
PUT |
/nar/<file> |
Upload a NAR (authenticated, streamed to disk) |
HEAD is answered wherever GET is.
A public instance runs at cache.novavero.ai:
extra-substituters = https://cache.novavero.ai
extra-trusted-public-keys = cache.novavero.ai-1:9gQ7tLWMM+2tdC9H5sKMJltDIPfD7X2GWlZe8Aa8hHQ=
cabal build
cabal testOptional flag: --flag server builds the cache server. Requires GHC 9.8+ and cabal-install 3.10+.
Apache-2.0 - Novavero AI Inc.