diff --git a/modules/module-list.nix b/modules/module-list.nix index 17a65a004021..7230998370c3 100644 --- a/modules/module-list.nix +++ b/modules/module-list.nix @@ -146,6 +146,7 @@ ./services/scheduling/fcron.nix ./services/security/tor.nix ./services/security/torsocks.nix + ./services/system/cgroups.nix ./services/system/dbus.nix ./services/system/kerberos.nix ./services/system/nscd.nix diff --git a/modules/services/system/cgroups.nix b/modules/services/system/cgroups.nix new file mode 100644 index 000000000000..08482643c3fa --- /dev/null +++ b/modules/services/system/cgroups.nix @@ -0,0 +1,140 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + cfg = config.services.cgroups; + + cgconfigConf = pkgs.writeText "cgconfig.conf" cfg.groups; + + cgrulesConf = pkgs.writeText "cgrules.conf" cfg.rules; + +in + +{ + + ###### interface + + options = { + + services.cgroups.enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable support for control groups, a Linux kernel + feature for resource management. It allows you to assign + processes to groups that share certain resource limits (e.g., + CPU or memory). The cgrulesengd daemon + automatically assigns processes to the right cgroup depending + on the rules defined in + . + ''; + }; + + services.cgroups.groups = mkOption { + type = types.string; + default = + '' + mount { + cpu = /dev/cgroup/cpu; + } + ''; + example = + '' + mount { + cpu = /dev/cgroup/cpu; + cpuacct = /dev/cgroup/cpuacct; + } + + # Create a "www" cgroup with a lower share of the CPU (the + # default is 1024). + group www { + cpu { + cpu.shares = "500"; + } + } + ''; + description = '' + The contents of the cgconfig.conf + configuration file, which defines the cgroups. + ''; + }; + + services.cgroups.rules = mkOption { + type = types.string; + default = ""; + example = + '' + # All processes executed by the "wwwrun" uid should be + # assigned to the "www" CPU cgroup. + wwwrun cpu www + ''; + description = '' + The contents of the cgrules.conf + configuration file, which determines to which cgroups + processes should be assigned by the + cgrulesengd daemon. + ''; + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + environment.systemPackages = [ pkgs.libcgroup ]; + + environment.etc = + [ { source = cgconfigConf; + target = "cgconfig.conf"; + } + { source = cgrulesConf; + target = "cgrules.conf"; + } + ]; + + jobs.cgroups = + { startOn = "startup"; + + description = "Control groups daemon"; + + path = [ pkgs.libcgroup pkgs.procps ]; + + preStart = + '' + # The daemon requires the userspace<->kernelspace netlink + # connector. + ${config.system.sbin.modprobe}/sbin/modprobe cn || true + + cgclear || true + + # Mount the cgroup hierarchies. Note: we refer to the + # store path of cgconfig.conf here to ensure that the job + # gets reloaded if the configuration changes. + cgconfigparser -l ${cgconfigConf} + + # Move existing processes to the right cgroup. + cgclassify --cancel-sticky $(ps --no-headers -eL o tid) || true + + # Force a restart if the rules change: + # ${cgrulesConf} + ''; + + # Run the daemon that moves new processes to the right cgroup. + exec = "cgrulesengd"; + + daemonType = "fork"; + + postStop = + '' + cgclear + ''; + }; + + + }; + +} diff --git a/modules/system/activation/activation-script.nix b/modules/system/activation/activation-script.nix index 72566507eccd..d7074810c273 100644 --- a/modules/system/activation/activation-script.nix +++ b/modules/system/activation/activation-script.nix @@ -129,14 +129,6 @@ in mkdir -p /media ''; - system.activationScripts.cgroups = - '' - if ! ${pkgs.sysvtools}/bin/mountpoint -q /dev/cgroup; then - mkdir -p /dev/cgroup - ${pkgs.utillinux}/bin/mount -t cgroup -o freezer,cpuacct,cpu,cpuset none /dev/cgroup - fi - ''; - }; }