Signing Keys
Nix will not use a substituted path unless it is signed by a key the client trusts. An unsigned Aeroflare cache is perfectly usable for storing artifacts, but every machine that tries to consume it will download the NAR and then refuse to install it. Signing is what closes that loop.
There are three steps, and all three are needed: generate a key pair, sign on push, and trust the public half on every consuming machine.
1. Generate a key pair
nix key generate-secret --key-name my-cache-1 > /path/to/cache-priv-key.pem
nix key convert-secret-to-public < /path/to/cache-priv-key.pem
The key name is arbitrary but should be unique to the cache; by convention it
carries a trailing number so the key can be rotated later (my-cache-1,
my-cache-2). The public key is printed as my-cache-1:AbCd...= — that whole
string, name included, is what clients trust.
Keep the private key secret. Anyone holding it can sign artifacts that your machines will install without question.
2. Sign on push
Pass the private key to whichever command uploads:
aeroflare push --store-path /nix/store/... --signing-key /path/to/cache-priv-key.pem
aeroflare run --signing-key /path/to/cache-priv-key.pem -- nix build .#default --print-out-paths
aeroflare prepare takes the same flag, if you are generating artifacts to
upload separately.
Without --signing-key, artifacts are pushed unsigned. Nothing fails at push
time — the consequence only appears on the machine trying to use the cache.
3. Publish the public key on the cache
Store the public key on the cache itself, so the proxy can serve it and clients can discover it:
aeroflare configure
This interactive command prompts for the public key and writes it to the
aeroflare.public-key annotation on the cache's cache-config manifest. It
prefills the current value, so re-running it is also how you inspect what is set.
The proxy exposes the result at /public-key, which is a quick way to confirm it
took:
curl http://127.0.0.1:8080/public-key
4. Trust the key on consuming machines
Add the public key to trusted-public-keys in nix.conf:
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= my-cache-1:AbCd...=
The list is space-separated. Keep cache.nixos.org-1 — dropping it breaks
substitution from upstream.
On NixOS:
nix.settings.trusted-public-keys = [
"my-cache-1:AbCd...="
];
Signing in CI
The CI runner takes the same setting through .aeroflare-ci.yaml, but with one
extra convenience: signing-key may be either a filesystem path or the name of
an environment variable holding the key material.
signing-key: NIX_SIGNING_KEY # the NAME of an env var, not a path
If $NIX_SIGNING_KEY is set, its contents are written to a temporary file with
mode 0600 and removed when the run ends. This is what lets you keep the key in
a GitHub Actions secret and never write it to the workspace. If the value is not
a set environment variable, it is treated as a path, and the run fails early if
no such file exists.
See CI Configuration and the GitHub Action guide.