diff --git a/CHANGELOG b/CHANGELOG index ce1694034..74591effe 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,15 @@ +2025-01-29 +- There is now a `nix.enable` toggle to disable management of the Nix + installation. Nix installation management has been made more + opinionated as a consequence; nix-darwin now only supports managing a + multi‐user daemon installation of Nix, and unconditionally takes + ownership of the nix-daemon launchd daemon and the `_nixbld*` build + users when Nix installation management is enabled. + + If the new constraints do not work with your setup, you can disable + the `nix.enable` option to opt out of Nix installation management + entirely; see the option documentation for caveats. + 2025-01-18 - The default configuration path for all new installations is `/etc/nix-darwin`. This was already the undocumented diff --git a/README.md b/README.md index b0f095a1d..1a9900b18 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,19 @@ nix-darwin is built up around [Nixpkgs](https://github.com/NixOS/nixpkgs), quite ## Prerequisites -The only prerequisite is a Nix implementation, both Nix and Lix are supported. +The only prerequisite is a Nix implementation; both Nix and Lix are supported. As the official Nix installer does not include an automated uninstaller, and manual uninstallation on macOS is a complex process, we recommend using one of the following installers instead: -- The [Nix installer from Determinate Systems](https://github.com/DeterminateSystems/nix-installer?tab=readme-ov-file#determinate-nix-installer) is only recommended for use with flake-based setups. **Make sure you use it without the `--determinate` flag**. The `--determinate` flag installs the Determinate Nix distribution which does not work out of the box with nix-darwin. +* The [Nix installer from Determinate Systems](https://github.com/DeterminateSystems/nix-installer?tab=readme-ov-file#determinate-nix-installer) is only recommended for use with flake-based setups. + It can install one of two distributions of Nix: + + * By default, it will install vanilla upstream [Nix](https://nixos.org/) with flakes enabled. + + * When run with the `--determinate` flag, it will install the [Determinate](https://docs.determinate.systems/) distribution. + As Determinate manages the Nix installation itself, you will need to set `nix.enable = false;` in your configuration to disable nix-darwin’s own Nix management. + Some nix-darwin functionality that relies on managing the Nix installation, like the `nix.*` options to adjust Nix settings or configure a Linux builder, will be unavailable. + * The [Lix installer](https://lix.systems/install/#on-any-other-linuxmacos-system) supports both flake-based and channel-based setups. diff --git a/modules/examples/lnl.nix b/modules/examples/lnl.nix index 90142f653..8dff10cc5 100644 --- a/modules/examples/lnl.nix +++ b/modules/examples/lnl.nix @@ -319,7 +319,6 @@ # path = /etc/per-user/lnl/gitconfig # environment.etc."per-user/lnl/gitconfig".text = builtins.readFile "${inputs.dotfiles}/git/gitconfig"; - nix.configureBuildUsers = true; nix.nrBuildUsers = 32; system.stateVersion = 6; diff --git a/modules/nix/default.nix b/modules/nix/default.nix index 857c4be81..b201a692e 100644 --- a/modules/nix/default.nix +++ b/modules/nix/default.nix @@ -12,6 +12,8 @@ let isNixAtLeast = versionAtLeast (getVersion nixPackage); + configureBuildUsers = !(config.nix.settings.auto-allocate-uids or false); + makeNixBuildUser = nr: { name = "_nixbld${toString nr}"; value = { @@ -134,6 +136,26 @@ let namedPaths ++ searchPaths; }; + handleUnmanaged = managedConfig: mkMerge [ + (mkIf cfg.enable managedConfig) + (mkIf (!cfg.enable) { + system.activationScripts.nix-daemon.text = '' + # Restore unmanaged Nix daemon if present + unmanagedNixProfile=/nix/var/nix/profiles/default + if [[ + -e /run/current-system/Library/LaunchDaemons/org.nixos.nix-daemon.plist + && -e $unmanagedNixProfile/Library/LaunchDaemons/org.nixos.nix-daemon.plist + ]]; then + printf >&2 'restoring unmanaged Nix daemon...\n' + cp \ + "$unmanagedNixProfile/Library/LaunchDaemons/org.nixos.nix-daemon.plist" \ + /Library/LaunchDaemons + launchctl load -w /Library/LaunchDaemons/org.nixos.nix-daemon.plist + fi + ''; + }) + ]; + in { @@ -144,7 +166,6 @@ in in [ # Only ever in NixOS - (mkRemovedOptionModule [ "nix" "enable" ] "No `nix-darwin` equivalent to this NixOS option.") (mkRemovedOptionModule [ "nix" "daemonCPUSchedPolicy" ] (altOption "nix.daemonProcessType")) (mkRemovedOptionModule [ "nix" "daemonIOSchedClass" ] (altOption "nix.daemonProcessType")) (mkRemovedOptionModule [ "nix" "daemonIOSchedPriority" ] (altOption "nix.daemonIOLowPriority")) @@ -157,6 +178,14 @@ in (mkRenamedOptionModule [ "users" "nix" "nrBuildUsers" ] [ "nix" "nrBuildUsers" ]) (mkRenamedOptionModule [ "nix" "daemonIONice" ] [ "nix" "daemonIOLowPriority" ]) (mkRemovedOptionModule [ "nix" "daemonNiceLevel" ] (consider "nix.daemonProcessType")) + (mkRemovedOptionModule [ "nix" "useDaemon" ] '' + nix-darwin now only supports managing multi‐user daemon + installations of Nix. + '') + (mkRemovedOptionModule [ "nix" "configureBuildUsers" ] '' + nix-darwin now manages build users unconditionally when + `nix.enable` is on. + '') ] ++ mapAttrsToList (oldConf: newConf: mkRenamedOptionModule [ "nix" oldConf ] [ "nix" "settings" newConf ]) legacyConfMappings; ###### interface @@ -165,23 +194,39 @@ in nix = { - package = mkOption { - type = types.package; - default = pkgs.nix; - defaultText = literalExpression "pkgs.nix"; + enable = lib.mkOption { + type = lib.types.bool; + default = true; description = '' - This option specifies the Nix package instance to use throughout the system. + Whether to enable Nix. + + Disabling this will stop nix-darwin from managing the + installed version of Nix, the nix-daemon launchd daemon, and + the settings in {file}`/etc/nix/nix.conf`. + + This allows you to use nix-darwin without it taking over your + system installation of Nix. Some nix-darwin functionality + that relies on managing the Nix installation, like the + `nix.*` options to adjust Nix settings or configure a Linux + builder, will be unavailable. You will also have to upgrade + Nix yourself, as nix-darwin will no longer do so. + + ::: {.warning} + If you have already removed your global system installation + of Nix, this will break nix-darwin and you will have to + reinstall Nix to fix it. + ::: ''; }; - # Not in NixOS module - useDaemon = mkOption { - type = types.bool; - default = false; + package = mkOption { + type = types.package; + default = warnIf (!cfg.enable) + "nix.package: accessed when `nix.enable` is off; this is a bug" + pkgs.nix; + defaultText = literalExpression "pkgs.nix"; description = '' - If set, Nix will use the daemon to perform operations. - Use this instead of services.nix-daemon.enable if you don't want the - daemon service to be managed for you. + This option specifies the Nix package instance to use throughout the system. ''; }; @@ -358,15 +403,6 @@ in description = "Environment variables used by Nix."; }; - # Not in NixOS module - configureBuildUsers = mkOption { - type = types.bool; - default = false; - description = '' - Enable configuration for nixbld group and users. - ''; - }; - nrBuildUsers = mkOption { type = types.int; description = '' @@ -678,7 +714,7 @@ in ###### implementation - config = { + config = handleUnmanaged { environment.systemPackages = [ nixPackage @@ -759,7 +795,7 @@ in # Not in NixOS module { assertion = elem "nixbld" config.users.knownGroups -> elem "nixbld" createdGroups; message = "refusing to delete group nixbld in users.knownGroups, this would break nix"; } - { assertion = elem "_nixbld1" config.users.knownGroups -> elem "_nixbld1" createdUsers; message = "refusing to delete user _nixbld1 in users.knownUsers, this would break nix"; } + { assertion = elem "_nixbld1" config.users.knownUsers -> elem "_nixbld1" createdUsers; message = "refusing to delete user _nixbld1 in users.knownUsers, this would break nix"; } { assertion = config.users.groups ? "nixbld" -> config.users.groups.nixbld.members != []; message = "refusing to remove all members from nixbld group, this would break nix"; } { @@ -785,21 +821,11 @@ in # Set up the environment variables for running Nix. environment.variables = cfg.envVars // { NIX_PATH = cfg.nixPath; }; - environment.extraInit = mkMerge [ - (mkIf cfg.channel.enable '' - if [ -e "$HOME/.nix-defexpr/channels" ]; then - export NIX_PATH="$HOME/.nix-defexpr/channels''${NIX_PATH:+:$NIX_PATH}" - fi - '') - # Not in NixOS module - '' - # Set up secure multi-user builds: non-root users build through the - # Nix daemon. - if [ ! -w /nix/var/nix/db ]; then - export NIX_REMOTE=daemon - fi - '' - ]; + environment.extraInit = mkIf cfg.channel.enable '' + if [ -e "$HOME/.nix-defexpr/channels" ]; then + export NIX_PATH="$HOME/.nix-defexpr/channels''${NIX_PATH:+:$NIX_PATH}" + fi + ''; environment.extraSetup = mkIf (!cfg.channel.enable) '' rm --force $out/bin/nix-channel @@ -807,10 +833,10 @@ in nix.nrBuildUsers = mkDefault (max 32 (if cfg.settings.max-jobs == "auto" then 0 else cfg.settings.max-jobs)); - users.users = mkIf cfg.configureBuildUsers nixbldUsers; + users.users = mkIf configureBuildUsers nixbldUsers; # Not in NixOS module - users.groups.nixbld = mkIf cfg.configureBuildUsers { + users.groups.nixbld = mkIf configureBuildUsers { description = "Nix build group for nix-daemon"; gid = config.ids.gids.nixbld; members = attrNames nixbldUsers; @@ -818,11 +844,11 @@ in users.knownUsers = let nixbldUserNames = attrNames nixbldUsers; in - mkIf cfg.configureBuildUsers (mkMerge [ + mkMerge [ nixbldUserNames (map (removePrefix "_") nixbldUserNames) # delete old style nixbld users - ]); - users.knownGroups = mkIf cfg.configureBuildUsers [ "nixbld" ]; + ]; + users.knownGroups = [ "nixbld" ]; # The Determinate Systems installer puts user‐specified settings in # `/etc/nix/nix.custom.conf` since v0.33.0. Supplement the @@ -873,7 +899,7 @@ in if [[ -e /etc/nix/nix.custom.conf ]]; then mv /etc/nix/nix.custom.conf{,.before-nix-darwin} fi - '' + optionalString cfg.useDaemon '' + if ! diff /etc/nix/nix.conf /run/current-system/etc/nix/nix.conf &> /dev/null || ! diff /etc/nix/machines /run/current-system/etc/nix/machines &> /dev/null; then echo "reloading nix-daemon..." >&2 launchctl kill HUP system/org.nixos.nix-daemon @@ -890,6 +916,9 @@ in trusted-users = [ "root" ]; substituters = mkAfter [ "https://cache.nixos.org/" ]; + # Not in NixOS module + build-users-group = "nixbld"; + # Not implemented yet # system-features = mkDefault ( # [ "nixos-test" "benchmark" "big-parallel" "kvm" ] ++ @@ -905,8 +934,6 @@ in (mkIf (isNixAtLeast "2.3pre") { sandbox-fallback = false; }) - # Not in NixOS module - (mkIf cfg.useDaemon { build-users-group = "nixbld"; }) ]; }; diff --git a/modules/services/buildkite-agents.nix b/modules/services/buildkite-agents.nix index 69bc1f65d..3c04d9046 100644 --- a/modules/services/buildkite-agents.nix +++ b/modules/services/buildkite-agents.nix @@ -227,8 +227,9 @@ in { path = cfg.runtimePackages ++ [ cfg.package pkgs.coreutils pkgs.darwin.DarwinTools ]; environment = { HOME = cfg.dataDir; + NIX_REMOTE = "daemon"; inherit (config.environment.variables) NIX_SSL_CERT_FILE; - } // (if config.nix.useDaemon then { NIX_REMOTE = "daemon"; } else {}); + }; ## NB: maximum care is taken so that secrets (ssh keys and the CI token) ## don't end up in the Nix store. diff --git a/modules/services/gitlab-runner.nix b/modules/services/gitlab-runner.nix index 94c291efd..329fd727e 100644 --- a/modules/services/gitlab-runner.nix +++ b/modules/services/gitlab-runner.nix @@ -551,8 +551,9 @@ in launchd.daemons.gitlab-runner = { environment = { #config.networking.proxy.envVars // { HOME = "${config.users.users.gitlab-runner.home}"; + NIX_REMOTE = "daemon"; NIX_SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"; - } // (if config.nix.useDaemon then { NIX_REMOTE = "daemon"; } else {}); + }; path = with pkgs; [ bash gawk diff --git a/modules/services/hercules-ci-agent/default.nix b/modules/services/hercules-ci-agent/default.nix index fc3d95200..391250659 100644 --- a/modules/services/hercules-ci-agent/default.nix +++ b/modules/services/hercules-ci-agent/default.nix @@ -74,7 +74,7 @@ in darwin.label = config.system.darwinLabel; darwin.revision = config.system.darwinRevision; darwin.version = config.system.darwinVersion; - darwin.nix.daemon = config.nix.useDaemon; + darwin.nix.daemon = true; darwin.nix.sandbox = config.nix.settings.sandbox; }; }; diff --git a/modules/services/nix-daemon.nix b/modules/services/nix-daemon.nix index ffc7e651b..404ca0571 100644 --- a/modules/services/nix-daemon.nix +++ b/modules/services/nix-daemon.nix @@ -3,17 +3,18 @@ let cfg = config.services.nix-daemon; - inherit (lib) mkDefault mkIf mkMerge mkOption types; + inherit (lib) mkRemovedOptionModule mkDefault mkIf mkMerge mkOption types; in { - options = { - services.nix-daemon.enable = mkOption { - type = types.bool; - default = true; - description = "Whether to enable the nix-daemon service."; - }; + imports = [ + (mkRemovedOptionModule [ "services" "nix-daemon" "enable" ] '' + nix-darwin now manages nix-daemon unconditionally when + `nix.enable` is on. + '') + ]; + options = { services.nix-daemon.enableSocketListener = mkOption { type = types.bool; default = false; @@ -39,9 +40,7 @@ in }; }; - config = mkIf cfg.enable { - - nix.useDaemon = true; + config = mkIf config.nix.enable { launchd.daemons.nix-daemon = { command = lib.getExe' config.nix.package "nix-daemon"; diff --git a/modules/services/nix-gc/default.nix b/modules/services/nix-gc/default.nix index 9fe8e86dd..44278e649 100644 --- a/modules/services/nix-gc/default.nix +++ b/modules/services/nix-gc/default.nix @@ -14,6 +14,7 @@ in (mkRemovedOptionModule [ "nix" "gc" "dates" ] "Use `nix.gc.interval` instead.") (mkRemovedOptionModule [ "nix" "gc" "randomizedDelaySec" ] "No `nix-darwin` equivalent to this NixOS option.") (mkRemovedOptionModule [ "nix" "gc" "persistent" ] "No `nix-darwin` equivalent to this NixOS option.") + (mkRemovedOptionModule [ "nix" "gc" "user" ] "The garbage collection service now always runs as `root`.") ]; ###### interface @@ -28,13 +29,6 @@ in description = "Automatically run the garbage collector at a specific time."; }; - # Not in NixOS module - user = mkOption { - type = types.nullOr types.str; - default = null; - description = "User that runs the garbage collector."; - }; - interval = mkOption { type = launchdTypes.StartCalendarInterval; default = [{ Weekday = 7; Hour = 3; Minute = 15; }]; @@ -66,10 +60,8 @@ in launchd.daemons.nix-gc = { command = "${config.nix.package}/bin/nix-collect-garbage ${cfg.options}"; - environment.NIX_REMOTE = optionalString config.nix.useDaemon "daemon"; serviceConfig.RunAtLoad = false; serviceConfig.StartCalendarInterval = cfg.interval; - serviceConfig.UserName = cfg.user; }; }; diff --git a/modules/services/nix-optimise/default.nix b/modules/services/nix-optimise/default.nix index c0ee0a387..4eefc480b 100644 --- a/modules/services/nix-optimise/default.nix +++ b/modules/services/nix-optimise/default.nix @@ -20,6 +20,7 @@ in { imports = [ (mkRemovedOptionModule [ "nix" "optimise" "dates" ] "Use `nix.optimise.interval` instead.") + (mkRemovedOptionModule [ "nix" "optimise" "user" ] "The store optimisation service now always runs as `root`.") ]; ###### interface @@ -34,13 +35,6 @@ in description = "Automatically run the nix store optimiser at a specific time."; }; - # Not in NixOS module - user = mkOption { - type = types.nullOr types.str; - default = null; - description = "User that runs the store optimisation."; - }; - interval = mkOption { type = launchdTypes.StartCalendarInterval; default = [{ Weekday = 7; Hour = 4; Minute = 15; }]; @@ -61,12 +55,10 @@ in config = mkIf cfg.automatic { launchd.daemons.nix-optimise = { - environment.NIX_REMOTE = optionalString config.nix.useDaemon "daemon"; command = "${lib.getExe' config.nix.package "nix-store"} --optimise"; serviceConfig = { RunAtLoad = false; StartCalendarInterval = cfg.interval; - UserName = cfg.user; }; }; diff --git a/modules/system/activation-scripts.nix b/modules/system/activation-scripts.nix index b95ea3240..341e782e0 100644 --- a/modules/system/activation-scripts.nix +++ b/modules/system/activation-scripts.nix @@ -13,6 +13,32 @@ let mkTextDerivation = name: text: pkgs.writeScript "activate-${name}" text; }; + activationPath = + lib.makeBinPath [ + pkgs.gnugrep + pkgs.coreutils + ] + + lib.optionalString (!config.nix.enable) '' + $( + # If `nix.enable` is off, there might be an unmanaged Nix + # installation (say in `/nix/var/nix/profiles/default`) that + # activation scripts (such as Home Manager) want to find on the + # `$PATH`. Search for it directly to avoid polluting the + # activation script environment with everything on the + # `environment.systemPath`. + if nixEnvPath=$( + PATH="${config.environment.systemPath}" command -v nix-env + ); then + printf ':' + ${lib.getExe' pkgs.coreutils "dirname"} -- "$( + ${lib.getExe' pkgs.coreutils "readlink"} \ + --canonicalize-missing \ + -- "$nixEnvPath" + )" + fi + )'' + + ":@out@/sw/bin:/usr/bin:/bin:/usr/sbin:/sbin"; + in { @@ -40,7 +66,9 @@ in #! ${stdenv.shell} set -e set -o pipefail - export PATH="${pkgs.gnugrep}/bin:${pkgs.coreutils}/bin:@out@/sw/bin:/usr/bin:/bin:/usr/sbin:/sbin" + + PATH="${activationPath}" + export PATH systemConfig=@out@ @@ -86,7 +114,9 @@ in #! ${stdenv.shell} set -e set -o pipefail - export PATH="${pkgs.gnugrep}/bin:${pkgs.coreutils}/bin:@out@/sw/bin:/usr/bin:/bin" + + PATH="${activationPath}" + export PATH systemConfig=@out@ diff --git a/modules/system/checks.nix b/modules/system/checks.nix index 2df08247b..6afe796cb 100644 --- a/modules/system/checks.nix +++ b/modules/system/checks.nix @@ -31,29 +31,31 @@ let fi ''; - oldBuildUsers = '' - if dscl . -list /Users | grep -q '^nixbld'; then - echo "error: Detected old style nixbld users, aborting activation" >&2 - echo "These can cause migration problems when upgrading to certain macOS versions" >&2 - echo "You can enable the following option to migrate to new style nixbld users" >&2 - echo >&2 - echo " nix.configureBuildUsers = true;" >&2 - echo >&2 - echo "or disable this check with" >&2 - echo >&2 - echo " system.checks.verifyBuildUsers = false;" >&2 - echo >&2 - exit 2 - fi - ''; + determinate = '' + if [[ -e /usr/local/bin/determinate-nixd ]]; then + printf >&2 '\e[1;31merror: Determinate detected, aborting activation\e[0m\n' + printf >&2 'Determinate uses its own daemon to manage the Nix installation that\n' + printf >&2 'conflicts with nix-darwin’s native Nix management.\n' + printf >&2 '\n' + printf >&2 'To turn off nix-darwin’s management of the Nix installation, set:\n' + printf >&2 '\n' + printf >&2 ' nix.enable = false;\n' + printf >&2 '\n' + printf >&2 'This will allow you to use nix-darwin with Determinate. Some nix-darwin\n' + printf >&2 'functionality that relies on managing the Nix installation, like the\n' + printf >&2 '`nix.*` options to adjust Nix settings or configure a Linux builder,\n' + printf >&2 'will be unavailable.\n' + exit 2 + fi + ''; preSequoiaBuildUsers = '' - ${lib.optionalString config.nix.configureBuildUsers '' - # Don’t complain when we’re about to migrate old‐style build users… - if ! dscl . -list /Users | grep -q '^nixbld'; then - ''} firstBuildUserID=$(dscl . -read /Users/_nixbld1 UniqueID | awk '{print $2}') - if [[ $firstBuildUserID != ${toString (config.ids.uids.nixbld + 1)} ]]; then + if + # Don’t complain when we’re about to migrate old‐style build users… + [[ $firstBuildUserID != ${toString (config.ids.uids.nixbld + 1)} ]] \ + && ! dscl . -list /Users | grep -q '^nixbld' + then printf >&2 '\e[1;31merror: Build users have unexpected UIDs, aborting activation\e[0m\n' printf >&2 'The default Nix build user ID range has been adjusted for\n' printf >&2 'compatibility with macOS Sequoia 15. Your _nixbld1 user currently has\n' @@ -86,22 +88,6 @@ let printf >&2 '\n' exit 2 fi - ${lib.optionalString config.nix.configureBuildUsers "fi"} - ''; - - buildUsers = '' - buildUser=$(dscl . -read /Groups/nixbld GroupMembership 2>&1 | awk '/^GroupMembership: / {print $2}') || true - if [[ -z "$buildUser" ]]; then - echo "error: Using the nix-daemon requires build users, aborting activation" >&2 - echo "Create the build users or disable the daemon:" >&2 - echo "$ darwin-install" >&2 - echo >&2 - echo "or set (this requires some manual intervention to restore permissions)" >&2 - echo >&2 - echo " services.nix-daemon.enable = false;" >&2 - echo >&2 - exit 2 - fi ''; buildGroupID = '' @@ -130,45 +116,21 @@ let fi ''; - nixDaemon = if config.nix.useDaemon then '' - if ! dscl . -read /Groups/nixbld PrimaryGroupID &> /dev/null; then - printf >&2 'error: The daemon should not be enabled for single-user installs, aborting activation\n' - printf >&2 'Disable the nix-daemon service:\n' + nixDaemon = '' + if [[ "$(stat --format='%u' /nix)" != 0 ]]; then + printf >&2 'error: single‐user install detected, aborting activation\n' + printf >&2 'nix-darwin now only supports managing multi‐user daemon installations\n' + printf >&2 'of Nix. You can uninstall nix-darwin and Nix and then reinstall both to\n' + printf >&2 'fix this.\n' printf >&2 '\n' - printf >&2 ' services.nix-daemon.enable = false;\n' + printf >&2 'If you don’t want to do that, you can disable management of the Nix\n' + printf >&2 'installation with:\n' printf >&2 '\n' - printf >&2 'and remove `nix.useDaemon` from your configuration if it is present.\n' + printf >&2 ' nix.enable = false;\n' printf >&2 '\n' + printf >&2 'See the `nix.enable` option documentation for caveats.\n' exit 2 fi - '' else '' - if dscl . -read /Groups/nixbld PrimaryGroupID &> /dev/null; then - printf >&2 'error: The daemon should be enabled for multi-user installs, aborting activation\n' - printf >&2 'Enable the nix-daemon service:\n' - printf >&2 '\n' - printf >&2 ' services.nix-daemon.enable = true;\n' - printf >&2 '\n' - exit 2 - fi - ''; - - nixChannels = '' - channelsLink=$(readlink "$HOME/.nix-defexpr/channels") || true - case "$channelsLink" in - *"$USER"*) - ;; - "") - ;; - *) - echo "error: The ~/.nix-defexpr/channels symlink does not point your users channels, aborting activation" >&2 - echo "Running nix-channel will regenerate it" >&2 - echo >&2 - echo " rm ~/.nix-defexpr/channels" >&2 - echo " nix-channel --update" >&2 - echo >&2 - exit 2 - ;; - esac ''; nixInstaller = '' @@ -233,43 +195,6 @@ let fi ''; - nixStore = '' - if test -w /nix/var/nix/db -a ! -O /nix/store; then - echo >&2 "error: the store is not owned by this user, but /nix/var/nix/db is writable" - echo >&2 "If you are using the daemon:" - echo >&2 - echo >&2 " sudo chown -R root:wheel /nix/var/nix/db" - echo >&2 - echo >&2 "Otherwise:" - echo >&2 - echo >&2 " sudo chown -R $USER:staff /nix/store" - echo >&2 - exit 2 - fi - ''; - - nixGarbageCollector = '' - if test -O /nix/store; then - echo "error: A single-user install can't run gc as root, aborting activation" >&2 - echo "Configure the garbage collector to run as the current user:" >&2 - echo >&2 - echo " nix.gc.user = \"$USER\";" >&2 - echo >&2 - exit 2 - fi - ''; - - nixStoreOptimiser = '' - if test -O /nix/store; then - echo "error: A single-user install can't run optimiser as root, aborting activation" >&2 - echo "Configure the optimiser to run as the current user:" >&2 - echo >&2 - echo " nix.optimise.user = \"$USER\";" >&2 - echo >&2 - exit 2 - fi - ''; - # TODO: Remove this a couple years down the line when we can assume # that anyone who cares about security has upgraded. oldSshAuthorizedKeysDirectory = '' @@ -315,24 +240,21 @@ let in { + imports = [ + (mkRemovedOptionModule [ "system" "checks" "verifyNixChannels" ] "This check has been removed.") + ]; + options = { system.checks.verifyNixPath = mkOption { type = types.bool; - default = true; + default = config.nix.enable; description = "Whether to run the NIX_PATH validation checks."; }; - system.checks.verifyNixChannels = mkOption { - type = types.bool; - default = config.nix.channel.enable; - description = "Whether to run the nix-channels validation checks."; - }; - system.checks.verifyBuildUsers = mkOption { type = types.bool; default = - (config.nix.useDaemon && !(config.nix.settings.auto-allocate-uids or false)) - || config.nix.configureBuildUsers; + config.nix.enable && !(config.nix.settings.auto-allocate-uids or false); description = "Whether to run the Nix build users validation checks."; }; @@ -353,15 +275,10 @@ in system.checks.text = mkMerge [ (mkIf cfg.verifyMacOSVersion macOSVersion) - (mkIf (cfg.verifyBuildUsers && !config.nix.configureBuildUsers) oldBuildUsers) - (mkIf cfg.verifyBuildUsers buildUsers) + (mkIf config.nix.enable determinate) (mkIf cfg.verifyBuildUsers preSequoiaBuildUsers) - (mkIf config.nix.configureBuildUsers buildGroupID) - nixDaemon - nixStore - (mkIf (config.nix.gc.automatic && config.nix.gc.user == null) nixGarbageCollector) - (mkIf (config.nix.optimise.automatic && config.nix.optimise.user == null) nixStoreOptimiser) - (mkIf cfg.verifyNixChannels nixChannels) + (mkIf cfg.verifyBuildUsers buildGroupID) + (mkIf config.nix.enable nixDaemon) nixInstaller (mkIf cfg.verifyNixPath nixPath) oldSshAuthorizedKeysDirectory diff --git a/pkgs/darwin-uninstaller/configuration.nix b/pkgs/darwin-uninstaller/configuration.nix index 56ab228fc..ce6be6ca0 100644 --- a/pkgs/darwin-uninstaller/configuration.nix +++ b/pkgs/darwin-uninstaller/configuration.nix @@ -12,8 +12,8 @@ with lib; launchd.daemons = mkForce {}; launchd.user.agents = mkForce {}; - # Don't try to reload `nix-daemon` - nix.useDaemon = mkForce false; + # Restore any unmanaged `nix-daemon`. + nix.enable = false; system.activationScripts.postUserActivation.text = mkAfter '' nix-channel --remove darwin || true @@ -30,14 +30,6 @@ with lib; rm /etc/static fi - # If the Nix Store is owned by root then we're on a multi-user system - if [[ -O /nix/store ]]; then - if [[ -e /nix/var/nix/profiles/default/Library/LaunchDaemons/org.nixos.nix-daemon.plist ]]; then - sudo cp /nix/var/nix/profiles/default/Library/LaunchDaemons/org.nixos.nix-daemon.plist /Library/LaunchDaemons/org.nixos.nix-daemon.plist - sudo launchctl load -w /Library/LaunchDaemons/org.nixos.nix-daemon.plist - fi - fi - # grep will return 1 when no lines matched which makes this line fail with `set -eo pipefail` dscl . -list /Users UserShell | { grep "\s/run/" || true; } | awk '{print $1}' | while read -r user; do shell=$(dscl . -read /Users/"$user" UserShell) diff --git a/pkgs/darwin-uninstaller/default.nix b/pkgs/darwin-uninstaller/default.nix index 0214652b5..6b43bcfc0 100644 --- a/pkgs/darwin-uninstaller/default.nix +++ b/pkgs/darwin-uninstaller/default.nix @@ -31,8 +31,11 @@ in writeShellApplication { echo >&2 " - remove /Applications/Nix Apps symlink" echo >&2 " - cleanup static /etc files" echo >&2 " - disable and remove all launchd services managed by nix-darwin" - if [[ $(stat -f '%Su' /nix/store) == "root" ]]; then - echo >&2 " - restore nix-daemon service from nix installer as this is a multi-user install" + if [[ + -e /run/current-system/Library/LaunchDaemons/org.nixos.nix-daemon.plist + && -e /nix/var/nix/profiles/default/Library/LaunchDaemons/org.nixos.nix-daemon.plist + ]]; then + echo >&2 " - restore nix-daemon service from the Nix installer" fi echo >&2 @@ -87,7 +90,7 @@ in writeShellApplication { launchctl print system/org.nixos.nix-daemon pgrep -l nix-daemon test -e /Library/LaunchDaemons/org.nixos.nix-daemon.plist - [[ "$(shasum -a 256 /Library/LaunchDaemons/org.nixos.nix-daemon.plist | awk '{print $1}')" == "$(shasum -a 256 /Library/LaunchDaemons/org.nixos.nix-daemon.plist | awk '{print $1}')" ]] + [[ "$(shasum -a 256 /Library/LaunchDaemons/org.nixos.nix-daemon.plist | awk '{print $1}')" == "$(shasum -a 256 /nix/var/nix/profiles/default/Library/LaunchDaemons/org.nixos.nix-daemon.plist | awk '{print $1}')" ]] nix-store --store daemon -q --hash ${stdenv.shell} fi echo >&2 ok diff --git a/release.nix b/release.nix index b3e2df7ed..115025eed 100644 --- a/release.nix +++ b/release.nix @@ -80,7 +80,6 @@ in { tests.activation-scripts = makeTest ./tests/activation-scripts.nix; tests.autossh = makeTest ./tests/autossh.nix; - tests.checks-nix-gc = makeTest ./tests/checks-nix-gc.nix; tests.environment-path = makeTest ./tests/environment-path.nix; tests.environment-terminfo = makeTest ./tests/environment-terminfo.nix; tests.homebrew = makeTest ./tests/homebrew.nix; @@ -88,6 +87,7 @@ in { tests.launchd-setenv = makeTest ./tests/launchd-setenv.nix; tests.networking-hostname = makeTest ./tests/networking-hostname.nix; tests.networking-networkservices = makeTest ./tests/networking-networkservices.nix; + tests.nix-enable = makeTest ./tests/nix-enable.nix; tests.nixpkgs-overlays = makeTest ./tests/nixpkgs-overlays.nix; tests.programs-ssh = makeTest ./tests/programs-ssh.nix; tests.programs-tmux = makeTest ./tests/programs-tmux.nix; diff --git a/tests/checks-nix-gc.nix b/tests/checks-nix-gc.nix deleted file mode 100644 index e3dccd7f6..000000000 --- a/tests/checks-nix-gc.nix +++ /dev/null @@ -1,19 +0,0 @@ -{ config, pkgs, ... }: - -let - nix = pkgs.runCommand "nix-2.2" {} "mkdir -p $out"; -in - -{ - nix.gc.automatic = true; - nix.package = nix; - - test = '' - echo checking nix-gc validation >&2 - grep "nix.gc.user = " ${config.out}/activate-user - - echo checking nix-gc service in /Library/LaunchDaemons >&2 - grep "org.nixos.nix-gc" ${config.out}/Library/LaunchDaemons/org.nixos.nix-gc.plist - (! grep "UserName" ${config.out}/Library/LaunchDaemons/org.nixos.nix-gc.plist) - ''; -} diff --git a/tests/nix-enable.nix b/tests/nix-enable.nix new file mode 100644 index 000000000..0828834f1 --- /dev/null +++ b/tests/nix-enable.nix @@ -0,0 +1,17 @@ +{ config, ... }: + +{ + nix.enable = false; + nix.package = throw "`nix.package` used when `nix.enable` is turned off"; + + test = '' + printf >&2 'checking for unexpected Nix binary in /sw/bin\n' + [[ -e ${config.out}/sw/bin/nix-env ]] && exit 1 + + printf >&2 'checking for unexpected nix-daemon plist in /Library/LaunchDaemons\n' + [[ -e ${config.out}/Library/LaunchDaemons/org.nixos.nix-daemon.plist ]] && exit 1 + + printf >&2 'checking for late‐bound Nix lookup in /activate\n' + grep nixEnvPath= ${config.out}/activate + ''; +} diff --git a/tests/services-nix-daemon.nix b/tests/services-nix-daemon.nix index 3a217cbb3..f8f06e5d9 100644 --- a/tests/services-nix-daemon.nix +++ b/tests/services-nix-daemon.nix @@ -6,7 +6,6 @@ let in { - services.nix-daemon.enable = true; nix.package = nix; launchd.labelPrefix = "org.nix-darwin"; # should not have an effect on nix-daemon @@ -27,8 +26,5 @@ in echo checking nix-daemon reload in /activate >&2 grep "launchctl kill HUP system/org.nixos.nix-daemon" ${config.out}/activate - - echo checking NIX_REMOTE=daemon in setEnvironment >&2 - grep "NIX_REMOTE=daemon" ${config.system.build.setEnvironment} ''; } diff --git a/tests/services-nix-gc.nix b/tests/services-nix-gc.nix index 6d7cdef82..9c8ba8176 100644 --- a/tests/services-nix-gc.nix +++ b/tests/services-nix-gc.nix @@ -7,19 +7,13 @@ in { nix.gc.automatic = true; nix.gc.options = "--delete-older-than 30d"; - nix.gc.user = "nixuser"; nix.package = nix; test = '' echo checking nix-gc service in /Library/LaunchDaemons >&2 grep "org.nixos.nix-gc" ${config.out}/Library/LaunchDaemons/org.nixos.nix-gc.plist grep "/bin/wait4path /nix/store && exec ${nix}/bin/nix-collect-garbage --delete-older-than 30d" ${config.out}/Library/LaunchDaemons/org.nixos.nix-gc.plist - grep "UserName" ${config.out}/Library/LaunchDaemons/org.nixos.nix-gc.plist - grep "nixuser" ${config.out}/Library/LaunchDaemons/org.nixos.nix-gc.plist (! grep "KeepAlive" ${config.out}/Library/LaunchDaemons/org.nixos.nix-gc.plist) - - echo checking nix-gc validation >&2 - (! grep "nix.gc.user = " ${config.out}/activate-user) ''; } diff --git a/tests/services-nix-optimise.nix b/tests/services-nix-optimise.nix index 4108eb0f2..acdc1dcef 100644 --- a/tests/services-nix-optimise.nix +++ b/tests/services-nix-optimise.nix @@ -6,7 +6,6 @@ in { nix.optimise.automatic = true; - nix.optimise.user = "nixuser"; nix.package = nix; test = '' @@ -15,11 +14,6 @@ in ${config.out}/Library/LaunchDaemons/org.nixos.nix-optimise.plist grep "/bin/wait4path /nix/store && exec ${nix}/bin/nix-store --optimise" \ ${config.out}/Library/LaunchDaemons/org.nixos.nix-optimise.plist - grep "UserName" ${config.out}/Library/LaunchDaemons/org.nixos.nix-optimise.plist - grep "nixuser" ${config.out}/Library/LaunchDaemons/org.nixos.nix-optimise.plist (! grep "KeepAlive" ${config.out}/Library/LaunchDaemons/org.nixos.nix-optimise.plist) - - echo checking nix-optimise validation >&2 - (! grep "nix.optimise.user = " ${config.out}/activate-user) ''; } diff --git a/tests/sockets-nix-daemon.nix b/tests/sockets-nix-daemon.nix index 606b7b6fd..bafd6c109 100644 --- a/tests/sockets-nix-daemon.nix +++ b/tests/sockets-nix-daemon.nix @@ -5,7 +5,6 @@ let in { - services.nix-daemon.enable = true; services.nix-daemon.enableSocketListener = true; nix.package = nix; launchd.labelPrefix = "org.nix-darwin"; # should not have an effect on nix-daemon