diff --git a/nixos/modules/services/monitoring/netdata.nix b/nixos/modules/services/monitoring/netdata.nix index e1fde4fc9500..d23b329eeb25 100644 --- a/nixos/modules/services/monitoring/netdata.nix +++ b/nixos/modules/services/monitoring/netdata.nix @@ -5,18 +5,25 @@ with lib; let cfg = config.services.netdata; - configFile = pkgs.writeText "netdata.conf" cfg.configText; + wrappedPlugins = pkgs.runCommand "wrapped-plugins" {} '' + mkdir -p $out/libexec/netdata/plugins.d + ln -s /run/wrappers/bin/apps.plugin $out/libexec/netdata/plugins.d/apps.plugin + ''; + + localConfig = { + global = { + "plugins directory" = "${wrappedPlugins}/libexec/netdata/plugins.d ${pkgs.netdata}/libexec/netdata/plugins.d"; + }; + }; + mkConfig = generators.toINI {} (recursiveUpdate localConfig cfg.config); + configFile = pkgs.writeText "netdata.conf" (if cfg.configText != null then cfg.configText else mkConfig); defaultUser = "netdata"; in { options = { services.netdata = { - enable = mkOption { - default = false; - type = types.bool; - description = "Whether to enable netdata monitoring."; - }; + enable = mkEnableOption "netdata"; user = mkOption { type = types.str; @@ -31,9 +38,9 @@ in { }; configText = mkOption { - type = types.lines; - default = ""; - description = "netdata.conf configuration."; + type = types.nullOr types.lines; + description = "Verbatim netdata.conf, cannot be combined with config."; + default = null; example = '' [global] debug log = syslog @@ -42,11 +49,29 @@ in { ''; }; + config = mkOption { + type = types.attrsOf types.attrs; + default = {}; + description = "netdata.conf configuration as nix attributes. cannot be combined with configText."; + example = literalExample '' + global = { + "debug log" = "syslog"; + "access log" = "syslog"; + "error log" = "syslog"; + }; + ''; + }; + }; }; - }; config = mkIf cfg.enable { + assertions = + [ { assertion = cfg.config != {} -> cfg.configText == null ; + message = "Cannot specify both config and configText"; + } + ]; systemd.services.netdata = { + path = with pkgs; [ gawk curl ]; description = "Real time performance monitoring"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; @@ -66,6 +91,15 @@ in { }; }; + security.wrappers."apps.plugin" = { + source = "${pkgs.netdata}/libexec/netdata/plugins.d/apps.plugin"; + capabilities = "cap_dac_read_search,cap_sys_ptrace+ep"; + owner = cfg.user; + group = cfg.group; + permissions = "u+rx,g+rx,o-rwx"; + }; + + users.extraUsers = optional (cfg.user == defaultUser) { name = defaultUser; }; diff --git a/nixos/release.nix b/nixos/release.nix index ad3337800384..846d87b18d6a 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -304,6 +304,7 @@ in rec { tests.nat.firewall = callTest tests/nat.nix { withFirewall = true; }; tests.nat.firewall-conntrack = callTest tests/nat.nix { withFirewall = true; withConntrackHelpers = true; }; tests.nat.standalone = callTest tests/nat.nix { withFirewall = false; }; + tests.netdata = callTest tests/netdata.nix { }; tests.networking.networkd = callSubTests tests/networking.nix { networkd = true; }; tests.networking.scripted = callSubTests tests/networking.nix { networkd = false; }; # TODO: put in networking.nix after the test becomes more complete diff --git a/nixos/tests/netdata.nix b/nixos/tests/netdata.nix new file mode 100644 index 000000000000..58733c1b3379 --- /dev/null +++ b/nixos/tests/netdata.nix @@ -0,0 +1,31 @@ +# This test runs netdata and checks for data via apps.plugin + +import ./make-test.nix ({ pkgs, ...} : { + name = "netdata"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ cransom ]; + }; + + nodes = { + netdata = + { config, pkgs, ... }: + { + environment.systemPackages = with pkgs; [ curl jq ]; + services.netdata.enable = true; + }; + }; + + testScript = '' + startAll; + + $netdata->waitForUnit("netdata.service"); + # check if netdata can read disk ops for root owned processes. + # if > 0, successful. verifies both netdata working and + # apps.plugin has elevated capabilities. + my $cmd = <<'CMD'; + curl -s http://localhost:19999/api/v1/data\?chart=users.pwrites | \ + jq -e '[.data[range(10)][.labels | indices("root")[0]]] | add | . > 0' + CMD + $netdata->waitUntilSucceeds($cmd); + ''; +})