From 63741020825b95f64bad04ce415e74029ce1995f Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 10 Feb 2025 19:14:24 +0000 Subject: [PATCH 01/11] nix-gc: check for `nix.enable` This was added to Nixpkgs in eb8b70c020e6693b29634660fa173d7f14f882eb. (cherry picked from commit fc9367a9ec8ce3527291fc3bfc1b12c0260bc676) --- modules/services/nix-gc/default.nix | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/modules/services/nix-gc/default.nix b/modules/services/nix-gc/default.nix index 9fe8e86dd..e18f8f4a4 100644 --- a/modules/services/nix-gc/default.nix +++ b/modules/services/nix-gc/default.nix @@ -62,15 +62,20 @@ in ###### implementation - config = mkIf cfg.automatic { - - launchd.daemons.nix-gc = { + config = { + assertions = [ + { + assertion = cfg.automatic -> config.nix.enable; + message = ''nix.gc.automatic requires nix.enable''; + } + ]; + + launchd.daemons.nix-gc = mkIf cfg.automatic { 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; }; - }; } From be5f5c546f8be88c2be1269ba3d006a2ae7f4196 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 10 Feb 2025 19:15:18 +0000 Subject: [PATCH 02/11] nix-optimise: check for `nix.enable` This was added to Nixpkgs in eb8b70c020e6693b29634660fa173d7f14f882eb. (cherry picked from commit 0176a5082ba8450e1480204a824ed188cdc81600) --- modules/services/nix-optimise/default.nix | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/modules/services/nix-optimise/default.nix b/modules/services/nix-optimise/default.nix index c0ee0a387..4926acf5b 100644 --- a/modules/services/nix-optimise/default.nix +++ b/modules/services/nix-optimise/default.nix @@ -58,9 +58,15 @@ in ###### implementation - config = mkIf cfg.automatic { - - launchd.daemons.nix-optimise = { + config = { + assertions = [ + { + assertion = cfg.automatic -> config.nix.enable; + message = ''nix.optimise.automatic requires nix.enable''; + } + ]; + + launchd.daemons.nix-optimise = mkIf cfg.automatic { environment.NIX_REMOTE = optionalString config.nix.useDaemon "daemon"; command = "${lib.getExe' config.nix.package "nix-store"} --optimise"; serviceConfig = { @@ -69,6 +75,5 @@ in UserName = cfg.user; }; }; - }; } From f49eef1b2c8426b25a1a5abbc88e649479e3ff62 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 10 Feb 2025 19:25:18 +0000 Subject: [PATCH 03/11] linux-builder: check for `nix.enable` (cherry picked from commit 7cca8f95f7761bff239066306148714e560cbc2e) --- modules/nix/linux-builder.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/nix/linux-builder.nix b/modules/nix/linux-builder.nix index ae39547f6..36a41310e 100644 --- a/modules/nix/linux-builder.nix +++ b/modules/nix/linux-builder.nix @@ -160,6 +160,13 @@ in }; config = mkIf cfg.enable { + assertions = [ + { + assertion = config.nix.enable; + message = ''`nix.linux-builder.enable` requires `nix.enable`''; + } + ]; + system.activationScripts.preActivation.text = '' mkdir -p ${cfg.workingDirectory} ''; From 77e5f792a8c5718a8726221c9a491c26d2e3fd68 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 10 Feb 2025 19:28:56 +0000 Subject: [PATCH 04/11] nixpkgs-flake: check for `nix.enable` (cherry picked from commit 147ed950e382ef45d083f060b4529df817077069) --- modules/nix/nixpkgs-flake.nix | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/modules/nix/nixpkgs-flake.nix b/modules/nix/nixpkgs-flake.nix index bb7c1b0a2..bc00c78d2 100644 --- a/modules/nix/nixpkgs-flake.nix +++ b/modules/nix/nixpkgs-flake.nix @@ -37,8 +37,8 @@ in setNixPath = mkOption { type = types.bool; - default = cfg.source != null; - defaultText = "config.nixpkgs.flake.source != null"; + default = config.nix.enable && cfg.source != null; + defaultText = literalExpression ''config.nix.enable && nixpkgs.flake.source != null''; description = '' Whether to set {env}`NIX_PATH` to include `nixpkgs=flake:nixpkgs` such that `` @@ -57,8 +57,8 @@ in setFlakeRegistry = mkOption { type = types.bool; - default = cfg.source != null; - defaultText = "config.nixpkgs.flake.source != null"; + default = config.nix.enable && cfg.source != null; + defaultText = literalExpression ''config.nix.enable && config.nixpkgs.flake.source != null''; description = '' Whether to pin nixpkgs in the system-wide flake registry (`/etc/nix/registry.json`) to the @@ -85,6 +85,18 @@ in be set, since it is implemented in terms of indirection through the flake registry. ''; } + + # TODO: Upstream these to NixOS. + + { + assertion = cfg.setNixPath -> config.nix.enable; + message = ''`nixpkgs.flake.setNixPath` requires `nix.enable`''; + } + + { + assertion = cfg.setFlakeRegistry -> config.nix.enable; + message = ''`nixpkgs.flake.setFlakeRegistry` requires `nix.enable`''; + } ]; } (mkIf cfg.setFlakeRegistry { From 9f452b8c834df0a105cd9009079e0b12543a71c2 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 10 Feb 2025 19:31:28 +0000 Subject: [PATCH 05/11] hercules-ci-agent: check for `nix.enable` (cherry picked from commit 57c93ffe6cbb627e5c9d10ceae7b31e68ba945ac) --- modules/services/hercules-ci-agent/default.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/services/hercules-ci-agent/default.nix b/modules/services/hercules-ci-agent/default.nix index fc3d95200..64bcca05e 100644 --- a/modules/services/hercules-ci-agent/default.nix +++ b/modules/services/hercules-ci-agent/default.nix @@ -22,6 +22,14 @@ in }; config = mkIf cfg.enable { + # TODO: Upstream this to NixOS. + assertions = [ + { + assertion = config.nix.enable; + message = ''`services.hercules-ci-agent.enable` requires `nix.enable`''; + } + ]; + launchd.daemons.hercules-ci-agent = { script = "exec ${cfg.package}/bin/hercules-ci-agent --config ${cfg.tomlFile}"; From 68760fcd7f992ed605b4398beda39b1e4539aca7 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 10 Feb 2025 19:41:14 +0000 Subject: [PATCH 06/11] lorri: check for `nix.enable` (cherry picked from commit aba0c60ebab549f69ece1622d99ffc5e6ad81af3) --- modules/services/lorri.nix | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/services/lorri.nix b/modules/services/lorri.nix index 0c1230043..c4e1acee2 100644 --- a/modules/services/lorri.nix +++ b/modules/services/lorri.nix @@ -29,6 +29,14 @@ in }; config = mkIf cfg.enable { + # TODO: Upstream this to NixOS. + assertions = [ + { + assertion = config.nix.enable; + message = ''`services.lorri.enable` requires `nix.enable`''; + } + ]; + environment.systemPackages = [ pkgs.lorri ]; launchd.user.agents.lorri = { command = with pkgs; "${lorri}/bin/lorri daemon"; @@ -43,4 +51,4 @@ in }; }; }; -} \ No newline at end of file +} From 1a3bd586678280ae04f5b83bca4b11a0c9415337 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 10 Feb 2025 19:49:48 +0000 Subject: [PATCH 07/11] ofborg: check for `nix.enable` (cherry picked from commit f4e2805e19f84420538590ff4e91b1bfa2e79784) --- modules/services/ofborg/default.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/services/ofborg/default.nix b/modules/services/ofborg/default.nix index 8959cc846..acd6974fb 100644 --- a/modules/services/ofborg/default.nix +++ b/modules/services/ofborg/default.nix @@ -46,6 +46,13 @@ in }; config = mkIf cfg.enable { + assertions = [ + { + assertion = config.nix.enable; + message = ''`services.ofborg.enable` requires `nix.enable`''; + } + ]; + warnings = mkIf (isDerivation cfg.configFile) [ "services.ofborg.configFile is a derivation, credentials will be world readable" ]; From 4884d2a217c322785bc6c9512538b99788b9406e Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 10 Feb 2025 19:51:42 +0000 Subject: [PATCH 08/11] github-runner: check for `nix.enable` (cherry picked from commit e3bde1588bc6b4cf774197228330139338a4a12c) --- modules/services/github-runner/service.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/services/github-runner/service.nix b/modules/services/github-runner/service.nix index 029f863e2..3668a7216 100644 --- a/modules/services/github-runner/service.nix +++ b/modules/services/github-runner/service.nix @@ -13,6 +13,11 @@ in { config.assertions = flatten ( flip mapAttrsToList config.services.github-runners (name: cfg: map (mkIf cfg.enable) [ + # TODO: Upstream this to NixOS. + { + assertion = config.nix.enable; + message = ''`services.github-runners.${name}.enable` requires `nix.enable`''; + } { assertion = (cfg.user == null && cfg.group == null) || (cfg.user != null); message = "`services.github-runners.${name}`: Either set `user` and `group` to `null` to have nix-darwin manage them or set at least `user` explicitly"; From a66e5dada1775f1072065ac6ac8b7ec07c1d9f4b Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 10 Feb 2025 19:53:25 +0000 Subject: [PATCH 09/11] cachix-agent: check for `nix.enable` (cherry picked from commit 42e16f31c6faf29a51a2aa15aeff64934bf5d157) --- modules/services/cachix-agent.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/services/cachix-agent.nix b/modules/services/cachix-agent.nix index d9e4a909c..508261afc 100644 --- a/modules/services/cachix-agent.nix +++ b/modules/services/cachix-agent.nix @@ -51,6 +51,14 @@ in { }; config = mkIf cfg.enable { + # TODO: Upstream this to NixOS. + assertions = [ + { + assertion = config.nix.enable; + message = ''`services.cachix-agent.enable` requires `nix.enable`''; + } + ]; + launchd.daemons.cachix-agent = { script = '' . ${cfg.credentialsFile} From 67d262f923d42a20b1327832239089c4621b4ac5 Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 10 Feb 2025 20:54:52 +0000 Subject: [PATCH 10/11] nix: catch reads of unmanaged defaults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we’re not managing the Nix installation, these defaults aren’t used out of the box and won’t accurately represent the state of any unmanaged Nix or the desired Nix package, so reading the option defaults is a bug. This was previously a warning for `nix.package` and a silent failure for all the others. Now that all the problematic accesses in nix-darwin have been appropriately conditionalized, and since a throw gives a backtrace where a warning doesn’t, give throwing defaults to all the `nix.*` options that don’t reflect reality and that that modules shouldn’t be reading when `nix.enable` is off. I’m not in love with the implementation strategy here… ideally we’d think of something better than this and then upstream it to NixOS. `nix.nrBuildUsers` growing a fake default that is never used is particularly unfortunate. But this should hopefully catch mistakes in module code reasonably reliably. (cherry picked from commit cd445c546561d5ca4e9124cb4668ce80939ac0c9) --- modules/nix/default.nix | 43 +++++++++++++++++++++++++---------------- tests/nix-enable.nix | 1 - 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/modules/nix/default.nix b/modules/nix/default.nix index 817bfc0ef..22f7fe688 100644 --- a/modules/nix/default.nix +++ b/modules/nix/default.nix @@ -154,6 +154,14 @@ let }) ]; + managedDefault = name: default: { + default = if cfg.enable then default else throw '' + ${name}: accessed when `nix.enable` is off; this is a bug in + nix-darwin or a third‐party module + ''; + defaultText = default; + }; + in { @@ -211,9 +219,7 @@ in package = mkOption { type = types.package; - default = warnIf (!cfg.enable) - "nix.package: accessed when `nix.enable` is off; this is a bug" - pkgs.nix; + inherit (managedDefault "nix.package" pkgs.nix) default; defaultText = literalExpression "pkgs.nix"; description = '' This option specifies the Nix package instance to use throughout the system. @@ -242,7 +248,7 @@ in distributedBuilds = mkOption { type = types.bool; - default = false; + inherit (managedDefault "nix.distributedBuilds" false) default defaultText; description = '' Whether to distribute builds to the machines listed in {option}`nix.buildMachines`. @@ -252,7 +258,7 @@ in # Not in NixOS module daemonProcessType = mkOption { type = types.enum [ "Background" "Standard" "Adaptive" "Interactive" ]; - default = "Standard"; + inherit (managedDefault "nix.daemonProcessType" "Standard") default defaultText; description = '' Nix daemon process resource limits class. These limits propagate to build processes. `Standard` is the default process type @@ -267,7 +273,7 @@ in # Not in NixOS module daemonIOLowPriority = mkOption { type = types.bool; - default = false; + inherit (managedDefault "nix.daemonIOLowPriority" false) default defaultText; description = '' Whether the Nix daemon process should considered to be low priority when doing file system I/O. @@ -395,7 +401,7 @@ in }; }; }); - default = [ ]; + inherit (managedDefault "nix.buildMachines" [ ]) default defaultText; description = '' This option lists the machines to be used if distributed builds are enabled (see {option}`nix.distributedBuilds`). @@ -409,7 +415,7 @@ in envVars = mkOption { type = types.attrs; internal = true; - default = { }; + inherit (managedDefault "nix.envVars" { }) default defaultText; description = "Environment variables used by Nix."; }; @@ -424,6 +430,7 @@ in nrBuildUsers = mkOption { type = types.int; + inherit (managedDefault "nix.nrBuildUsers" 0) default defaultText; description = '' Number of `nixbld` user accounts created to perform secure concurrent builds. If you receive an error @@ -451,11 +458,13 @@ in # Definition differs substantially from NixOS module nixPath = mkOption { type = nixPathType; - default = lib.optionals cfg.channel.enable [ - # Include default path . - { darwin-config = "${config.environment.darwinConfig}"; } - "/nix/var/nix/profiles/per-user/root/channels" - ]; + inherit (managedDefault "nix.nixPath" ( + lib.optionals cfg.channel.enable [ + # Include default path . + { darwin-config = "${config.environment.darwinConfig}"; } + "/nix/var/nix/profiles/per-user/root/channels" + ] + )) default; defaultText = lib.literalExpression '' lib.optionals cfg.channel.enable [ @@ -477,7 +486,7 @@ in checkConfig = mkOption { type = types.bool; - default = true; + inherit (managedDefault "nix.checkConfig" true) default defaultText; description = '' If enabled (the default), checks for data type mismatches and that Nix can parse the generated nix.conf. @@ -538,7 +547,7 @@ in }; } )); - default = { }; + inherit (managedDefault "nix.registry" { }) default defaultText; description = '' A system-wide flake registry. ''; @@ -546,7 +555,7 @@ in extraOptions = mkOption { type = types.lines; - default = ""; + inherit (managedDefault "nix.extraOptions" "") default defaultText; example = '' keep-outputs = true keep-derivations = true @@ -715,7 +724,7 @@ in }; }; }; - default = { }; + inherit (managedDefault "nix.settings" { }) default defaultText; description = '' Configuration for Nix, see diff --git a/tests/nix-enable.nix b/tests/nix-enable.nix index 0828834f1..e052aa2f4 100644 --- a/tests/nix-enable.nix +++ b/tests/nix-enable.nix @@ -2,7 +2,6 @@ { 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' From d0f10e610f5a1e3d02ee14084062a932a4089d0e Mon Sep 17 00:00:00 2001 From: Emily Date: Tue, 11 Feb 2025 19:46:21 +0000 Subject: [PATCH 11/11] {activation-scripts,activate-system}: check `gcroots` before linking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When `nix.enable` is off, we don’t necessarily have an active Nix installation, so there won’t necessarily be an active `/nix/var/nix/gcroots` directory to link things into. NixOS just skips this unconditionally when `nix.enable` is off, but that doesn’t work well with a context in which we usually expect `nix.enable` to be coupled with an unmanaged system installation of Nix. (cherry picked from commit 731910af010086c4dbe23eb6ae79d81bcec703aa) --- modules/services/activate-system/default.nix | 4 +++- modules/system/activation-scripts.nix | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/services/activate-system/default.nix b/modules/services/activate-system/default.nix index 6a982fe83..58d2e2422 100644 --- a/modules/services/activate-system/default.nix +++ b/modules/services/activate-system/default.nix @@ -21,7 +21,9 @@ ln -sfn $(cat ${config.system.profile}/systemConfig) /run/current-system # Prevent the current configuration from being garbage-collected. - ln -sfn /run/current-system /nix/var/nix/gcroots/current-system + if [[ -d /nix/var/nix/gcroots ]]; then + ln -sfn /run/current-system /nix/var/nix/gcroots/current-system + fi ${config.system.activationScripts.etcChecks.text} ${config.system.activationScripts.etc.text} diff --git a/modules/system/activation-scripts.nix b/modules/system/activation-scripts.nix index b051972b5..4f42d4112 100644 --- a/modules/system/activation-scripts.nix +++ b/modules/system/activation-scripts.nix @@ -109,7 +109,9 @@ in ln -sfn "$(readlink -f "$systemConfig")" /run/current-system # Prevent the current configuration from being garbage-collected. - ln -sfn /run/current-system /nix/var/nix/gcroots/current-system + if [[ -d /nix/var/nix/gcroots ]]; then + ln -sfn /run/current-system /nix/var/nix/gcroots/current-system + fi exit $_status '';