Archived
Move nix-cache's binary cache signing key into sops
nix-serve's secretKeyFile was a manual, undocumented-outside-a-comment `nix-store --generate-binary-cache-key` step per host -- easy to miss on a fresh nix-cache instance (as lxc-nix-cache testing just found: systemd fails the unit with EXIT_CREDENTIALS when LoadCredential can't find the source file, which nginx then reports as a 502 from clients). It also can't be regenerated per-host safely: modules/nix-cache/client.nix hardcodes every client's trust in one specific public key, so every nix-cache instance has to share the exact same keypair. Sourced from secrets/nix-cache.yaml's new cache-priv-key entry instead, via the same sops-nix pattern every other secret in this repo already uses. Verified the added value derives to the exact public key modules/nix-cache/client.nix already trusts before committing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01La55Nsss8jZ7ZuzUV9mfot
This commit is contained in:
+28
-9
@@ -11,19 +11,38 @@ This repository configures `nix-cache` as a **binary cache server** and a **remo
|
|||||||
- Client hosts import `modules/nix-cache/client.nix` and, when remote building is enabled, `modules/nix-cache/remote-builder-client.nix`.
|
- Client hosts import `modules/nix-cache/client.nix` and, when remote building is enabled, `modules/nix-cache/remote-builder-client.nix`.
|
||||||
- The `nix-cache` host imports `modules/nix-cache/server.nix`.
|
- The `nix-cache` host imports `modules/nix-cache/server.nix`.
|
||||||
|
|
||||||
## Binary cache signing keys (on nix-cache)
|
## Binary cache signing key
|
||||||
|
|
||||||
|
`modules/nix-cache/client.nix` hardcodes every client's trust in one
|
||||||
|
specific public key (`cache.local-1:usoWYanY3Kpq2+kDIS2nhWoLZiRxanmdysdzqCFBHW4=`).
|
||||||
|
That means whichever host is currently playing the `nix-cache` role has to
|
||||||
|
use that *exact* keypair — not a freshly generated one — or no client will
|
||||||
|
accept substitutes from it (they'd just silently fall back to building
|
||||||
|
from source). So unlike most per-host secrets, this one can't be
|
||||||
|
self-generated on first boot; it's managed via sops-nix like every other
|
||||||
|
secret in this repo, sourced from `secrets/nix-cache.yaml`'s
|
||||||
|
`cache-priv-key` entry (`modules/nix-cache/server.nix`).
|
||||||
|
|
||||||
|
**Adding or rotating the value:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo install -d -m 0700 /etc/nix
|
nix-shell -p sops --run 'sops secrets/nix-cache.yaml'
|
||||||
sudo nix-store --generate-binary-cache-key nix-cache-1 /etc/nix/cache-priv.pem /etc/nix/cache-pub.pem
|
|
||||||
sudo chmod 0600 /etc/nix/cache-priv.pem
|
|
||||||
sudo chmod 0644 /etc/nix/cache-pub.pem
|
|
||||||
cat /etc/nix/cache-pub.pem
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Do not commit private keys.
|
Add (or replace) a `cache-priv-key` entry with the private key file's exact
|
||||||
Do not commit new password hashes or live credentials. Existing committed hashes
|
contents. If you don't have it yet, generate a keypair once:
|
||||||
should be rotated and moved to host-local secret management.
|
|
||||||
|
```bash
|
||||||
|
nix-store --generate-binary-cache-key nix-cache-1 cache-priv.pem cache-pub.pem
|
||||||
|
```
|
||||||
|
|
||||||
|
— paste `cache-priv.pem`'s contents into the `cache-priv-key` entry above,
|
||||||
|
delete both local files afterward, and update
|
||||||
|
`trusted-public-keys` in `modules/nix-cache/client.nix` (and every already-built
|
||||||
|
client) to match `cache-pub.pem` if this is a genuine rotation rather than
|
||||||
|
a first-time bootstrap. Any `nixos-configurations.*-nix-cache` host picks
|
||||||
|
the new key up automatically on next activation — no more manual
|
||||||
|
`/etc/nix/cache-priv.pem` install step.
|
||||||
|
|
||||||
## Remote builder SSH keys
|
## Remote builder SSH keys
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
{ config, pkgs, vars, ... }:
|
{ config, pkgs, vars, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
# Generate the binary cache key pair on the nix-cache host:
|
# nix-serve's signing key has to be the *same* key on every host that
|
||||||
# sudo install -d -m 0700 /etc/nix
|
# ever plays the nix-cache role -- modules/nix-cache/client.nix hardcodes
|
||||||
# sudo nix-store --generate-binary-cache-key nix-cache-1 \
|
# every client's trust in one specific public key ("cache.local-1:..."),
|
||||||
# /etc/nix/cache-priv.pem \
|
# so a freshly self-generated key here wouldn't be trusted by anyone.
|
||||||
# /etc/nix/cache-pub.pem
|
# Managed via sops-nix like every other secret in this repo instead of
|
||||||
# sudo chmod 0600 /etc/nix/cache-priv.pem
|
# the old manual `nix-store --generate-binary-cache-key` step -- see
|
||||||
# sudo chmod 0644 /etc/nix/cache-pub.pem
|
# "Binary cache signing key" in docs/nix-cache.md for how to add/rotate
|
||||||
# cat /etc/nix/cache-pub.pem
|
# the value in secrets/nix-cache.yaml.
|
||||||
|
sops.secrets."cache-priv-key".sopsFile = ../../secrets/nix-cache.yaml;
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
nix-serve = {
|
nix-serve = {
|
||||||
enable = true;
|
enable = true;
|
||||||
secretKeyFile = "/etc/nix/cache-priv.pem";
|
secretKeyFile = config.sops.secrets."cache-priv-key".path;
|
||||||
};
|
};
|
||||||
|
|
||||||
nginx = {
|
nginx = {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
beszel-token: ENC[AES256_GCM,data:meuzUP/6wCssJDVTgbC0XwiLZPMGyDl55HEIiON9xOXCD9k6,iv:TDqWcp+8Mxd8wN09r5otQRQXq3XTeQphaTWxvvuLTAs=,tag:cRPZQGlwB/dTguBAheWPQg==,type:str]
|
beszel-token: ENC[AES256_GCM,data:meuzUP/6wCssJDVTgbC0XwiLZPMGyDl55HEIiON9xOXCD9k6,iv:TDqWcp+8Mxd8wN09r5otQRQXq3XTeQphaTWxvvuLTAs=,tag:cRPZQGlwB/dTguBAheWPQg==,type:str]
|
||||||
|
cache-priv-key: ENC[AES256_GCM,data:6vQKIf7eS0WNL2Eptoi4VWr18SRMZfN/H/aFUUtXdMYQY5LLyBp2EHRKqZcGFuh1nZhUdAxUztq/CVXx+QFxKW+ElHxCxUSp0QqI1fdSkBkKZb8hlit5SoX9JtLzZGg0HBNM3nJu,iv:0J+xmrPJhInHhFR/c41ACjuTfaIoMkQFSfbL2KkgFa8=,tag:f4s9Szs5oprVVRSyXaX48A==,type:str]
|
||||||
sops:
|
sops:
|
||||||
age:
|
age:
|
||||||
- enc: |
|
- enc: |
|
||||||
@@ -28,7 +29,7 @@ sops:
|
|||||||
2SEMsctdGC+5E3ilPXvPpZ5RONZHbXxn6kQRBlBv6AJERpGDzsfgfA==
|
2SEMsctdGC+5E3ilPXvPpZ5RONZHbXxn6kQRBlBv6AJERpGDzsfgfA==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
recipient: age164px2a8e48ptsf9ngtan38aa6jls4jdl26mzrgzf6sn3vcvt49hqjrgr8w
|
recipient: age164px2a8e48ptsf9ngtan38aa6jls4jdl26mzrgzf6sn3vcvt49hqjrgr8w
|
||||||
lastmodified: "2026-07-19T02:30:40Z"
|
lastmodified: "2026-07-19T23:30:21Z"
|
||||||
mac: ENC[AES256_GCM,data:7+FeT6aeCGn+JFBXbPO0qP4BJ1nHPSennewv1kWkG+hOTIqs1ymuswUK1Hyfi6Z9h2umFX9HvK+o3qtmYvk6k7BUNe6w6QUHTNwm6lmNqrb7sgAE3iFVI2p9m14NGhgoTfnXx1M4JIZ1iuNYhCukpENI4+svIe+r7x5YeE5Evac=,iv:4AKAPI6upyAvHBr8BLWX7R/NupmJdcXdqiN8e0ZQ3ls=,tag:TkpfpCaLhn+Mx5cQZZuMdA==,type:str]
|
mac: ENC[AES256_GCM,data:kLGE2xawQT7mx+sfw68hmGk5nCEGiEjZrqTEl9B1dtQmTrMwmoVr/1RISi4LfJrwxy31mDgff4lcIL4wIJuM373uk3X8j4RNyYQNTfKEkORT6r8NHeepNs267O77pKGd7OmcM4MT/BqOnB8ELS7Wlf2ect7CAlvUUVyc8icxgZE=,iv:EYLDsHYHZ1XOQXafOTqHHWpk/OBNq/R6IJnOBYV33E4=,tag:thxrCPC5oGvDjhK7Dz87YA==,type:str]
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.13.1
|
version: 3.13.1
|
||||||
|
|||||||
Reference in New Issue
Block a user