about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSilvan Mosberger <infinisil@icloud.com>2019-02-05 19:35:03 +0100
committerGitHub <noreply@github.com>2019-02-05 19:35:03 +0100
commitdfce20e4e3b603428a6cb7f13bf7372a60900e22 (patch)
treede7866974174d6a5fb6e8c8c08ac3732ecd34848
parent140a648e46f9a255849d938efd92930297258621 (diff)
parent85cdd06e0c079369a46351a126ef67f9a7142a80 (diff)
downloadnixlib-dfce20e4e3b603428a6cb7f13bf7372a60900e22.tar
nixlib-dfce20e4e3b603428a6cb7f13bf7372a60900e22.tar.gz
nixlib-dfce20e4e3b603428a6cb7f13bf7372a60900e22.tar.bz2
nixlib-dfce20e4e3b603428a6cb7f13bf7372a60900e22.tar.lz
nixlib-dfce20e4e3b603428a6cb7f13bf7372a60900e22.tar.xz
nixlib-dfce20e4e3b603428a6cb7f13bf7372a60900e22.tar.zst
nixlib-dfce20e4e3b603428a6cb7f13bf7372a60900e22.zip
Merge pull request #51980 from ToxicFrog/munin-plugins
nixos/munin: New options (and some bugfixes) for service configuration
-rw-r--r--nixos/modules/services/monitoring/munin.nix209
-rw-r--r--nixos/tests/munin.nix4
-rw-r--r--pkgs/servers/monitoring/munin/default.nix5
3 files changed, 201 insertions, 17 deletions
diff --git a/nixos/modules/services/monitoring/munin.nix b/nixos/modules/services/monitoring/munin.nix
index 2b265d5b5a90..f67986327245 100644
--- a/nixos/modules/services/monitoring/munin.nix
+++ b/nixos/modules/services/monitoring/munin.nix
@@ -4,7 +4,7 @@
 # TODO: LWP/Pg perl libs aren't recognized
 
 # TODO: support fastcgi
-# http://munin-monitoring.org/wiki/CgiHowto2
+# 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
@@ -24,6 +24,8 @@ let
       logdir    /var/log/munin
       rundir    /run/munin
 
+      ${lib.optionalString (cronCfg.extraCSS != "") "staticdir ${customStaticDir}"}
+
       ${cronCfg.extraGlobalConfig}
 
       ${cronCfg.hosts}
@@ -63,6 +65,11 @@ let
       [ipmi*]
       user root
       group root
+
+      [munin*]
+      env.UPDATE_STATSFILE /var/lib/munin/munin-update.stats
+
+      ${nodeCfg.extraPluginConfig}
     '';
 
   pluginConfDir = pkgs.stdenv.mkDerivation {
@@ -72,6 +79,54 @@ let
       ln -s ${pluginConf} $out/nixos-config
     '';
   };
+
+  # Copy one Munin plugin into the Nix store with a specific name.
+  # This is suitable for use with plugins going directly into /etc/munin/plugins,
+  # i.e. munin.extraPlugins.
+  internOnePlugin = name: path:
+    "cp -a '${path}' '${name}'";
+
+  # Copy an entire tree of Munin plugins into a single directory in the Nix
+  # store, with no renaming.
+  # This is suitable for use with munin-node-configure --suggest, i.e.
+  # munin.extraAutoPlugins.
+  internManyPlugins = name: path:
+    "find '${path}' -type f -perm /a+x -exec cp -a -t . '{}' '+'";
+
+  # Use the appropriate intern-fn to copy the plugins into the store and patch
+  # them afterwards in an attempt to get them to run on NixOS.
+  internAndFixPlugins = name: intern-fn: paths:
+    pkgs.runCommand name {} ''
+      mkdir -p "$out"
+      cd "$out"
+      ${lib.concatStringsSep "\n"
+          (lib.attrsets.mapAttrsToList intern-fn paths)}
+      chmod -R u+w .
+      find . -type f -exec sed -E -i '
+        s,(/usr)?/s?bin/,/run/current-system/sw/bin/,g
+      ' '{}' '+'
+    '';
+
+  # TODO: write a derivation for munin-contrib, so that for contrib plugins
+  # you can just refer to them by name rather than needing to include a copy
+  # of munin-contrib in your nixos configuration.
+  extraPluginDir = internAndFixPlugins "munin-extra-plugins.d"
+    internOnePlugin nodeCfg.extraPlugins;
+
+  extraAutoPluginDir = internAndFixPlugins "munin-extra-auto-plugins.d"
+    internManyPlugins
+    (builtins.listToAttrs
+      (map
+        (path: { name = baseNameOf path; value = path; })
+        nodeCfg.extraAutoPlugins));
+
+  customStaticDir = pkgs.runCommand "munin-custom-static-data" {} ''
+    cp -a "${pkgs.munin}/etc/opt/munin/static" "$out"
+    cd "$out"
+    chmod -R u+w .
+    echo "${cronCfg.extraCSS}" >> style.css
+    echo "${cronCfg.extraCSS}" >> style-new.css
+  '';
 in
 
 {
@@ -82,11 +137,12 @@ in
 
       enable = mkOption {
         default = false;
+        type = types.bool;
         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 <link xlink:href='http://munin-monitoring.org/wiki/munin-node.conf' />.
+          See <link xlink:href='http://guide.munin-monitoring.org/en/latest/architecture/index.html' />.
         '';
       };
 
@@ -95,18 +151,108 @@ in
         type = types.lines;
         description = ''
           <filename>munin-node.conf</filename> extra configuration. See
-          <link xlink:href='http://munin-monitoring.org/wiki/munin-node.conf' />
+          <link xlink:href='http://guide.munin-monitoring.org/en/latest/reference/munin-node.conf.html' />
+        '';
+      };
+
+      extraPluginConfig = mkOption {
+        default = "";
+        type = types.lines;
+        description = ''
+          <filename>plugin-conf.d</filename> extra plugin configuration. See
+          <link xlink:href='http://guide.munin-monitoring.org/en/latest/plugin/use.html' />
+        '';
+        example = ''
+          [fail2ban_*]
+          user root
         '';
       };
 
