at 24.11-pre 9.1 kB view raw
1/* 2 Declares what makes the nix-daemon work on systemd. 3 4 See also 5 - nixos/modules/config/nix.nix: the nix.conf 6 - nixos/modules/config/nix-remote-build.nix: the nix.conf 7*/ 8{ config, lib, pkgs, ... }: 9 10with lib; 11 12let 13 14 cfg = config.nix; 15 16 nixPackage = cfg.package.out; 17 18 isNixAtLeast = versionAtLeast (getVersion nixPackage); 19 20 makeNixBuildUser = nr: { 21 name = "nixbld${toString nr}"; 22 value = { 23 description = "Nix build user ${toString nr}"; 24 25 /* 26 For consistency with the setgid(2), setuid(2), and setgroups(2) 27 calls in `libstore/build.cc', don't add any supplementary group 28 here except "nixbld". 29 */ 30 uid = builtins.add config.ids.uids.nixbld nr; 31 isSystemUser = true; 32 group = "nixbld"; 33 extraGroups = [ "nixbld" ]; 34 }; 35 }; 36 37 nixbldUsers = listToAttrs (map makeNixBuildUser (range 1 cfg.nrBuildUsers)); 38 39in 40 41{ 42 imports = [ 43 (mkRenamedOptionModuleWith { sinceRelease = 2205; from = [ "nix" "daemonIONiceLevel" ]; to = [ "nix" "daemonIOSchedPriority" ]; }) 44 (mkRenamedOptionModuleWith { sinceRelease = 2211; from = [ "nix" "readOnlyStore" ]; to = [ "boot" "readOnlyNixStore" ]; }) 45 (mkRemovedOptionModule [ "nix" "daemonNiceLevel" ] "Consider nix.daemonCPUSchedPolicy instead.") 46 ]; 47 48 ###### interface 49 50 options = { 51 52 nix = { 53 54 enable = mkOption { 55 type = types.bool; 56 default = true; 57 description = '' 58 Whether to enable Nix. 59 Disabling Nix makes the system hard to modify and the Nix programs and configuration will not be made available by NixOS itself. 60 ''; 61 }; 62 63 package = mkOption { 64 type = types.package; 65 default = pkgs.nix; 66 defaultText = literalExpression "pkgs.nix"; 67 description = '' 68 This option specifies the Nix package instance to use throughout the system. 69 ''; 70 }; 71 72 daemonCPUSchedPolicy = mkOption { 73 type = types.enum [ "other" "batch" "idle" ]; 74 default = "other"; 75 example = "batch"; 76 description = '' 77 Nix daemon process CPU scheduling policy. This policy propagates to 78 build processes. `other` is the default scheduling 79 policy for regular tasks. The `batch` policy is 80 similar to `other`, but optimised for 81 non-interactive tasks. `idle` is for extremely 82 low-priority tasks that should only be run when no other task 83 requires CPU time. 84 85 Please note that while using the `idle` policy may 86 greatly improve responsiveness of a system performing expensive 87 builds, it may also slow down and potentially starve crucial 88 configuration updates during load. 89 90 `idle` may therefore be a sensible policy for 91 systems that experience only intermittent phases of high CPU load, 92 such as desktop or portable computers used interactively. Other 93 systems should use the `other` or 94 `batch` policy instead. 95 96 For more fine-grained resource control, please refer to 97 {manpage}`systemd.resource-control(5)` and adjust 98 {option}`systemd.services.nix-daemon` directly. 99 ''; 100 }; 101 102 daemonIOSchedClass = mkOption { 103 type = types.enum [ "best-effort" "idle" ]; 104 default = "best-effort"; 105 example = "idle"; 106 description = '' 107 Nix daemon process I/O scheduling class. This class propagates to 108 build processes. `best-effort` is the default 109 class for regular tasks. The `idle` class is for 110 extremely low-priority tasks that should only perform I/O when no 111 other task does. 112 113 Please note that while using the `idle` scheduling 114 class can improve responsiveness of a system performing expensive 115 builds, it might also slow down or starve crucial configuration 116 updates during load. 117 118 `idle` may therefore be a sensible class for 119 systems that experience only intermittent phases of high I/O load, 120 such as desktop or portable computers used interactively. Other 121 systems should use the `best-effort` class. 122 ''; 123 }; 124 125 daemonIOSchedPriority = mkOption { 126 type = types.int; 127 default = 4; 128 example = 1; 129 description = '' 130 Nix daemon process I/O scheduling priority. This priority propagates 131 to build processes. The supported priorities depend on the 132 scheduling policy: With idle, priorities are not used in scheduling 133 decisions. best-effort supports values in the range 0 (high) to 7 134 (low). 135 ''; 136 }; 137 138 # Environment variables for running Nix. 139 envVars = mkOption { 140 type = types.attrs; 141 internal = true; 142 default = { }; 143 description = "Environment variables used by Nix."; 144 }; 145 146 nrBuildUsers = mkOption { 147 type = types.int; 148 description = '' 149 Number of `nixbld` user accounts created to 150 perform secure concurrent builds. If you receive an error 151 message saying that all build users are currently in use, 152 you should increase this value. 153 ''; 154 }; 155 }; 156 }; 157 158 159 ###### implementation 160 161 config = mkIf cfg.enable { 162 environment.systemPackages = 163 [ 164 nixPackage 165 pkgs.nix-info 166 ] 167 ++ optional (config.programs.bash.enableCompletion) pkgs.nix-bash-completions; 168 169 systemd.packages = [ nixPackage ]; 170 171 systemd.tmpfiles = mkMerge [ 172 (mkIf (isNixAtLeast "2.8") { 173 packages = [ nixPackage ]; 174 }) 175 (mkIf (!isNixAtLeast "2.8") { 176 rules = [ 177 "d /nix/var/nix/daemon-socket 0755 root root - -" 178 ]; 179 }) 180 ]; 181 182 systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ]; 183 184 systemd.services.nix-daemon = 185 { 186 path = [ nixPackage pkgs.util-linux config.programs.ssh.package ] 187 ++ optionals cfg.distributedBuilds [ pkgs.gzip ]; 188 189 environment = cfg.envVars 190 // { CURL_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt"; } 191 // config.networking.proxy.envVars; 192 193 unitConfig.RequiresMountsFor = "/nix/store"; 194 195 serviceConfig = 196 { 197 CPUSchedulingPolicy = cfg.daemonCPUSchedPolicy; 198 IOSchedulingClass = cfg.daemonIOSchedClass; 199 IOSchedulingPriority = cfg.daemonIOSchedPriority; 200 LimitNOFILE = 1048576; 201 }; 202 203 restartTriggers = [ config.environment.etc."nix/nix.conf".source ]; 204 205 # `stopIfChanged = false` changes to switch behavior 206 # from stop -> update units -> start 207 # to update units -> restart 208 # 209 # The `stopIfChanged` setting therefore controls a trade-off between a 210 # more predictable lifecycle, which runs the correct "version" of 211 # the `ExecStop` line, and on the other hand the availability of 212 # sockets during the switch, as the effectiveness of the stop operation 213 # depends on the socket being stopped as well. 214 # 215 # As `nix-daemon.service` does not make use of `ExecStop`, we prefer 216 # to keep the socket up and available. This is important for machines 217 # that run Nix-based services, such as automated build, test, and deploy 218 # services, that expect the daemon socket to be available at all times. 219 # 220 # Notably, the Nix client does not retry on failure to connect to the 221 # daemon socket, and the in-process RemoteStore instance will disable 222 # itself. This makes retries infeasible even for services that are 223 # aware of the issue. Failure to connect can affect not only new client 224 # processes, but also new RemoteStore instances in existing processes, 225 # as well as existing RemoteStore instances that have not saturated 226 # their connection pool. 227 # 228 # Also note that `stopIfChanged = true` does not kill existing 229 # connection handling daemons, as one might wish to happen before a 230 # breaking Nix upgrade (which is rare). The daemon forks that handle 231 # the individual connections split off into their own sessions, causing 232 # them not to be stopped by systemd. 233 # If a Nix upgrade does require all existing daemon processes to stop, 234 # nix-daemon must do so on its own accord, and only when the new version 235 # starts and detects that Nix's persistent state needs an upgrade. 236 stopIfChanged = false; 237 238 }; 239 240 # Set up the environment variables for running Nix. 241 environment.sessionVariables = cfg.envVars; 242 243 nix.nrBuildUsers = mkDefault ( 244 if cfg.settings.auto-allocate-uids or false then 0 245 else max 32 (if cfg.settings.max-jobs == "auto" then 0 else cfg.settings.max-jobs) 246 ); 247 248 users.users = nixbldUsers; 249 250 services.displayManager.hiddenUsers = attrNames nixbldUsers; 251 252 # Legacy configuration conversion. 253 nix.settings = mkMerge [ 254 (mkIf (isNixAtLeast "2.3pre") { sandbox-fallback = false; }) 255 ]; 256 257 }; 258 259}