vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / networking / smokeping.nix
blobd9c314f5ec647dc834de70f67beb1cbbd48a4c51
1 { config, lib, pkgs, ... }:
3 with lib;
4 let
6   cfg = config.services.smokeping;
7   smokepingHome = "/var/lib/smokeping";
8   smokepingPidDir = "/run";
9   configFile =
10     if cfg.config == null
11     then
12       ''
13         *** General ***
14         cgiurl   = ${cfg.cgiUrl}
15         contact = ${cfg.ownerEmail}
16         datadir  = ${smokepingHome}/data
17         imgcache = ${smokepingHome}/cache
18         imgurl   = ${cfg.imgUrl}
19         linkstyle = ${cfg.linkStyle}
20         ${lib.optionalString (cfg.mailHost != "") "mailhost = ${cfg.mailHost}"}
21         owner = ${cfg.owner}
22         pagedir = ${smokepingHome}/cache
23         piddir  = ${smokepingPidDir}
24         ${lib.optionalString (cfg.sendmail != null) "sendmail = ${cfg.sendmail}"}
25         smokemail = ${cfg.smokeMailTemplate}
26         *** Presentation ***
27         template = ${cfg.presentationTemplate}
28         ${cfg.presentationConfig}
29         *** Alerts ***
30         ${cfg.alertConfig}
31         *** Database ***
32         ${cfg.databaseConfig}
33         *** Probes ***
34         ${cfg.probeConfig}
35         *** Targets ***
36         ${cfg.targetConfig}
37         ${cfg.extraConfig}
38       ''
39     else
40       cfg.config;
42   configPath = pkgs.writeText "smokeping.conf" configFile;
43   cgiHome = pkgs.writeScript "smokeping.fcgi" ''
44     #!${pkgs.bash}/bin/bash
45     ${cfg.package}/bin/smokeping_cgi /etc/smokeping.conf
46   '';
50   imports = [
51     (mkRemovedOptionModule [ "services" "smokeping" "port" ] ''
52       The smokeping web service is now served by nginx.
53       In order to change the port, you need to change the nginx configuration under `services.nginx.virtualHosts.smokeping.listen.*.port`.
54     '')
55   ];
57   options = {
58     services.smokeping = {
59       enable = mkEnableOption "smokeping service";
61       alertConfig = mkOption {
62         type = types.lines;
63         default = ''
64           to = root@localhost
65           from = smokeping@localhost
66         '';
67         example = ''
68           to = alertee@address.somewhere
69           from = smokealert@company.xy
71           +someloss
72           type = loss
73           # in percent
74           pattern = >0%,*12*,>0%,*12*,>0%
75           comment = loss 3 times  in a row;
76         '';
77         description = "Configuration for alerts.";
78       };
79       cgiUrl = mkOption {
80         type = types.str;
81         default = "http://${cfg.hostName}/smokeping.cgi";
82         defaultText = literalExpression ''"http://''${hostName}/smokeping.cgi"'';
83         example = "https://somewhere.example.com/smokeping.cgi";
84         description = "URL to the smokeping cgi.";
85       };
86       config = mkOption {
87         type = types.nullOr types.lines;
88         default = null;
89         description = ''
90           Full smokeping config supplied by the user. Overrides
91           and replaces any other configuration supplied.
92         '';
93       };
94       databaseConfig = mkOption {
95         type = types.lines;
96         default = ''
97           step     = 300
98           pings    = 20
99           # consfn mrhb steps total
100           AVERAGE  0.5   1  1008
101           AVERAGE  0.5  12  4320
102               MIN  0.5  12  4320
103               MAX  0.5  12  4320
104           AVERAGE  0.5 144   720
105               MAX  0.5 144   720
106               MIN  0.5 144   720
108         '';
109         example = ''
110           # near constant pings.
111           step     = 30
112           pings    = 20
113           # consfn mrhb steps total
114           AVERAGE  0.5   1  10080
115           AVERAGE  0.5  12  43200
116               MIN  0.5  12  43200
117               MAX  0.5  12  43200
118           AVERAGE  0.5 144   7200
119               MAX  0.5 144   7200
120               MIN  0.5 144   7200
121         '';
122         description = ''Configure the ping frequency and retention of the rrd files.
123           Once set, changing the interval will require deletion or migration of all
124           the collected data.'';
125       };
126       extraConfig = mkOption {
127         type = types.lines;
128         default = "";
129         description = "Any additional customization not already included.";
130       };
131       hostName = mkOption {
132         type = types.str;
133         default = config.networking.fqdn;
134         defaultText = literalExpression "config.networking.fqdn";
135         example = "somewhere.example.com";
136         description = "DNS name for the urls generated in the cgi.";
137       };
138       imgUrl = mkOption {
139         type = types.str;
140         default = "cache";
141         defaultText = literalExpression ''"cache"'';
142         example = "https://somewhere.example.com/cache";
143         description = ''
144           Base url for images generated in the cgi.
146           The default is a relative URL to ensure it works also when e.g. forwarding
147           the GUI port via SSH.
148         '';
149       };
150       linkStyle = mkOption {
151         type = types.enum [ "original" "absolute" "relative" ];
152         default = "relative";
153         example = "absolute";
154         description = "DNS name for the urls generated in the cgi.";
155       };
156       mailHost = mkOption {
157         type = types.str;
158         default = "";
159         example = "localhost";
160         description = "Use this SMTP server to send alerts";
161       };
162       owner = mkOption {
163         type = types.str;
164         default = "nobody";
165         example = "Bob Foobawr";
166         description = "Real name of the owner of the instance";
167       };
168       ownerEmail = mkOption {
169         type = types.str;
170         default = "no-reply@${cfg.hostName}";
171         defaultText = literalExpression ''"no-reply@''${hostName}"'';
172         example = "no-reply@yourdomain.com";
173         description = "Email contact for owner";
174       };
175       package = mkPackageOption pkgs "smokeping" { };
176       host = mkOption {
177         type = types.nullOr types.str;
178         default = "localhost";
179         example = "192.0.2.1"; # rfc5737 example IP for documentation
180         description = ''
181           Host/IP to bind to for the web server.
183           Setting it to `null` skips passing the -h option to thttpd,
184           which makes it bind to all interfaces.
185         '';
186       };
187       presentationConfig = mkOption {
188         type = types.lines;
189         default = ''
190           + charts
191           menu = Charts
192           title = The most interesting destinations
193           ++ stddev
194           sorter = StdDev(entries=>4)
195           title = Top Standard Deviation
196           menu = Std Deviation
197           format = Standard Deviation %f
198           ++ max
199           sorter = Max(entries=>5)
200           title = Top Max Roundtrip Time
201           menu = by Max
202           format = Max Roundtrip Time %f seconds
203           ++ loss
204           sorter = Loss(entries=>5)
205           title = Top Packet Loss
206           menu = Loss
207           format = Packets Lost %f
208           ++ median
209           sorter = Median(entries=>5)
210           title = Top Median Roundtrip Time
211           menu = by Median
212           format = Median RTT %f seconds
213           + overview
214           width = 600
215           height = 50
216           range = 10h
217           + detail
218           width = 600
219           height = 200
220           unison_tolerance = 2
221           "Last 3 Hours"    3h
222           "Last 30 Hours"   30h
223           "Last 10 Days"    10d
224           "Last 360 Days"   360d
225         '';
226         description = "presentation graph style";
227       };
228       presentationTemplate = mkOption {
229         type = types.str;
230         default = "${pkgs.smokeping}/etc/basepage.html.dist";
231         defaultText = literalExpression ''"''${pkgs.smokeping}/etc/basepage.html.dist"'';
232         description = "Default page layout for the web UI.";
233       };
234       probeConfig = mkOption {
235         type = types.lines;
236         default = ''
237           + FPing
238           binary = ${config.security.wrapperDir}/fping
239         '';
240         defaultText = literalExpression ''
241           '''
242             + FPing
243             binary = ''${config.security.wrapperDir}/fping
244           '''
245         '';
246         description = "Probe configuration";
247       };
248       sendmail = mkOption {
249         type = types.nullOr types.path;
250         default = null;
251         example = "/run/wrappers/bin/sendmail";
252         description = "Use this sendmail compatible script to deliver alerts";
253       };
254       smokeMailTemplate = mkOption {
255         type = types.str;
256         default = "${cfg.package}/etc/smokemail.dist";
257         defaultText = literalExpression ''"''${package}/etc/smokemail.dist"'';
258         description = "Specify the smokemail template for alerts.";
259       };
260       targetConfig = mkOption {
261         type = types.lines;
262         default = ''
263           probe = FPing
264           menu = Top
265           title = Network Latency Grapher
266           remark = Welcome to the SmokePing website of xxx Company. \
267                    Here you will learn all about the latency of our network.
268           + Local
269           menu = Local
270           title = Local Network
271           ++ LocalMachine
272           menu = Local Machine
273           title = This host
274           host = localhost
275         '';
276         description = "Target configuration";
277       };
278       user = mkOption {
279         type = types.str;
280         default = "smokeping";
281         description = "User that runs smokeping and (optionally) thttpd. A group of the same name will be created as well.";
282       };
283       webService = mkOption {
284         type = types.bool;
285         default = true;
286         description = "Enable a smokeping web interface";
287       };
288     };
290   };
292   config = mkIf cfg.enable {
293     assertions = [
294       {
295         assertion = !(cfg.sendmail != null && cfg.mailHost != "");
296         message = "services.smokeping: sendmail and Mailhost cannot both be enabled.";
297       }
298     ];
299     security.wrappers = {
300       fping =
301         {
302           setuid = true;
303           owner = "root";
304           group = "root";
305           source = "${pkgs.fping}/bin/fping";
306         };
307     };
308     environment.etc."smokeping.conf".source = configPath;
309     environment.systemPackages = [ pkgs.fping ];
310     users.users.${cfg.user} = {
311       isNormalUser = false;
312       isSystemUser = true;
313       group = cfg.user;
314       description = "smokeping daemon user";
315       home = smokepingHome;
316     };
318     users.users.${config.services.nginx.user} = mkIf cfg.webService {
319       extraGroups = [
320         cfg.user ## user == group in this module
321       ];
322     };
324     users.groups.${cfg.user} = { };
326     systemd.services.smokeping = {
327       reloadTriggers = [ configPath ];
328       requiredBy = [ "multi-user.target" ];
329       serviceConfig = {
330         User = cfg.user;
331         Restart = "on-failure";
332         ExecStart = "${cfg.package}/bin/smokeping --config=/etc/smokeping.conf --nodaemon";
333       };
334       preStart = ''
335         ${cfg.package}/bin/smokeping --check --config=${configPath}
336         ${cfg.package}/bin/smokeping --static --config=${configPath}
337       '';
338     };
340     systemd.tmpfiles.rules = [
341       # create cache and data directories
342       "d ${smokepingHome}/cache 0750 ${cfg.user} ${cfg.user}"
343       "d ${smokepingHome}/data 0750 ${cfg.user} ${cfg.user}"
344       # create symlings
345       "L+ ${smokepingHome}/css - - - - ${cfg.package}/htdocs/css"
346       "L+ ${smokepingHome}/js - - - - ${cfg.package}/htdocs/js"
347       "L+ ${smokepingHome}/smokeping.fcgi - - - - ${cgiHome}"
348       # recursively adjust access mode and ownership (in case config change)
349       "Z ${smokepingHome} 0750 ${cfg.user} ${cfg.user}"
350     ];
352     # use nginx to serve the smokeping web service
353     services.fcgiwrap.instances.smokeping = mkIf cfg.webService {
354       process.user = cfg.user;
355       process.group = cfg.user;
356       socket = { inherit (config.services.nginx) user group; };
357     };
358     services.nginx = mkIf cfg.webService {
359       enable = true;
360       virtualHosts."smokeping" = {
361         serverName = mkDefault cfg.host;
362         locations."/" = {
363           root = smokepingHome;
364           index = "smokeping.fcgi";
365         };
366         locations."/smokeping.fcgi" = {
367           extraConfig = ''
368             include ${config.services.nginx.package}/conf/fastcgi_params;
369             fastcgi_pass unix:${config.services.fcgiwrap.instances.smokeping.socket.address};
370             fastcgi_param SCRIPT_FILENAME ${smokepingHome}/smokeping.fcgi;
371             fastcgi_param DOCUMENT_ROOT ${smokepingHome};
372           '';
373         };
374       };
375     };
376   };
378   meta.maintainers = with lib.maintainers; [
379     erictapen
380     nh2
381   ];