Skip to content

Commit

Permalink
Merge pull request #1313 from emilazy/push-tzwxwyvonslk
Browse files Browse the repository at this point in the history
nix: add `nix.enable` option to disable Nix management
  • Loading branch information
emilazy authored Feb 11, 2025
2 parents a36049d + a2e44a8 commit a674621
Show file tree
Hide file tree
Showing 21 changed files with 211 additions and 257 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -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
Expand Down
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.


Expand Down
1 change: 0 additions & 1 deletion modules/examples/lnl.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
121 changes: 74 additions & 47 deletions modules/nix/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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

{
Expand All @@ -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"))
Expand All @@ -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
Expand All @@ -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.
'';
};

Expand Down Expand Up @@ -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 = ''
Expand Down Expand Up @@ -678,7 +714,7 @@ in

###### implementation

config = {
config = handleUnmanaged {
environment.systemPackages =
[
nixPackage
Expand Down Expand Up @@ -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"; }

{
Expand All @@ -785,44 +821,34 @@ 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
'';

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;
};
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
Expand Down Expand Up @@ -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
Expand All @@ -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" ] ++
Expand All @@ -905,8 +934,6 @@ in

(mkIf (isNixAtLeast "2.3pre") { sandbox-fallback = false; })

# Not in NixOS module
(mkIf cfg.useDaemon { build-users-group = "nixbld"; })
];

};
Expand Down
3 changes: 2 additions & 1 deletion modules/services/buildkite-agents.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion modules/services/gitlab-runner.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion modules/services/hercules-ci-agent/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
};
Expand Down
19 changes: 9 additions & 10 deletions modules/services/nix-daemon.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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";
Expand Down
10 changes: 1 addition & 9 deletions modules/services/nix-gc/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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; }];
Expand Down Expand Up @@ -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;
};

};
Expand Down
Loading

0 comments on commit a674621

Please sign in to comment.