at 21.11-pre 9.0 kB view raw
1{ config, pkgs, lib, ... }: 2 3with lib; 4 5let 6 cfg = config.services.netdata; 7 8 wrappedPlugins = pkgs.runCommand "wrapped-plugins" { preferLocalBuild = true; } '' 9 mkdir -p $out/libexec/netdata/plugins.d 10 ln -s /run/wrappers/bin/apps.plugin $out/libexec/netdata/plugins.d/apps.plugin 11 ln -s /run/wrappers/bin/cgroup-network $out/libexec/netdata/plugins.d/cgroup-network 12 ln -s /run/wrappers/bin/freeipmi.plugin $out/libexec/netdata/plugins.d/freeipmi.plugin 13 ln -s /run/wrappers/bin/perf.plugin $out/libexec/netdata/plugins.d/perf.plugin 14 ln -s /run/wrappers/bin/slabinfo.plugin $out/libexec/netdata/plugins.d/slabinfo.plugin 15 ''; 16 17 plugins = [ 18 "${cfg.package}/libexec/netdata/plugins.d" 19 "${wrappedPlugins}/libexec/netdata/plugins.d" 20 ] ++ cfg.extraPluginPaths; 21 22 localConfig = { 23 global = { 24 "plugins directory" = concatStringsSep " " plugins; 25 }; 26 web = { 27 "web files owner" = "root"; 28 "web files group" = "root"; 29 }; 30 "plugin:cgroups" = { 31 "script to get cgroup network interfaces" = "${wrappedPlugins}/libexec/netdata/plugins.d/cgroup-network"; 32 "use unified cgroups" = "yes"; 33 }; 34 }; 35 mkConfig = generators.toINI {} (recursiveUpdate localConfig cfg.config); 36 configFile = pkgs.writeText "netdata.conf" (if cfg.configText != null then cfg.configText else mkConfig); 37 38 defaultUser = "netdata"; 39 40in { 41 options = { 42 services.netdata = { 43 enable = mkEnableOption "netdata"; 44 45 package = mkOption { 46 type = types.package; 47 default = pkgs.netdata; 48 defaultText = "pkgs.netdata"; 49 description = "Netdata package to use."; 50 }; 51 52 user = mkOption { 53 type = types.str; 54 default = "netdata"; 55 description = "User account under which netdata runs."; 56 }; 57 58 group = mkOption { 59 type = types.str; 60 default = "netdata"; 61 description = "Group under which netdata runs."; 62 }; 63 64 configText = mkOption { 65 type = types.nullOr types.lines; 66 description = "Verbatim netdata.conf, cannot be combined with config."; 67 default = null; 68 example = '' 69 [global] 70 debug log = syslog 71 access log = syslog 72 error log = syslog 73 ''; 74 }; 75 76 python = { 77 enable = mkOption { 78 type = types.bool; 79 default = true; 80 description = '' 81 Whether to enable python-based plugins 82 ''; 83 }; 84 extraPackages = mkOption { 85 type = types.functionTo (types.listOf types.package); 86 default = ps: []; 87 defaultText = "ps: []"; 88 example = literalExample '' 89 ps: [ 90 ps.psycopg2 91 ps.docker 92 ps.dnspython 93 ] 94 ''; 95 description = '' 96 Extra python packages available at runtime 97 to enable additional python plugins. 98 ''; 99 }; 100 }; 101 102 extraPluginPaths = mkOption { 103 type = types.listOf types.path; 104 default = [ ]; 105 example = literalExample '' 106 [ "/path/to/plugins.d" ] 107 ''; 108 description = '' 109 Extra paths to add to the netdata global "plugins directory" 110 option. Useful for when you want to include your own 111 collection scripts. 112 </para><para> 113 Details about writing a custom netdata plugin are available at: 114 <link xlink:href="https://docs.netdata.cloud/collectors/plugins.d/"/> 115 </para><para> 116 Cannot be combined with configText. 117 ''; 118 }; 119 120 config = mkOption { 121 type = types.attrsOf types.attrs; 122 default = {}; 123 description = "netdata.conf configuration as nix attributes. cannot be combined with configText."; 124 example = literalExample '' 125 global = { 126 "debug log" = "syslog"; 127 "access log" = "syslog"; 128 "error log" = "syslog"; 129 }; 130 ''; 131 }; 132 133 enableAnalyticsReporting = mkOption { 134 type = types.bool; 135 default = false; 136 description = '' 137 Enable reporting of anonymous usage statistics to Netdata Inc. via either 138 Google Analytics (in versions prior to 1.29.4), or Netdata Inc.'s 139 self-hosted PostHog (in versions 1.29.4 and later). 140 See: <link xlink:href="https://learn.netdata.cloud/docs/agent/anonymous-statistics"/> 141 ''; 142 }; 143 }; 144 }; 145 146 config = mkIf cfg.enable { 147 assertions = 148 [ { assertion = cfg.config != {} -> cfg.configText == null ; 149 message = "Cannot specify both config and configText"; 150 } 151 ]; 152 153 systemd.services.netdata = { 154 description = "Real time performance monitoring"; 155 after = [ "network.target" ]; 156 wantedBy = [ "multi-user.target" ]; 157 path = (with pkgs; [ curl gawk iproute2 which ]) 158 ++ lib.optional cfg.python.enable (pkgs.python3.withPackages cfg.python.extraPackages) 159 ++ lib.optional config.virtualisation.libvirtd.enable (config.virtualisation.libvirtd.package); 160 environment = { 161 PYTHONPATH = "${cfg.package}/libexec/netdata/python.d/python_modules"; 162 } // lib.optionalAttrs (!cfg.enableAnalyticsReporting) { 163 DO_NOT_TRACK = "1"; 164 }; 165 serviceConfig = { 166 ExecStart = "${cfg.package}/bin/netdata -P /run/netdata/netdata.pid -D -c ${configFile}"; 167 ExecReload = "${pkgs.util-linux}/bin/kill -s HUP -s USR1 -s USR2 $MAINPID"; 168 TimeoutStopSec = 60; 169 Restart = "on-failure"; 170 # User and group 171 User = cfg.user; 172 Group = cfg.group; 173 # Performance 174 LimitNOFILE = "30000"; 175 # Runtime directory and mode 176 RuntimeDirectory = "netdata"; 177 RuntimeDirectoryMode = "0750"; 178 # State directory and mode 179 StateDirectory = "netdata"; 180 StateDirectoryMode = "0750"; 181 # Cache directory and mode 182 CacheDirectory = "netdata"; 183 CacheDirectoryMode = "0750"; 184 # Logs directory and mode 185 LogsDirectory = "netdata"; 186 LogsDirectoryMode = "0750"; 187 # Configuration directory and mode 188 ConfigurationDirectory = "netdata"; 189 ConfigurationDirectoryMode = "0755"; 190 # Capabilities 191 CapabilityBoundingSet = [ 192 "CAP_DAC_OVERRIDE" # is required for freeipmi and slabinfo plugins 193 "CAP_DAC_READ_SEARCH" # is required for apps plugin 194 "CAP_FOWNER" # is required for freeipmi plugin 195 "CAP_SETPCAP" # is required for apps, perf and slabinfo plugins 196 "CAP_SYS_ADMIN" # is required for perf plugin 197 "CAP_SYS_PTRACE" # is required for apps plugin 198 "CAP_SYS_RESOURCE" # is required for ebpf plugin 199 "CAP_NET_RAW" # is required for fping app 200 "CAP_SYS_CHROOT" # is required for cgroups plugin 201 "CAP_SETUID" # is required for cgroups and cgroups-network plugins 202 ]; 203 # Sandboxing 204 ProtectSystem = "full"; 205 ProtectHome = "read-only"; 206 PrivateTmp = true; 207 ProtectControlGroups = true; 208 PrivateMounts = true; 209 }; 210 }; 211 212 systemd.enableCgroupAccounting = true; 213 214 security.wrappers."apps.plugin" = { 215 source = "${cfg.package}/libexec/netdata/plugins.d/apps.plugin.org"; 216 capabilities = "cap_dac_read_search,cap_sys_ptrace+ep"; 217 owner = cfg.user; 218 group = cfg.group; 219 permissions = "u+rx,g+x,o-rwx"; 220 }; 221 222 security.wrappers."cgroup-network" = { 223 source = "${cfg.package}/libexec/netdata/plugins.d/cgroup-network.org"; 224 capabilities = "cap_setuid+ep"; 225 owner = cfg.user; 226 group = cfg.group; 227 permissions = "u+rx,g+x,o-rwx"; 228 }; 229 230 security.wrappers."freeipmi.plugin" = { 231 source = "${cfg.package}/libexec/netdata/plugins.d/freeipmi.plugin.org"; 232 capabilities = "cap_dac_override,cap_fowner+ep"; 233 owner = cfg.user; 234 group = cfg.group; 235 permissions = "u+rx,g+x,o-rwx"; 236 }; 237 238 security.wrappers."perf.plugin" = { 239 source = "${cfg.package}/libexec/netdata/plugins.d/perf.plugin.org"; 240 capabilities = "cap_sys_admin+ep"; 241 owner = cfg.user; 242 group = cfg.group; 243 permissions = "u+rx,g+x,o-rwx"; 244 }; 245 246 security.wrappers."slabinfo.plugin" = { 247 source = "${cfg.package}/libexec/netdata/plugins.d/slabinfo.plugin.org"; 248 capabilities = "cap_dac_override+ep"; 249 owner = cfg.user; 250 group = cfg.group; 251 permissions = "u+rx,g+x,o-rwx"; 252 }; 253 254 security.pam.loginLimits = [ 255 { domain = "netdata"; type = "soft"; item = "nofile"; value = "10000"; } 256 { domain = "netdata"; type = "hard"; item = "nofile"; value = "30000"; } 257 ]; 258 259 users.users = optionalAttrs (cfg.user == defaultUser) { 260 ${defaultUser} = { 261 isSystemUser = true; 262 }; 263 }; 264 265 users.groups = optionalAttrs (cfg.group == defaultUser) { 266 ${defaultUser} = { }; 267 }; 268 269 }; 270}