diff --git a/modules/home-manager/sops.nix b/modules/home-manager/sops.nix index a1c601b..ea48ce6 100644 --- a/modules/home-manager/sops.nix +++ b/modules/home-manager/sops.nix @@ -62,6 +62,14 @@ let }; }); + pathNotInStore = lib.mkOptionType { + name = "pathNotInStore"; + description = "path not in the Nix store"; + descriptionClass = "noun"; + check = x: !lib.path.hasStorePathPrefix x; + merge = lib.mergeEqualOption; + }; + manifestFor = suffix: secrets: pkgs.writeTextFile { name = "manifest${suffix}.json"; text = builtins.toJSON { @@ -166,7 +174,7 @@ in { age = { keyFile = lib.mkOption { - type = lib.types.nullOr lib.types.path; + type = lib.types.nullOr pathNotInStore; default = null; example = "/home/someuser/.age-key.txt"; description = '' diff --git a/modules/sops/default.nix b/modules/sops/default.nix index 356f0c7..c8488c4 100644 --- a/modules/sops/default.nix +++ b/modules/sops/default.nix @@ -10,6 +10,14 @@ let }; manifest = manifestFor "" regularSecrets {}; + pathNotInStore = lib.mkOptionType { + name = "pathNotInStore"; + description = "path not in the Nix store"; + descriptionClass = "noun"; + check = x: !lib.path.hasStorePathPrefix (/. + x); + merge = lib.mergeEqualOption; + }; + regularSecrets = lib.filterAttrs (_: v: !v.neededForUsers) cfg.secrets; sysusersEnabled = options.systemd ? sysusers && config.systemd.sysusers.enable; @@ -237,7 +245,7 @@ in { age = { keyFile = lib.mkOption { - type = lib.types.nullOr lib.types.path; + type = lib.types.nullOr pathNotInStore; default = null; example = "/var/lib/sops-nix/key.txt"; description = '' diff --git a/pkgs/sops-install-secrets/nixos-test.nix b/pkgs/sops-install-secrets/nixos-test.nix index f44f790..2236f14 100644 --- a/pkgs/sops-install-secrets/nixos-test.nix +++ b/pkgs/sops-install-secrets/nixos-test.nix @@ -9,7 +9,7 @@ let extraConfig ]; sops = { - age.keyFile = ./test-assets/age-keys.txt; + age.keyFile = "/run/age-keys.txt"; defaultSopsFile = ./test-assets/secrets.yaml; secrets.test_key.neededForUsers = true; secrets."nested/test/file".owner = "example-user"; @@ -70,12 +70,18 @@ in { nodes.machine = { lib, ... }: { imports = [ ../../modules/sops ]; sops = { - age.keyFile = ./test-assets/age-keys.txt; + age.keyFile = "/run/age-keys.txt"; defaultSopsFile = ./test-assets/secrets.yaml; secrets.test_key = { }; keepGenerations = lib.mkDefault 0; }; + # must run before sops sets up keys + boot.initrd.postDeviceCommands = '' + cp -r ${./test-assets/age-keys.txt} /run/age-keys.txt + chmod -R 700 /run/age-keys.txt + ''; + specialisation.pruning.configuration.sops.keepGenerations = 10; }; @@ -108,13 +114,19 @@ in { age-keys = makeTest { name = "sops-age-keys"; - nodes.machine = { + nodes.machine = { lib, ... }: { imports = [ ../../modules/sops ]; sops = { - age.keyFile = ./test-assets/age-keys.txt; + age.keyFile = "/run/age-keys.txt"; defaultSopsFile = ./test-assets/secrets.yaml; secrets.test_key = { }; }; + + # must run before sops sets up keys + boot.initrd.postDeviceCommands = '' + cp -r ${./test-assets/age-keys.txt} /run/age-keys.txt + chmod -R 700 /run/age-keys.txt + ''; }; testScript = '' @@ -213,14 +225,20 @@ in { templates = makeTest { name = "sops-templates"; - nodes.machine = { config, ... }: { + nodes.machine = { config, lib, ... }: { imports = [ ../../modules/sops ]; sops = { - age.keyFile = ./test-assets/age-keys.txt; + age.keyFile = "/run/age-keys.txt"; defaultSopsFile = ./test-assets/secrets.yaml; secrets.test_key = { }; }; + # must run before sops sets up keys + boot.initrd.postDeviceCommands = '' + cp -r ${./test-assets/age-keys.txt} /run/age-keys.txt + chmod -R 700 /run/age-keys.txt + ''; + sops.templates.test_template = { content = '' This line is not modified. @@ -275,7 +293,7 @@ in { imports = [ ../../modules/sops ]; sops = { - age.keyFile = ./test-assets/age-keys.txt; + age.keyFile = "/run/age-keys.txt"; defaultSopsFile = ./test-assets/secrets.yaml; secrets.test_key = { restartUnits = [ "restart-unit.service" "reload-unit.service" ]; @@ -283,6 +301,12 @@ in { }; }; + # must run before sops sets up keys + boot.initrd.postDeviceCommands = '' + cp -r ${./test-assets/age-keys.txt} /run/age-keys.txt + chmod -R 700 /run/age-keys.txt + ''; + systemd.services."restart-unit" = { description = "Restart unit"; # not started on boot @@ -380,7 +404,13 @@ in { inherit (pkgs) system; }; - user-passwords = userPasswordTest "sops-user-passwords" {}; + user-passwords = userPasswordTest "sops-user-passwords" { + # must run before sops sets up keys + boot.initrd.postDeviceCommands = '' + cp -r ${./test-assets/age-keys.txt} /run/age-keys.txt + chmod -R 700 /run/age-keys.txt + ''; + }; } // pkgs.lib.optionalAttrs (pkgs.lib.versionAtLeast (pkgs.lib.versions.majorMinor pkgs.lib.version) "24.05") { user-passwords-sysusers = userPasswordTest "sops-user-passwords-sysusers" { systemd.sysusers.enable = true; @@ -388,5 +418,11 @@ in { system.etc.overlay.enable = true; boot.initrd.systemd.enable = true; boot.kernelPackages = pkgs.linuxPackages_latest; + + # must run before sops sets up keys + systemd.services."sops-install-secrets-for-users".preStart = '' + printf '${builtins.readFile ./test-assets/age-keys.txt}' > /run/age-keys.txt + chmod -R 700 /run/age-keys.txt + ''; }; }