-      # TODO: add option to add additional plugins
+      extraPlugins = mkOption {
+        default = {};
+        type = with types; attrsOf path;
+        description = ''
+          Additional Munin plugins to activate. Keys are the name of the plugin
+          symlink, values are the path to the underlying plugin script. You
+          can use the same plugin script multiple times (e.g. for wildcard
+          plugins).
+
+          Note that these plugins do not participate in autoconfiguration. If
+          you want to autoconfigure additional plugins, use
+          <option>services.munin-node.extraAutoPlugins</option>.
+
+          Plugins enabled in this manner take precedence over autoconfigured
+          plugins.
+
+          Plugins will be copied into the Nix store, and it will attempt to
+          modify them to run properly by fixing hardcoded references to
+          <literal>/bin</literal>, <literal>/usr/bin</literal>,
+          <literal>/sbin</literal>, and <literal>/usr/sbin</literal>.
+        '';
+        example = literalExample ''
+          {
+            zfs_usage_bigpool = /src/munin-contrib/plugins/zfs/zfs_usage_;
+            zfs_usage_smallpool = /src/munin-contrib/plugins/zfs/zfs_usage_;
+            zfs_list = /src/munin-contrib/plugins/zfs/zfs_list;
+          };
+        '';
+      };
 
+      extraAutoPlugins = mkOption {
+        default = [];
+        type = with types; listOf path;
+        description = ''
+          Additional Munin plugins to autoconfigure, using
+          <literal>munin-node-configure --suggest</literal>. These should be
+          the actual paths to the plugin files (or directories containing them),
+          not just their names.
+
+          If you want to manually enable individual plugins instead, use
+          <option>services.munin-node.extraPlugins</option>.
+
+          Note that only plugins that have the 'autoconfig' capability will do
+          anything if listed here, since plugins that cannot autoconfigure
+          won't be automatically enabled by
+          <literal>munin-node-configure</literal>.
+
+          Plugins will be copied into the Nix store, and it will attempt to
+          modify them to run properly by fixing hardcoded references to
+          <literal>/bin</literal>, <literal>/usr/bin</literal>,
+          <literal>/sbin</literal>, and <literal>/usr/sbin</literal>.
+        '';
+        example = literalExample ''
+          [
+            /src/munin-contrib/plugins/zfs
+            /src/munin-contrib/plugins/ssh
+          ];
+        '';
+      };
+
+      disabledPlugins = mkOption {
+        # TODO: figure out why Munin isn't writing the log file and fix it.
+        # In the meantime this at least suppresses a useless graph full of
+        # NaNs in the output.
+        default = [ "munin_stats" ];
+        type = with types; listOf string;
+        description = ''
+          Munin plugins to disable, even if
+          <literal>munin-node-configure --suggest</literal> tries to enable
+          them. To disable a wildcard plugin, use an actual wildcard, as in
+          the example.
+
+          munin_stats is disabled by default as it tries to read
+          <literal>/var/log/munin/munin-update.log</literal> for timing
+          information, and the NixOS build of Munin does not write this file.
+        '';
+        example = [ "diskstats" "zfs_usage_*" ];
+      };
     };
 
     services.munin-cron = {
 
       enable = mkOption {
         default = false;
+        type = types.bool;
         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,
@@ -119,11 +265,12 @@ in
 
       extraGlobalConfig = mkOption {
         default = "";
+        type = types.lines;
         description = ''
           <filename>munin.conf</filename> extra global configuration.
-          See <link xlink:href='http://munin-monitoring.org/wiki/munin.conf' />.
+          See <link xlink:href='http://guide.munin-monitoring.org/en/latest/reference/munin.conf.html' />.
           Useful to setup notifications, see
-          <link xlink:href='http://munin-monitoring.org/wiki/HowToContact' />
+          <link xlink:href='http://guide.munin-monitoring.org/en/latest/tutorial/alert.html' />
         '';
         example = ''
           contact.email.command mail -s "Munin notification for ''${var:host}" someone@example.com
@@ -131,14 +278,34 @@ in
       };
 
       hosts = mkOption {
+        default = "";
+        type = types.lines;
+        description = ''
+          Definitions of hosts of nodes to collect data from. Needs at least one
+          host for cron to succeed. See
+          <link xlink:href='http://guide.munin-monitoring.org/en/latest/reference/munin.conf.html' />
+        '';
         example = ''
           [''${config.networking.hostName}]
           address localhost
         '';
+      };
+
+      extraCSS = mkOption {
+        default = "";
+        type = types.lines;
         description = ''
-          Definitions of hosts of nodes to collect data from. Needs at least one
-          hosts for cron to succeed. See
-          <link xlink:href='http://munin-monitoring.org/wiki/munin.conf' />
+          Custom styling for the HTML that munin-cron generates. This will be
+          appended to the CSS files used by munin-cron and will thus take
+          precedence over the builtin styles.
+        '';
+        example = ''
+          /* A simple dark theme. */
+          html, body { background: #222222; }
+          #header, #footer { background: #333333; }
+          img.i, img.iwarn, img.icrit, img.iunkn {
+            filter: invert(100%) hue-rotate(-30deg);
+          }
         '';
       };
 
@@ -155,6 +322,7 @@ in
       description = "Munin monitoring user";
       group = "munin";
       uid = config.ids.uids.munin;
+      home = "/var/lib/munin";
     }];
 
     users.groups = [{
@@ -173,14 +341,27 @@ in
       environment.MUNIN_PLUGSTATE = "/run/munin";
       environment.MUNIN_LOGDIR = "/var/log/munin";
       preStart = ''
-        echo "updating munin plugins..."
+        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
 
-        # NOTE: we disable disktstats because plugin seems to fail and it hangs html generation (100% CPU + memory leak)
-        rm /etc/munin/plugins/diskstats || true
+        # Autoconfigure extra plugins
+        ${pkgs.munin}/bin/munin-node-configure --suggest --shell --families contrib,auto,manual --config ${nodeConf} --libdir=${extraAutoPluginDir} --servicedir=/etc/munin/plugins --sconfdir=${pluginConfDir} 2>/dev/null | ${pkgs.bash}/bin/bash
+
+        ${lib.optionalString (nodeCfg.extraPlugins != {}) ''
+            # Link in manually enabled plugins
+            ln -f -s -t /etc/munin/plugins ${extraPluginDir}/*
+          ''}
+
+        ${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}";
@@ -192,6 +373,10 @@ in
 
   }) (mkIf cronCfg.enable {
 
+    # Munin is hardcoded to use DejaVu Mono and the graphs come out wrong if
+    # it's not available.
+    fonts.fonts = [ pkgs.dejavu_fonts ];
+
     systemd.timers.munin-cron = {
       description = "batch Munin master programs";
       wantedBy = [ "timers.target" ];
diff --git a/nixos/tests/munin.nix b/nixos/tests/munin.nix
index 9f66005292ab..95cecf17b8cc 100644
--- a/nixos/tests/munin.nix
+++ b/nixos/tests/munin.nix
@@ -15,9 +15,7 @@ import ./make-test.nix ({ pkgs, ...} : {
            munin-node = {
              enable = true;
              # disable a failing plugin to prevent irrelevant error message, see #23049
-             extraConfig = ''
-               ignore_file ^apc_nis$
-             '';
+             disabledPlugins = [ "apc_nis" ];
            };
            munin-cron = {
             enable = true;
diff --git a/pkgs/servers/monitoring/munin/default.nix b/pkgs/servers/monitoring/munin/default.nix
index 032789ef05d0..5153fcc5ef61 100644
--- a/pkgs/servers/monitoring/munin/default.nix
+++ b/pkgs/servers/monitoring/munin/default.nix
@@ -3,14 +3,14 @@
 }:
 
 stdenv.mkDerivation rec {
-  version = "2.0.37";
+  version = "2.0.43";
   name = "munin-${version}";
 
   src = fetchFromGitHub {
     owner = "munin-monitoring";
     repo = "munin";
     rev = version;
-    sha256 = "10niyzckx90dwdr4d7vj07d1qjy3nk7xzp30nqnlxzbaww7n5v78";
+    sha256 = "1ydhf9hcb3n5h0ss5f1zf9yz4r4njqxazlz931ixvx5gyhj9gq5l";
   };
 
   buildInputs = [
@@ -75,6 +75,7 @@ stdenv.mkDerivation rec {
   ];
 
   preBuild = ''
+    echo "${version}" > RELEASE
     substituteInPlace "Makefile" \
       --replace "/bin/pwd" "pwd" \
       --replace "HTMLOld.3pm" "HTMLOld.3"