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