1{ config, lib, pkgs, ... }:
2
3with lib;
4let
5
6 cfg = config.services.smokeping;
7 smokepingHome = "/var/lib/smokeping";
8 smokepingPidDir = "/run";
9 configFile = ''
10 *** General ***
11 owner = ${cfg.owner}
12 contact = ${cfg.ownerEmail}
13 mailhost = ${cfg.mailHost}
14 #sendmail = /var/setuid-wrappers/sendmail
15 imgcache = ${smokepingHome}/cache
16 imgurl = http://${cfg.hostName}:${builtins.toString cfg.port}/cache
17 datadir = ${smokepingHome}/data
18 piddir = ${smokepingPidDir}
19 cgiurl = http://${cfg.hostName}:${builtins.toString cfg.port}/smokeping.cgi
20 smokemail = ${cfg.smokeMailTemplate}
21 *** Presentation ***
22 template = ${cfg.presentationTemplate}
23 ${cfg.presentationConfig}
24 #*** Alerts ***
25 #${cfg.alertConfig}
26 *** Database ***
27 ${cfg.databaseConfig}
28 *** Probes ***
29 ${cfg.probeConfig}
30 *** Targets ***
31 ${cfg.targetConfig}
32 ${cfg.extraConfig}
33 '';
34 configPath = pkgs.writeText "smokeping.conf" configFile;
35 cgiHome = pkgs.writeScript "smokeping.fcgi" ''
36 #!${pkgs.bash}/bin/bash
37 ${cfg.package}/bin/smokeping_cgi ${configPath}
38 '';
39in
40
41{
42 options = {
43 services.smokeping = {
44 enable = mkOption {
45 type = types.bool;
46 default = false;
47 description = "Enable the smokeping service";
48 };
49 webService = mkOption {
50 type = types.bool;
51 default = true;
52 description = "Enable a smokeping web interface";
53 };
54
55 user = mkOption {
56 type = types.string;
57 default = "smokeping";
58 description = "User that runs smokeping and (optionally) thttpd";
59 };
60 mailHost = mkOption {
61 type = types.string;
62 default = "127.0.0.1";
63 description = "Use this SMTP server rather than localhost";
64 };
65 smokeMailTemplate = mkOption {
66 type = types.string;
67 default = "${cfg.package}/etc/smokemail.dist";
68 description = "Specify the smokemail template for alerts.";
69 };
70
71 package = mkOption {
72 type = types.package;
73 default = pkgs.smokeping;
74 description = "Specify a custom smokeping package";
75 };
76 owner = mkOption {
77 type = types.string;
78 default = "nobody";
79 example = "Joe Admin";
80 description = "Real name of the owner of the instance";
81 };
82 hostName = mkOption {
83 type = types.string;
84 default = config.networking.hostName;
85 example = "somewhere.example.com";
86 description = "DNS name for the urls generated in the cgi.";
87 };
88 port = mkOption {
89 type = types.int;
90 default = 8081;
91 example = 8081;
92 description = "TCP port to use for the web server.";
93 };
94 ownerEmail = mkOption {
95 type = types.string;
96 default = "no-reply@${cfg.hostName}";
97 example = "no-reply@yourdomain.com";
98 description = "Email contact for owner";
99 };
100
101 databaseConfig = mkOption {
102 type = types.string;
103 default = ''
104 step = 300
105 pings = 20
106 # consfn mrhb steps total
107 AVERAGE 0.5 1 1008
108 AVERAGE 0.5 12 4320
109 MIN 0.5 12 4320
110 MAX 0.5 12 4320
111 AVERAGE 0.5 144 720
112 MAX 0.5 144 720
113 MIN 0.5 144 720
114
115 '';
116 example = literalExample ''
117 # near constant pings.
118 step = 30
119 pings = 20
120 # consfn mrhb steps total
121 AVERAGE 0.5 1 10080
122 AVERAGE 0.5 12 43200
123 MIN 0.5 12 43200
124 MAX 0.5 12 43200
125 AVERAGE 0.5 144 7200
126 MAX 0.5 144 7200
127 MIN 0.5 144 7200
128 '';
129 description = ''Configure the ping frequency and retention of the rrd files.
130 Once set, changing the interval will require deletion or migration of all
131 the collected data.'';
132 };
133 alertConfig = mkOption {
134 type = types.string;
135 default = "";
136 example = literalExample ''
137 to = alertee@address.somewhere
138 from = smokealert@company.xy
139
140 +someloss
141 type = loss
142 # in percent
143 pattern = >0%,*12*,>0%,*12*,>0%
144 comment = loss 3 times in a row;
145 '';
146 description = "Configuration for alerts.";
147 };
148 presentationTemplate = mkOption {
149 type = types.string;
150 default = "${pkgs.smokeping}/etc/basepage.html.dist";
151 description = "Default page layout for the web UI.";
152 };
153
154 presentationConfig = mkOption {
155 type = types.string;
156 default = ''
157 + charts
158 menu = Charts
159 title = The most interesting destinations
160 ++ stddev
161 sorter = StdDev(entries=>4)
162 title = Top Standard Deviation
163 menu = Std Deviation
164 format = Standard Deviation %f
165 ++ max
166 sorter = Max(entries=>5)
167 title = Top Max Roundtrip Time
168 menu = by Max
169 format = Max Roundtrip Time %f seconds
170 ++ loss
171 sorter = Loss(entries=>5)
172 title = Top Packet Loss
173 menu = Loss
174 format = Packets Lost %f
175 ++ median
176 sorter = Median(entries=>5)
177 title = Top Median Roundtrip Time
178 menu = by Median
179 format = Median RTT %f seconds
180 + overview
181 width = 600
182 height = 50
183 range = 10h
184 + detail
185 width = 600
186 height = 200
187 unison_tolerance = 2
188 "Last 3 Hours" 3h
189 "Last 30 Hours" 30h
190 "Last 10 Days" 10d
191 "Last 360 Days" 360d
192 '';
193 description = "presentation graph style";
194 };
195 probeConfig = mkOption {
196 type = types.string;
197 default = ''
198 + FPing
199 binary = ${pkgs.fping}/bin/fping
200 '';
201 description = "Probe configuration";
202 };
203 targetConfig = mkOption {
204 type = types.string;
205 default = ''
206 probe = FPing
207 menu = Top
208 title = Network Latency Grapher
209 remark = Welcome to the SmokePing website of xxx Company. \
210 Here you will learn all about the latency of our network.
211 + Local
212 menu = Local
213 title = Local Network
214 ++ LocalMachine
215 menu = Local Machine
216 title = This host
217 host = localhost
218 '';
219 description = "Target configuration";
220 };
221 extraConfig = mkOption {
222 type = types.string;
223 default = "";
224 description = "Any additional customization not already included.";
225 };
226
227 };
228
229 };
230
231 config = mkIf cfg.enable {
232 users.extraUsers = singleton {
233 name = cfg.user;
234 isNormalUser = false;
235 isSystemUser = true;
236 uid = config.ids.uids.smokeping;
237 description = "smokeping daemon user";
238 home = smokepingHome;
239 };
240 systemd.services.smokeping = {
241 wantedBy = [ "multi-user.target"];
242 serviceConfig.User = cfg.user;
243 serviceConfig.PermissionsStartOnly = true;
244 preStart = ''
245 mkdir -m 0755 -p ${smokepingHome}/cache ${smokepingHome}/data
246 chown -R ${cfg.user} ${smokepingHome}
247 cp ${cgiHome} ${smokepingHome}/smokeping.fcgi
248 ${cfg.package}/bin/smokeping --check --config=${configPath}
249 '';
250 script = ''${cfg.package}/bin/smokeping --config=${configPath} --nodaemon'';
251 };
252 systemd.services.thttpd = mkIf cfg.webService {
253 wantedBy = [ "multi-user.target"];
254 requires = [ "smokeping.service"];
255 partOf = [ "smokeping.service"];
256 path = with pkgs; [ bash rrdtool smokeping ];
257 script = ''${pkgs.thttpd}/bin/thttpd -u ${cfg.user} -c "**.fcgi" -d ${smokepingHome} -p ${builtins.toString cfg.port} -D'';
258 };
259 };
260}
261