Leveraging age and agenix,
this project allows you to inject variables containing secrets into your flakes' devShells.
This simplifies the onboarding process for new developers by enabling secure secret sharing (with access control) and making projects more self-contained by eliminating the need for external tools.
Basic knowledge of how agenix works is required.
It relies on the same setup as agenix:
secrets directory containing all the encrypted secrets.secrets.nix file that lists the secrets and specifies which keys can decrypt each one.Example of secrets/secrets.nix:
{
"foo.age".publicKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPDpVA+jisOuuNDeCJ67M11qUP8YY29cipajWzTFAobi"
];
}
While this is the format expected by agenix, you are not strictly bound to it, agenix-shell only requires you to specify the paths for the .age files, similar to agenix modules, following the secrets/secrets.nix structure is only useful if you want to use the agenix CLI.
agenix-shell injects two environment variables for each secret:
_PATH to the variable name).For example:
foo: Contains the secret.foo_PATH: Contains the path to the secret.{
devShells.${system}.default = let
installationScript = inputs.agenix-shell.lib.installationScript system {
secrets = {
foo.file = ./secrets/foo.age;
};
};
in pkgs.mkShell {
shellHook = ''
source ${lib.getExe installationScript}
'';
};
}
Check the basic example for a working setup. You'll need to delete the encrypted secret and encrypt your own using your key. Alternatively, you can use the provided key (not for production use).
Initialize with:
nix flake init -t github:aciceri/agenix-shell#basic
Internally, this approach uses flake-parts for argument evaluation. Refer to the flake.parts documentation for a full list of options.
flake-parts{
imports = [
inputs.agenix-shell.flakeModules.default
];
agenix-shell = {
secrets = {
foo.file = ./secrets/foo.age;
};
};
perSystem = {pkgs, config, lib, ...}: {
devShells.default = pkgs.mkShell {
shellHook = ''
source ${lib.getExe config.agenix-shell.installationScript}
'';
};
};
}
Check the flake-parts template for a working example. Initialize with:
nix flake init -t github:aciceri/agenix-shell#flake-parts
devenvFind a working template here.
Initialize with:
nix flake init -t github:aciceri/agenix-shell#devenv
The functionality is straightforward:
agenix-shell exports a configurable script, which is sourced in the devShell (e.g. via a shellHook).$HOME/.ssh/id_rsa or $HOME/.ssh/id_ed25519).$XDG_RUNTIME_DIR/agenix-shell/<hash> (commonly mounted on tmpfs).~/.agenix-shell/<hash> (mounted on hfs, similar to tmpfs).AGENIX_SHELL_SECRETS_PATH pointing to the base directory where all secrets are stored.Everything is highly customizable via options. Refer to flake.parts for a complete list and defaults.
The script is hygienic:
PATH is used to isolate dependencies (on Linux).Nix
100.0%
Leveraging age and agenix,
this project allows you to inject variables containing secrets into your flakes' devShells.
This simplifies the onboarding process for new developers by enabling secure secret sharing (with access control) and making projects more self-contained by eliminating the need for external tools.
Basic knowledge of how agenix works is required.
It relies on the same setup as agenix:
secrets directory containing all the encrypted secrets.secrets.nix file that lists the secrets and specifies which keys can decrypt each one.Example of secrets/secrets.nix:
{
"foo.age".publicKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPDpVA+jisOuuNDeCJ67M11qUP8YY29cipajWzTFAobi"
];
}
While this is the format expected by agenix, you are not strictly bound to it, agenix-shell only requires you to specify the paths for the .age files, similar to agenix modules, following the secrets/secrets.nix structure is only useful if you want to use the agenix CLI.
agenix-shell injects two environment variables for each secret:
_PATH to the variable name).For example:
foo: Contains the secret.foo_PATH: Contains the path to the secret.{
devShells.${system}.default = let
installationScript = inputs.agenix-shell.lib.installationScript system {
secrets = {
foo.file = ./secrets/foo.age;
};
};
in pkgs.mkShell {
shellHook = ''
source ${lib.getExe installationScript}
'';
};
}
Check the basic example for a working setup. You'll need to delete the encrypted secret and encrypt your own using your key. Alternatively, you can use the provided key (not for production use).
Initialize with:
nix flake init -t github:aciceri/agenix-shell#basic
Internally, this approach uses flake-parts for argument evaluation. Refer to the flake.parts documentation for a full list of options.
flake-parts{
imports = [
inputs.agenix-shell.flakeModules.default
];
agenix-shell = {
secrets = {
foo.file = ./secrets/foo.age;
};
};
perSystem = {pkgs, config, lib, ...}: {
devShells.default = pkgs.mkShell {
shellHook = ''
source ${lib.getExe config.agenix-shell.installationScript}
'';
};
};
}
Check the flake-parts template for a working example. Initialize with:
nix flake init -t github:aciceri/agenix-shell#flake-parts
devenvFind a working template here.
Initialize with:
nix flake init -t github:aciceri/agenix-shell#devenv
The functionality is straightforward:
agenix-shell exports a configurable script, which is sourced in the devShell (e.g. via a shellHook).$HOME/.ssh/id_rsa or $HOME/.ssh/id_ed25519).$XDG_RUNTIME_DIR/agenix-shell/<hash> (commonly mounted on tmpfs).~/.agenix-shell/<hash> (mounted on hfs, similar to tmpfs).AGENIX_SHELL_SECRETS_PATH pointing to the base directory where all secrets are stored.Everything is highly customizable via options. Refer to flake.parts for a complete list and defaults.
The script is hygienic:
PATH is used to isolate dependencies (on Linux).Nix
100.0%