nixpkgs/nixos/modules/services/networking/smokeping.nix
Casey Ransom 74558c88fb smokeping module: fix missing js, broken alerts
The initial commit accidentally left in some commented code and if you were
using alerts, they simply didn't work.

Smokeping also includes some JS code for the webui allowing you to zoom into
graphs and it was not passed into the homedir. Additionally, generate
static html pages for other webservers to serve the cache directory.

Add additional options to specify sendmail path or mailhost and verify that both
are not set.

Add one extra config hook that allows you to bypass all of the invidual config
stanzas and just hand it a string.
2016-10-08 20:52:45 -04:00

305 lines
9.3 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.smokeping;
smokepingHome = "/var/lib/smokeping";
smokepingPidDir = "/run";
configFile =
if cfg.config == null
then
''
*** General ***
owner = ${cfg.owner}
contact = ${cfg.ownerEmail}
${lib.optionalString (cfg.mailHost != "") "mailhost = ${cfg.mailHost}"}
${lib.optionalString (cfg.sendmail != null) "sendmail = ${cfg.sendmail}"}
imgcache = ${smokepingHome}/cache
imgurl = http://${cfg.hostName}:${builtins.toString cfg.port}/cache
datadir = ${smokepingHome}/data
pagedir = ${smokepingHome}/cache
piddir = ${smokepingPidDir}
cgiurl = http://${cfg.hostName}:${builtins.toString cfg.port}/smokeping.cgi
linkstyle = ${cfg.linkStyle}
smokemail = ${cfg.smokeMailTemplate}
*** Presentation ***
template = ${cfg.presentationTemplate}
${cfg.presentationConfig}
*** Alerts ***
${cfg.alertConfig}
*** Database ***
${cfg.databaseConfig}
*** Probes ***
${cfg.probeConfig}
*** Targets ***
${cfg.targetConfig}
${cfg.extraConfig}
''
else
cfg.config;
configPath = pkgs.writeText "smokeping.conf" configFile;
cgiHome = pkgs.writeScript "smokeping.fcgi" ''
#!${pkgs.bash}/bin/bash
${cfg.package}/bin/smokeping_cgi ${configPath}
'';
in
{
options = {
services.smokeping = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable the smokeping service";
};
webService = mkOption {
type = types.bool;
default = true;
description = "Enable a smokeping web interface";
};
user = mkOption {
type = types.string;
default = "smokeping";
description = "User that runs smokeping and (optionally) thttpd";
};
mailHost = mkOption {
type = types.string;
default = "";
example = "localhost";
description = "Use this SMTP server to send alerts";
};
sendmail = mkOption {
type = types.nullOr types.path;
default = null;
example = "/var/setuid-wrappers/sendmail";
description = "Use this sendmail compatible script to deliver alerts";
};
smokeMailTemplate = mkOption {
type = types.string;
default = "${cfg.package}/etc/smokemail.dist";
description = "Specify the smokemail template for alerts.";
};
package = mkOption {
type = types.package;
default = pkgs.smokeping;
defaultText = "pkgs.smokeping";
description = "Specify a custom smokeping package";
};
owner = mkOption {
type = types.string;
default = "nobody";
example = "Joe Admin";
description = "Real name of the owner of the instance";
};
hostName = mkOption {
type = types.string;
default = config.networking.hostName;
example = "somewhere.example.com";
description = "DNS name for the urls generated in the cgi.";
};
linkStyle = mkOption {
type = types.enum ["original" "absolute" "relative"];
default = "relative";
example = "absolute";
description = "DNS name for the urls generated in the cgi.";
};
port = mkOption {
type = types.int;
default = 8081;
example = 8081;
description = "TCP port to use for the web server.";
};
ownerEmail = mkOption {
type = types.string;
default = "no-reply@${cfg.hostName}";
example = "no-reply@yourdomain.com";
description = "Email contact for owner";
};
databaseConfig = mkOption {
type = types.string;
default = ''
step = 300
pings = 20
# consfn mrhb steps total
AVERAGE 0.5 1 1008
AVERAGE 0.5 12 4320
MIN 0.5 12 4320
MAX 0.5 12 4320
AVERAGE 0.5 144 720
MAX 0.5 144 720
MIN 0.5 144 720
'';
example = literalExample ''
# near constant pings.
step = 30
pings = 20
# consfn mrhb steps total
AVERAGE 0.5 1 10080
AVERAGE 0.5 12 43200
MIN 0.5 12 43200
MAX 0.5 12 43200
AVERAGE 0.5 144 7200
MAX 0.5 144 7200
MIN 0.5 144 7200
'';
description = ''Configure the ping frequency and retention of the rrd files.
Once set, changing the interval will require deletion or migration of all
the collected data.'';
};
alertConfig = mkOption {
type = types.string;
default = ''
to = root@localhost
from = smokeping@localhost
'';
example = literalExample ''
to = alertee@address.somewhere
from = smokealert@company.xy
+someloss
type = loss
# in percent
pattern = >0%,*12*,>0%,*12*,>0%
comment = loss 3 times in a row;
'';
description = "Configuration for alerts.";
};
presentationTemplate = mkOption {
type = types.string;
default = "${pkgs.smokeping}/etc/basepage.html.dist";
description = "Default page layout for the web UI.";
};
presentationConfig = mkOption {
type = types.string;
default = ''
+ charts
menu = Charts
title = The most interesting destinations
++ stddev
sorter = StdDev(entries=>4)
title = Top Standard Deviation
menu = Std Deviation
format = Standard Deviation %f
++ max
sorter = Max(entries=>5)
title = Top Max Roundtrip Time
menu = by Max
format = Max Roundtrip Time %f seconds
++ loss
sorter = Loss(entries=>5)
title = Top Packet Loss
menu = Loss
format = Packets Lost %f
++ median
sorter = Median(entries=>5)
title = Top Median Roundtrip Time
menu = by Median
format = Median RTT %f seconds
+ overview
width = 600
height = 50
range = 10h
+ detail
width = 600
height = 200
unison_tolerance = 2
"Last 3 Hours" 3h
"Last 30 Hours" 30h
"Last 10 Days" 10d
"Last 360 Days" 360d
'';
description = "presentation graph style";
};
probeConfig = mkOption {
type = types.string;
default = ''
+ FPing
binary = ${pkgs.fping}/bin/fping
'';
description = "Probe configuration";
};
targetConfig = mkOption {
type = types.string;
default = ''
probe = FPing
menu = Top
title = Network Latency Grapher
remark = Welcome to the SmokePing website of xxx Company. \
Here you will learn all about the latency of our network.
+ Local
menu = Local
title = Local Network
++ LocalMachine
menu = Local Machine
title = This host
host = localhost
'';
description = "Target configuration";
};
extraConfig = mkOption {
type = types.string;
default = "";
description = "Any additional customization not already included.";
};
config = mkOption {
type = types.nullOr types.string;
default = null;
description = "Full smokeping config supplied by the user. Overrides " +
"and replaces any other configuration supplied.";
};
};
};
config = mkIf cfg.enable {
assertions = [
{
assertion = !(cfg.sendmail != null && cfg.mailHost != "");
message = "services.smokeping: sendmail and Mailhost cannot both be enabled.";
}
];
security.setuidPrograms = [ "fping" ];
environment.systemPackages = [ pkgs.fping ];
users.extraUsers = singleton {
name = cfg.user;
isNormalUser = false;
isSystemUser = true;
uid = config.ids.uids.smokeping;
description = "smokeping daemon user";
home = smokepingHome;
};
systemd.services.smokeping = {
wantedBy = [ "multi-user.target"];
serviceConfig.User = cfg.user;
serviceConfig.PermissionsStartOnly = true;
preStart = ''
mkdir -m 0755 -p ${smokepingHome}/cache ${smokepingHome}/data
rm -f ${smokepingHome}/cropper
ln -s ${cfg.package}/htdocs/cropper ${smokepingHome}/cropper
chown -R ${cfg.user} ${smokepingHome}
cp ${cgiHome} ${smokepingHome}/smokeping.fcgi
${cfg.package}/bin/smokeping --check --config=${configPath}
${cfg.package}/bin/smokeping --static --config=${configPath}
'';
script = ''${cfg.package}/bin/smokeping --config=${configPath} --nodaemon'';
};
systemd.services.thttpd = mkIf cfg.webService {
wantedBy = [ "multi-user.target"];
requires = [ "smokeping.service"];
partOf = [ "smokeping.service"];
path = with pkgs; [ bash rrdtool smokeping thttpd ];
script = ''thttpd -u ${cfg.user} -c "**.fcgi" -d ${smokepingHome} -p ${builtins.toString cfg.port} -D -nos'';
serviceConfig.Restart = "always";
};
};
}