1{ config, pkgs, lib, ... }:
2with lib;
3
4let
5 cfg = config.services.kthxbye;
6in
7
8{
9 options.services.kthxbye = {
10 enable = mkEnableOption "kthxbye alert acknowledgement management daemon";
11
12 package = mkPackageOption pkgs "kthxbye" { };
13
14 openFirewall = mkOption {
15 type = types.bool;
16 default = false;
17 description = ''
18 Whether to open ports in the firewall needed for the daemon to function.
19 '';
20 };
21
22 extraOptions = mkOption {
23 type = with types; listOf str;
24 default = [];
25 description = ''
26 Extra command line options.
27
28 Documentation can be found [here](https://github.com/prymitive/kthxbye/blob/main/README.md).
29 '';
30 example = literalExpression ''
31 [
32 "-extend-with-prefix 'ACK!'"
33 ];
34 '';
35 };
36
37 alertmanager = {
38 timeout = mkOption {
39 type = types.str;
40 default = "1m0s";
41 description = ''
42 Alertmanager request timeout duration in the [time.Duration](https://pkg.go.dev/time#ParseDuration) format.
43 '';
44 example = "30s";
45 };
46 uri = mkOption {
47 type = types.str;
48 default = "http://localhost:9093";
49 description = ''
50 Alertmanager URI to use.
51 '';
52 example = "https://alertmanager.example.com";
53 };
54 };
55
56 extendBy = mkOption {
57 type = types.str;
58 default = "15m0s";
59 description = ''
60 Extend silences by adding DURATION seconds.
61
62 DURATION should be provided in the [time.Duration](https://pkg.go.dev/time#ParseDuration) format.
63 '';
64 example = "6h0m0s";
65 };
66
67 extendIfExpiringIn = mkOption {
68 type = types.str;
69 default = "5m0s";
70 description = ''
71 Extend silences that are about to expire in the next DURATION seconds.
72
73 DURATION should be provided in the [time.Duration](https://pkg.go.dev/time#ParseDuration) format.
74 '';
75 example = "1m0s";
76 };
77
78 extendWithPrefix = mkOption {
79 type = types.str;
80 default = "ACK!";
81 description = ''
82 Extend silences with comment starting with PREFIX string.
83 '';
84 example = "!perma-silence";
85 };
86
87 interval = mkOption {
88 type = types.str;
89 default = "45s";
90 description = ''
91 Silence check interval duration in the [time.Duration](https://pkg.go.dev/time#ParseDuration) format.
92 '';
93 example = "30s";
94 };
95
96 listenAddress = mkOption {
97 type = types.str;
98 default = "0.0.0.0";
99 description = ''
100 The address to listen on for HTTP requests.
101 '';
102 example = "127.0.0.1";
103 };
104
105 port = mkOption {
106 type = types.port;
107 default = 8080;
108 description = ''
109 The port to listen on for HTTP requests.
110 '';
111 };
112
113 logJSON = mkOption {
114 type = types.bool;
115 default = false;
116 description = ''
117 Format logged messages as JSON.
118 '';
119 };
120
121 maxDuration = mkOption {
122 type = with types; nullOr str;
123 default = null;
124 description = ''
125 Maximum duration of a silence, it won't be extended anymore after reaching it.
126
127 Duration should be provided in the [time.Duration](https://pkg.go.dev/time#ParseDuration) format.
128 '';
129 example = "30d";
130 };
131 };
132
133 config = mkIf cfg.enable {
134 systemd.services.kthxbye = {
135 description = "kthxbye Alertmanager ack management daemon";
136 wantedBy = [ "multi-user.target" ];
137 script = ''
138 ${cfg.package}/bin/kthxbye \
139 -alertmanager.timeout ${cfg.alertmanager.timeout} \
140 -alertmanager.uri ${cfg.alertmanager.uri} \
141 -extend-by ${cfg.extendBy} \
142 -extend-if-expiring-in ${cfg.extendIfExpiringIn} \
143 -extend-with-prefix ${cfg.extendWithPrefix} \
144 -interval ${cfg.interval} \
145 -listen ${cfg.listenAddress}:${toString cfg.port} \
146 ${optionalString cfg.logJSON "-log-json"} \
147 ${optionalString (cfg.maxDuration != null) "-max-duration ${cfg.maxDuration}"} \
148 ${concatStringsSep " " cfg.extraOptions}
149 '';
150 serviceConfig = {
151 Type = "simple";
152 DynamicUser = true;
153 Restart = "on-failure";
154 };
155 };
156
157 networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
158 };
159}