commit b2a06aeb2dbaea5946262fb5b4133ae3da19b5d5
parent 95d27d9711a53bd8423d0979b1dec265b2565dac
Author: Katja (ctucx) <git@ctu.cx>
Date: Tue, 11 Mar 2025 09:40:13 +0100
parent 95d27d9711a53bd8423d0979b1dec265b2565dac
Author: Katja (ctucx) <git@ctu.cx>
Date: Tue, 11 Mar 2025 09:40:13 +0100
flake: add agenixSecrets (also add flake support to `agenix`-utility)
12 files changed, 76 insertions(+), 170 deletions(-)
D
|
133
-------------------------------------------------------------------------------
diff --git a/agenix b/agenix @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -eo pipefail + +tempfile=$(mktemp) + +trap "rm -f ${tempfile}" SIGINT SIGTERM ERR EXIT + +touch ${tempfile} +chmod 600 ${tempfile} + +if [ -x "$(which bw)" ]; then + privkey=$(bw get notes ea70a317-7cac-455e-bee0-7c97d7505a7b) + if [ $? -ne 0 ]; then exit; fi; +else + privkey=$(pass agenix-privkey) + if [ $? -ne 0 ]; then exit; fi; +fi + +echo "${privkey}" > ${tempfile} + +agenix -i ${tempfile} "$@"
diff --git a/flake.nix b/flake.nix @@ -27,8 +27,10 @@ in { - packages = forAllSystems (pkgs: ((loadDir (pkgsLoader pkgs) ./pkgs/all) // (if pkgs.stdenv.isDarwin then (loadDir (pkgsLoader pkgs) ./pkgs/darwin) else {}))); checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks inputs.self.deploy) (nixpkgsLib.filterAttrs (key: value: key != "x86_64-darwin") inputs.deploy-rs.lib); + packages = forAllSystems (pkgs: ( + (loadDir (pkgsLoader pkgs) ./pkgs/all) // nixpkgsLib.optionalAttrs pkgs.stdenv.isDarwin (loadDir (pkgsLoader pkgs) ./pkgs/darwin) + )); nixosModules = loadDir pathLoader ./modules/nixos; darwinModules = loadDir pathLoader ./modules/darwin; @@ -41,8 +43,35 @@ nodes = loadDir importLoader ./machines; lib = loadDir (path: path: import path inputs) ./lib; - secrets = loadDir [(inputs.haumea.lib.matchers.extension "age" pathLoader)] ./secrets; + agenixKeys = (inputs.self.nodes |> builtins.mapAttrs (nodeName: nodeConfig: nodeConfig.sshPubKey)) // { + main = "age1mn57hntgx775kwcwx4jrrd7rfl7z4wl54kqtgq8w2kzg7agz7alsv5eesw"; + }; + agenixSecrets = ( + inputs.self.secrets + |> nixpkgsLib.mapAttrsRecursive (path: value: [ + (nixpkgsLib.nameValuePair "secrets/${nixpkgsLib.concatStringsSep "/" path}.age" { + publicKeys = ( + if inputs.self.nodes ? "${builtins.elemAt path 0}" then [ + inputs.self.agenixKeys.main + inputs.self.agenixKeys."${builtins.elemAt path 0}" + ] else ( + if (builtins.elemAt path 0) == "global" then + inputs.self.agenixKeys + else + [ inputs.self.agenixKeys.main ] + ) + ); + }) + ]) + |> nixpkgsLib.collect builtins.isList + |> nixpkgsLib.flatten + |> builtins.listToAttrs + ) // { + "secrets/resticServer/briefkasten.age".publicKeys = with inputs.self.agenixKeys; [ main trabbi hector briefkasten ]; + "secrets/resticServer/wanderduene.age".publicKeys = with inputs.self.agenixKeys; [ main trabbi hector briefkasten ]; + "secrets/briefkasten/influx/grafanaTokenMqttData.age".publicKeys = with inputs.self.agenixKeys; [ main briefkasten hector ]; + }; ctucxConfig = rec { homeManager = loadDir pathLoader ./configurations/homeManager; @@ -51,14 +80,15 @@ darwin = nixpkgsLib.recursiveUpdate common (loadDir pathLoader ./configurations/darwin); }; - + deploy.activationTimeout = 600; + deploy.confirmTimeout = 240; deploy.nodes = builtins.mapAttrs (nodeName: node: { - hostname = inputs.self.nixosConfigurations."${nodeName}".config.networking.fqdn; + hostname = node.config.networking.fqdn; sshUser = "root"; - sshOpts = [ "-p" "${builtins.toString (nixpkgsLib.head inputs.self.nixosConfigurations."${nodeName}".config.services.openssh.ports)}" ]; + sshOpts = [ "-p" "${builtins.toString (nixpkgsLib.head node.config.services.openssh.ports)}" ]; profiles.system = { user = "root"; - path = inputs.deploy-rs.lib.${inputs.self.nodes.${nodeName}.system}.activate.nixos inputs.self.nixosConfigurations."${nodeName}"; + path = inputs.deploy-rs.lib.${node.config.nixpkgs.system}.activate.nixos node; }; }) inputs.self.nixosConfigurations;
diff --git a/machines/blechkasten/default.nix b/machines/blechkasten/default.nix @@ -1,6 +1,9 @@ { system = "aarch64-darwin"; + + sshPubKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIMnLFWr1zTU8sEJr3XZaRoLxto0QAB9HOQRbyDphBS+"; + configuration = { config, pkgs, lib, ... }: { networking.hostName = "blechkasten";
diff --git a/machines/briefkasten/default.nix b/machines/briefkasten/default.nix @@ -1,6 +1,9 @@ { system = "x86_64-linux"; + + sshPubKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN8mi9ZKPdhn20g9gyxE7NYBq/vAKemW4lhaQlLw5QVc"; + interface = "brlan"; ip4IsPrivate = true;
diff --git a/machines/hector/default.nix b/machines/hector/default.nix @@ -2,6 +2,8 @@ system = "x86_64-linux"; + sshPubKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIILONdCJED/Lmd215tO8KBkJSl1E9ZdMyC+syxSqmo7o"; + interface = "ens3"; ip4IsPrivate = false;
diff --git a/machines/seifenkiste/default.nix b/machines/seifenkiste/default.nix @@ -1,6 +1,9 @@ { system = "x86_64-linux"; + + sshPubKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMX8q2ux3YdAFGLRfD8/fCEAEalqxsRQwkOSp6gYedFt"; + configuration = { config, ctucxConfig, lib, pkgs, ... }: { imports = [
diff --git a/machines/trabbi/default.nix b/machines/trabbi/default.nix @@ -2,6 +2,8 @@ system = "x86_64-linux"; + sshPubKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBwzDl1dHpDIZxFfRBLQyFn85RVTsg7OgO3Eahdn3FTJ"; + interface = "ens3"; ip4IsPrivate = false;
diff --git a/machines/wanderduene/default.nix b/machines/wanderduene/default.nix @@ -2,6 +2,8 @@ system = "x86_64-linux"; + sshPubKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH8uAvUnwhg3pnCdaaoclWDKV275SyNSyrkJON+R5Boi"; + interface = "ens3"; ip4IsPrivate = false;
diff --git a/pkgs/all/agenix/agenix.sh b/pkgs/all/agenix/agenix.sh @@ -26,9 +26,6 @@ function show_help () { echo ' ' echo 'If STDIN is not interactive, EDITOR will be set to "cp /dev/stdin"' echo ' ' - echo 'RULES environment variable with path to Nix file specifying recipient public keys.' - echo "Defaults to './secrets.nix'" - echo ' ' echo "agenix version: @version@" echo "age binary path: @ageBin@" echo "age version: $(@ageBin@ --version)" @@ -101,7 +98,6 @@ while test $# -gt 0; do esac done -RULES=${RULES:-./secrets.nix} function cleanup { if [ -n "${CLEARTEXT_DIR+x}" ] then @@ -115,7 +111,7 @@ function cleanup { trap "cleanup" 0 2 3 15 function keys { - (@nixInstantiate@ --json --eval --strict -E "(let rules = import $RULES; in rules.\"$1\".publicKeys)" | @jqBin@ -r .[]) || exit 1 + (@nix@ eval --json ".#agenixSecrets.\"$1\".publicKeys)" | @jqBin@ -r .[]) || exit 1 } function decrypt { @@ -123,7 +119,7 @@ function decrypt { KEYS=$2 if [ -z "$KEYS" ] then - err "There is no rule for $FILE in $RULES." + err "There is no rule for $FILE in nix-flake." fi if [ -f "$FILE" ] @@ -189,7 +185,7 @@ function edit { } function rekey { - FILES=$( (@nixInstantiate@ --json --eval -E "(let rules = import $RULES; in builtins.attrNames rules)" | @jqBin@ -r .[]) || exit 1) + FILES=$( (@nix@ eval --json '.#agenixSecrets' --apply 'builtins.attrNames' | @jqBin@ -r .[]) || exit 1) for FILE in $FILES do
diff --git a/pkgs/all/agenix/default.nix b/pkgs/all/agenix/default.nix @@ -17,7 +17,7 @@ stdenv.mkDerivation rec { src = substituteAll { inherit ageBin version; jqBin = "${jq}/bin/jq"; - nixInstantiate = "${nix}/bin/nix-instantiate"; + nix = "${nix}/bin/nix"; mktempBin = "${mktemp}/bin/mktemp"; diffBin = "${diffutils}/bin/diff"; src = ./agenix.sh;
diff --git a/secrets/agenix b/secrets/agenix @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -set -eo pipefail - -tempfile=$(mktemp) - -trap "rm -f ${tempfile}" SIGINT SIGTERM ERR EXIT - -touch ${tempfile} -chmod 600 ${tempfile} - -if [ -x "$(which bw)" ]; then - privkey=$(bw get notes ea70a317-7cac-455e-bee0-7c97d7505a7b) - if [ $? -ne 0 ]; then exit; fi; -else - privkey=$(pass agenix-privkey) - if [ $? -ne 0 ]; then exit; fi; -fi - -echo "${privkey}" > ${tempfile} - -cd "`git rev-parse --show-toplevel`/secrets" - -agenix -i ${tempfile} "$@"
diff --git a/secrets/secrets.nix b/secrets/secrets.nix @@ -1,133 +0,0 @@ -let - keys = { - main = "age1mn57hntgx775kwcwx4jrrd7rfl7z4wl54kqtgq8w2kzg7agz7alsv5eesw"; - - blechkasten = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIMnLFWr1zTU8sEJr3XZaRoLxto0QAB9HOQRbyDphBS+"; - seifenkiste = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMX8q2ux3YdAFGLRfD8/fCEAEalqxsRQwkOSp6gYedFt"; - - #servers - briefkasten = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN8mi9ZKPdhn20g9gyxE7NYBq/vAKemW4lhaQlLw5QVc"; - hector = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIILONdCJED/Lmd215tO8KBkJSl1E9ZdMyC+syxSqmo7o"; - trabbi = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBwzDl1dHpDIZxFfRBLQyFn85RVTsg7OgO3Eahdn3FTJ"; - wanderduene = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH8uAvUnwhg3pnCdaaoclWDKV275SyNSyrkJON+R5Boi"; - }; - - plainSecrets = { - "restic-server/briefkasten.age".publicKeys = with keys; [ main trabbi hector briefkasten ]; - "restic-server/wanderduene.age".publicKeys = with keys; [ main trabbi hector briefkasten ]; - "briefkasten/influx/grafana_token_mqttData.age".publicKeys = with keys; [ main briefkasten hector ]; - }; - - globalSecrets = [ - "passwords/leah-at-f2k1-de.age" - "passwords/katja.age" - ]; - - hostSecrets = { - blechkasten = [ - "syncthing/key.age" - "syncthing/cert.age" - ]; - - seifenkiste = [ - "acme-tsig-key.age" - - "syncthing/key.age" - "syncthing/cert.age" - ]; - - briefkasten = [ - "acme-tsig-key.age" - "wireguard-privkey.age" - "restic-server-htpasswd.age" - "pppd-env.age" - "caPassword.age" - - "restic/gotosocial.age" - "restic/influxdb.age" - - "influx/telegraf_token_mqttData.age" - "influx/master_token.age" - "influx/backup_env.age" - - "telegraf/secrets.env.age" - - "zigbee2mqtt/secrets.age" - - "syncthing/key.age" - "syncthing/cert.age" - "syncthing/htpasswd.age" - - "restic/syncthing-audiobooks-orig.age" - "restic/syncthing-audiobooks.age" - "restic/syncthing-documents.age" - "restic/syncthing-music-orig.age" - "restic/syncthing-music.age" - "restic/syncthing-pictures.age" - "restic/syncthing-media.age" - "restic/syncthing-bahn-richtlinien.age" - ]; - - hector = [ - "knot-keys.age" - "acme-tsig-key.age" - "radicale-users.age" - "vaultwarden-secrets.age" - "gotosocial-env.age" - - "restic/radicale.age" - "restic/vaultwarden.age" - "restic/ctucx-things.age" - "restic/gitolite.age" - "restic/gotosocial.age" - "restic/matrix-synapse.age" - "restic/mail.age" - - "syncthing/key.age" - "syncthing/cert.age" - - "mail/password-katja-ctu.cx.age" - "mail/password-gts-ctu.cx.age" - "mail/password-gts-zuggeschmack.de.age" - "mail/password-info-zuggeschmack.de.age" - "mail/password-vaultwarden-ctu.cx.age" - - "matrix-synapse/registration_shared_secret.age" - ]; - - trabbi = [ - "acme-tsig-key.age" - "gotosocial-env.age" - - "restic/gotosocial.age" - ]; - - wanderduene = [ - "acme-tsig-key.age" - "wireguard-privkey.age" - "restic-server-htpasswd.age" - "rclone-config.age" - - "syncthing/key.age" - "syncthing/cert.age" - - "matrix-dendrite/private-key.age" - ]; - }; - -in plainSecrets // ( - globalSecrets - |> builtins.map (secret: { name = secret; value = { publicKeys = (builtins.attrValues keys); }; }) - |> builtins.listToAttrs -) // ( - hostSecrets - |> builtins.mapAttrs ( - hostName: secrets: ( - secrets - |> builtins.map (secret: { name = "${hostName}/${secret}"; value = { publicKeys = [ keys.main keys."${hostName}" ]; }; }) - ) - ) - |> builtins.attrValues - |> builtins.concatLists - |> builtins.listToAttrs -)