1/*
2 Manages /etc/nix/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{
11 config,
12 lib,
13 pkgs,
14 ...
15}:
16
17let
18 inherit (lib)
19 concatStringsSep
20 boolToString
21 escape
22 filterAttrs
23 floatToString
24 getVersion
25 hasPrefix
26 isBool
27 isDerivation
28 isFloat
29 isInt
30 isList
31 isString
32 literalExpression
33 mapAttrsToList
34 mkAfter
35 mkIf
36 mkOption
37 mkRenamedOptionModuleWith
38 optionalString
39 optionals
40 strings
41 systems
42 toPretty
43 types
44 versionAtLeast
45 ;
46
47 cfg = config.nix;
48
49 nixPackage = cfg.package.out;
50
51 isNixAtLeast = versionAtLeast (getVersion nixPackage);
52
53 defaultSystemFeatures =
54 [
55 "nixos-test"
56 "benchmark"
57 "big-parallel"
58 "kvm"
59 ]
60 ++ optionals (pkgs.stdenv.hostPlatform ? gcc.arch) (
61 # a builder can run code for `gcc.arch` and inferior architectures
62 [ "gccarch-${pkgs.stdenv.hostPlatform.gcc.arch}" ]
63 ++ map (x: "gccarch-${x}") (
64 systems.architectures.inferiors.${pkgs.stdenv.hostPlatform.gcc.arch} or [ ]
65 )
66 );
67
68 legacyConfMappings = {
69 useSandbox = "sandbox";
70 buildCores = "cores";
71 maxJobs = "max-jobs";
72 sandboxPaths = "extra-sandbox-paths";
73 binaryCaches = "substituters";
74 trustedBinaryCaches = "trusted-substituters";
75 binaryCachePublicKeys = "trusted-public-keys";
76 autoOptimiseStore = "auto-optimise-store";
77 requireSignedBinaryCaches = "require-sigs";
78 trustedUsers = "trusted-users";
79 allowedUsers = "allowed-users";
80 systemFeatures = "system-features";
81 };
82
83 semanticConfType =
84 with types;
85 let
86 confAtom =
87 nullOr (oneOf [
88 bool
89 int
90 float
91 str
92 path
93 package
94 ])
95 // {
96 description = "Nix config atom (null, bool, int, float, str, path or package)";
97 };
98 in
99 attrsOf (either confAtom (listOf confAtom));
100
101 nixConf =
102 assert isNixAtLeast "2.2";
103 let
104
105 mkValueString =
106 v:
107 if v == null then
108 ""
109 else if isInt v then
110 toString v
111 else if isBool v then
112 boolToString v
113 else if isFloat v then
114 floatToString v
115 else if isList v then
116 toString v
117 else if isDerivation v then
118 toString v
119 else if builtins.isPath v then
120 toString v
121 else if isString v then
122 v
123 else if strings.isConvertibleWithToString v then
124 toString v
125 else
126 abort "The nix conf value: ${toPretty { } v} can not be encoded";
127
128 mkKeyValue = k: v: "${escape [ "=" ] k} = ${mkValueString v}";
129
130 mkKeyValuePairs = attrs: concatStringsSep "\n" (mapAttrsToList mkKeyValue attrs);
131
132 isExtra = key: hasPrefix "extra-" key;
133
134 in
135 pkgs.writeTextFile {
136 name = "nix.conf";
137 # workaround for https://github.com/NixOS/nix/issues/9487
138 # extra-* settings must come after their non-extra counterpart
139 text = ''
140 # WARNING: this file is generated from the nix.* options in
141 # your NixOS configuration, typically
142 # /etc/nixos/configuration.nix. Do not edit it!
143 ${mkKeyValuePairs (filterAttrs (key: value: !(isExtra key)) cfg.settings)}
144 ${mkKeyValuePairs (filterAttrs (key: value: isExtra key) cfg.settings)}
145 ${cfg.extraOptions}
146 '';
147 checkPhase = lib.optionalString cfg.checkConfig (
148 if pkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform then
149 ''
150 echo "Ignoring validation for cross-compilation"
151 ''
152 else
153 let
154 showCommand = if isNixAtLeast "2.20pre" then "config show" else "show-config";
155 in
156 ''
157 echo "Validating generated nix.conf"
158 ln -s $out ./nix.conf
159 set -e
160 set +o pipefail
161 NIX_CONF_DIR=$PWD \
162 ${cfg.package}/bin/nix ${showCommand} ${optionalString (isNixAtLeast "2.3pre") "--no-net"} \
163 ${optionalString (isNixAtLeast "2.4pre") "--option experimental-features nix-command"} \
164 |& sed -e 's/^warning:/error:/' \
165 | (! grep '${if cfg.checkAllErrors then "^error:" else "^error: unknown setting"}')
166 set -o pipefail
167 ''
168 );
169 };
170
171in
172{
173 imports =
174 [
175 (mkRenamedOptionModuleWith {
176 sinceRelease = 2003;
177 from = [
178 "nix"
179 "useChroot"
180 ];
181 to = [
182 "nix"
183 "useSandbox"
184 ];
185 })
186 (mkRenamedOptionModuleWith {
187 sinceRelease = 2003;
188 from = [
189 "nix"
190 "chrootDirs"
191 ];
192 to = [
193 "nix"
194 "sandboxPaths"
195 ];
196 })
197 ]
198 ++ mapAttrsToList (
199 oldConf: newConf:
200 mkRenamedOptionModuleWith {
201 sinceRelease = 2205;
202 from = [
203 "nix"
204 oldConf
205 ];
206 to = [
207 "nix"
208 "settings"
209 newConf
210 ];
211 }
212 ) legacyConfMappings;
213
214 options = {
215 nix = {
216 checkConfig = mkOption {
217 type = types.bool;
218 default = true;
219 description = ''
220 If enabled, checks that Nix can parse the generated nix.conf.
221 '';
222 };
223
224 checkAllErrors = mkOption {
225 type = types.bool;
226 default = true;
227 description = ''
228 If enabled, checks the nix.conf parsing for any kind of error. When disabled, checks only for unknown settings.
229 '';
230 };
231
232 extraOptions = mkOption {
233 type = types.lines;
234 default = "";
235 example = ''
236 keep-outputs = true
237 keep-derivations = true
238 '';
239 description = "Additional text appended to {file}`nix.conf`.";
240 };
241
242 settings = mkOption {
243 type = types.submodule {
244 freeformType = semanticConfType;
245
246 options = {
247 max-jobs = mkOption {
248 type = types.either types.int (types.enum [ "auto" ]);
249 default = "auto";
250 example = 64;
251 description = ''
252 This option defines the maximum number of jobs that Nix will try to
253 build in parallel. The default is auto, which means it will use all
254 available logical cores. It is recommend to set it to the total
255 number of logical cores in your system (e.g., 16 for two CPUs with 4
256 cores each and hyper-threading).
257 '';
258 };
259
260 auto-optimise-store = mkOption {
261 type = types.bool;
262 default = false;
263 example = true;
264 description = ''
265 If set to true, Nix automatically detects files in the store that have
266 identical contents, and replaces them with hard links to a single copy.
267 This saves disk space. If set to false (the default), you can still run
268 nix-store --optimise to get rid of duplicate files.
269 '';
270 };
271
272 cores = mkOption {
273 type = types.int;
274 default = 0;
275 example = 64;
276 description = ''
277 This option defines the maximum number of concurrent tasks during
278 one build. It affects, e.g., -j option for make.
279 The special value 0 means that the builder should use all
280 available CPU cores in the system. Some builds may become
281 non-deterministic with this option; use with care! Packages will
282 only be affected if enableParallelBuilding is set for them.
283 '';
284 };
285
286 sandbox = mkOption {
287 type = types.either types.bool (types.enum [ "relaxed" ]);
288 default = true;
289 description = ''
290 If set, Nix will perform builds in a sandboxed environment that it
291 will set up automatically for each build. This prevents impurities
292 in builds by disallowing access to dependencies outside of the Nix
293 store by using network and mount namespaces in a chroot environment.
294
295 This is enabled by default even though it has a possible performance
296 impact due to the initial setup time of a sandbox for each build. It
297 doesn't affect derivation hashes, so changing this option will not
298 trigger a rebuild of packages.
299
300 When set to "relaxed", this option permits derivations that set
301 `__noChroot = true;` to run outside of the sandboxed environment.
302 Exercise caution when using this mode of operation! It is intended to
303 be a quick hack when building with packages that are not easily setup
304 to be built reproducibly.
305 '';
306 };
307
308 extra-sandbox-paths = mkOption {
309 type = types.listOf types.str;
310 default = [ ];
311 example = [
312 "/dev"
313 "/proc"
314 ];
315 description = ''
316 Directories from the host filesystem to be included
317 in the sandbox.
318 '';
319 };
320
321 substituters = mkOption {
322 type = types.listOf types.str;
323 description = ''
324 List of binary cache URLs used to obtain pre-built binaries
325 of Nix packages.
326
327 By default https://cache.nixos.org/ is added.
328 '';
329 };
330
331 trusted-substituters = mkOption {
332 type = types.listOf types.str;
333 default = [ ];
334 example = [ "https://hydra.nixos.org/" ];
335 description = ''
336 List of binary cache URLs that non-root users can use (in
337 addition to those specified using
338 {option}`nix.settings.substituters`) by passing
339 `--option binary-caches` to Nix commands.
340 '';
341 };
342
343 require-sigs = mkOption {
344 type = types.bool;
345 default = true;
346 description = ''
347 If enabled (the default), Nix will only download binaries from binary caches if
348 they are cryptographically signed with any of the keys listed in
349 {option}`nix.settings.trusted-public-keys`. If disabled, signatures are neither
350 required nor checked, so it's strongly recommended that you use only
351 trustworthy caches and https to prevent man-in-the-middle attacks.
352 '';
353 };
354
355 trusted-public-keys = mkOption {
356 type = types.listOf types.str;
357 example = [ "hydra.nixos.org-1:CNHJZBh9K4tP3EKF6FkkgeVYsS3ohTl+oS0Qa8bezVs=" ];
358 description = ''
359 List of public keys used to sign binary caches. If
360 {option}`nix.settings.trusted-public-keys` is enabled,
361 then Nix will use a binary from a binary cache if and only
362 if it is signed by *any* of the keys
363 listed here. By default, only the key for
364 `cache.nixos.org` is included.
365 '';
366 };
367
368 trusted-users = mkOption {
369 type = types.listOf types.str;
370 example = [
371 "root"
372 "alice"
373 "@wheel"
374 ];
375 description = ''
376 A list of names of users that have additional rights when
377 connecting to the Nix daemon, such as the ability to specify
378 additional binary caches, or to import unsigned NARs. You
379 can also specify groups by prefixing them with
380 `@`; for instance,
381 `@wheel` means all users in the wheel
382 group.
383 '';
384 };
385
386 system-features = mkOption {
387 type = types.listOf types.str;
388 # We expose system-featuers here and in config below.
389 # This allows users to access the default value via `options.nix.settings.system-features`
390 default = defaultSystemFeatures;
391 defaultText = literalExpression ''[ "nixos-test" "benchmark" "big-parallel" "kvm" "gccarch-<arch>" ]'';
392 description = ''
393 The set of features supported by the machine. Derivations
394 can express dependencies on system features through the
395 `requiredSystemFeatures` attribute.
396 '';
397 };
398
399 allowed-users = mkOption {
400 type = types.listOf types.str;
401 default = [ "*" ];
402 example = [
403 "@wheel"
404 "@builders"
405 "alice"
406 "bob"
407 ];
408 description = ''
409 A list of names of users (separated by whitespace) that are
410 allowed to connect to the Nix daemon. As with
411 {option}`nix.settings.trusted-users`, you can specify groups by
412 prefixing them with `@`. Also, you can
413 allow all users by specifying `*`. The
414 default is `*`. Note that trusted users are
415 always allowed to connect.
416 '';
417 };
418 };
419 };
420 default = { };
421 example = literalExpression ''
422 {
423 use-sandbox = true;
424 show-trace = true;
425
426 sandbox-paths = [ "/bin/sh=''${pkgs.busybox-sandbox-shell.out}/bin/busybox" ];
427 }
428 '';
429 description = ''
430 Configuration for Nix, see
431 <https://nixos.org/manual/nix/stable/command-ref/conf-file.html> or
432 {manpage}`nix.conf(5)` for available options.
433 The value declared here will be translated directly to the key-value pairs Nix expects.
434
435 You can use {command}`nix-instantiate --eval --strict '<nixpkgs/nixos>' -A config.nix.settings`
436 to view the current value. By default it is empty.
437
438 Nix configurations defined under {option}`nix.*` will be translated and applied to this
439 option. In addition, configuration specified in {option}`nix.extraOptions` will be appended
440 verbatim to the resulting config file.
441 '';
442 };
443 };
444 };
445
446 config = mkIf cfg.enable {
447 environment.etc."nix/nix.conf".source = nixConf;
448 nix.settings = {
449 trusted-public-keys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ];
450 trusted-users = [ "root" ];
451 substituters = mkAfter [ "https://cache.nixos.org/" ];
452 system-features = defaultSystemFeatures;
453 };
454 };
455}