nixpkgs/nixos/modules/services/networking/smokeping.nix
pennae bd56368848 nixos/*: md-convert hidden plaintext options
most of these are hidden because they're either part of a submodule that
doesn't have its type rendered (eg because the submodule type is used in
an either type) or because they are explicitly hidden. some of them are
merely hidden from nix-doc-munge by how their option is put together.
2022-08-31 16:32:54 +02:00

365 lines
12 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 ***
cgiurl = ${cfg.cgiUrl}
contact = ${cfg.ownerEmail}
datadir = ${smokepingHome}/data
imgcache = ${smokepingHome}/cache
imgurl = ${cfg.imgUrl}
linkstyle = ${cfg.linkStyle}
${lib.optionalString (cfg.mailHost != "") "mailhost = ${cfg.mailHost}"}
owner = ${cfg.owner}
pagedir = ${smokepingHome}/cache
piddir = ${smokepingPidDir}
${lib.optionalString (cfg.sendmail != null) "sendmail = ${cfg.sendmail}"}
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 = lib.mdDoc "Enable the smokeping service";
};
alertConfig = mkOption {
type = types.lines;
default = ''
to = root@localhost
from = smokeping@localhost
'';
example = ''
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 = lib.mdDoc "Configuration for alerts.";
};
cgiUrl = mkOption {
type = types.str;
default = "http://${cfg.hostName}:${toString cfg.port}/smokeping.cgi";
defaultText = literalExpression ''"http://''${hostName}:''${toString port}/smokeping.cgi"'';
example = "https://somewhere.example.com/smokeping.cgi";
description = lib.mdDoc "URL to the smokeping cgi.";
};
config = mkOption {
type = types.nullOr types.lines;
default = null;
description = lib.mdDoc ''
Full smokeping config supplied by the user. Overrides
and replaces any other configuration supplied.
'';
};
databaseConfig = mkOption {
type = types.lines;
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 = ''
# 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 = lib.mdDoc ''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.'';
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = lib.mdDoc "Any additional customization not already included.";
};
hostName = mkOption {
type = types.str;
default = config.networking.fqdn;
defaultText = literalExpression "config.networking.fqdn";
example = "somewhere.example.com";
description = lib.mdDoc "DNS name for the urls generated in the cgi.";
};
imgUrl = mkOption {
type = types.str;
default = "cache";
defaultText = literalExpression ''"cache"'';
example = "https://somewhere.example.com/cache";
description = lib.mdDoc ''
Base url for images generated in the cgi.
The default is a relative URL to ensure it works also when e.g. forwarding
the GUI port via SSH.
'';
};
linkStyle = mkOption {
type = types.enum ["original" "absolute" "relative"];
default = "relative";
example = "absolute";
description = lib.mdDoc "DNS name for the urls generated in the cgi.";
};
mailHost = mkOption {
type = types.str;
default = "";
example = "localhost";
description = lib.mdDoc "Use this SMTP server to send alerts";
};
owner = mkOption {
type = types.str;
default = "nobody";
example = "Bob Foobawr";
description = lib.mdDoc "Real name of the owner of the instance";
};
ownerEmail = mkOption {
type = types.str;
default = "no-reply@${cfg.hostName}";
defaultText = literalExpression ''"no-reply@''${hostName}"'';
example = "no-reply@yourdomain.com";
description = lib.mdDoc "Email contact for owner";
};
package = mkOption {
type = types.package;
default = pkgs.smokeping;
defaultText = literalExpression "pkgs.smokeping";
description = lib.mdDoc "Specify a custom smokeping package";
};
host = mkOption {
type = types.nullOr types.str;
default = "localhost";
example = "192.0.2.1"; # rfc5737 example IP for documentation
description = lib.mdDoc ''
Host/IP to bind to for the web server.
Setting it to `null` skips passing the -h option to thttpd,
which makes it bind to all interfaces.
'';
};
port = mkOption {
type = types.int;
default = 8081;
description = lib.mdDoc "TCP port to use for the web server.";
};
presentationConfig = mkOption {
type = types.lines;
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 = lib.mdDoc "presentation graph style";
};
presentationTemplate = mkOption {
type = types.str;
default = "${pkgs.smokeping}/etc/basepage.html.dist";
defaultText = literalExpression ''"''${pkgs.smokeping}/etc/basepage.html.dist"'';
description = lib.mdDoc "Default page layout for the web UI.";
};
probeConfig = mkOption {
type = types.lines;
default = ''
+ FPing
binary = ${config.security.wrapperDir}/fping
'';
defaultText = literalExpression ''
'''
+ FPing
binary = ''${config.security.wrapperDir}/fping
'''
'';
description = lib.mdDoc "Probe configuration";
};
sendmail = mkOption {
type = types.nullOr types.path;
default = null;
example = "/run/wrappers/bin/sendmail";
description = lib.mdDoc "Use this sendmail compatible script to deliver alerts";
};
smokeMailTemplate = mkOption {
type = types.str;
default = "${cfg.package}/etc/smokemail.dist";
defaultText = literalExpression ''"''${package}/etc/smokemail.dist"'';
description = lib.mdDoc "Specify the smokemail template for alerts.";
};
targetConfig = mkOption {
type = types.lines;
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 = lib.mdDoc "Target configuration";
};
user = mkOption {
type = types.str;
default = "smokeping";
description = lib.mdDoc "User that runs smokeping and (optionally) thttpd. A group of the same name will be created as well.";
};
webService = mkOption {
type = types.bool;
default = true;
description = lib.mdDoc "Enable a smokeping web interface";
};
};
};
config = mkIf cfg.enable {
assertions = [
{
assertion = !(cfg.sendmail != null && cfg.mailHost != "");
message = "services.smokeping: sendmail and Mailhost cannot both be enabled.";
}
];
security.wrappers = {
fping =
{ setuid = true;
owner = "root";
group = "root";
source = "${pkgs.fping}/bin/fping";
};
};
environment.systemPackages = [ pkgs.fping ];
users.users.${cfg.user} = {
isNormalUser = false;
isSystemUser = true;
group = cfg.user;
description = "smokeping daemon user";
home = smokepingHome;
createHome = true;
};
users.groups.${cfg.user} = {};
systemd.services.smokeping = {
requiredBy = [ "multi-user.target"];
serviceConfig = {
User = cfg.user;
Restart = "on-failure";
ExecStart = "${cfg.package}/bin/smokeping --config=${configPath} --nodaemon";
};
preStart = ''
mkdir -m 0755 -p ${smokepingHome}/cache ${smokepingHome}/data
rm -f ${smokepingHome}/cropper
ln -s ${cfg.package}/htdocs/cropper ${smokepingHome}/cropper
rm -f ${smokepingHome}/smokeping.fcgi
ln -s ${cgiHome} ${smokepingHome}/smokeping.fcgi
${cfg.package}/bin/smokeping --check --config=${configPath}
${cfg.package}/bin/smokeping --static --config=${configPath}
'';
};
systemd.services.thttpd = mkIf cfg.webService {
requiredBy = [ "multi-user.target"];
requires = [ "smokeping.service"];
path = with pkgs; [ bash rrdtool smokeping thttpd ];
serviceConfig = {
Restart = "always";
ExecStart = lib.concatStringsSep " " (lib.concatLists [
[ "${pkgs.thttpd}/bin/thttpd" ]
[ "-u ${cfg.user}" ]
[ ''-c "**.fcgi"'' ]
[ "-d ${smokepingHome}" ]
(lib.optional (cfg.host != null) "-h ${cfg.host}")
[ "-p ${builtins.toString cfg.port}" ]
[ "-D -nos" ]
]);
};
};
};
meta.maintainers = with lib.maintainers; [
erictapen
nh2
];
}