Skip to content
Draft
Show file tree
Hide file tree
Changes from 75 commits
Commits
Show all changes
129 commits
Select commit Hold shift + click to select a range
3e6ad5e
nixos-vars: Init
prescientmoon Jun 5, 2026
ef34047
nixos-vars: Set up nix evaluation
prescientmoon Jun 5, 2026
b9930da
nixos-vars: Attempt to implement the proper logic for evaluating conf…
prescientmoon Jun 5, 2026
1c45c6a
nixos-vars: Add a comment explaining the stub target-host-nixpkgs import
prescientmoon Jun 5, 2026
1cfbb45
nixos-vars: Delete some older code
prescientmoon Jun 5, 2026
8bdaf56
nixos-vars: Add a flake example
prescientmoon Jun 19, 2026
0e0a9dc
nixos-vars: Improve NixOS module
prescientmoon Jun 19, 2026
ac586ed
nixos-vars: Explicitly set Python styling parameters
prescientmoon Jun 19, 2026
a08030b
nixos-vars: Implement config evaluation, including flake support
prescientmoon Jun 19, 2026
a1e3320
nixos-vars: Add support for direct JSON input
prescientmoon Jun 19, 2026
9c96029
nixos-vars: Remove --nixpkgs arg
prescientmoon Jun 19, 2026
b8b8b74
nixos-vars: Fix up example
prescientmoon Jun 19, 2026
f8e386b
nixos-vars: Compute the evaluation order
prescientmoon Jun 24, 2026
ab7a25c
nixos-vars: Make variable casing consistent
prescientmoon Jun 24, 2026
58542cf
nixos-vars: Implement rebuild order computation & checking whether fi…
prescientmoon Jun 24, 2026
9c0e8f3
nixos-vars: Implement generation logic for secrets
prescientmoon Jun 24, 2026
f1c5df5
nixos-vars: Add rudimentary error handling to generation logic
prescientmoon Jun 24, 2026
c78a7e6
nixos-vars: Make generation logic respec --dry-run
prescientmoon Jun 24, 2026
e74c2a7
nixos-vars: Package the CLI using Nix
prescientmoon Jul 1, 2026
cab535f
nixos-vars: Proper error messages for script failure + pick a unique …
prescientmoon Jul 1, 2026
9b2e0e6
nixos-vars: Support non root store paths for deferred packages
prescientmoon Jul 1, 2026
f3355e5
nixos-vars: Implement garbage collection
prescientmoon Jul 1, 2026
cec175c
nixos-vars: Add a basic NixOS test
prescientmoon Jul 1, 2026
e20fef3
nixos-vars: Implement the "regenerate" command
prescientmoon Jul 1, 2026
0296e18
nixos-vars: Fix test
prescientmoon Jul 1, 2026
60e5211
nixos-vars: Remove scuffed postInstall in favour of setuptools.packag…
prescientmoon Jul 1, 2026
5abaf45
nixos-vars: Merge generate and regenerate into a single command
prescientmoon Jul 7, 2026
c1af279
nixos-vars: Add bubblewrap support
prescientmoon Jul 7, 2026
9288cc7
nixos-vars: Run fixup scripts
prescientmoon Jul 7, 2026
6770c62
nixos-vars: Improve the docs slightly
prescientmoon Jul 7, 2026
ea60b93
nixos-vars: Implement prompts
prescientmoon Jul 7, 2026
e1c5339
nixos-vars: Bump python version
prescientmoon Jul 7, 2026
044449d
nixos-vars: Add rudimentary deploy script support
prescientmoon Jul 7, 2026
d87924b
nixos-vars: Update test for the meeting
prescientmoon Jul 7, 2026
2e35a17
nixos-vars: Oops, the test should pass now! (with no sandbox though :…
prescientmoon Jul 7, 2026
f12c0f4
nixos-vars: Attempt to use closureInfo
prescientmoon Jul 7, 2026
77143dd
nixos-vars: Attempt to make the test pass within the Nix sandbox
prescientmoon Jul 9, 2026
96dd3a5
nixos-vars: Bind mount more paths in the bubblewrap sandbox
prescientmoon Jul 9, 2026
4a0edf7
nixos-vars: Make the test pass
prescientmoon Jul 9, 2026
5029e65
nixos-vars: Abstract away the closure computation used by the tests
prescientmoon Jul 9, 2026
f236713
nixos-vars: Support local deployments
prescientmoon Jul 14, 2026
e864e4c
nixos-vars: Add test for local deployment
prescientmoon Jul 14, 2026
b4d88f2
nixos-vars: import history
prescientmoon Jul 14, 2026
67156d7
nixos-vars: Implement a simple age backend
prescientmoon Jul 15, 2026
547c640
nixos-vars: move module to the NixOS module tree
prescientmoon Jul 21, 2026
8a74436
nixos-vars: implement age backend local deployments & pass file list …
prescientmoon Jul 21, 2026
67a204b
nixos-vars: make logs slightly more consistent
prescientmoon Jul 21, 2026
091cc58
nixos-vars: remove generatorModule in favour of the built-in way of m…
prescientmoon Jul 21, 2026
9024982
nivos-vars: write a scuffed demo deploy script for the age backend
prescientmoon Jul 22, 2026
b8318aa
nixos-vars: remove the unused --yes option
prescientmoon Jul 22, 2026
4c41e5d
nixos-vars: start writing some docs
prescientmoon Jul 22, 2026
89f2738
nixos-vars: write a bit more of the docs
prescientmoon Jul 23, 2026
d47e58e
nixos-vars: clean up examples slightly
prescientmoon Jul 23, 2026
afafead
nixos-vars: clean up example directory a bit further
prescientmoon Jul 23, 2026
012cc13
nixos-vars: add docs about the vars schema
prescientmoon Jul 23, 2026
d2eac07
nixos-vars: make a few more things optional, and start working on the…
prescientmoon Jul 23, 2026
ed0c328
nixos-vars: improve docs (slightly)
prescientmoon Jul 23, 2026
610cf25
nixos-vars: Remove {shell,default}.nix
prescientmoon Aug 3, 2026
e433f35
nixos-vars: remove example entrypoints that reference the current nix…
prescientmoon Aug 3, 2026
2ddbb25
nixos-vars: fix the thingies treefmt was complaining about
prescientmoon Aug 3, 2026
807ec47
nixos-vars: move test to the proper spot + fix some dangling paths
prescientmoon Aug 3, 2026
cab67aa
nixos-vars: fix arg parsing for `--set`
prescientmoon Aug 3, 2026
4350292
nixos-vars: remove lib.fileset usage
prescientmoon Aug 3, 2026
c3a8d16
nixos-vars: make age backend file extraction atomic
prescientmoon Aug 5, 2026
60c84df
meta: add myself to the maintainer list
prescientmoon Aug 5, 2026
778326c
nixos-vars: add meta attribute
prescientmoon Aug 5, 2026
1fcba3c
nixos-vars: improve docs & incorporate more PR feedback
prescientmoon Aug 5, 2026
3b5c4f3
nixos-vars: improve phrasing a bit
prescientmoon Aug 5, 2026
e4b0148
nixos-vars: enlarge the code snippet explaining how to write a genera…
prescientmoon Aug 5, 2026
35682d5
nixos-vars: remove editorconfig file
prescientmoon Aug 5, 2026
3a37e55
nixos-vars: remove gitignore
prescientmoon Aug 5, 2026
ee17f8f
nixos-vars: remove ruff config (?)
prescientmoon Aug 5, 2026
1fd6229
nixos-vars: reformat everything to match the root .editorconfig
prescientmoon Aug 5, 2026
a777107
nixos-vars: remove TODO related to merging from the age backend
prescientmoon Aug 5, 2026
80802c8
nixos-vars: add example `identity.target` to age backend
prescientmoon Aug 5, 2026
a0a09c9
nixos-vars: pass both labels and descriptions to prompt scripts
prescientmoon Aug 10, 2026
4aa05d4
nixos-vars: make `fixup` a batch operation
prescientmoon Aug 10, 2026
fa2cf5a
nixos-vars: remove age from devshell
prescientmoon Aug 10, 2026
34fd2f0
nixos-vars: remove unused arg
prescientmoon Aug 10, 2026
d96e647
nixos-vars: use the old CLI when --flake is not used
prescientmoon Aug 10, 2026
fa1db85
nixos-vars: change test to not enable the new CLI
prescientmoon Aug 10, 2026
a32d547
nixos-vars: do not use --impure
prescientmoon Aug 10, 2026
e699983
nixos-vars: replace `nix-vars` with `nixos-vars` everywhere
prescientmoon Aug 10, 2026
aba1dfa
nixos-vars: also replace `nix_vars` -> `nixos_vars`
prescientmoon Aug 10, 2026
8c6dfd7
nixos-vars: rename `deploy` -> `local` and remove the unused `secret`…
prescientmoon Aug 16, 2026
ae61f34
nixos-vars: `deploy` -> `deploy.remote`, `deployLocal` -> `deploy.local`
prescientmoon Aug 18, 2026
db80469
nixos-vars: fix naming inconsistencies with `delayedPackage` and `def…
prescientmoon Aug 18, 2026
ab38bf2
nixos-vars: fix invalid usage of `writeShellScript` in examples
prescientmoon Aug 18, 2026
a1782f8
nixos-vars: fix failing test
prescientmoon Aug 18, 2026
5061bf1
nixos-vars: tiny var name changes (as discussed in the meeting)
prescientmoon Aug 18, 2026
791ac25
nixos-vars: don't directly import <nixpkgs> as a fallback, thus getti…
prescientmoon Aug 18, 2026
8b236a9
nixos-vars: allow mutating names in the NixOS module (instead of alwa…
prescientmoon Aug 18, 2026
c5f0167
nixos-vars: do not fail on the first fixup script error
prescientmoon Aug 18, 2026
f622a0b
nixos-vars: enable __structuredAttrs in order to make nixpkgs-vet happy
prescientmoon Aug 18, 2026
f6c894d
nixos-vars: better `safeName` error messages & check the names on the…
prescientmoon Aug 19, 2026
4d2ffa5
nixos-vars: try to add more comments to `jsonify.nix`, explaining som…
prescientmoon Aug 19, 2026
6971c2e
nixos-secrets: rename from `nixos-vars`
prescientmoon Aug 19, 2026
245c7e2
nixos-secrets: extract common example backends into their own directory
prescientmoon Aug 19, 2026
1643cea
nixos-secrets: add an example of how one can tack structured IDs on t…
prescientmoon Aug 19, 2026
1edf118
nixos-secrets: use "with lib.types" in the module
prescientmoon Aug 19, 2026
fdd076b
nixos-secrets: rename the `!local` flag back to `deploy`
prescientmoon Aug 20, 2026
b985c1f
nixos-secrets: add safety comments to examples
prescientmoon Aug 20, 2026
8f2ad76
nixos-secrets: write jsonschema for secrets configurations
prescientmoon Aug 20, 2026
5f93e3f
nixos-secrets: rework naming structure
prescientmoon Aug 21, 2026
3848fc8
nixos-secrets: make prompt names `safeName`s
prescientmoon Aug 21, 2026
d558dc7
nixos-secrets: fix bad arg description
prescientmoon Aug 21, 2026
2508fb1
nixos-secrets: remove reference to never-captured stderr when running…
prescientmoon Aug 21, 2026
51cef8d
nixos-secrets: fix failure to retrieve files being attributed to the …
prescientmoon Aug 21, 2026
16174d5
nixos-vars: error out on secret with no files
prescientmoon Aug 25, 2026
b5e70fe
nixos-secrets: implement --set and checking whether files have actual…
prescientmoon Aug 25, 2026
4088ff8
nixos-secrets: quote file name in error message
prescientmoon Aug 25, 2026
ee65459
nixos-secrets: generator script timeouts
prescientmoon Aug 25, 2026
9c89013
nixos-secrets: pass info required for git-root detection via env vars
prescientmoon Aug 25, 2026
bb1ff15
nixos-secrets: pass `--die-with-parent` to bwrap
prescientmoon Aug 25, 2026
7b77f48
nixos-secrets: probe for bwrap before using it
prescientmoon Aug 25, 2026
f0c051f
nixos-secrets: testing prompt backend
prescientmoon Aug 26, 2026
9f3963d
nixos-secrets: reset terminal state after running user commands
prescientmoon Aug 26, 2026
d525841
nixos-secrets: improve docs related to the prompt backend changes
prescientmoon Aug 26, 2026
303c627
nixos-secrets: pass empty stdin to generator scripts
prescientmoon Aug 26, 2026
bd8f05b
nixos-secrets: crash if bwrap is avaiable and --no-sandbox is not given
prescientmoon Aug 28, 2026
26752fc
nixos-secrets: proper consistency checks
prescientmoon Aug 28, 2026
3254df8
nixos-secrets: move examples to modulesPath and make test use said ex…
prescientmoon Aug 28, 2026
d2d6bf7
nixos-secrets: make the test pass
prescientmoon Sep 2, 2026
e6af758
nixos-secrets: rewrite the plain-text backend from Bash to Python
prescientmoon Sep 2, 2026
58c856c
nixos-secrets: rework docs
prescientmoon Sep 9, 2026
6336988
nixos-secrets: fix tests
prescientmoon Sep 9, 2026
e0171a0
nixos-secrets: fix docs
prescientmoon Sep 11, 2026
b226dac
nixos-secrets: remove the `exists` script in favour of `list`
prescientmoon Sep 11, 2026
cd8bd49
nixos-secrets: explain when bad things might happen
prescientmoon Sep 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions maintainers/maintainer-list.nix
Original file line number Diff line number Diff line change
Expand Up @@ -22571,6 +22571,13 @@
githubId = 11898437;
name = "Florian Ströger";
};
prescientmoon = {
email = "nix@moonythm.dev";
matrix = "@prescientmoon:moonythm.dev";
github = "prescientmoon";
githubId = 39400800;
name = "prescientmoon";
};
presto8 = {
name = "Preston Hunt";
email = "me@prestonhunt.com";
Expand Down
341 changes: 341 additions & 0 deletions nixos/modules/security/vars.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,341 @@
{ lib, config, ... }:
let
safeName = lib.types.strMatching "[a-zA-Z0-9:_\\.-]*";
cfg = config.vars;

delayedPackage =
description:
lib.mkOption {
inherit description;
type = lib.types.functionTo lib.types.pathInStore;
example = pkgs: pkgs.writeShellScript "echo 'Hi!'";
};

nullableDelayedPackage =
description:
lib.mkOption {
inherit description;
type = lib.types.nullOr (lib.types.functionTo lib.types.pathInStore);
example = pkgs: pkgs.writeShellScript "echo 'Hi!'";
default = null;
};

generatorBackendModule = lib.types.submodule (
{ name, ... }:
{
options = {
name = lib.mkOption {
description = "The name of the backend.";
type = lib.types.str;
readOnly = true;
default = name;
};

get = nullableDelayedPackage ''
Given $1=gen_name and $2=file_name, the script retrieves the
respective secret to $out.
'';

set = delayedPackage ''
Given $1=gen_name and $2=file_name, the script retrieves the
respective secret from $in and stores it in the appropriate location.
'';

exists = delayedPackage ''
Given $1=gen_name and $2=file_name, the script exists with status
code 0 if the secret exists, and with status code 42 otherwise.

This script must not perform side effects.
'';

delete = nullableDelayedPackage ''
Given $1=gen_name and $2=file_name, the script deletes the respective
secret if it does exist.
'';

list = nullableDelayedPackage ''
A script that lists all files managed by this backend. Should output
space-separated or newline-separated pairs of: generator_name
file_name.

If the backend supports multiple hosts, then this command should only
list the secrets owned by the current host. In particular, files
included in this command's output will be deleted by the
collect-garbage command, unless they appear in the user's generator
configuration.

This script must not perform side effects.
'';

fixup = nullableDelayedPackage ''
This script will be run on every invocation of the CLI's generator
command. Given $1=gen_name and $2=file_name, the script performs any
necessary updates to the secrets' files (e.g. rekeying encrypted
secrets). This script can perform side effects, but must be
idempotent.
'';

deploy = nullableDelayedPackage ''
Deploys every available file to the given machine. Any additional
information required by the deploy script can be provided by the user
through environment variables.
'';

deployLocal = nullableDelayedPackage ''
Deploys every available file to the machine with system root mounted
at $1=system_root. This is useful for fresh installs from
environments live live CDs, where the target system is not yet up and
running (even if nixos-install has successfully completed).
'';

fileModule = lib.mkOption {
type = lib.types.deferredModule;
internal = true;
default = { };
description = ''
A module to be imported in every
vars.generators.<name>.files.<name> submodule. Used by backends to
define the `path` attribute. The module will have the following
additional arguments passed to it:
- `generator`, containing the generator the file belongs to
- `backend`, containing the backend associated with said generator
'';
};
};
}
);

fileModule =
{ name, backend, ... }:
{
imports = [ backend.fileModule ];
options = {
name = lib.mkOption {
description = "name of the generated file";
type = safeName;
readOnly = true;
default = name;
defaultText = "Name of the file";
};

path = lib.mkOption {
description = "Path to the generated file; usually set by the backend";
type = lib.types.path;
};

deploy = lib.mkOption {
description = ''
Whether the file should be deployed to the target machine. Disable
this if the generated file is only used as an input to other
generators.

This option is not currently used by the CLI.
Comment thread
prescientmoon marked this conversation as resolved.
Outdated
'';
type = lib.types.bool;
default = true;
};

secret = lib.mkOption {
Comment thread
prescientmoon marked this conversation as resolved.
Outdated
description = ''
Whether the file should be treated as a secret. Backends might
treat such files differently (e.g. they might choose not to encrypt
them).

This option is not currently used by the CLI.
'';
type = lib.types.bool;
default = true;
};
};
};

generatorModule = lib.types.submodule (
{ name, config, ... }:
let
backend = cfg.generatorBackends.${config.backend};
in
{
options = {
name = lib.mkOption {
description = ''
The name of the generator.
This name will be used to refer to the generator in other generators.
'';
type = safeName;
readOnly = true;
default = name;
defaultText = "Name of the generator";
};

prompts = lib.mkOption {
description = ''
A list of prompts this generator will have at its disposal.
'';
type = lib.types.listOf safeName;
default = [ ];
};

dependencies = lib.mkOption {
description = ''
A list of other generators this generator should be able to read the
output(s) of.
'';
type = lib.types.listOf safeName;
default = [ ];
};

files = lib.mkOption {
description = ''
A set of files to generate. The generator 'script' is expected to
produce exactly these files under $out.
'';
default = { };
type = lib.types.attrsOf (
lib.types.submoduleWith {
modules = [ fileModule ];
specialArgs = {
inherit backend;
generator = config;
};
}
);
};

script = delayedPackage ''
The script to run to generate the files. The script will be run with
the following environment variables:
- $in: The directory containing the output values of all declared
dependencies
- $out: The output directory to put the generated files
- $prompts: The directory containing the prompted values as files
The script should produce the files specified in the 'files' attribute
under $out.
'';

backend = lib.mkOption {
type = safeName;
description = "The backend responsible for handling this secret.";
default = cfg.defaultGeneratorBackend;
};
};
}
);

promptBackendModule = lib.types.submodule (
{ name, ... }:
{
options = {
name = lib.mkOption {
description = "The name of the backend.";
type = lib.types.str;
readOnly = true;
default = name;
};

script = delayedPackage ''
Given $1=prompt_type and $2=prompt_text, the script runs the prompt
by the user, then saves respective value to $out.
'';
};
}
);

promptModule = lib.types.submodule (
{ name, ... }:
{
options = {
name = lib.mkOption {
description = "The name of the backend.";
type = lib.types.str;
readOnly = true;
default = name;
};

description = lib.mkOption {
description = ''
The description of the prompted value
'';
type = lib.types.str;
default = name;
Comment thread
prescientmoon marked this conversation as resolved.
Outdated
defaultText = "Name of the prompt";
example = "SSH private key";
};

type = lib.mkOption {
description = ''
The input type of the prompt.
The following types are available:
- hidden: A hidden text (e.g. password)
- line: A single line of text
- multiline: A multiline text
'';
type = lib.types.enum [
"hidden"
"line"
"multiline"
];
default = "line";
};

backend = lib.mkOption {
type = safeName;
description = "The backend responsible for handling this prompt.";
default = cfg.defaultPromptBackend;
};
};
}
);
in
{
options.vars = {
generatorBackends = lib.mkOption {
description = ''
A set of backends that handle storing and retrieving generated files.
'';
default = { };
type = lib.types.attrsOf generatorBackendModule;
};

generators = lib.mkOption {
description = ''
A set of generators that are each expected to produce a set of files
under a directory. Generators can produce files using a script,
possibly referencing values produced by other generators and user
input.
'';
default = { };
type = lib.types.attrsOf generatorModule;
};

defaultGeneratorBackend = lib.mkOption {
description = ''
The default backend to use for generators that do not specify one.
'';
type = safeName;
};

promptBackends = lib.mkOption {
description = ''
A set of backends that handle retrieving user inputs.
'';
default = { };
type = lib.types.attrsOf promptBackendModule;
};

prompts = lib.mkOption {
description = ''
A set of prompts the user can use to provide manual input to the
generator backends.
'';
default = { };
type = lib.types.attrsOf promptModule;
};

defaultPromptBackend = lib.mkOption {
description = ''
The default backend to use for prompts that do not specify one.
'';
type = safeName;
};
};
}
1 change: 1 addition & 0 deletions nixos/tests/all-tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,7 @@ in
nixos-rebuild-target-host = runTest {
imports = [ ./nixos-rebuild-target-host.nix ];
};
nixos-vars-basic-generators = runTest ./nixos-vars/basic-generators;
nixpkgs = pkgs.callPackage ../modules/misc/nixpkgs/test.nix { inherit evalMinimalConfig; };
nixpkgs-config-allow-unfree =
pkgs.callPackage ../modules/misc/nixpkgs/test-nixpkgs-config-allow-unfree.nix
Expand Down
Loading
Loading