at 18.03-beta 17 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.nix; 8 9 nix = cfg.package.out; 10 11 isNix20 = versionAtLeast (getVersion nix) "2.0pre"; 12 13 makeNixBuildUser = nr: 14 { name = "nixbld${toString nr}"; 15 description = "Nix build user ${toString nr}"; 16 17 /* For consistency with the setgid(2), setuid(2), and setgroups(2) 18 calls in `libstore/build.cc', don't add any supplementary group 19 here except "nixbld". */ 20 uid = builtins.add config.ids.uids.nixbld nr; 21 group = "nixbld"; 22 extraGroups = [ "nixbld" ]; 23 }; 24 25 nixbldUsers = map makeNixBuildUser (range 1 cfg.nrBuildUsers); 26 27 nixConf = 28 let 29 # In Nix < 2.0, If we're using sandbox for builds, then provide 30 # /bin/sh in the sandbox as a bind-mount to bash. This means we 31 # also need to include the entire closure of bash. Nix >= 2.0 32 # provides a /bin/sh by default. 33 sh = pkgs.stdenv.shell; 34 binshDeps = pkgs.writeReferencesToFile sh; 35 in 36 pkgs.runCommand "nix.conf" { extraOptions = cfg.extraOptions; } '' 37 ${optionalString (!isNix20) '' 38 extraPaths=$(for i in $(cat ${binshDeps}); do if test -d $i; then echo $i; fi; done) 39 ''} 40 cat > $out <<END 41 # WARNING: this file is generated from the nix.* options in 42 # your NixOS configuration, typically 43 # /etc/nixos/configuration.nix. Do not edit it! 44 build-users-group = nixbld 45 ${if isNix20 then "max-jobs" else "build-max-jobs"} = ${toString (cfg.maxJobs)} 46 ${if isNix20 then "cores" else "build-cores"} = ${toString (cfg.buildCores)} 47 ${if isNix20 then "sandbox" else "build-use-sandbox"} = ${if (builtins.isBool cfg.useSandbox) then boolToString cfg.useSandbox else cfg.useSandbox} 48 ${if isNix20 then "extra-sandbox-paths" else "build-sandbox-paths"} = ${toString cfg.sandboxPaths} ${optionalString (!isNix20) "/bin/sh=${sh} $(echo $extraPaths)"} 49 ${if isNix20 then "substituters" else "binary-caches"} = ${toString cfg.binaryCaches} 50 ${if isNix20 then "trusted-substituters" else "trusted-binary-caches"} = ${toString cfg.trustedBinaryCaches} 51 ${if isNix20 then "trusted-public-keys" else "binary-cache-public-keys"} = ${toString cfg.binaryCachePublicKeys} 52 auto-optimise-store = ${boolToString cfg.autoOptimiseStore} 53 ${if isNix20 then '' 54 require-sigs = ${if cfg.requireSignedBinaryCaches then "true" else "false"} 55 '' else '' 56 signed-binary-caches = ${if cfg.requireSignedBinaryCaches then "*" else ""} 57 ''} 58 trusted-users = ${toString cfg.trustedUsers} 59 allowed-users = ${toString cfg.allowedUsers} 60 ${optionalString (isNix20 && !cfg.distributedBuilds) '' 61 builders = 62 ''} 63 $extraOptions 64 END 65 ''; 66 67in 68 69{ 70 71 ###### interface 72 73 options = { 74 75 nix = { 76 77 package = mkOption { 78 type = types.package; 79 default = pkgs.nix; 80 defaultText = "pkgs.nix"; 81 description = '' 82 This option specifies the Nix package instance to use throughout the system. 83 ''; 84 }; 85 86 maxJobs = mkOption { 87 type = types.int; 88 default = 1; 89 example = 64; 90 description = '' 91 This option defines the maximum number of jobs that Nix will try 92 to build in parallel. The default is 1. You should generally 93 set it to the total number of logical cores in your system (e.g., 16 94 for two CPUs with 4 cores each and hyper-threading). 95 ''; 96 }; 97 98 autoOptimiseStore = mkOption { 99 type = types.bool; 100 default = false; 101 example = true; 102 description = '' 103 If set to true, Nix automatically detects files in the store that have 104 identical contents, and replaces them with hard links to a single copy. 105 This saves disk space. If set to false (the default), you can still run 106 nix-store --optimise to get rid of duplicate files. 107 ''; 108 }; 109 110 buildCores = mkOption { 111 type = types.int; 112 default = 1; 113 example = 64; 114 description = '' 115 This option defines the maximum number of concurrent tasks during 116 one build. It affects, e.g., -j option for make. The default is 1. 117 The special value 0 means that the builder should use all 118 available CPU cores in the system. Some builds may become 119 non-deterministic with this option; use with care! Packages will 120 only be affected if enableParallelBuilding is set for them. 121 ''; 122 }; 123 124 useSandbox = mkOption { 125 type = types.either types.bool (types.enum ["relaxed"]); 126 default = false; 127 description = " 128 If set, Nix will perform builds in a sandboxed environment that it 129 will set up automatically for each build. This prevents 130 impurities in builds by disallowing access to dependencies 131 outside of the Nix store. This isn't enabled by default for 132 performance. It doesn't affect derivation hashes, so changing 133 this option will not trigger a rebuild of packages. 134 "; 135 }; 136 137 sandboxPaths = mkOption { 138 type = types.listOf types.str; 139 default = []; 140 example = [ "/dev" "/proc" ]; 141 description = 142 '' 143 Directories from the host filesystem to be included 144 in the sandbox. 145 ''; 146 }; 147 148 extraOptions = mkOption { 149 type = types.lines; 150 default = ""; 151 example = '' 152 gc-keep-outputs = true 153 gc-keep-derivations = true 154 ''; 155 description = "Additional text appended to <filename>nix.conf</filename>."; 156 }; 157 158 distributedBuilds = mkOption { 159 type = types.bool; 160 default = false; 161 description = '' 162 Whether to distribute builds to the machines listed in 163 <option>nix.buildMachines</option>. 164 ''; 165 }; 166 167 daemonNiceLevel = mkOption { 168 type = types.int; 169 default = 0; 170 description = '' 171 Nix daemon process priority. This priority propagates to build processes. 172 0 is the default Unix process priority, 19 is the lowest. 173 ''; 174 }; 175 176 daemonIONiceLevel = mkOption { 177 type = types.int; 178 default = 0; 179 description = '' 180 Nix daemon process I/O priority. This priority propagates to build processes. 181 0 is the default Unix process I/O priority, 7 is the lowest. 182 ''; 183 }; 184 185 buildMachines = mkOption { 186 type = types.listOf types.attrs; 187 default = []; 188 example = literalExample '' 189 [ { hostName = "voila.labs.cs.uu.nl"; 190 sshUser = "nix"; 191 sshKey = "/root/.ssh/id_buildfarm"; 192 system = "powerpc-darwin"; 193 maxJobs = 1; 194 } 195 { hostName = "linux64.example.org"; 196 sshUser = "buildfarm"; 197 sshKey = "/root/.ssh/id_buildfarm"; 198 system = "x86_64-linux"; 199 maxJobs = 2; 200 speedFactor = 2; 201 supportedFeatures = [ "kvm" ]; 202 mandatoryFeatures = [ "perf" ]; 203 } 204 ] 205 ''; 206 description = '' 207 This option lists the machines to be used if distributed 208 builds are enabled (see 209 <option>nix.distributedBuilds</option>). Nix will perform 210 derivations on those machines via SSH by copying the inputs 211 to the Nix store on the remote machine, starting the build, 212 then copying the output back to the local Nix store. Each 213 element of the list should be an attribute set containing 214 the machine's host name (<varname>hostname</varname>), the 215 user name to be used for the SSH connection 216 (<varname>sshUser</varname>), the Nix system type 217 (<varname>system</varname>, e.g., 218 <literal>"i686-linux"</literal>), the maximum number of 219 jobs to be run in parallel on that machine 220 (<varname>maxJobs</varname>), the path to the SSH private 221 key to be used to connect (<varname>sshKey</varname>), a 222 list of supported features of the machine 223 (<varname>supportedFeatures</varname>) and a list of 224 mandatory features of the machine 225 (<varname>mandatoryFeatures</varname>). The SSH private key 226 should not have a passphrase, and the corresponding public 227 key should be added to 228 <filename>~<replaceable>sshUser</replaceable>/authorized_keys</filename> 229 on the remote machine. 230 ''; 231 }; 232 233 # Environment variables for running Nix. 234 envVars = mkOption { 235 type = types.attrs; 236 internal = true; 237 default = {}; 238 description = "Environment variables used by Nix."; 239 }; 240 241 nrBuildUsers = mkOption { 242 type = types.int; 243 description = '' 244 Number of <literal>nixbld</literal> user accounts created to 245 perform secure concurrent builds. If you receive an error 246 message saying that all build users are currently in use, 247 you should increase this value. 248 ''; 249 }; 250 251 readOnlyStore = mkOption { 252 type = types.bool; 253 default = true; 254 description = '' 255 If set, NixOS will enforce the immutability of the Nix store 256 by making <filename>/nix/store</filename> a read-only bind 257 mount. Nix will automatically make the store writable when 258 needed. 259 ''; 260 }; 261 262 binaryCaches = mkOption { 263 type = types.listOf types.str; 264 default = [ https://cache.nixos.org/ ]; 265 description = '' 266 List of binary cache URLs used to obtain pre-built binaries 267 of Nix packages. 268 ''; 269 }; 270 271 trustedBinaryCaches = mkOption { 272 type = types.listOf types.str; 273 default = [ ]; 274 example = [ http://hydra.nixos.org/ ]; 275 description = '' 276 List of binary cache URLs that non-root users can use (in 277 addition to those specified using 278 <option>nix.binaryCaches</option>) by passing 279 <literal>--option binary-caches</literal> to Nix commands. 280 ''; 281 }; 282 283 requireSignedBinaryCaches = mkOption { 284 type = types.bool; 285 default = true; 286 description = '' 287 If enabled (the default), Nix will only download binaries from binary caches if 288 they are cryptographically signed with any of the keys listed in 289 <option>nix.binaryCachePublicKeys</option>. If disabled, signatures are neither 290 required nor checked, so it's strongly recommended that you use only 291 trustworthy caches and https to prevent man-in-the-middle attacks. 292 ''; 293 }; 294 295 binaryCachePublicKeys = mkOption { 296 type = types.listOf types.str; 297 example = [ "hydra.nixos.org-1:CNHJZBh9K4tP3EKF6FkkgeVYsS3ohTl+oS0Qa8bezVs=" ]; 298 description = '' 299 List of public keys used to sign binary caches. If 300 <option>nix.requireSignedBinaryCaches</option> is enabled, 301 then Nix will use a binary from a binary cache if and only 302 if it is signed by <emphasis>any</emphasis> of the keys 303 listed here. By default, only the key for 304 <uri>cache.nixos.org</uri> is included. 305 ''; 306 }; 307 308 trustedUsers = mkOption { 309 type = types.listOf types.str; 310 default = [ "root" ]; 311 example = [ "root" "alice" "@wheel" ]; 312 description = '' 313 A list of names of users that have additional rights when 314 connecting to the Nix daemon, such as the ability to specify 315 additional binary caches, or to import unsigned NARs. You 316 can also specify groups by prefixing them with 317 <literal>@</literal>; for instance, 318 <literal>@wheel</literal> means all users in the wheel 319 group. 320 ''; 321 }; 322 323 allowedUsers = mkOption { 324 type = types.listOf types.str; 325 default = [ "*" ]; 326 example = [ "@wheel" "@builders" "alice" "bob" ]; 327 description = '' 328 A list of names of users (separated by whitespace) that are 329 allowed to connect to the Nix daemon. As with 330 <option>nix.trustedUsers</option>, you can specify groups by 331 prefixing them with <literal>@</literal>. Also, you can 332 allow all users by specifying <literal>*</literal>. The 333 default is <literal>*</literal>. Note that trusted users are 334 always allowed to connect. 335 ''; 336 }; 337 338 nixPath = mkOption { 339 type = types.listOf types.str; 340 default = 341 [ "nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs" 342 "nixos-config=/etc/nixos/configuration.nix" 343 "/nix/var/nix/profiles/per-user/root/channels" 344 ]; 345 description = '' 346 The default Nix expression search path, used by the Nix 347 evaluator to look up paths enclosed in angle brackets 348 (e.g. <literal>&lt;nixpkgs&gt;</literal>). 349 ''; 350 }; 351 352 }; 353 354 }; 355 356 357 ###### implementation 358 359 config = { 360 361 nix.binaryCachePublicKeys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ]; 362 363 environment.etc."nix/nix.conf".source = nixConf; 364 365 # List of machines for distributed Nix builds in the format 366 # expected by build-remote.pl. 367 environment.etc."nix/machines" = 368 { enable = cfg.buildMachines != []; 369 text = 370 concatMapStrings (machine: 371 "${if machine ? sshUser then "${machine.sshUser}@" else ""}${machine.hostName} " 372 + machine.system or (concatStringsSep "," machine.systems) 373 + " ${machine.sshKey or "-"} ${toString machine.maxJobs or 1} " 374 + toString (machine.speedFactor or 1) 375 + " " 376 + concatStringsSep "," (machine.mandatoryFeatures or [] ++ machine.supportedFeatures or []) 377 + " " 378 + concatStringsSep "," machine.mandatoryFeatures or [] 379 + "\n" 380 ) cfg.buildMachines; 381 }; 382 383 systemd.packages = [ nix ]; 384 385 systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ]; 386 387 systemd.services.nix-daemon = 388 { path = [ nix pkgs.utillinux ] 389 ++ optionals cfg.distributedBuilds [ config.programs.ssh.package pkgs.gzip ] 390 ++ optionals (!isNix20) [ pkgs.openssl.bin ]; 391 392 environment = cfg.envVars 393 // { CURL_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt"; } 394 // config.networking.proxy.envVars; 395 396 unitConfig.RequiresMountsFor = "/nix/store"; 397 398 serviceConfig = 399 { Nice = cfg.daemonNiceLevel; 400 IOSchedulingPriority = cfg.daemonIONiceLevel; 401 LimitNOFILE = 4096; 402 }; 403 404 restartTriggers = [ nixConf ]; 405 }; 406 407 nix.envVars = 408 optionalAttrs (!isNix20) { 409 NIX_CONF_DIR = "/etc/nix"; 410 411 # Enable the copy-from-other-stores substituter, which allows 412 # builds to be sped up by copying build results from remote 413 # Nix stores. To do this, mount the remote file system on a 414 # subdirectory of /run/nix/remote-stores. 415 NIX_OTHER_STORES = "/run/nix/remote-stores/*/nix"; 416 } 417 418 // optionalAttrs (cfg.distributedBuilds && !isNix20) { 419 NIX_BUILD_HOOK = "${nix}/libexec/nix/build-remote.pl"; 420 }; 421 422 # Set up the environment variables for running Nix. 423 environment.sessionVariables = cfg.envVars // 424 { NIX_PATH = concatStringsSep ":" cfg.nixPath; 425 }; 426 427 environment.extraInit = optionalString (!isNix20) 428 '' 429 # Set up secure multi-user builds: non-root users build through the 430 # Nix daemon. 431 if [ "$USER" != root -o ! -w /nix/var/nix/db ]; then 432 export NIX_REMOTE=daemon 433 fi 434 ''; 435 436 nix.nrBuildUsers = mkDefault (lib.max 32 cfg.maxJobs); 437 438 users.extraUsers = nixbldUsers; 439 440 services.xserver.displayManager.hiddenUsers = map ({ name, ... }: name) nixbldUsers; 441 442 system.activationScripts.nix = stringAfter [ "etc" "users" ] 443 '' 444 # Nix initialisation. 445 mkdir -m 0755 -p \ 446 /nix/var/nix/gcroots \ 447 /nix/var/nix/temproots \ 448 /nix/var/nix/manifests \ 449 /nix/var/nix/userpool \ 450 /nix/var/nix/profiles \ 451 /nix/var/nix/db \ 452 /nix/var/log/nix/drvs \ 453 /nix/var/nix/channel-cache 454 mkdir -m 1777 -p \ 455 /nix/var/nix/gcroots/per-user \ 456 /nix/var/nix/profiles/per-user \ 457 /nix/var/nix/gcroots/tmp 458 ''; 459 460 }; 461 462}