1{
2 config,
3 pkgs,
4 lib,
5 ...
6}:
7let
8 cfg = config.services.prometheus.pushgateway;
9
10 cmdlineArgs =
11 opt "web.listen-address" cfg.web.listen-address
12 ++ opt "web.telemetry-path" cfg.web.telemetry-path
13 ++ opt "web.external-url" cfg.web.external-url
14 ++ opt "web.route-prefix" cfg.web.route-prefix
15 ++ lib.optional cfg.persistMetrics ''--persistence.file="/var/lib/${cfg.stateDir}/metrics"''
16 ++ opt "persistence.interval" cfg.persistence.interval
17 ++ opt "log.level" cfg.log.level
18 ++ opt "log.format" cfg.log.format
19 ++ cfg.extraFlags;
20
21 opt = k: v: lib.optional (v != null) ''--${k}="${v}"'';
22
23in
24{
25 options = {
26 services.prometheus.pushgateway = {
27 enable = lib.mkEnableOption "Prometheus Pushgateway";
28
29 package = lib.mkPackageOption pkgs "prometheus-pushgateway" { };
30
31 web.listen-address = lib.mkOption {
32 type = lib.types.nullOr lib.types.str;
33 default = null;
34 description = ''
35 Address to listen on for the web interface, API and telemetry.
36
37 `null` will default to `:9091`.
38 '';
39 };
40
41 web.telemetry-path = lib.mkOption {
42 type = lib.types.nullOr lib.types.str;
43 default = null;
44 description = ''
45 Path under which to expose metrics.
46
47 `null` will default to `/metrics`.
48 '';
49 };
50
51 web.external-url = lib.mkOption {
52 type = lib.types.nullOr lib.types.str;
53 default = null;
54 description = ''
55 The URL under which Pushgateway is externally reachable.
56 '';
57 };
58
59 web.route-prefix = lib.mkOption {
60 type = lib.types.nullOr lib.types.str;
61 default = null;
62 description = ''
63 Prefix for the internal routes of web endpoints.
64
65 Defaults to the path of
66 {option}`services.prometheus.pushgateway.web.external-url`.
67 '';
68 };
69
70 persistence.interval = lib.mkOption {
71 type = lib.types.nullOr lib.types.str;
72 default = null;
73 example = "10m";
74 description = ''
75 The minimum interval at which to write out the persistence file.
76
77 `null` will default to `5m`.
78 '';
79 };
80
81 log.level = lib.mkOption {
82 type = lib.types.nullOr (
83 lib.types.enum [
84 "debug"
85 "info"
86 "warn"
87 "error"
88 "fatal"
89 ]
90 );
91 default = null;
92 description = ''
93 Only log messages with the given severity or above.
94
95 `null` will default to `info`.
96 '';
97 };
98
99 log.format = lib.mkOption {
100 type = lib.types.nullOr lib.types.str;
101 default = null;
102 example = "logger:syslog?appname=bob&local=7";
103 description = ''
104 Set the log target and format.
105
106 `null` will default to `logger:stderr`.
107 '';
108 };
109
110 extraFlags = lib.mkOption {
111 type = lib.types.listOf lib.types.str;
112 default = [ ];
113 description = ''
114 Extra commandline options when launching the Pushgateway.
115 '';
116 };
117
118 persistMetrics = lib.mkOption {
119 type = lib.types.bool;
120 default = false;
121 description = ''
122 Whether to persist metrics to a file.
123
124 When enabled metrics will be saved to a file called
125 `metrics` in the directory
126 `/var/lib/pushgateway`. The directory below
127 `/var/lib` can be set using
128 {option}`services.prometheus.pushgateway.stateDir`.
129 '';
130 };
131
132 stateDir = lib.mkOption {
133 type = lib.types.str;
134 default = "pushgateway";
135 description = ''
136 Directory below `/var/lib` to store metrics.
137
138 This directory will be created automatically using systemd's
139 StateDirectory mechanism when
140 {option}`services.prometheus.pushgateway.persistMetrics`
141 is enabled.
142 '';
143 };
144 };
145 };
146
147 config = lib.mkIf cfg.enable {
148 assertions = [
149 {
150 assertion = !lib.hasPrefix "/" cfg.stateDir;
151 message =
152 "The option services.prometheus.pushgateway.stateDir"
153 + " shouldn't be an absolute directory."
154 + " It should be a directory relative to /var/lib.";
155 }
156 ];
157 systemd.services.pushgateway = {
158 wantedBy = [ "multi-user.target" ];
159 after = [ "network.target" ];
160 serviceConfig = {
161 ExecStart =
162 "${cfg.package}/bin/pushgateway"
163 + lib.optionalString (lib.length cmdlineArgs != 0) (
164 " \\\n " + lib.concatStringsSep " \\\n " cmdlineArgs
165 );
166
167 CapabilityBoundingSet = [ "" ];
168 DeviceAllow = [ "" ];
169 DynamicUser = true;
170 NoNewPrivileges = true;
171
172 MemoryDenyWriteExecute = true;
173
174 LockPersonality = true;
175
176 ProtectProc = "invisible";
177 ProtectSystem = "strict";
178 ProtectHome = "tmpfs";
179
180 PrivateTmp = true;
181 PrivateDevices = true;
182 PrivateIPC = true;
183
184 ProcSubset = "pid";
185
186 ProtectHostname = true;
187 ProtectClock = true;
188 ProtectKernelTunables = true;
189 ProtectKernelModules = true;
190 ProtectKernelLogs = true;
191 ProtectControlGroups = true;
192
193 Restart = "always";
194
195 RestrictAddressFamilies = [
196 "AF_INET"
197 "AF_INET6"
198 ];
199 RestrictNamespaces = true;
200 RestrictRealtime = true;
201 RestrictSUIDSGID = true;
202
203 StateDirectory = if cfg.persistMetrics then cfg.stateDir else null;
204 SystemCallFilter = [
205 "@system-service"
206 "~@cpu-emulation"
207 "~@privileged"
208 "~@reboot"
209 "~@setuid"
210 "~@swap"
211 ];
212 };
213 };
214 };
215}