diff --git a/default.nix b/default.nix index 4f8afc17..44d9f11a 100644 --- a/default.nix +++ b/default.nix @@ -20,6 +20,7 @@ let packages ./modules/alias.nix ./modules/system + ./modules/system/activation-checks.nix ./modules/system/activation-scripts.nix ./modules/system/defaults-write.nix ./modules/system/defaults/NSGlobalDomain.nix diff --git a/modules/nix/default.nix b/modules/nix/default.nix index 070e79f9..107d4abb 100644 --- a/modules/nix/default.nix +++ b/modules/nix/default.nix @@ -3,9 +3,7 @@ with lib; let - cfg = config.nix; - daemon = config.services.nix-daemon; buildHook = if versionAtLeast (cfg.package.version or "") "1.12pre" then "build-remote" else "build-remote.pl"; @@ -23,7 +21,7 @@ let # WARNING: this file is generated from the nix.* options in # your NixOS configuration, typically # /etc/nixos/configuration.nix. Do not edit it! - ${optionalString daemon.enable '' + ${optionalString config.services.nix-daemon.enable '' build-users-group = nixbld ''} build-max-jobs = ${toString cfg.maxJobs} @@ -43,267 +41,260 @@ let $extraOptions END ''; - in { options = { - - nix = { - - package = mkOption { - type = types.path; - default = "/nix/var/nix/profiles/default"; - example = "pkgs.nix"; - description = '' - This option specifies the package or profile that contains the version of Nix to use throughout the system. - ''; - }; - - maxJobs = mkOption { - type = types.int; - default = 1; - example = 64; - description = '' - This option defines the maximum number of jobs that Nix will try - to build in parallel. The default is 1. You should generally - set it to the total number of logical cores in your system (e.g., 16 - for two CPUs with 4 cores each and hyper-threading). - ''; - }; - - buildCores = mkOption { - type = types.int; - default = 1; - example = 64; - description = '' - This option defines the maximum number of concurrent tasks during - one build. It affects, e.g., -j option for make. The default is 1. - The special value 0 means that the builder should use all - available CPU cores in the system. Some builds may become - non-deterministic with this option; use with care! Packages will - only be affected if enableParallelBuilding is set for them. - ''; - }; - - useSandbox = mkOption { - type = types.either types.bool (types.enum ["relaxed"]); - default = false; - description = " - If set, Nix will perform builds in a sandboxed environment that it - will set up automatically for each build. This prevents - impurities in builds by disallowing access to dependencies - outside of the Nix store. - "; - }; - - sandboxPaths = mkOption { - type = types.listOf types.str; - default = []; - example = [ "/dev" "/proc" ]; - description = - '' - Directories from the host filesystem to be included - in the sandbox. - ''; - }; - - extraOptions = mkOption { - type = types.lines; - default = ""; - example = '' - gc-keep-outputs = true - gc-keep-derivations = true - ''; - description = "Additional text appended to nix.conf."; - }; - - distributedBuilds = mkOption { - type = types.bool; - default = false; - description = '' - Whether to distribute builds to the machines listed in - . - ''; - }; - - daemonNiceLevel = mkOption { - type = types.int; - default = 0; - description = '' - Nix daemon process priority. This priority propagates to build processes. - 0 is the default Unix process priority, 19 is the lowest. - ''; - }; - - daemonIONice = mkOption { - type = types.bool; - default = false; - description = '' - Whether the Nix daemon process should considered to be low priority when - doing file system I/O. - ''; - }; - - buildMachines = mkOption { - type = types.listOf types.attrs; - default = []; - example = [ - { hostName = "voila.labs.cs.uu.nl"; - sshUser = "nix"; - sshKey = "/root/.ssh/id_buildfarm"; - system = "powerpc-darwin"; - maxJobs = 1; - } - { hostName = "linux64.example.org"; - sshUser = "buildfarm"; - sshKey = "/root/.ssh/id_buildfarm"; - system = "x86_64-linux"; - maxJobs = 2; - supportedFeatures = [ "kvm" ]; - mandatoryFeatures = [ "perf" ]; - } - ]; - description = '' - This option lists the machines to be used if distributed - builds are enabled (see - ). Nix will perform - derivations on those machines via SSH by copying the inputs - to the Nix store on the remote machine, starting the build, - then copying the output back to the local Nix store. Each - element of the list should be an attribute set containing - the machine's host name (hostname), the - user name to be used for the SSH connection - (sshUser), the Nix system type - (system, e.g., - "i686-linux"), the maximum number of - jobs to be run in parallel on that machine - (maxJobs), the path to the SSH private - key to be used to connect (sshKey), a - list of supported features of the machine - (supportedFeatures) and a list of - mandatory features of the machine - (mandatoryFeatures). The SSH private key - should not have a passphrase, and the corresponding public - key should be added to - ~sshUser/authorized_keys - on the remote machine. - ''; - }; - - # Environment variables for running Nix. - envVars = mkOption { - type = types.attrs; - internal = true; - default = {}; - description = "Environment variables used by Nix."; - }; - - readOnlyStore = mkOption { - type = types.bool; - default = true; - description = '' - If set, NixOS will enforce the immutability of the Nix store - by making /nix/store a read-only bind - mount. Nix will automatically make the store writable when - needed. - ''; - }; - - binaryCaches = mkOption { - type = types.listOf types.str; - example = [ https://cache.example.org/ ]; - description = '' - List of binary cache URLs used to obtain pre-built binaries - of Nix packages. - ''; - }; - - trustedBinaryCaches = mkOption { - type = types.listOf types.str; - default = [ ]; - example = [ https://hydra.example.org/ ]; - description = '' - List of binary cache URLs that non-root users can use (in - addition to those specified using - ) by passing - --option binary-caches to Nix commands. - ''; - }; - - requireSignedBinaryCaches = mkOption { - type = types.bool; - default = true; - description = '' - If enabled (the default), Nix will only download binaries from binary caches if - they are cryptographically signed with any of the keys listed in - . If disabled, signatures are neither - required nor checked, so it's strongly recommended that you use only - trustworthy caches and https to prevent man-in-the-middle attacks. - ''; - }; - - binaryCachePublicKeys = mkOption { - type = types.listOf types.str; - example = [ "hydra.nixos.org-1:CNHJZBh9K4tP3EKF6FkkgeVYsS3ohTl+oS0Qa8bezVs=" ]; - description = '' - List of public keys used to sign binary caches. If - is enabled, - then Nix will use a binary from a binary cache if and only - if it is signed by any of the keys - listed here. By default, only the key for - cache.nixos.org is included. - ''; - }; - - trustedUsers = mkOption { - type = types.listOf types.str; - default = [ "root" ]; - example = [ "root" "alice" "@wheel" ]; - description = '' - A list of names of users that have additional rights when - connecting to the Nix daemon, such as the ability to specify - additional binary caches, or to import unsigned NARs. You - can also specify groups by prefixing them with - @; for instance, - @wheel means all users in the wheel - group. - ''; - }; - - allowedUsers = mkOption { - type = types.listOf types.str; - default = [ "*" ]; - example = [ "@wheel" "@builders" "alice" "bob" ]; - description = '' - A list of names of users (separated by whitespace) that are - allowed to connect to the Nix daemon. As with - , you can specify groups by - prefixing them with @. Also, you can - allow all users by specifying *. The - default is *. Note that trusted users are - always allowed to connect. - ''; - }; - - nixPath = mkOption { - type = types.listOf types.str; - default = - [ # Incldue default paths for and . - "darwin=$HOME/.nix-defexpr/darwin" - "darwin-config=$HOME/.nixpkgs/darwin-configuration.nix" - "$HOME/.nix-defexpr/channels" - "/nix/var/nix/profiles/per-user/root/channels" - ]; - description = '' - The default Nix expression search path, used by the Nix - evaluator to look up paths enclosed in angle brackets - (e.g. <nixpkgs>). - ''; - }; - + nix.package = mkOption { + type = types.path; + default = "/nix/var/nix/profiles/default"; + example = "pkgs.nix"; + description = '' + This option specifies the package or profile that contains the version of Nix to use throughout the system. + ''; }; + nix.maxJobs = mkOption { + type = types.int; + default = 1; + example = 64; + description = '' + This option defines the maximum number of jobs that Nix will try + to build in parallel. The default is 1. You should generally + set it to the total number of logical cores in your system (e.g., 16 + for two CPUs with 4 cores each and hyper-threading). + ''; + }; + + nix.buildCores = mkOption { + type = types.int; + default = 1; + example = 64; + description = '' + This option defines the maximum number of concurrent tasks during + one build. It affects, e.g., -j option for make. The default is 1. + The special value 0 means that the builder should use all + available CPU cores in the system. Some builds may become + non-deterministic with this option; use with care! Packages will + only be affected if enableParallelBuilding is set for them. + ''; + }; + + nix.useSandbox = mkOption { + type = types.either types.bool (types.enum ["relaxed"]); + default = false; + description = " + If set, Nix will perform builds in a sandboxed environment that it + will set up automatically for each build. This prevents + impurities in builds by disallowing access to dependencies + outside of the Nix store. + "; + }; + + nix.sandboxPaths = mkOption { + type = types.listOf types.str; + default = []; + example = [ "/dev" "/proc" ]; + description = + '' + Directories from the host filesystem to be included + in the sandbox. + ''; + }; + + nix.extraOptions = mkOption { + type = types.lines; + default = ""; + example = '' + gc-keep-outputs = true + gc-keep-derivations = true + ''; + description = "Additional text appended to nix.conf."; + }; + + nix.distributedBuilds = mkOption { + type = types.bool; + default = false; + description = '' + Whether to distribute builds to the machines listed in + . + ''; + }; + + nix.daemonNiceLevel = mkOption { + type = types.int; + default = 0; + description = '' + Nix daemon process priority. This priority propagates to build processes. + 0 is the default Unix process priority, 19 is the lowest. + ''; + }; + + nix.daemonIONice = mkOption { + type = types.bool; + default = false; + description = '' + Whether the Nix daemon process should considered to be low priority when + doing file system I/O. + ''; + }; + + nix.buildMachines = mkOption { + type = types.listOf types.attrs; + default = []; + example = [ + { hostName = "voila.labs.cs.uu.nl"; + sshUser = "nix"; + sshKey = "/root/.ssh/id_buildfarm"; + system = "powerpc-darwin"; + maxJobs = 1; + } + { hostName = "linux64.example.org"; + sshUser = "buildfarm"; + sshKey = "/root/.ssh/id_buildfarm"; + system = "x86_64-linux"; + maxJobs = 2; + supportedFeatures = [ "kvm" ]; + mandatoryFeatures = [ "perf" ]; + } + ]; + description = '' + This option lists the machines to be used if distributed + builds are enabled (see + ). Nix will perform + derivations on those machines via SSH by copying the inputs + to the Nix store on the remote machine, starting the build, + then copying the output back to the local Nix store. Each + element of the list should be an attribute set containing + the machine's host name (hostname), the + user name to be used for the SSH connection + (sshUser), the Nix system type + (system, e.g., + "i686-linux"), the maximum number of + jobs to be run in parallel on that machine + (maxJobs), the path to the SSH private + key to be used to connect (sshKey), a + list of supported features of the machine + (supportedFeatures) and a list of + mandatory features of the machine + (mandatoryFeatures). The SSH private key + should not have a passphrase, and the corresponding public + key should be added to + ~sshUser/authorized_keys + on the remote machine. + ''; + }; + + # Environment variables for running Nix. + nix.envVars = mkOption { + type = types.attrs; + internal = true; + default = {}; + description = "Environment variables used by Nix."; + }; + + nix.readOnlyStore = mkOption { + type = types.bool; + default = true; + description = '' + If set, NixOS will enforce the immutability of the Nix store + by making /nix/store a read-only bind + mount. Nix will automatically make the store writable when + needed. + ''; + }; + + nix.binaryCaches = mkOption { + type = types.listOf types.str; + example = [ https://cache.example.org/ ]; + description = '' + List of binary cache URLs used to obtain pre-built binaries + of Nix packages. + ''; + }; + + nix.trustedBinaryCaches = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ https://hydra.example.org/ ]; + description = '' + List of binary cache URLs that non-root users can use (in + addition to those specified using + ) by passing + --option binary-caches to Nix commands. + ''; + }; + + nix.requireSignedBinaryCaches = mkOption { + type = types.bool; + default = true; + description = '' + If enabled (the default), Nix will only download binaries from binary caches if + they are cryptographically signed with any of the keys listed in + . If disabled, signatures are neither + required nor checked, so it's strongly recommended that you use only + trustworthy caches and https to prevent man-in-the-middle attacks. + ''; + }; + + nix.binaryCachePublicKeys = mkOption { + type = types.listOf types.str; + example = [ "hydra.nixos.org-1:CNHJZBh9K4tP3EKF6FkkgeVYsS3ohTl+oS0Qa8bezVs=" ]; + description = '' + List of public keys used to sign binary caches. If + is enabled, + then Nix will use a binary from a binary cache if and only + if it is signed by any of the keys + listed here. By default, only the key for + cache.nixos.org is included. + ''; + }; + + nix.trustedUsers = mkOption { + type = types.listOf types.str; + default = [ "root" ]; + example = [ "root" "alice" "@wheel" ]; + description = '' + A list of names of users that have additional rights when + connecting to the Nix daemon, such as the ability to specify + additional binary caches, or to import unsigned NARs. You + can also specify groups by prefixing them with + @; for instance, + @wheel means all users in the wheel + group. + ''; + }; + + nix.allowedUsers = mkOption { + type = types.listOf types.str; + default = [ "*" ]; + example = [ "@wheel" "@builders" "alice" "bob" ]; + description = '' + A list of names of users (separated by whitespace) that are + allowed to connect to the Nix daemon. As with + , you can specify groups by + prefixing them with @. Also, you can + allow all users by specifying *. The + default is *. Note that trusted users are + always allowed to connect. + ''; + }; + + nix.nixPath = mkOption { + type = types.listOf types.str; + default = + [ # Incldue default paths for and . + "darwin=$HOME/.nix-defexpr/darwin" + "darwin-config=$HOME/.nixpkgs/darwin-configuration.nix" + "$HOME/.nix-defexpr/channels" + "/nix/var/nix/profiles/per-user/root/channels" + ]; + description = '' + The default Nix expression search path, used by the Nix + evaluator to look up paths enclosed in angle brackets + (e.g. <nixpkgs>). + ''; + }; }; config = { @@ -361,13 +352,5 @@ in fi ''; - system.activationScripts.nix-daemon.text = mkIf daemon.enable '' - buildUser=$(dscl . -read /Groups/nixbld 2>&1 | awk '/^GroupMembership: / {print $2}') || true - if [ -z $buildUser ]; then - echo "Using the nix-daemon requires build users, aborting activation" >&2 - exit 2 - fi - ''; - }; } diff --git a/modules/system/activation-checks.nix b/modules/system/activation-checks.nix new file mode 100644 index 00000000..3f07cb00 --- /dev/null +++ b/modules/system/activation-checks.nix @@ -0,0 +1,28 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + buildUsers = optionalString config.services.nix-daemon.enable '' + buildUser=$(dscl . -read /Groups/nixbld GroupMembership 2>&1 | awk '/^GroupMembership: / {print $2}') + if [ -z $buildUser ]; then + echo "Using the nix-daemon requires build users, aborting activation" >&2 + exit 2 + fi + ''; +in + +{ + options = { + }; + + config = { + + system.activationScripts.checks.text = '' + set +e + ${buildUsers} + set -e + ''; + + }; +} diff --git a/modules/system/activation-scripts.nix b/modules/system/activation-scripts.nix index aa97633c..48d27737 100644 --- a/modules/system/activation-scripts.nix +++ b/modules/system/activation-scripts.nix @@ -52,9 +52,7 @@ in ${cfg.activationScripts.extraActivation.text} - ${cfg.activationScripts.nix-daemon.text} ${cfg.activationScripts.nix.text} - ${cfg.activationScripts.accessibility.text} ${cfg.activationScripts.applications.text} ${cfg.activationScripts.etc.text} @@ -88,6 +86,8 @@ in # Ensure a consistent umask. umask 0022 + ${cfg.activationScripts.checks.text} + ${cfg.activationScripts.extraUserActivation.text} ${cfg.activationScripts.defaults.text}