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