Using Agenix with devShells
Table of Contents
Tip
This article is part of the Agenix series
- Getting Started with Agenix
- Using Agenix with Home Manager
- 👉 Using Agenix with devShells
Nix with Flakes allows you to easily centralize project environments and setup right in your repository. Often, your README will tell the reader "get an API key for FOOSERVICE from a teammate"
Just like NixOS modules and home-manager, we can use Agenix to encrypt and store secrets without exposing them to our git repository.
flake-parts
The easiest way to use Agenix with devShells is to use the agenix-shell module for flake-parts.
Let's start with a basic flake using flake-parts.
{
description = "Agenix example for devShells";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
+ flake-parts.url = "github:hercules-ci/flake-parts";
};
- outputs = { self, nixpkgs }:
+ outputs = { self, nixpkgs, flake-parts }:
+ flake-parts.lib.mkFlake {inherit inputs;} {
+ imports = [];
+ systems = ["x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin"];
+ perSystem = { pkgs, ... }: {
+ devShells.default = pkgs.mkShell {
+ packages = [];
+ };
+ };
+ }
+ };
}
Add Agenix and agenix-shell
Lets add flake-parts and the agenix-shell module.
{
description = "Agenix example for devShells";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
flake-parts.url = "github:hercules-ci/flake-parts";
+ agenix.url = "github:ryantm/agenix";
+ agenix-shell.url = "github:aciceri/agenix-shell";
};
- outputs = { self, nixpkgs, flake-parts }:
+ outputs = { self, nixpkgs, flake-parts, agenix, agenix-shell }:
flake-parts.lib.mkFlake {inherit inputs;} {
- imports = [];
+ imports = [
+ agenix-shell.flakeModules.default
+ ];
systems = ["x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin"];
- perSystem = { pkgs, ... }: {
+ perSystem = { pkgs, config, lib ... }: {
devShells.default = pkgs.mkShell {
- packages = [];
+ packages = [agenix.packages.${system}.default];
+ shellHook = ''
+ source ${lib.getExe config.agenix-shell.installationScript}
+ '';
};
};
}
};
}
Configure your secrets recipients
You can reference the section we described last time.
This time, we're going to encrypt a file called api-keys.age
.
Create your secrets files
Create your secrets files by running agenix -e <key-name>.age
in the same directory as secrets.nix
. Fill them in with the relevant values.
# service-a-api-key.age
foo
Use your secrets
{
description = "Agenix example for devShells";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
flake-parts.url = "github:hercules-ci/flake-parts";
agenix.url = "github:ryantm/agenix";
agenix-shell.url = "github:aciceri/agenix-shell";
};
outputs = { self, nixpkgs, flake-parts, agenix, agenix-shell }:
flake-parts.lib.mkFlake {inherit inputs;} {
imports = [
agenix-shell.flakeModules.default
];
systems = ["x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin"];
+ agenix-shell = {
+ secrets = {
+ SERVICE_A_API_KEY.file = ./service-a-api-key.age;
+ SERVICE_B_API_KEY.file = ./service-b-api-key.age;
+ SERVICE_C_API_KEY.file = ./service-c-api-key.age;
+ };
+ };
perSystem = { pkgs, config, lib ... }: {
devShells.default = pkgs.mkShell {
packages = [agenix.packages.${system}.default];
shellHook = ''
source ${lib.getExe config.agenix-shell.installationScript}
'';
};
};
}
};
}
Your local project secrets are now available when you enter your devShell with nix develop
.
Wrapping Up
Agenix seemed complicated to me at first, but once I got it set up up in the three usual scenarios (NixOS, home-manager, and devShells), its simplicity came to light.
I hope this series helps you take advantage of Agenix as well.
Full Example
flake.nix
{
description = "Agenix example for devShells";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
flake-parts.url = "github:hercules-ci/flake-parts";
agenix.url = "github:ryantm/agenix";
agenix-shell.url = "github:aciceri/agenix-shell";
};
outputs = { self, nixpkgs, flake-parts, agenix, agenix-shell }:
flake-parts.lib.mkFlake {inherit inputs;} {
imports = [
agenix-shell.flakeModules.default
];
systems = ["x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin"];
agenix-shell = {
secrets = {
SERVICE_A_API_KEY.file = ./service-a-api-key.age;
SERVICE_B_API_KEY.file = ./service-b-api-key.age;
SERVICE_C_API_KEY.file = ./service-c-api-key.age;
};
};
perSystem = { pkgs, config, lib ... }: {
devShells.default = pkgs.mkShell {
packages = [agenix.packages.${system}.default];
shellHook = ''
source ${lib.getExe config.agenix-shell.installationScript}
'';
};
};
}
};
}
secrets.nix
let
local = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP55ETmYHSCjtvDZ/SDoHDTblYZPD2XDmObLMQvc+9xR mitchell@nixos";
remote = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII5SFrZIaTh42TWQKSXeGRhBZ5CAvJWoJov+eiaUbwxa root@nixos";
in {
"service-a-api-key.age".publicKeys = [local remote];
"service-b-api-key.age".publicKeys = [local remote];
"service-c-api-key.age".publicKeys = [local remote];
}