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