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