python3Packages.orjson: Disable failing tests on 32 bit
[NixPkgs.git] / nixos / modules / services / monitoring / netdata.nix
blob92c870bb23f1d49ff08b69ccac9c72f975f7b483
1 { config, pkgs, lib, ... }:
3 with lib;
5 let
6   cfg = config.services.netdata;
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/perf.plugin $out/libexec/netdata/plugins.d/perf.plugin
13     ln -s /run/wrappers/bin/slabinfo.plugin $out/libexec/netdata/plugins.d/slabinfo.plugin
14     ln -s /run/wrappers/bin/freeipmi.plugin $out/libexec/netdata/plugins.d/freeipmi.plugin
15   '';
17   plugins = [
18     "${cfg.package}/libexec/netdata/plugins.d"
19     "${wrappedPlugins}/libexec/netdata/plugins.d"
20   ] ++ cfg.extraPluginPaths;
22   configDirectory = pkgs.runCommand "netdata-config-d" { } ''
23     mkdir $out
24     ${concatStringsSep "\n" (mapAttrsToList (path: file: ''
25         mkdir -p "$out/$(dirname ${path})"
26         ln -s "${file}" "$out/${path}"
27       '') cfg.configDir)}
28   '';
30   localConfig = {
31     global = {
32       "config directory" = "/etc/netdata/conf.d";
33       "plugins directory" = concatStringsSep " " plugins;
34     };
35     web = {
36       "web files owner" = "root";
37       "web files group" = "root";
38     };
39     "plugin:cgroups" = {
40       "script to get cgroup network interfaces" = "${wrappedPlugins}/libexec/netdata/plugins.d/cgroup-network";
41       "use unified cgroups" = "yes";
42     };
43   };
44   mkConfig = generators.toINI {} (recursiveUpdate localConfig cfg.config);
45   configFile = pkgs.writeText "netdata.conf" (if cfg.configText != null then cfg.configText else mkConfig);
47   defaultUser = "netdata";
49 in {
50   options = {
51     services.netdata = {
52       enable = mkEnableOption (lib.mdDoc "netdata");
54       package = mkOption {
55         type = types.package;
56         default = pkgs.netdata;
57         defaultText = literalExpression "pkgs.netdata";
58         description = lib.mdDoc "Netdata package to use.";
59       };
61       user = mkOption {
62         type = types.str;
63         default = "netdata";
64         description = lib.mdDoc "User account under which netdata runs.";
65       };
67       group = mkOption {
68         type = types.str;
69         default = "netdata";
70         description = lib.mdDoc "Group under which netdata runs.";
71       };
73       configText = mkOption {
74         type = types.nullOr types.lines;
75         description = lib.mdDoc "Verbatim netdata.conf, cannot be combined with config.";
76         default = null;
77         example = ''
78           [global]
79           debug log = syslog
80           access log = syslog
81           error log = syslog
82         '';
83       };
85       python = {
86         enable = mkOption {
87           type = types.bool;
88           default = true;
89           description = lib.mdDoc ''
90             Whether to enable python-based plugins
91           '';
92         };
93         extraPackages = mkOption {
94           type = types.functionTo (types.listOf types.package);
95           default = ps: [];
96           defaultText = literalExpression "ps: []";
97           example = literalExpression ''
98             ps: [
99               ps.psycopg2
100               ps.docker
101               ps.dnspython
102             ]
103           '';
104           description = lib.mdDoc ''
105             Extra python packages available at runtime
106             to enable additional python plugins.
107           '';
108         };
109       };
111       extraPluginPaths = mkOption {
112         type = types.listOf types.path;
113         default = [ ];
114         example = literalExpression ''
115           [ "/path/to/plugins.d" ]
116         '';
117         description = lib.mdDoc ''
118           Extra paths to add to the netdata global "plugins directory"
119           option.  Useful for when you want to include your own
120           collection scripts.
122           Details about writing a custom netdata plugin are available at:
123           <https://docs.netdata.cloud/collectors/plugins.d/>
125           Cannot be combined with configText.
126         '';
127       };
129       config = mkOption {
130         type = types.attrsOf types.attrs;
131         default = {};
132         description = lib.mdDoc "netdata.conf configuration as nix attributes. cannot be combined with configText.";
133         example = literalExpression ''
134           global = {
135             "debug log" = "syslog";
136             "access log" = "syslog";
137             "error log" = "syslog";
138           };
139         '';
140       };
142       configDir = mkOption {
143         type = types.attrsOf types.path;
144         default = {};
145         description = lib.mdDoc ''
146           Complete netdata config directory except netdata.conf.
147           The default configuration is merged with changes
148           defined in this option.
149           Each top-level attribute denotes a path in the configuration
150           directory as in environment.etc.
151           Its value is the absolute path and must be readable by netdata.
152           Cannot be combined with configText.
153         '';
154         example = literalExpression ''
155           "health_alarm_notify.conf" = pkgs.writeText "health_alarm_notify.conf" '''
156             sendmail="/path/to/sendmail"
157           ''';
158           "health.d" = "/run/secrets/netdata/health.d";
159         '';
160       };
162       enableAnalyticsReporting = mkOption {
163         type = types.bool;
164         default = false;
165         description = lib.mdDoc ''
166           Enable reporting of anonymous usage statistics to Netdata Inc. via either
167           Google Analytics (in versions prior to 1.29.4), or Netdata Inc.'s
168           self-hosted PostHog (in versions 1.29.4 and later).
169           See: <https://learn.netdata.cloud/docs/agent/anonymous-statistics>
170         '';
171       };
172     };
173   };
175   config = mkIf cfg.enable {
176     assertions =
177       [ { assertion = cfg.config != {} -> cfg.configText == null ;
178           message = "Cannot specify both config and configText";
179         }
180       ];
182     environment.etc."netdata/netdata.conf".source = configFile;
183     environment.etc."netdata/conf.d".source = configDirectory;
185     systemd.services.netdata = {
186       description = "Real time performance monitoring";
187       after = [ "network.target" ];
188       wantedBy = [ "multi-user.target" ];
189       path = (with pkgs; [ curl gawk iproute2 which procps bash ])
190         ++ lib.optional cfg.python.enable (pkgs.python3.withPackages cfg.python.extraPackages)
191         ++ lib.optional config.virtualisation.libvirtd.enable (config.virtualisation.libvirtd.package);
192       environment = {
193         PYTHONPATH = "${cfg.package}/libexec/netdata/python.d/python_modules";
194       } // lib.optionalAttrs (!cfg.enableAnalyticsReporting) {
195         DO_NOT_TRACK = "1";
196       };
197       restartTriggers = [
198         config.environment.etc."netdata/netdata.conf".source
199         config.environment.etc."netdata/conf.d".source
200       ];
201       serviceConfig = {
202         ExecStart = "${cfg.package}/bin/netdata -P /run/netdata/netdata.pid -D -c /etc/netdata/netdata.conf";
203         ExecReload = "${pkgs.util-linux}/bin/kill -s HUP -s USR1 -s USR2 $MAINPID";
204         ExecStartPost = pkgs.writeShellScript "wait-for-netdata-up" ''
205           while [ "$(${pkgs.netdata}/bin/netdatacli ping)" != pong ]; do sleep 0.5; done
206         '';
208         TimeoutStopSec = 60;
209         Restart = "on-failure";
210         # User and group
211         User = cfg.user;
212         Group = cfg.group;
213         # Performance
214         LimitNOFILE = "30000";
215         # Runtime directory and mode
216         RuntimeDirectory = "netdata";
217         RuntimeDirectoryMode = "0750";
218         # State directory and mode
219         StateDirectory = "netdata";
220         StateDirectoryMode = "0750";
221         # Cache directory and mode
222         CacheDirectory = "netdata";
223         CacheDirectoryMode = "0750";
224         # Logs directory and mode
225         LogsDirectory = "netdata";
226         LogsDirectoryMode = "0750";
227         # Configuration directory and mode
228         ConfigurationDirectory = "netdata";
229         ConfigurationDirectoryMode = "0755";
230         # Capabilities
231         CapabilityBoundingSet = [
232           "CAP_DAC_OVERRIDE"      # is required for freeipmi and slabinfo plugins
233           "CAP_DAC_READ_SEARCH"   # is required for apps plugin
234           "CAP_FOWNER"            # is required for freeipmi plugin
235           "CAP_SETPCAP"           # is required for apps, perf and slabinfo plugins
236           "CAP_SYS_ADMIN"         # is required for perf plugin
237           "CAP_SYS_PTRACE"        # is required for apps plugin
238           "CAP_SYS_RESOURCE"      # is required for ebpf plugin
239           "CAP_NET_RAW"           # is required for fping app
240           "CAP_SYS_CHROOT"        # is required for cgroups plugin
241           "CAP_SETUID"            # is required for cgroups and cgroups-network plugins
242         ];
243         # Sandboxing
244         ProtectSystem = "full";
245         ProtectHome = "read-only";
246         PrivateTmp = true;
247         ProtectControlGroups = true;
248         PrivateMounts = true;
249       };
250     };
252     systemd.enableCgroupAccounting = true;
254     security.wrappers = {
255       "apps.plugin" = {
256         source = "${cfg.package}/libexec/netdata/plugins.d/apps.plugin.org";
257         capabilities = "cap_dac_read_search,cap_sys_ptrace+ep";
258         owner = cfg.user;
259         group = cfg.group;
260         permissions = "u+rx,g+x,o-rwx";
261       };
263       "cgroup-network" = {
264         source = "${cfg.package}/libexec/netdata/plugins.d/cgroup-network.org";
265         capabilities = "cap_setuid+ep";
266         owner = cfg.user;
267         group = cfg.group;
268         permissions = "u+rx,g+x,o-rwx";
269       };
271       "perf.plugin" = {
272         source = "${cfg.package}/libexec/netdata/plugins.d/perf.plugin.org";
273         capabilities = "cap_sys_admin+ep";
274         owner = cfg.user;
275         group = cfg.group;
276         permissions = "u+rx,g+x,o-rwx";
277       };
279       "slabinfo.plugin" = {
280         source = "${cfg.package}/libexec/netdata/plugins.d/slabinfo.plugin.org";
281         capabilities = "cap_dac_override+ep";
282         owner = cfg.user;
283         group = cfg.group;
284         permissions = "u+rx,g+x,o-rwx";
285       };
287     } // optionalAttrs (cfg.package.withIpmi) {
288       "freeipmi.plugin" = {
289         source = "${cfg.package}/libexec/netdata/plugins.d/freeipmi.plugin.org";
290         capabilities = "cap_dac_override,cap_fowner+ep";
291         owner = cfg.user;
292         group = cfg.group;
293         permissions = "u+rx,g+x,o-rwx";
294       };
295     };
297     security.pam.loginLimits = [
298       { domain = "netdata"; type = "soft"; item = "nofile"; value = "10000"; }
299       { domain = "netdata"; type = "hard"; item = "nofile"; value = "30000"; }
300     ];
302     users.users = optionalAttrs (cfg.user == defaultUser) {
303       ${defaultUser} = {
304         group = defaultUser;
305         isSystemUser = true;
306       };
307     };
309     users.groups = optionalAttrs (cfg.group == defaultUser) {
310       ${defaultUser} = { };
311     };
313   };