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