feat(pi): merge sops-managed auth keys
This commit is contained in:
@@ -21,6 +21,50 @@ let
|
||||
];
|
||||
|
||||
piPackagesJson = pkgs.writeText "pi-packages.json" (builtins.toJSON piPackages);
|
||||
|
||||
# Pi Auth Api Keys - These are merged into mutable auth.json on activation.
|
||||
# Add another entry here to manage another top-level provider auth key.
|
||||
piAuthApiKeys = [
|
||||
{
|
||||
provider = "zai";
|
||||
secretName = "zai_apikey";
|
||||
jqVar = "zai";
|
||||
sopsFile = lib.snowfall.fs.get-file "secrets/common/evanreichard.yaml";
|
||||
}
|
||||
];
|
||||
|
||||
piAuthJqRawfiles = lib.concatStringsSep " \\\n " (map
|
||||
(auth: ''--rawfile ${auth.jqVar} "${config.sops.secrets.${auth.secretName}.path}"'')
|
||||
piAuthApiKeys);
|
||||
|
||||
piAuthJqFilter = lib.concatStringsSep " | " (map
|
||||
(auth: ''.["${auth.provider}"] = { type: "api_key", key: ($'' + auth.jqVar + '' | rtrimstr("\n")) }'')
|
||||
piAuthApiKeys);
|
||||
|
||||
piAuthMergeScript = pkgs.writeShellScript "pi-auth-merge" ''
|
||||
set -euo pipefail
|
||||
|
||||
PI_AUTH="$HOME/.pi/agent/auth.json"
|
||||
mkdir -p "$(dirname "$PI_AUTH")"
|
||||
|
||||
if [ -L "$PI_AUTH" ]; then
|
||||
rm "$PI_AUTH"
|
||||
fi
|
||||
|
||||
for secret in ${lib.concatStringsSep " " (map (auth: ''"${config.sops.secrets.${auth.secretName}.path}"'') piAuthApiKeys)}; do
|
||||
if [ ! -e "$secret" ]; then
|
||||
echo "Skipping pi auth merge; missing sops secret: $secret" >&2
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
[ -s "$PI_AUTH" ] || echo '{}' > "$PI_AUTH"
|
||||
tmp=$(mktemp)
|
||||
${pkgs.jq}/bin/jq ${piAuthJqRawfiles} \
|
||||
'${piAuthJqFilter}' "$PI_AUTH" > "$tmp"
|
||||
mv "$tmp" "$PI_AUTH"
|
||||
chmod 600 "$PI_AUTH"
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.${namespace}.programs.terminal.pi = {
|
||||
@@ -57,9 +101,16 @@ in
|
||||
# Pi Models Config - Inject llama-swap API key from sops into models.json
|
||||
# so pi can authenticate against the llm-api endpoint.
|
||||
sops = lib.mkIf osConfig.${namespace}.security.sops.enable {
|
||||
secrets."llama_swap_api_keys/pi" = {
|
||||
sopsFile = lib.snowfall.fs.get-file "secrets/common/llama-swap.yaml";
|
||||
};
|
||||
secrets = {
|
||||
"llama_swap_api_keys/pi" = {
|
||||
sopsFile = lib.snowfall.fs.get-file "secrets/common/llama-swap.yaml";
|
||||
};
|
||||
} // lib.listToAttrs (map
|
||||
(auth: {
|
||||
name = auth.secretName;
|
||||
value.sopsFile = auth.sopsFile;
|
||||
})
|
||||
piAuthApiKeys);
|
||||
templates."pi-models.json" = {
|
||||
path = "${config.home.homeDirectory}/.pi/agent/models.json";
|
||||
content = builtins.toJSON {
|
||||
@@ -88,5 +139,30 @@ in
|
||||
'.packages = $pkgs[0]' "$PI_SETTINGS" > "$tmp"
|
||||
mv "$tmp" "$PI_SETTINGS"
|
||||
'';
|
||||
|
||||
# Merge Api Key Auth Into Mutable auth.json - Pi needs auth.json to stay
|
||||
# writable, so merge sops-managed API keys instead of symlinking the whole
|
||||
# file. Existing provider auth entries are preserved.
|
||||
home.activation.piAuthMerge = lib.mkIf osConfig.${namespace}.security.sops.enable (
|
||||
config.lib.dag.entryAfter [ "sops-nix" "writeBoundary" ] ''
|
||||
${piAuthMergeScript}
|
||||
''
|
||||
);
|
||||
|
||||
# Run Pi Auth Merge After Sops - During NixOS system activation, sops-nix
|
||||
# can be restarted asynchronously and secrets may not exist yet. This user
|
||||
# service retries the merge in the normal user systemd graph after sops-nix.
|
||||
systemd.user.services.pi-auth-merge = lib.mkIf osConfig.${namespace}.security.sops.enable {
|
||||
Unit = {
|
||||
Description = "Merge sops-managed Pi auth entries";
|
||||
After = [ "sops-nix.service" ];
|
||||
Requires = [ "sops-nix.service" ];
|
||||
};
|
||||
Service = {
|
||||
Type = "oneshot";
|
||||
ExecStart = piAuthMergeScript;
|
||||
};
|
||||
Install.WantedBy = [ "default.target" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user