nixos/vmalert: support multiple instances

vmalert only supports a single datasource for querying metrics and
managing alerts. Because of that, we need two instances to manage alerts
for both VictoriaLogs and VictoriaMetrics.

This is strongly inspired by the change made to Redis, i.e. a new
`instances` option was introduced with each option inside it.
With `mkRenamedOptionModule` it's ensured that existing configurations
still evaluate to the same result.
This commit is contained in:
Maximilian Bosch 2025-05-25 16:24:19 +02:00
parent b932c31ba4
commit 0d46fda974
No known key found for this signature in database
4 changed files with 159 additions and 109 deletions

View file

@ -23,6 +23,9 @@
- Added `rewriteURL` attribute to the nixpkgs `config`, to allow for rewriting the URLs downloaded by `fetchurl`. - Added `rewriteURL` attribute to the nixpkgs `config`, to allow for rewriting the URLs downloaded by `fetchurl`.
- `vmalert` now supports multiple instances with the option `services.vmalert.instances."".enable`
et al..
## Nixpkgs Library {#sec-nixpkgs-release-25.11-lib} ## Nixpkgs Library {#sec-nixpkgs-release-25.11-lib}
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. --> <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->

View file

@ -105,7 +105,7 @@ In addition to numerous new and updated packages, this release has the following
- [ivpn](https://www.ivpn.net/), a secure, private VPN with fast WireGuard connections. Available as [services.ivpn](#opt-services.ivpn.enable). - [ivpn](https://www.ivpn.net/), a secure, private VPN with fast WireGuard connections. Available as [services.ivpn](#opt-services.ivpn.enable).
- [vmalert](https://victoriametrics.com/), an alerting engine for VictoriaMetrics. Available as [services.vmalert](#opt-services.vmalert.enable). - [vmalert](https://victoriametrics.com/), an alerting engine for VictoriaMetrics. Available as [services.vmalert.instances](#opt-services.vmalert.instances._name_.enable).
- [jellyseerr](https://github.com/Fallenbagel/jellyseerr), a web-based requests manager for Jellyfin, forked from Overseerr. Available as [services.jellyseerr](#opt-services.jellyseerr.enable). - [jellyseerr](https://github.com/Fallenbagel/jellyseerr), a web-based requests manager for Jellyfin, forked from Overseerr. Available as [services.jellyseerr](#opt-services.jellyseerr.enable).

View file

@ -10,9 +10,9 @@ let
format = pkgs.formats.yaml { }; format = pkgs.formats.yaml { };
confOpts = concatStringsSep " \\\n" ( mkConfOpts =
mapAttrsToList mkLine (filterAttrs (_: v: v != false) cfg.settings) settings:
); concatStringsSep " \\\n" (mapAttrsToList mkLine (filterAttrs (_: v: v != false) settings));
confType = confType =
with types; with types;
let let
@ -33,10 +33,41 @@ let
concatMapStringsSep " " (v: "-${key}=${escapeShellArg (toString v)}") value concatMapStringsSep " " (v: "-${key}=${escapeShellArg (toString v)}") value
else else
"-${key}=${escapeShellArg (toString value)}"; "-${key}=${escapeShellArg (toString value)}";
vmalertName = name: "vmalert" + lib.optionalString (name != "") ("-" + name);
enabledInstances = lib.filterAttrs (name: conf: conf.enable) config.services.vmalert.instances;
in in
{ {
imports = [
(lib.mkRenamedOptionModule
[ "services" "vmalert" "enable" ]
[ "services" "vmalert" "instances" "" "enable" ]
)
(lib.mkRenamedOptionModule
[ "services" "vmalert" "rules" ]
[ "services" "vmalert" "instances" "" "rules" ]
)
(lib.mkRenamedOptionModule
[ "services" "vmalert" "settings" ]
[ "services" "vmalert" "instances" "" "settings" ]
)
];
# interface # interface
options.services.vmalert = { options.services.vmalert.package = mkPackageOption pkgs "victoriametrics" { };
options.services.vmalert.instances = mkOption {
default = { };
description = ''
Define multiple instances of vmalert.
'';
type = types.attrsOf (
types.submodule (
{ name, config, ... }:
{
options = {
enable = lib.mkOption { enable = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = false; default = false;
@ -47,8 +78,6 @@ in
''; '';
}; };
package = mkPackageOption pkgs "victoriametrics" { };
settings = mkOption { settings = mkOption {
type = types.submodule { type = types.submodule {
freeformType = confType; freeformType = confType;
@ -77,7 +106,7 @@ in
Path to the files with alerting and/or recording rules. Path to the files with alerting and/or recording rules.
::: {.note} ::: {.note}
Consider using the {option}`services.vmalert.rules` option as a convenient alternative for declaring rules Consider using the {option}`services.vmalert.instances.<name>.rules` option as a convenient alternative for declaring rules
directly in the `nix` language. directly in the `nix` language.
::: :::
''; '';
@ -130,27 +159,45 @@ in
}; };
}; };
# implementation config = {
config = mkIf cfg.enable { settings.rule = [
"/etc/${vmalertName name}/rules.yml"
environment.etc."vmalert/rules.yml".source = format.generate "rules.yml" cfg.rules;
services.vmalert.settings.rule = [
"/etc/vmalert/rules.yml"
]; ];
};
}
)
);
};
systemd.services.vmalert = { # implementation
config = mkIf (enabledInstances != { }) {
environment.etc = lib.mapAttrs' (
name:
{ rules, ... }:
lib.nameValuePair "${vmalertName name}/rules.yml" {
source = format.generate "rules.yml" rules;
}
) enabledInstances;
systemd.services = lib.mapAttrs' (
name:
{ settings, ... }:
let
name' = vmalertName name;
in
lib.nameValuePair name' {
description = "vmalert service"; description = "vmalert service";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
after = [ "network.target" ]; after = [ "network.target" ];
reloadTriggers = [ config.environment.etc."vmalert/rules.yml".source ]; reloadTriggers = [ config.environment.etc."${name'}/rules.yml".source ];
serviceConfig = { serviceConfig = {
DynamicUser = true; DynamicUser = true;
Restart = "on-failure"; Restart = "on-failure";
ExecStart = "${cfg.package}/bin/vmalert ${confOpts}"; ExecStart = "${cfg.package}/bin/vmalert ${mkConfOpts settings}";
ExecReload = ''${pkgs.coreutils}/bin/kill -SIGHUP "$MAINPID"''; ExecReload = ''${pkgs.coreutils}/bin/kill -SIGHUP "$MAINPID"'';
}; };
}; }
) enabledInstances;
}; };
} }

View file

@ -55,7 +55,7 @@ import ../make-test-python.nix (
}; };
}; };
services.vmalert = { services.vmalert.instances."" = {
enable = true; enable = true;
settings = { settings = {
"datasource.url" = "http://localhost:8428"; # victoriametrics' api "datasource.url" = "http://localhost:8428"; # victoriametrics' api