Unable to use nix-sops
Describe the bug
I'm trying to use nix-sops to handle some secrets, but I can't make it.
To Reproduce
- In flake.nix
systemConfigs =
let makeSystemConfig = inputs.system-manager.lib.makeSystemConfig;
in {
"minami" = makeSystemConfig {
modules = [ ./system/minami inputs.sops-nix.nixosModules.sops ];
extraSpecialArgs = { inherit inputs; };
};
};
In system/minami/default.nix
{
imports = [ ./other-modules ];
sops = {
age.sshKeyPaths = [ "/etc/ssh/nix-sops" ];
secrets = {
secret = {
sopsFile = ./secrets/secret.json;
format = "json";
};
};
};
config = {
nixpkgs.hostPlatform = "x86_64-linux";
# other config
};
}
nix repl --extra-experimental-features 'flakes repl-flake' flake.nix --show-trace
nix-repl> systemConfigs.minami
error:
… while evaluating the attribute 'minami'
at /nix/store/n2xvix786b3v8sni332pikjq3j8r3ygw-source/flake.nix:89:9:
88| makeSystemConfig { modules = [ ./system/marushiru.nix ]; };
89| "minami" = makeSystemConfig {
| ^
90| modules = [ ./system/minami inputs.sops-nix.nixosModules.sops ];
… from call site
at /nix/store/n2xvix786b3v8sni332pikjq3j8r3ygw-source/flake.nix:89:20:
88| makeSystemConfig { modules = [ ./system/marushiru.nix ]; };
89| "minami" = makeSystemConfig {
| ^
90| modules = [ ./system/minami inputs.sops-nix.nixosModules.sops ];
… while calling 'makeSystemConfig'
at /nix/store/ncibdc9d87f9ysfvjkaiqpmwxgiayl05-source/nix/lib.nix:17:5:
16| makeSystemConfig =
17| { modules
| ^
18| , extraSpecialArgs ? { }
… from call site
at /nix/store/ncibdc9d87f9ysfvjkaiqpmwxgiayl05-source/nix/lib.nix:92:5:
91| in
92| returnIfNoAssertions toplevel;
| ^
93|
… while calling 'returnIfNoAssertions'
at /nix/store/ncibdc9d87f9ysfvjkaiqpmwxgiayl05-source/nix/lib.nix:46:30:
45|
46| returnIfNoAssertions = drv:
| ^
47| let
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/modules.nix:242:28:
241| # For definitions that have an associated option
242| declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
| ^
243|
… while calling 'mapAttrsRecursiveCond'
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/attrsets.nix:1167:5:
1166| f:
1167| set:
| ^
1168| let
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/modules.nix:234:33:
233| ({ inherit lib options config specialArgs; } // specialArgs);
234| in mergeModules prefix (reverseList collected);
| ^
235|
… while calling 'reverseList'
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/lists.nix:1068:17:
1067| */
1068| reverseList = xs:
| ^
1069| let l = length xs; in genList (n: elemAt xs (l - n - 1)) l;
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/modules.nix:229:25:
228| merged =
229| let collected = collectModules
| ^
230| class
… while calling anonymous lambda
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/modules.nix:445:37:
444|
445| in modulesPath: initialModules: args:
| ^
446| filterModules modulesPath (collectStructuredModules unknownModule "" initialModules args);
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/modules.nix:446:7:
445| in modulesPath: initialModules: args:
446| filterModules modulesPath (collectStructuredModules unknownModule "" initialModules args);
| ^
447|
… while calling 'filterModules'
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/modules.nix:413:36:
412| # modules recursively. It returns the final list of unique-by-key modules
413| filterModules = modulesPath: { disabled, modules }:
| ^
414| let
… while calling anonymous lambda
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/modules.nix:439:31:
438| disabledKeys = concatMap ({ file, disabled }: map (moduleKey file) disabled) disabled;
439| keyFilter = filter (attrs: ! elem attrs.key disabledKeys);
| ^
440| in map (attrs: attrs.module) (builtins.genericClosure {
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/modules.nix:400:22:
399| let
400| module = checkModule (loadModule args parentFile "${parentKey}:anon-${toString n}" x);
| ^
401| collectedImports = collectStructuredModules module._file module.key module.imports args;
… while calling anonymous lambda
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/modules.nix:365:11:
364| else
365| m: m;
| ^
366|
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/modules.nix:400:35:
399| let
400| module = checkModule (loadModule args parentFile "${parentKey}:anon-${toString n}" x);
| ^
401| collectedImports = collectStructuredModules module._file module.key module.imports args;
… while calling 'loadModule'
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/modules.nix:336:53:
335| # Like unifyModuleSyntax, but also imports paths and calls functions if necessary
336| loadModule = args: fallbackFile: fallbackKey: m:
| ^
337| if isFunction m then
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/modules.nix:354:14:
353| throw "Module imports can't be nested lists. Perhaps you meant to remove one level of lists? Definitions: ${showDefs defs}"
354| else unifyModuleSyntax (toString m) (toString m) (applyModuleArgsIfFunction (toString m) (import m) args);
| ^
355|
… while calling 'unifyModuleSyntax'
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/modules.nix:454:34:
453| of ‘options’, ‘config’ and ‘imports’ attributes. */
454| unifyModuleSyntax = file: key: m:
| ^
455| let
error: Module `/nix/store/n2xvix786b3v8sni332pikjq3j8r3ygw-source/system/minami' has an unsupported attribute `sops'. This is caused by introducing a top-level `config' or `options' attribute. Add configuration attributes immediately on the top level instead, or move all of them (namely: sops) into the explicit `config' attribute.
Expected behavior
The configure can be built normally.
System information
latest system-manager and nix-sops
Ubuntu 22.04
Additional context
It seems that system-manager cannot use nixos modules. I'm wondering if the home-manager module can be used.
No you should use the NixOS module, not the HM module.
From the error, I have a suspicion that you didn't share your full config, because that error is a generic one from the module system that you get when you put attributes in the top-level module scope together with an explicit options or config attribute.
Do you by any chance have something like this?
{
sops = { ... };
config = { ... };
}
In that case you'd need to move the sops part inside config.
If you introduce an options attribute, you also need to put the actual config inside config.
That being said, I didn't test sops-nix with system-manager, so I'm not sure if it works.
No you should use the NixOS module, not the HM module.
From the error, I have a suspicion that you didn't share your full config, because that error is a generic one from the module system that you get when you put attributes in the top-level module scope together with an explicit options or config attribute.
Do you by any chance have something like this?
{ sops = { ... }; config = { ... }; }In that case you'd need to move the
sopspart insideconfig. If you introduce anoptionsattribute, you also need to put the actual config insideconfig.That being said, I didn't test sops-nix with system-manager, so I'm not sure if it works.
Yes, I didn't upload the full config. I would upload a minimum reproduction if needed.
However, there are still errors if I move sops options into config, or even I import sops nixos module only. I will upload such error messages later since they may contain some more helpful information.
{
imports = [ ./../../modules/system/xray.nix ];
config = {
nixpkgs.hostPlatform = "x86_64-linux";
sops = {
age.sshKeyPaths = [ "/etc/ssh/nix-sops" ];
secrets = {
secret = {
sopsFile = ./secrets/secret.json;
format = "json";
};
};
};
# other config
};
}
After moving sops into config, I got:
error:
… while evaluating the attribute 'minami'
at /nix/store/jc7jknyri77nx3giz3rzzbxdflsrl1mj-source/flake.nix:89:9:
88| makeSystemConfig { modules = [ ./system/marushiru.nix ]; };
89| "minami" = makeSystemConfig {
| ^
90| modules = [ ./system/minami inputs.sops-nix.nixosModules.sops ];
… from call site
at /nix/store/jc7jknyri77nx3giz3rzzbxdflsrl1mj-source/flake.nix:89:20:
88| makeSystemConfig { modules = [ ./system/marushiru.nix ]; };
89| "minami" = makeSystemConfig {
| ^
90| modules = [ ./system/minami inputs.sops-nix.nixosModules.sops ];
… while calling 'makeSystemConfig'
at /nix/store/ncibdc9d87f9ysfvjkaiqpmwxgiayl05-source/nix/lib.nix:17:5:
16| makeSystemConfig =
17| { modules
| ^
18| , extraSpecialArgs ? { }
… from call site
at /nix/store/ncibdc9d87f9ysfvjkaiqpmwxgiayl05-source/nix/lib.nix:92:5:
91| in
92| returnIfNoAssertions toplevel;
| ^
93|
… while calling 'returnIfNoAssertions'
at /nix/store/ncibdc9d87f9ysfvjkaiqpmwxgiayl05-source/nix/lib.nix:46:30:
45|
46| returnIfNoAssertions = drv:
| ^
47| let
… while evaluating the error message for definitions for `system', which is an option that does not exist
… while evaluating a definition from `/nix/store/jslmnzssy01r4pighp0mnhp9dd5yk2w9-source/modules/sops/secrets-for-users'
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/modules.nix:272:25:
271| "while evaluating a definition from `${firstDef.file}'"
272| ( showDefs [ firstDef ])
| ^
273| );
… while calling 'showDefs'
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/options.nix:445:14:
444|
445| showDefs = defs: concatMapStrings (def:
| ^
446| let
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/options.nix:445:20:
444|
445| showDefs = defs: concatMapStrings (def:
| ^
446| let
… while calling 'concatMapStrings'
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/strings.nix:60:25:
59| */
60| concatMapStrings = f: list: concatStrings (map f list);
| ^
61|
… while calling anonymous lambda
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/options.nix:445:38:
444|
445| showDefs = defs: concatMapStrings (def:
| ^
446| let
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/options.nix:449:10:
448| prettyEval = builtins.tryEval
449| (lib.generators.toPretty { }
| ^
450| (lib.generators.withRecursion { depthLimit = 10; throwOnDepthLimit = false; } def.value));
… while calling 'go'
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/generators.nix:343:18:
342| let
343| go = indent: v:
| ^
344| let introSpace = if multiline then "\n${indent} " else " ";
… while calling anonymous lambda
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/attrsets.nix:1062:10:
1061| attrs:
1062| map (name: f name attrs.${name}) (attrNames attrs);
| ^
1063|
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/attrsets.nix:1062:16:
1061| attrs:
1062| map (name: f name attrs.${name}) (attrNames attrs);
| ^
1063|
… while calling anonymous lambda
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/generators.nix:391:22:
390| + concatStringsSep introSpace (mapAttrsToList
391| (name: value:
| ^
392| "${escapeNixIdentifier name} = ${
… while evaluating an attribute `activationScripts`
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/generators.nix:394:22:
393| addErrorContext "while evaluating an attribute `${name}`"
394| (go (indent + " ") value)
| ^
395| };") v)
… while calling 'go'
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/generators.nix:343:18:
342| let
343| go = indent: v:
| ^
344| let introSpace = if multiline then "\n${indent} " else " ";
… while calling anonymous lambda
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/attrsets.nix:1062:10:
1061| attrs:
1062| map (name: f name attrs.${name}) (attrNames attrs);
| ^
1063|
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/attrsets.nix:1062:16:
1061| attrs:
1062| map (name: f name attrs.${name}) (attrNames attrs);
| ^
1063|
… while calling anonymous lambda
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/generators.nix:391:22:
390| + concatStringsSep introSpace (mapAttrsToList
391| (name: value:
| ^
392| "${escapeNixIdentifier name} = ${
… while evaluating an attribute `content`
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/generators.nix:394:22:
393| addErrorContext "while evaluating an attribute `${name}`"
394| (go (indent + " ") value)
| ^
395| };") v)
… while calling 'go'
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/generators.nix:343:18:
342| let
343| go = indent: v:
| ^
344| let introSpace = if multiline then "\n${indent} " else " ";
… while calling anonymous lambda
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/attrsets.nix:1062:10:
1061| attrs:
1062| map (name: f name attrs.${name}) (attrNames attrs);
| ^
1063|
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/attrsets.nix:1062:16:
1061| attrs:
1062| map (name: f name attrs.${name}) (attrNames attrs);
| ^
1063|
… while calling anonymous lambda
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/generators.nix:391:22:
390| + concatStringsSep introSpace (mapAttrsToList
391| (name: value:
| ^
392| "${escapeNixIdentifier name} = ${
… while evaluating an attribute `setupSecretsForUsers`
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/generators.nix:394:22:
393| addErrorContext "while evaluating an attribute `${name}`"
394| (go (indent + " ") value)
| ^
395| };") v)
… while calling 'go'
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/generators.nix:343:18:
342| let
343| go = indent: v:
| ^
344| let introSpace = if multiline then "\n${indent} " else " ";
… while calling 'evalNext'
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/generators.nix:318:24:
317| let
318| evalNext = x: mapAny (depth + 1) (transform (depth + 1) x);
| ^
319| in
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/generators.nix:318:27:
317| let
318| evalNext = x: mapAny (depth + 1) (transform (depth + 1) x);
| ^
319| in
… while calling 'mapAny'
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/generators.nix:316:25:
315| else id;
316| mapAny = depth: v:
| ^
317| let
… from call site
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/generators.nix:318:47:
317| let
318| evalNext = x: mapAny (depth + 1) (transform (depth + 1) x);
| ^
319| in
… while calling 'id'
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/trivial.nix:36:8:
35| */
36| id = x: x;
| ^
37|
… from call site
at /nix/store/jslmnzssy01r4pighp0mnhp9dd5yk2w9-source/modules/sops/secrets-for-users/default.nix:36:11:
35| ${withEnvironment "${cfg.package}/bin/sops-install-secrets -ignore-passwd ${manifestForUsers}"}
36| '' // lib.optionalAttrs (config.system ? dryActivationScript) {
| ^
37| supportsDryActivation = true;
… while calling 'optionalAttrs'
at /nix/store/j10523yhkcc34478azkgcl70yzcx6j2j-source/lib/attrsets.nix:1318:5:
1317| cond:
1318| as:
| ^
1319| if cond then as else {};
error: attribute 'system' missing
at /nix/store/jslmnzssy01r4pighp0mnhp9dd5yk2w9-source/modules/sops/secrets-for-users/default.nix:36:30:
35| ${withEnvironment "${cfg.package}/bin/sops-install-secrets -ignore-passwd ${manifestForUsers}"}
36| '' // lib.optionalAttrs (config.system ? dryActivationScript) {
| ^
37| supportsDryActivation = true;
Did you mean systemd?
Right, you'd need to add system as an option in https://github.com/numtide/system-manager/blob/55b5f097e79b97223a60785cf76ecc48caef4885/nix/modules/upstream/nixpkgs/default.nix#L18-L27
options = {
system = lib.mkOption { type = lib.types.raw; };
services.openssh = {
enable = lib.mkOption {
type = lib.types.bool;
default = false;
};
};
};
I managed to make it work after adding such options. However, the secret file couldn't be read at runtime (and there is no /run/secrets).
It seems that system-manager needs to handle system.activationScripts
https://github.com/Mic92/sops-nix/blob/538c114cfdf1f0458f507087b1dcf018ce1c0c4c/modules/sops/default.nix#L331-L347
It seems that system-manager needs to handle
system.activationScriptshttps://github.com/Mic92/sops-nix/blob/538c114cfdf1f0458f507087b1dcf018ce1c0c4c/modules/sops/default.nix#L331-L347
A better solution would be for sops to decrypt secrets through a systemd service instead of an activation script, which is the general direction in which things are going anyway, with systemd initrd and such.
relevant: https://github.com/Mic92/sops-nix/pull/39