cbcf122422
Haiku ops agent + 3 tools (nbshell expect+PTY admin-shell driver, nbapi read-only HTTP client, nb-substituters guarded cache manager) + 2 skills (nixbuild-settings, nixbuild-usage). Encodes the two-control-surface model and the path-style-substituter-URL gotcha.
109 lines
4.0 KiB
Bash
Executable File
109 lines
4.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# nb-substituters — manage nixbuild.net account binary-cache substituters and
|
|
# their trusted public keys, with a guard for nixbuild's URL rules.
|
|
#
|
|
# WHY a wrapper: nixbuild's `settings substituters --add` REJECTS path-style
|
|
# URLs (e.g. https://host/cache-name → "invalid substituter", trailing slash
|
|
# doesn't help). It accepts only host-root HTTPS (https://host), s3://bucket/
|
|
# prefix, or cachix://name. An Attic/nix-serve cache served at a sub-path must
|
|
# therefore be reached path-LESS — e.g. front it at a host root with a reverse
|
|
# proxy that rewrites `/<hash>.narinfo` and `/nar/*` into the cache namespace
|
|
# (the oleks fleet does this for Attic at https://nix-cache-custom.oleks.space
|
|
# via a Caddy root-rewrite). This wrapper catches the path-style mistake before
|
|
# it hits the shell and explains the fix.
|
|
#
|
|
# Also: `builders-use-substitutes = true` on the CLIENT does NOT forward the
|
|
# client's substituter list to nixbuild — it tells the remote to use ITS OWN
|
|
# (these, account-side) substituters. So caches must be registered here to take
|
|
# effect during remote builds.
|
|
#
|
|
# Usage:
|
|
# nb-substituters list # show substituters + trusted keys
|
|
# nb-substituters add-cache <url> [public-key] # add substituter (+ key if given)
|
|
# nb-substituters add-key <public-key> # add a trusted public key only
|
|
# nb-substituters remove <url> # remove a substituter
|
|
# nb-substituters remove-key <public-key> # remove a trusted public key
|
|
# nb-substituters reset # reset both back to defaults
|
|
#
|
|
# Delegates the actual shell I/O to nbshell (sibling script).
|
|
|
|
set -euo pipefail
|
|
|
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
NBSHELL="${HERE}/nbshell"
|
|
|
|
valid_substituter() {
|
|
# Accept: https://host (no path), s3://bucket[/prefix], cachix://name.
|
|
# Reject: https://host/path (the nixbuild gotcha), http (warn), bare host.
|
|
local u="$1"
|
|
case "$u" in
|
|
https://*/*/* | https://*/?* )
|
|
# has a path component after the host
|
|
return 1 ;;
|
|
https://*/ )
|
|
return 1 ;;
|
|
https://* )
|
|
return 0 ;;
|
|
s3://* | cachix://* )
|
|
return 0 ;;
|
|
*)
|
|
return 1 ;;
|
|
esac
|
|
}
|
|
|
|
case "${1:-}" in
|
|
list)
|
|
"$NBSHELL" 'settings substituters --show' 'settings trusted-public-keys --show'
|
|
;;
|
|
add-cache)
|
|
url="${2:-}"; key="${3:-}"
|
|
[ -n "$url" ] || { echo "add-cache: need a URL" >&2; exit 2; }
|
|
if ! valid_substituter "$url"; then
|
|
cat >&2 <<EOF
|
|
nb-substituters: '$url' is not an acceptable nixbuild substituter.
|
|
nixbuild accepts only host-root HTTPS (https://host, NO path), s3://bucket/prefix,
|
|
or cachix://name. A cache served at a sub-path (Attic, nix-serve) must be exposed
|
|
path-less — e.g. front it at a host root with a reverse-proxy rewrite of
|
|
/<hash>.narinfo and /nar/* into the cache namespace, then add that bare host here.
|
|
EOF
|
|
exit 1
|
|
fi
|
|
if [ -n "$key" ]; then
|
|
"$NBSHELL" \
|
|
"settings substituters --add ${url}" \
|
|
"settings trusted-public-keys --add ${key}" \
|
|
'settings substituters --show' \
|
|
'settings trusted-public-keys --show'
|
|
else
|
|
echo "note: no public key given — content from $url will only validate if its signing key is already trusted." >&2
|
|
"$NBSHELL" "settings substituters --add ${url}" 'settings substituters --show'
|
|
fi
|
|
;;
|
|
add-key)
|
|
key="${2:-}"; [ -n "$key" ] || { echo "add-key: need a public key" >&2; exit 2; }
|
|
"$NBSHELL" "settings trusted-public-keys --add ${key}" 'settings trusted-public-keys --show'
|
|
;;
|
|
remove)
|
|
url="${2:-}"; [ -n "$url" ] || { echo "remove: need a URL" >&2; exit 2; }
|
|
"$NBSHELL" "settings substituters --remove ${url}" 'settings substituters --show'
|
|
;;
|
|
remove-key)
|
|
key="${2:-}"; [ -n "$key" ] || { echo "remove-key: need a public key" >&2; exit 2; }
|
|
"$NBSHELL" "settings trusted-public-keys --remove ${key}" 'settings trusted-public-keys --show'
|
|
;;
|
|
reset)
|
|
"$NBSHELL" \
|
|
'settings substituters --reset' \
|
|
'settings trusted-public-keys --reset' \
|
|
'settings substituters --show' \
|
|
'settings trusted-public-keys --show'
|
|
;;
|
|
""|-h|--help|help)
|
|
sed -n '2,32p' "$0"
|
|
;;
|
|
*)
|
|
echo "nb-substituters: unknown command '${1}'" >&2
|
|
exit 2
|
|
;;
|
|
esac
|