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