1{
2 config,
3 pkgs,
4 lib,
5 ...
6}:
7with lib;
8let
9 cfg = config.services.vmalert;
10
11 format = pkgs.formats.yaml { };
12
13 confOpts = concatStringsSep " \\\n" (
14 mapAttrsToList mkLine (filterAttrs (_: v: v != false) cfg.settings)
15 );
16 confType =
17 with types;
18 let
19 valueType = oneOf [
20 bool
21 int
22 path
23 str
24 ];
25 in
26 attrsOf (either valueType (listOf valueType));
27
28 mkLine =
29 key: value:
30 if value == true then
31 "-${key}"
32 else if isList value then
33 concatMapStringsSep " " (v: "-${key}=${escapeShellArg (toString v)}") value
34 else
35 "-${key}=${escapeShellArg (toString value)}";
36in
37{
38 # interface
39 options.services.vmalert = {
40 enable = lib.mkOption {
41 type = lib.types.bool;
42 default = false;
43 description = ''
44 Wether to enable VictoriaMetrics's `vmalert`.
45
46 `vmalert` evaluates alerting and recording rules against a data source, sends notifications via Alertmanager.
47 '';
48 };
49
50 package = mkPackageOption pkgs "victoriametrics" { };
51
52 settings = mkOption {
53 type = types.submodule {
54 freeformType = confType;
55 options = {
56
57 "datasource.url" = mkOption {
58 type = types.nonEmptyStr;
59 example = "http://localhost:8428";
60 description = ''
61 Datasource compatible with Prometheus HTTP API.
62 '';
63 };
64
65 "notifier.url" = mkOption {
66 type = with types; listOf nonEmptyStr;
67 default = [ ];
68 example = [ "http://127.0.0.1:9093" ];
69 description = ''
70 Prometheus Alertmanager URL. List all Alertmanager URLs if it runs in the cluster mode to ensure high availability.
71 '';
72 };
73
74 "rule" = mkOption {
75 type = with types; listOf path;
76 description = ''
77 Path to the files with alerting and/or recording rules.
78
79 ::: {.note}
80 Consider using the {option}`services.vmalert.rules` option as a convenient alternative for declaring rules
81 directly in the `nix` language.
82 :::
83 '';
84 };
85
86 };
87 };
88 default = { };
89 example = {
90 "datasource.url" = "http://localhost:8428";
91 "datasource.disableKeepAlive" = true;
92 "datasource.showURL" = false;
93 "rule" = [
94 "http://<some-server-addr>/path/to/rules"
95 "dir/*.yaml"
96 ];
97 };
98 description = ''
99 `vmalert` configuration, passed via command line flags. Refer to
100 <https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/app/vmalert/README.md#configuration>
101 for details on supported values.
102 '';
103 };
104
105 rules = mkOption {
106 type = format.type;
107 default = { };
108 example = {
109 group = [
110 {
111 name = "TestGroup";
112 rules = [
113 {
114 alert = "ExampleAlertAlwaysFiring";
115 expr = ''
116 sum by(job)
117 (up == 1)
118 '';
119 }
120 ];
121 }
122 ];
123 };
124 description = ''
125 A list of the given alerting or recording rules against configured `"datasource.url"` compatible with
126 Prometheus HTTP API for `vmalert` to execute. Refer to
127 <https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/app/vmalert/README.md#rules>
128 for details on supported values.
129 '';
130 };
131 };
132
133 # implementation
134 config = mkIf cfg.enable {
135
136 environment.etc."vmalert/rules.yml".source = format.generate "rules.yml" cfg.rules;
137
138 services.vmalert.settings.rule = [
139 "/etc/vmalert/rules.yml"
140 ];
141
142 systemd.services.vmalert = {
143 description = "vmalert service";
144 wantedBy = [ "multi-user.target" ];
145 after = [ "network.target" ];
146 reloadTriggers = [ config.environment.etc."vmalert/rules.yml".source ];
147
148 serviceConfig = {
149 DynamicUser = true;
150 Restart = "on-failure";
151 ExecStart = "${cfg.package}/bin/vmalert ${confOpts}";
152 ExecReload = ''${pkgs.coreutils}/bin/kill -SIGHUP "$MAINPID"'';
153 };
154 };
155 };
156}