Watch
0
0
Fork
You've already forked hyperhive
0

hive-c0re pulls closures through the nix daemon; hive-priv verifies the swarm signature before applying

This commit is contained in:
atlas 2026-11-07 13:20:55 +01:00 • committed by mara
commit ecd4445680

View file

@ -1,22 +1,26 @@
# The root-side copy of the two cache facts hive-priv trusts: the key a
# downloaded closure must be signed by and the netrc the pull token goes out
# in. The script runs as root on the hive host under the hive's own store
# identity and writes both into `dir`, which only root can read.
# The root-side copy of the cache facts the host's nix daemon and hive-priv
# trust: the key a downloaded closure must be signed by and the netrc the pull
# token goes out in. The script runs as root on the hive host under the hive's
# own store identity and writes both into `dir`, which only root can read, and
# a nix.conf fragment at `confFile` that the host's nix.conf includes.
#
# Everything hive-priv decides on is here or in the host's configuration, and
# nothing is read from a file hive-c0re (unprivileged) writes: the key and the
# token come from the store, the cache's address from
# `services.hyperhive.swarm.attic.{domain,cache}`.
# What the daemon and hive-priv decide on is here or in the host's
# configuration, and nothing is read from a file hive-c0re (unprivileged)
# writes: the key and the token come from the store, the cache's address from
# `services.hyperhive.swarm.attic.{domain,cache}`. The fragment holds no secret
# (the key is public, the netrc stays in `dir`) and hive-c0re can read it: it
# takes the cache's address from there.
#
# A store that holds no facts yet, or cannot be reached, leaves what is in `dir`
# as it is. Nothing here removes a file.
# and `confFile` as they are. Nothing here removes a file.
#
# Pure function — NOT a NixOS module. Call it from a unit's `script`, with
# `bao`, `coreutils` and `gnugrep` on its `path` and the `BAO_*` client
# environment set:
# `bao`, `coreutils`, `gnugrep` and `systemd` on its `path` and the `BAO_*`
# client environment set:
#
# script = import ./lib/attic-root-facts.nix { inherit lib; } {
# hive = "alpha"; host = "attic.example.org"; dir = "/run/hyperhive-priv/attic";
# url = "https://attic.example.org/swarm"; confFile = "/run/hyperhive-nix/cache.conf";
# };
{ lib }:
{
@ -25,8 +29,12 @@
hive,
# The cache server's host name, which the netrc line names.
host,
# Where the two files go.
# Where the key and the netrc go.
dir,
# The cache's address as the daemon lists it in `trusted-substituters`.
url,
# Where the nix.conf fragment goes; its directory is root's and readable.
confFile,
}:
''
set -euo pipefail
@ -35,7 +43,9 @@
${import ./refresh-consumer.nix { }}
dir=${lib.escapeShellArg dir}
conf=${lib.escapeShellArg confFile}
install -d -m 0700 "$dir"
install -d -m 0755 "$(dirname -- "$conf")"
store_init
store_login
@ -84,4 +94,17 @@
if secret_differs "$dir/netrc" "$netrc"; then
atomic_write_secret 0600 "" "$dir/netrc" "$netrc"
fi
# Last, so a daemon that reads the fragment finds the netrc in place. The
# address is the one hive-c0re may name as the substituter. The mtime moves
# only with the content. Lix re-reads nix.conf for every connection, CppNix
# only at start, so a daemon that started before this write is restarted.
printf -v fragment '%s\n%s\n%s' \
${lib.escapeShellArg "extra-trusted-substituters = ${url}"} \
"extra-trusted-public-keys = $key" \
"netrc-file = $dir/netrc"
if secret_differs "$conf" "$fragment"; then
atomic_write_secret 0644 "" "$conf" "$fragment"
fi
refresh_unit nix-daemon.service "$conf"
''