{ config, lib, pkgs, ... }: # TODO: support munin-async # TODO: LWP/Pg perl libs aren't recognized # TODO: support fastcgi # http://guide.munin-monitoring.org/en/latest/example/webserver/apache-cgi.html # spawn-fcgi -s /run/munin/fastcgi-graph.sock -U www-data -u munin -g munin /usr/lib/munin/cgi/munin-cgi-graph # spawn-fcgi -s /run/munin/fastcgi-html.sock -U www-data -u munin -g munin /usr/lib/munin/cgi/munin-cgi-html # https://paste.sh/vofcctHP#-KbDSXVeWoifYncZmLfZzgum # nginx http://munin.readthedocs.org/en/latest/example/webserver/nginx.html with lib; let nodeCfg = config.services.munin-node; cronCfg = config.services.munin-cron; muninConf = pkgs.writeText "munin.conf" '' dbdir /var/lib/munin htmldir /var/www/munin logdir /var/log/munin rundir /run/munin ${cronCfg.extraGlobalConfig} ${cronCfg.hosts} ''; nodeConf = pkgs.writeText "munin-node.conf" '' log_level 3 log_file Sys::Syslog port 4949 host * background 0 user root group root host_name ${config.networking.hostName} setsid 0 # wrapped plugins by makeWrapper being with dots ignore_file ^\. allow ^::1$ allow ^127\.0\.0\.1$ ${nodeCfg.extraConfig} ''; pluginConf = pkgs.writeText "munin-plugin-conf" '' [hddtemp_smartctl] user root group root [meminfo] user root group root [ipmi*] user root group root ${nodeCfg.extraPluginConfig} ''; pluginConfDir = pkgs.stdenv.mkDerivation { name = "munin-plugin-conf.d"; buildCommand = '' mkdir $out ln -s ${pluginConf} $out/nixos-config ''; }; in { options = { services.munin-node = { enable = mkOption { default = false; description = '' Enable Munin Node agent. Munin node listens on 0.0.0.0 and by default accepts connections only from 127.0.0.1 for security reasons. See . ''; }; extraConfig = mkOption { default = ""; type = types.lines; description = '' munin-node.conf extra configuration. See ''; }; # TODO: add option to add additional plugins extraPluginConfig = mkOption { default = ""; type = types.lines; description = '' plugin-conf.d extra plugin configuration. See ''; example = '' [fail2ban_*] user root ''; }; disabledPlugins = mkOption { default = []; type = with types; listOf string; description = '' Munin plugins to disable, even if munin-node-configure --suggest tries to enable them. To disable a wildcard plugin, use an actual wildcard, as in the example. ''; example = [ "diskstats" "zfs_usage_*" ]; }; }; services.munin-cron = { enable = mkOption { default = false; description = '' Enable munin-cron. Takes care of all heavy lifting to collect data from nodes and draws graphs to html. Runs munin-update, munin-limits, munin-graphs and munin-html in that order. HTML output is in /var/www/munin/, configure your favourite webserver to serve static files. ''; }; extraGlobalConfig = mkOption { default = ""; description = '' munin.conf extra global configuration. See . Useful to setup notifications, see ''; example = '' contact.email.command mail -s "Munin notification for ''${var:host}" someone@example.com ''; }; hosts = mkOption { example = '' [''${config.networking.hostName}] address localhost ''; description = '' Definitions of hosts of nodes to collect data from. Needs at least one host for cron to succeed. See ''; }; }; }; config = mkMerge [ (mkIf (nodeCfg.enable || cronCfg.enable) { environment.systemPackages = [ pkgs.munin ]; users.users = [{ name = "munin"; description = "Munin monitoring user"; group = "munin"; uid = config.ids.uids.munin; }]; users.groups = [{ name = "munin"; gid = config.ids.gids.munin; }]; }) (mkIf nodeCfg.enable { systemd.services.munin-node = { description = "Munin Node"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; path = with pkgs; [ munin smartmontools "/run/current-system/sw" "/run/wrappers" ]; environment.MUNIN_LIBDIR = "${pkgs.munin}/lib"; environment.MUNIN_PLUGSTATE = "/run/munin"; environment.MUNIN_LOGDIR = "/var/log/munin"; preStart = '' echo "Updating munin plugins..." mkdir -p /etc/munin/plugins rm -rf /etc/munin/plugins/* # Autoconfigure builtin plugins ${pkgs.munin}/bin/munin-node-configure --suggest --shell --families contrib,auto,manual --config ${nodeConf} --libdir=${pkgs.munin}/lib/plugins --servicedir=/etc/munin/plugins --sconfdir=${pluginConfDir} 2>/dev/null | ${pkgs.bash}/bin/bash ${lib.optionalString (nodeCfg.disabledPlugins != []) '' # Disable plugins cd /etc/munin/plugins rm -f ${toString nodeCfg.disabledPlugins} ''} ''; serviceConfig = { ExecStart = "${pkgs.munin}/sbin/munin-node --config ${nodeConf} --servicedir /etc/munin/plugins/ --sconfdir=${pluginConfDir}"; }; }; # munin_stats plugin breaks as of 2.0.33 when this doesn't exist systemd.tmpfiles.rules = [ "d /run/munin 0755 munin munin -" ]; }) (mkIf cronCfg.enable { systemd.timers.munin-cron = { description = "batch Munin master programs"; wantedBy = [ "timers.target" ]; timerConfig.OnCalendar = "*:0/5"; }; systemd.services.munin-cron = { description = "batch Munin master programs"; unitConfig.Documentation = "man:munin-cron(8)"; serviceConfig = { Type = "oneshot"; User = "munin"; ExecStart = "${pkgs.munin}/bin/munin-cron --config ${muninConf}"; }; }; systemd.tmpfiles.rules = [ "d /run/munin 0755 munin munin -" "d /var/log/munin 0755 munin munin -" "d /var/www/munin 0755 munin munin -" "d /var/lib/munin 0755 munin munin -" ]; })]; }