1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.nix;
8
9 nixPackage = cfg.package.out;
10
11 isNixAtLeast = versionAtLeast (getVersion nixPackage);
12
13 makeNixBuildUser = nr: {
14 name = "nixbld${toString nr}";
15 value = {
16 description = "Nix build user ${toString nr}";
17
18 /*
19 For consistency with the setgid(2), setuid(2), and setgroups(2)
20 calls in `libstore/build.cc', don't add any supplementary group
21 here except "nixbld".
22 */
23 uid = builtins.add config.ids.uids.nixbld nr;
24 isSystemUser = true;
25 group = "nixbld";
26 extraGroups = [ "nixbld" ];
27 };
28 };
29
30 nixbldUsers = listToAttrs (map makeNixBuildUser (range 1 cfg.nrBuildUsers));
31
32 nixConf =
33 assert isNixAtLeast "2.2";
34 let
35
36 mkValueString = v:
37 if v == null then ""
38 else if isInt v then toString v
39 else if isBool v then boolToString v
40 else if isFloat v then floatToString v
41 else if isList v then toString v
42 else if isDerivation v then toString v
43 else if builtins.isPath v then toString v
44 else if isString v then v
45 else if isCoercibleToString v then toString v
46 else abort "The nix conf value: ${toPretty {} v} can not be encoded";
47
48 mkKeyValue = k: v: "${escape [ "=" ] k} = ${mkValueString v}";
49
50 mkKeyValuePairs = attrs: concatStringsSep "\n" (mapAttrsToList mkKeyValue attrs);
51
52 in
53 pkgs.writeTextFile {
54 name = "nix.conf";
55 text = ''
56 # WARNING: this file is generated from the nix.* options in
57 # your NixOS configuration, typically
58 # /etc/nixos/configuration.nix. Do not edit it!
59 ${mkKeyValuePairs cfg.settings}
60 ${cfg.extraOptions}
61 '';
62 checkPhase = lib.optionalString cfg.checkConfig (
63 if pkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform then ''
64 echo "Ignoring validation for cross-compilation"
65 ''
66 else ''
67 echo "Validating generated nix.conf"
68 ln -s $out ./nix.conf
69 set -e
70 set +o pipefail
71 NIX_CONF_DIR=$PWD \
72 ${cfg.package}/bin/nix show-config ${optionalString (isNixAtLeast "2.3pre") "--no-net"} \
73 ${optionalString (isNixAtLeast "2.4pre") "--option experimental-features nix-command"} \
74 |& sed -e 's/^warning:/error:/' \
75 | (! grep '${if cfg.checkAllErrors then "^error:" else "^error: unknown setting"}')
76 set -o pipefail
77 '');
78 };
79
80 legacyConfMappings = {
81 useSandbox = "sandbox";
82 buildCores = "cores";
83 maxJobs = "max-jobs";
84 sandboxPaths = "extra-sandbox-paths";
85 binaryCaches = "substituters";
86 trustedBinaryCaches = "trusted-substituters";
87 binaryCachePublicKeys = "trusted-public-keys";
88 autoOptimiseStore = "auto-optimise-store";
89 requireSignedBinaryCaches = "require-sigs";
90 trustedUsers = "trusted-users";
91 allowedUsers = "allowed-users";
92 systemFeatures = "system-features";
93 };
94
95 semanticConfType = with types;
96 let
97 confAtom = nullOr
98 (oneOf [
99 bool
100 int
101 float
102 str
103 path
104 package
105 ]) // {
106 description = "Nix config atom (null, bool, int, float, str, path or package)";
107 };
108 in
109 attrsOf (either confAtom (listOf confAtom));
110
111in
112
113{
114 imports = [
115 (mkRenamedOptionModuleWith { sinceRelease = 2003; from = [ "nix" "useChroot" ]; to = [ "nix" "useSandbox" ]; })
116 (mkRenamedOptionModuleWith { sinceRelease = 2003; from = [ "nix" "chrootDirs" ]; to = [ "nix" "sandboxPaths" ]; })
117 (mkRenamedOptionModuleWith { sinceRelease = 2205; from = [ "nix" "daemonIONiceLevel" ]; to = [ "nix" "daemonIOSchedPriority" ]; })
118 (mkRemovedOptionModule [ "nix" "daemonNiceLevel" ] "Consider nix.daemonCPUSchedPolicy instead.")
119 ] ++ mapAttrsToList (oldConf: newConf: mkRenamedOptionModuleWith { sinceRelease = 2205; from = [ "nix" oldConf ]; to = [ "nix" "settings" newConf ]; }) legacyConfMappings;
120
121 ###### interface
122
123 options = {
124
125 nix = {
126
127 enable = mkOption {
128 type = types.bool;
129 default = true;
130 description = lib.mdDoc ''
131 Whether to enable Nix.
132 Disabling Nix makes the system hard to modify and the Nix programs and configuration will not be made available by NixOS itself.
133 '';
134 };
135
136 package = mkOption {
137 type = types.package;
138 default = pkgs.nix;
139 defaultText = literalExpression "pkgs.nix";
140 description = lib.mdDoc ''
141 This option specifies the Nix package instance to use throughout the system.
142 '';
143 };
144
145 distributedBuilds = mkOption {
146 type = types.bool;
147 default = false;
148 description = lib.mdDoc ''
149 Whether to distribute builds to the machines listed in
150 {option}`nix.buildMachines`.
151 '';
152 };
153
154 daemonCPUSchedPolicy = mkOption {
155 type = types.enum [ "other" "batch" "idle" ];
156 default = "other";
157 example = "batch";
158 description = lib.mdDoc ''
159 Nix daemon process CPU scheduling policy. This policy propagates to
160 build processes. `other` is the default scheduling
161 policy for regular tasks. The `batch` policy is
162 similar to `other`, but optimised for
163 non-interactive tasks. `idle` is for extremely
164 low-priority tasks that should only be run when no other task
165 requires CPU time.
166
167 Please note that while using the `idle` policy may
168 greatly improve responsiveness of a system performing expensive
169 builds, it may also slow down and potentially starve crucial
170 configuration updates during load.
171
172 `idle` may therefore be a sensible policy for
173 systems that experience only intermittent phases of high CPU load,
174 such as desktop or portable computers used interactively. Other
175 systems should use the `other` or
176 `batch` policy instead.
177
178 For more fine-grained resource control, please refer to
179 {manpage}`systemd.resource-control(5)` and adjust
180 {option}`systemd.services.nix-daemon` directly.
181 '';
182 };
183
184 daemonIOSchedClass = mkOption {
185 type = types.enum [ "best-effort" "idle" ];
186 default = "best-effort";
187 example = "idle";
188 description = lib.mdDoc ''
189 Nix daemon process I/O scheduling class. This class propagates to
190 build processes. `best-effort` is the default
191 class for regular tasks. The `idle` class is for
192 extremely low-priority tasks that should only perform I/O when no
193 other task does.
194
195 Please note that while using the `idle` scheduling
196 class can improve responsiveness of a system performing expensive
197 builds, it might also slow down or starve crucial configuration
198 updates during load.
199
200 `idle` may therefore be a sensible class for
201 systems that experience only intermittent phases of high I/O load,
202 such as desktop or portable computers used interactively. Other
203 systems should use the `best-effort` class.
204 '';
205 };
206
207 daemonIOSchedPriority = mkOption {
208 type = types.int;
209 default = 4;
210 example = 1;
211 description = lib.mdDoc ''
212 Nix daemon process I/O scheduling priority. This priority propagates
213 to build processes. The supported priorities depend on the
214 scheduling policy: With idle, priorities are not used in scheduling
215 decisions. best-effort supports values in the range 0 (high) to 7
216 (low).
217 '';
218 };
219
220 buildMachines = mkOption {
221 type = types.listOf (types.submodule {
222 options = {
223 hostName = mkOption {
224 type = types.str;
225 example = "nixbuilder.example.org";
226 description = lib.mdDoc ''
227 The hostname of the build machine.
228 '';
229 };
230 protocol = mkOption {
231 type = types.enum [ null "ssh" "ssh-ng" ];
232 default = "ssh";
233 example = "ssh-ng";
234 description = lib.mdDoc ''
235 The protocol used for communicating with the build machine.
236 Use `ssh-ng` if your remote builder and your
237 local Nix version support that improved protocol.
238
239 Use `null` when trying to change the special localhost builder
240 without a protocol which is for example used by hydra.
241 '';
242 };
243 system = mkOption {
244 type = types.nullOr types.str;
245 default = null;
246 example = "x86_64-linux";
247 description = lib.mdDoc ''
248 The system type the build machine can execute derivations on.
249 Either this attribute or {var}`systems` must be
250 present, where {var}`system` takes precedence if
251 both are set.
252 '';
253 };
254 systems = mkOption {
255 type = types.listOf types.str;
256 default = [ ];
257 example = [ "x86_64-linux" "aarch64-linux" ];
258 description = lib.mdDoc ''
259 The system types the build machine can execute derivations on.
260 Either this attribute or {var}`system` must be
261 present, where {var}`system` takes precedence if
262 both are set.
263 '';
264 };
265 sshUser = mkOption {
266 type = types.nullOr types.str;
267 default = null;
268 example = "builder";
269 description = lib.mdDoc ''
270 The username to log in as on the remote host. This user must be
271 able to log in and run nix commands non-interactively. It must
272 also be privileged to build derivations, so must be included in
273 {option}`nix.settings.trusted-users`.
274 '';
275 };
276 sshKey = mkOption {
277 type = types.nullOr types.str;
278 default = null;
279 example = "/root/.ssh/id_buildhost_builduser";
280 description = lib.mdDoc ''
281 The path to the SSH private key with which to authenticate on
282 the build machine. The private key must not have a passphrase.
283 If null, the building user (root on NixOS machines) must have an
284 appropriate ssh configuration to log in non-interactively.
285
286 Note that for security reasons, this path must point to a file
287 in the local filesystem, *not* to the nix store.
288 '';
289 };
290 maxJobs = mkOption {
291 type = types.int;
292 default = 1;
293 description = lib.mdDoc ''
294 The number of concurrent jobs the build machine supports. The
295 build machine will enforce its own limits, but this allows hydra
296 to schedule better since there is no work-stealing between build
297 machines.
298 '';
299 };
300 speedFactor = mkOption {
301 type = types.int;
302 default = 1;
303 description = lib.mdDoc ''
304 The relative speed of this builder. This is an arbitrary integer
305 that indicates the speed of this builder, relative to other
306 builders. Higher is faster.
307 '';
308 };
309 mandatoryFeatures = mkOption {
310 type = types.listOf types.str;
311 default = [ ];
312 example = [ "big-parallel" ];
313 description = lib.mdDoc ''
314 A list of features mandatory for this builder. The builder will
315 be ignored for derivations that don't require all features in
316 this list. All mandatory features are automatically included in
317 {var}`supportedFeatures`.
318 '';
319 };
320 supportedFeatures = mkOption {
321 type = types.listOf types.str;
322 default = [ ];
323 example = [ "kvm" "big-parallel" ];
324 description = lib.mdDoc ''
325 A list of features supported by this builder. The builder will
326 be ignored for derivations that require features not in this
327 list.
328 '';
329 };
330 publicHostKey = mkOption {
331 type = types.nullOr types.str;
332 default = null;
333 description = lib.mdDoc ''
334 The (base64-encoded) public host key of this builder. The field
335 is calculated via {command}`base64 -w0 /etc/ssh/ssh_host_type_key.pub`.
336 If null, SSH will use its regular known-hosts file when connecting.
337 '';
338 };
339 };
340 });
341 default = [ ];
342 description = lib.mdDoc ''
343 This option lists the machines to be used if distributed builds are
344 enabled (see {option}`nix.distributedBuilds`).
345 Nix will perform derivations on those machines via SSH by copying the
346 inputs to the Nix store on the remote machine, starting the build,
347 then copying the output back to the local Nix store.
348 '';
349 };
350
351 # Environment variables for running Nix.
352 envVars = mkOption {
353 type = types.attrs;
354 internal = true;
355 default = { };
356 description = lib.mdDoc "Environment variables used by Nix.";
357 };
358
359 nrBuildUsers = mkOption {
360 type = types.int;
361 description = lib.mdDoc ''
362 Number of `nixbld` user accounts created to
363 perform secure concurrent builds. If you receive an error
364 message saying that “all build users are currently in use”,
365 you should increase this value.
366 '';
367 };
368
369 readOnlyStore = mkOption {
370 type = types.bool;
371 default = true;
372 description = lib.mdDoc ''
373 If set, NixOS will enforce the immutability of the Nix store
374 by making {file}`/nix/store` a read-only bind
375 mount. Nix will automatically make the store writable when
376 needed.
377 '';
378 };
379
380 nixPath = mkOption {
381 type = types.listOf types.str;
382 default = [
383 "nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos"
384 "nixos-config=/etc/nixos/configuration.nix"
385 "/nix/var/nix/profiles/per-user/root/channels"
386 ];
387 description = lib.mdDoc ''
388 The default Nix expression search path, used by the Nix
389 evaluator to look up paths enclosed in angle brackets
390 (e.g. `<nixpkgs>`).
391 '';
392 };
393
394 checkConfig = mkOption {
395 type = types.bool;
396 default = true;
397 description = lib.mdDoc ''
398 If enabled, checks that Nix can parse the generated nix.conf.
399 '';
400 };
401
402 checkAllErrors = mkOption {
403 type = types.bool;
404 default = true;
405 description = lib.mdDoc ''
406 If enabled, checks the nix.conf parsing for any kind of error. When disabled, checks only for unknown settings.
407 '';
408 };
409
410 registry = mkOption {
411 type = types.attrsOf (types.submodule (
412 let
413 referenceAttrs = with types; attrsOf (oneOf [
414 str
415 int
416 bool
417 package
418 ]);
419 in
420 { config, name, ... }:
421 {
422 options = {
423 from = mkOption {
424 type = referenceAttrs;
425 example = { type = "indirect"; id = "nixpkgs"; };
426 description = lib.mdDoc "The flake reference to be rewritten.";
427 };
428 to = mkOption {
429 type = referenceAttrs;
430 example = { type = "github"; owner = "my-org"; repo = "my-nixpkgs"; };
431 description = lib.mdDoc "The flake reference {option}`from` is rewritten to.";
432 };
433 flake = mkOption {
434 type = types.nullOr types.attrs;
435 default = null;
436 example = literalExpression "nixpkgs";
437 description = lib.mdDoc ''
438 The flake input {option}`from` is rewritten to.
439 '';
440 };
441 exact = mkOption {
442 type = types.bool;
443 default = true;
444 description = lib.mdDoc ''
445 Whether the {option}`from` reference needs to match exactly. If set,
446 a {option}`from` reference like `nixpkgs` does not
447 match with a reference like `nixpkgs/nixos-20.03`.
448 '';
449 };
450 };
451 config = {
452 from = mkDefault { type = "indirect"; id = name; };
453 to = mkIf (config.flake != null) (mkDefault (
454 {
455 type = "path";
456 path = config.flake.outPath;
457 } // filterAttrs
458 (n: _: n == "lastModified" || n == "rev" || n == "revCount" || n == "narHash")
459 config.flake
460 ));
461 };
462 }
463 ));
464 default = { };
465 description = lib.mdDoc ''
466 A system-wide flake registry.
467 '';
468 };
469
470 extraOptions = mkOption {
471 type = types.lines;
472 default = "";
473 example = ''
474 keep-outputs = true
475 keep-derivations = true
476 '';
477 description = lib.mdDoc "Additional text appended to {file}`nix.conf`.";
478 };
479
480 settings = mkOption {
481 type = types.submodule {
482 freeformType = semanticConfType;
483
484 options = {
485 max-jobs = mkOption {
486 type = types.either types.int (types.enum [ "auto" ]);
487 default = "auto";
488 example = 64;
489 description = lib.mdDoc ''
490 This option defines the maximum number of jobs that Nix will try to
491 build in parallel. The default is auto, which means it will use all
492 available logical cores. It is recommend to set it to the total
493 number of logical cores in your system (e.g., 16 for two CPUs with 4
494 cores each and hyper-threading).
495 '';
496 };
497
498 auto-optimise-store = mkOption {
499 type = types.bool;
500 default = false;
501 example = true;
502 description = lib.mdDoc ''
503 If set to true, Nix automatically detects files in the store that have
504 identical contents, and replaces them with hard links to a single copy.
505 This saves disk space. If set to false (the default), you can still run
506 nix-store --optimise to get rid of duplicate files.
507 '';
508 };
509
510 cores = mkOption {
511 type = types.int;
512 default = 0;
513 example = 64;
514 description = lib.mdDoc ''
515 This option defines the maximum number of concurrent tasks during
516 one build. It affects, e.g., -j option for make.
517 The special value 0 means that the builder should use all
518 available CPU cores in the system. Some builds may become
519 non-deterministic with this option; use with care! Packages will
520 only be affected if enableParallelBuilding is set for them.
521 '';
522 };
523
524 sandbox = mkOption {
525 type = types.either types.bool (types.enum [ "relaxed" ]);
526 default = true;
527 description = lib.mdDoc ''
528 If set, Nix will perform builds in a sandboxed environment that it
529 will set up automatically for each build. This prevents impurities
530 in builds by disallowing access to dependencies outside of the Nix
531 store by using network and mount namespaces in a chroot environment.
532 This is enabled by default even though it has a possible performance
533 impact due to the initial setup time of a sandbox for each build. It
534 doesn't affect derivation hashes, so changing this option will not
535 trigger a rebuild of packages.
536 '';
537 };
538
539 extra-sandbox-paths = mkOption {
540 type = types.listOf types.str;
541 default = [ ];
542 example = [ "/dev" "/proc" ];
543 description = lib.mdDoc ''
544 Directories from the host filesystem to be included
545 in the sandbox.
546 '';
547 };
548
549 substituters = mkOption {
550 type = types.listOf types.str;
551 description = lib.mdDoc ''
552 List of binary cache URLs used to obtain pre-built binaries
553 of Nix packages.
554
555 By default https://cache.nixos.org/ is added.
556 '';
557 };
558
559 trusted-substituters = mkOption {
560 type = types.listOf types.str;
561 default = [ ];
562 example = [ "https://hydra.nixos.org/" ];
563 description = lib.mdDoc ''
564 List of binary cache URLs that non-root users can use (in
565 addition to those specified using
566 {option}`nix.settings.substituters`) by passing
567 `--option binary-caches` to Nix commands.
568 '';
569 };
570
571 require-sigs = mkOption {
572 type = types.bool;
573 default = true;
574 description = lib.mdDoc ''
575 If enabled (the default), Nix will only download binaries from binary caches if
576 they are cryptographically signed with any of the keys listed in
577 {option}`nix.settings.trusted-public-keys`. If disabled, signatures are neither
578 required nor checked, so it's strongly recommended that you use only
579 trustworthy caches and https to prevent man-in-the-middle attacks.
580 '';
581 };
582
583 trusted-public-keys = mkOption {
584 type = types.listOf types.str;
585 example = [ "hydra.nixos.org-1:CNHJZBh9K4tP3EKF6FkkgeVYsS3ohTl+oS0Qa8bezVs=" ];
586 description = lib.mdDoc ''
587 List of public keys used to sign binary caches. If
588 {option}`nix.settings.trusted-public-keys` is enabled,
589 then Nix will use a binary from a binary cache if and only
590 if it is signed by *any* of the keys
591 listed here. By default, only the key for
592 `cache.nixos.org` is included.
593 '';
594 };
595
596 trusted-users = mkOption {
597 type = types.listOf types.str;
598 default = [ "root" ];
599 example = [ "root" "alice" "@wheel" ];
600 description = lib.mdDoc ''
601 A list of names of users that have additional rights when
602 connecting to the Nix daemon, such as the ability to specify
603 additional binary caches, or to import unsigned NARs. You
604 can also specify groups by prefixing them with
605 `@`; for instance,
606 `@wheel` means all users in the wheel
607 group.
608 '';
609 };
610
611 system-features = mkOption {
612 type = types.listOf types.str;
613 example = [ "kvm" "big-parallel" "gccarch-skylake" ];
614 description = lib.mdDoc ''
615 The set of features supported by the machine. Derivations
616 can express dependencies on system features through the
617 `requiredSystemFeatures` attribute.
618
619 By default, pseudo-features `nixos-test`, `benchmark`,
620 and `big-parallel` used in Nixpkgs are set, `kvm`
621 is also included in it is avaliable.
622 '';
623 };
624
625 allowed-users = mkOption {
626 type = types.listOf types.str;
627 default = [ "*" ];
628 example = [ "@wheel" "@builders" "alice" "bob" ];
629 description = lib.mdDoc ''
630 A list of names of users (separated by whitespace) that are
631 allowed to connect to the Nix daemon. As with
632 {option}`nix.settings.trusted-users`, you can specify groups by
633 prefixing them with `@`. Also, you can
634 allow all users by specifying `*`. The
635 default is `*`. Note that trusted users are
636 always allowed to connect.
637 '';
638 };
639 };
640 };
641 default = { };
642 example = literalExpression ''
643 {
644 use-sandbox = true;
645 show-trace = true;
646
647 system-features = [ "big-parallel" "kvm" "recursive-nix" ];
648 sandbox-paths = { "/bin/sh" = "''${pkgs.busybox-sandbox-shell.out}/bin/busybox"; };
649 }
650 '';
651 description = lib.mdDoc ''
652 Configuration for Nix, see
653 <https://nixos.org/manual/nix/stable/#sec-conf-file> or
654 {manpage}`nix.conf(5)` for avalaible options.
655 The value declared here will be translated directly to the key-value pairs Nix expects.
656
657 You can use {command}`nix-instantiate --eval --strict '<nixpkgs/nixos>' -A config.nix.settings`
658 to view the current value. By default it is empty.
659
660 Nix configurations defined under {option}`nix.*` will be translated and applied to this
661 option. In addition, configuration specified in {option}`nix.extraOptions` which will be appended
662 verbatim to the resulting config file.
663 '';
664 };
665 };
666 };
667
668
669 ###### implementation
670
671 config = mkIf cfg.enable {
672 environment.systemPackages =
673 [
674 nixPackage
675 pkgs.nix-info
676 ]
677 ++ optional (config.programs.bash.enableCompletion) pkgs.nix-bash-completions;
678
679 environment.etc."nix/nix.conf".source = nixConf;
680
681 environment.etc."nix/registry.json".text = builtins.toJSON {
682 version = 2;
683 flakes = mapAttrsToList (n: v: { inherit (v) from to exact; }) cfg.registry;
684 };
685
686 # List of machines for distributed Nix builds in the format
687 # expected by build-remote.pl.
688 environment.etc."nix/machines" = mkIf (cfg.buildMachines != [ ]) {
689 text =
690 concatMapStrings
691 (machine:
692 (concatStringsSep " " ([
693 "${optionalString (machine.protocol != null) "${machine.protocol}://"}${optionalString (machine.sshUser != null) "${machine.sshUser}@"}${machine.hostName}"
694 (if machine.system != null then machine.system else if machine.systems != [ ] then concatStringsSep "," machine.systems else "-")
695 (if machine.sshKey != null then machine.sshKey else "-")
696 (toString machine.maxJobs)
697 (toString machine.speedFactor)
698 (let res = (machine.supportedFeatures ++ machine.mandatoryFeatures);
699 in if (res == []) then "-" else (concatStringsSep "," res))
700 (let res = machine.mandatoryFeatures;
701 in if (res == []) then "-" else (concatStringsSep "," machine.mandatoryFeatures))
702 ]
703 ++ optional (isNixAtLeast "2.4pre") (if machine.publicHostKey != null then machine.publicHostKey else "-")))
704 + "\n"
705 )
706 cfg.buildMachines;
707 };
708
709 assertions =
710 let badMachine = m: m.system == null && m.systems == [ ];
711 in
712 [
713 {
714 assertion = !(any badMachine cfg.buildMachines);
715 message = ''
716 At least one system type (via <varname>system</varname> or
717 <varname>systems</varname>) must be set for every build machine.
718 Invalid machine specifications:
719 '' + " " +
720 (concatStringsSep "\n "
721 (map (m: m.hostName)
722 (filter (badMachine) cfg.buildMachines)));
723 }
724 ];
725
726 systemd.packages = [ nixPackage ];
727
728 # Will only work once https://github.com/NixOS/nix/pull/6285 is merged
729 # systemd.tmpfiles.packages = [ nixPackage ];
730
731 # Can be dropped for Nix > https://github.com/NixOS/nix/pull/6285
732 systemd.tmpfiles.rules = [
733 "d /nix/var/nix/daemon-socket 0755 root root - -"
734 ];
735
736 systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ];
737
738 systemd.services.nix-daemon =
739 {
740 path = [ nixPackage pkgs.util-linux config.programs.ssh.package ]
741 ++ optionals cfg.distributedBuilds [ pkgs.gzip ];
742
743 environment = cfg.envVars
744 // { CURL_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt"; }
745 // config.networking.proxy.envVars;
746
747 unitConfig.RequiresMountsFor = "/nix/store";
748
749 serviceConfig =
750 {
751 CPUSchedulingPolicy = cfg.daemonCPUSchedPolicy;
752 IOSchedulingClass = cfg.daemonIOSchedClass;
753 IOSchedulingPriority = cfg.daemonIOSchedPriority;
754 LimitNOFILE = 1048576;
755 };
756
757 restartTriggers = [ nixConf ];
758
759 # `stopIfChanged = false` changes to switch behavior
760 # from stop -> update units -> start
761 # to update units -> restart
762 #
763 # The `stopIfChanged` setting therefore controls a trade-off between a
764 # more predictable lifecycle, which runs the correct "version" of
765 # the `ExecStop` line, and on the other hand the availability of
766 # sockets during the switch, as the effectiveness of the stop operation
767 # depends on the socket being stopped as well.
768 #
769 # As `nix-daemon.service` does not make use of `ExecStop`, we prefer
770 # to keep the socket up and available. This is important for machines
771 # that run Nix-based services, such as automated build, test, and deploy
772 # services, that expect the daemon socket to be available at all times.
773 #
774 # Notably, the Nix client does not retry on failure to connect to the
775 # daemon socket, and the in-process RemoteStore instance will disable
776 # itself. This makes retries infeasible even for services that are
777 # aware of the issue. Failure to connect can affect not only new client
778 # processes, but also new RemoteStore instances in existing processes,
779 # as well as existing RemoteStore instances that have not saturated
780 # their connection pool.
781 #
782 # Also note that `stopIfChanged = true` does not kill existing
783 # connection handling daemons, as one might wish to happen before a
784 # breaking Nix upgrade (which is rare). The daemon forks that handle
785 # the individual connections split off into their own sessions, causing
786 # them not to be stopped by systemd.
787 # If a Nix upgrade does require all existing daemon processes to stop,
788 # nix-daemon must do so on its own accord, and only when the new version
789 # starts and detects that Nix's persistent state needs an upgrade.
790 stopIfChanged = false;
791
792 };
793
794 # Set up the environment variables for running Nix.
795 environment.sessionVariables = cfg.envVars // { NIX_PATH = cfg.nixPath; };
796
797 environment.extraInit =
798 ''
799 if [ -e "$HOME/.nix-defexpr/channels" ]; then
800 export NIX_PATH="$HOME/.nix-defexpr/channels''${NIX_PATH:+:$NIX_PATH}"
801 fi
802 '';
803
804 nix.nrBuildUsers = mkDefault (max 32 (if cfg.settings.max-jobs == "auto" then 0 else cfg.settings.max-jobs));
805
806 users.users = nixbldUsers;
807
808 services.xserver.displayManager.hiddenUsers = attrNames nixbldUsers;
809
810 system.activationScripts.nix = stringAfter [ "etc" "users" ]
811 ''
812 install -m 0755 -d /nix/var/nix/{gcroots,profiles}/per-user
813
814 # Subscribe the root user to the NixOS channel by default.
815 if [ ! -e "/root/.nix-channels" ]; then
816 echo "${config.system.defaultChannel} nixos" > "/root/.nix-channels"
817 fi
818 '';
819
820 # Legacy configuration conversion.
821 nix.settings = mkMerge [
822 {
823 trusted-public-keys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ];
824 substituters = mkAfter [ "https://cache.nixos.org/" ];
825
826 system-features = mkDefault (
827 [ "nixos-test" "benchmark" "big-parallel" "kvm" ] ++
828 optionals (pkgs.hostPlatform ? gcc.arch) (
829 # a builder can run code for `gcc.arch` and inferior architectures
830 [ "gccarch-${pkgs.hostPlatform.gcc.arch}" ] ++
831 map (x: "gccarch-${x}") systems.architectures.inferiors.${pkgs.hostPlatform.gcc.arch}
832 )
833 );
834 }
835
836 (mkIf (!cfg.distributedBuilds) { builders = null; })
837
838 (mkIf (isNixAtLeast "2.3pre") { sandbox-fallback = false; })
839 ];
840
841 };
842
843}