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
12let
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
126in
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}