ctucx.git: nixfiles

ctucx' nixfiles

commit b2a06aeb2dbaea5946262fb5b4133ae3da19b5d5
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(-)
A
agenix
|
21
+++++++++++++++++++++
M
flake.nix
|
42
++++++++++++++++++++++++++++++++++++------
M
machines/blechkasten/default.nix
|
3
+++
M
machines/briefkasten/default.nix
|
3
+++
M
machines/hector/default.nix
|
2
++
M
machines/seifenkiste/default.nix
|
3
+++
M
machines/trabbi/default.nix
|
2
++
M
machines/wanderduene/default.nix
|
2
++
M
pkgs/all/agenix/agenix.sh
|
10
+++-------
M
pkgs/all/agenix/default.nix
|
2
+-
D
secrets/agenix
|
23
-----------------------
D
secrets/secrets.nix
|
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
-)