nixpkgs/nixos/modules/services/security/vault-agent.nix
emilylange 4b038dfbab
nixos/{consul-template,vault-agent}: drop template sub-option
An HCL config can be represented as JSON in different ways and we forced
users to use a list of attrsets for `cfg.settings.template` prior to
this change.

Similarly, a user may opt to use `vault-agent` exclusively as auth-proxy
without any templates, which would result in `null` ending up in the
resulting JSON configuration and prevent `vault-agent` from starting.

A lot of NixOS modules opt to recursively filter out any `null` values
when hitting this, either by defining a function in `apply =` in
`cfg.settings` or in the `format.generate` call, but that comes with its
own set of downsides.

While I personally can't think of a use-case involving `consul-template`
 without templates, it does manage to start without one just fine and
`consul-template` is equally affected by our opinionated JSON
representation forced onto the user.

As such, we decided in favor of removing the option entirely in the
discussion leading up to this.

This is one of the 3 suggested implementations from issue 420208.
You can see the other 2 there too, if you are curious.

tl;dr: Non-breaking bug fix to allow using `vault-agent` without
templates and no longer forcing our opinionated JSON representation onto
the user.
2025-08-04 23:19:08 +02:00

156 lines
4.3 KiB
Nix

{
config,
lib,
pkgs,
...
}:
let
format = pkgs.formats.json { };
commonOptions =
{
pkgName,
flavour ? pkgName,
}:
lib.mkOption {
default = { };
description = ''
Attribute set of ${flavour} instances.
Creates independent `${flavour}-''${name}.service` systemd units for each instance defined here.
'';
type =
with lib.types;
attrsOf (
submodule (
{ name, ... }:
{
options = {
enable = lib.mkEnableOption "this ${flavour} instance" // {
default = true;
};
package = lib.mkPackageOption pkgs pkgName { };
user = lib.mkOption {
type = types.str;
default = "root";
description = ''
User under which this instance runs.
'';
};
group = lib.mkOption {
type = types.str;
default = "root";
description = ''
Group under which this instance runs.
'';
};
settings = lib.mkOption {
type = types.submodule {
freeformType = format.type;
options = {
pid_file = lib.mkOption {
default = "/run/${flavour}/${name}.pid";
type = types.str;
description = ''
Path to use for the pid file.
'';
};
};
};
default = { };
description =
let
upstreamDocs =
if flavour == "vault-agent" then
"https://developer.hashicorp.com/vault/docs/agent#configuration-file-options"
else
"https://github.com/hashicorp/consul-template/blob/main/docs/configuration.md#configuration-file";
in
''
Free-form settings written directly to the `config.json` file.
Refer to <${upstreamDocs}> for supported values.
::: {.note}
Resulting format is JSON not HCL.
Refer to <https://www.hcl2json.com/> if you are unsure how to convert HCL options to JSON.
:::
'';
};
};
}
)
);
};
createAgentInstance =
{
instance,
name,
flavour,
}:
let
configFile = format.generate "${name}.json" instance.settings;
in
lib.mkIf (instance.enable) {
description = "${flavour} daemon - ${name}";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
path = [ pkgs.getent ];
startLimitIntervalSec = 60;
startLimitBurst = 3;
serviceConfig = {
User = instance.user;
Group = instance.group;
RuntimeDirectory = flavour;
ExecStart = "${lib.getExe instance.package} ${
lib.optionalString (flavour == "vault-agent") "agent"
} -config ${configFile}";
ExecReload = "${pkgs.coreutils}/bin/kill -SIGHUP $MAINPID";
KillSignal = "SIGINT";
TimeoutStopSec = "30s";
Restart = "on-failure";
};
};
in
{
options = {
services.consul-template.instances = commonOptions { pkgName = "consul-template"; };
services.vault-agent.instances = commonOptions {
pkgName = "vault";
flavour = "vault-agent";
};
};
config = lib.mkMerge (
map
(
flavour:
let
cfg = config.services.${flavour};
in
lib.mkIf (cfg.instances != { }) {
systemd.services = lib.mapAttrs' (
name: instance:
lib.nameValuePair "${flavour}-${name}" (createAgentInstance {
inherit name instance flavour;
})
) cfg.instances;
}
)
[
"consul-template"
"vault-agent"
]
);
meta.maintainers = with lib.maintainers; [
emilylange
tcheronneau
];
}