diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
new file mode 100644
index 00000000..92331afe
--- /dev/null
+++ b/.git-blame-ignore-revs
@@ -0,0 +1,2 @@
+# nixpkgs: format with `nixfmt`
+dc1c716ded39758062ed7e6bc410ad274119de9f
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 25211d30..d87b7636 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -6,67 +6,73 @@ on:
- master
env:
- CURRENT_STABLE_CHANNEL: nixpkgs-24.05-darwin
+ NIXPKGS_BRANCH: nixpkgs-unstable
+ NIX_VERSION: 2.24.11
jobs:
+ # The `test-stable` and `install-against-stable` job names are
+ # load‐bearing, despite their inaccuracy on the unstable branch, as
+ # they are set as required checks in the repository configuration,
+ # which only repository admins can change.
+ #
+ # TODO: Change them once the repository configuration is updated.
+
test-stable:
runs-on: macos-13
steps:
- uses: actions/checkout@v4
- - name: Install nix corresponding to latest stable channel
+ - name: Install Nix
uses: cachix/install-nix-action@v30
with:
- install_url: https://releases.nixos.org/nix/nix-2.18.8/install
- - run: nix flake check --override-input nixpkgs nixpkgs/${{ env.CURRENT_STABLE_CHANNEL }}
-
- test-unstable:
- runs-on: macos-13
- steps:
- - uses: actions/checkout@v4
- - name: Install nix from current unstable channel
- uses: cachix/install-nix-action@v30
- with:
- install_url: https://releases.nixos.org/nix/nix-2.24.9/install
- - run: nix flake check --override-input nixpkgs nixpkgs/nixpkgs-unstable
+ install_url: https://releases.nixos.org/nix/nix-${{ env.NIX_VERSION }}/install
+ - run: nix flake check --override-input nixpkgs nixpkgs/${{ env.NIXPKGS_BRANCH }}
install-against-stable:
runs-on: macos-13
+ timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- - name: Install nix corresponding to latest stable channel
+ - name: Install Nix
uses: cachix/install-nix-action@v30
with:
- install_url: https://releases.nixos.org/nix/nix-2.18.8/install
- nix_path: nixpkgs=channel:${{ env.CURRENT_STABLE_CHANNEL }}
+ install_url: https://releases.nixos.org/nix/nix-${{ env.NIX_VERSION }}/install
+ nix_path: nixpkgs=channel:${{ env.NIXPKGS_BRANCH }}
- name: Install channels
run: |
- nix-channel --add https://github.com/LnL7/nix-darwin/archive/master.tar.gz darwin
- nix-channel --add https://nixos.org/channels/${{ env.CURRENT_STABLE_CHANNEL }} nixpkgs
+ nix-channel --add https://nixos.org/channels/${{ env.NIXPKGS_BRANCH }} nixpkgs
nix-channel --update
- name: Install nix-darwin
run: |
- export NIX_PATH=$HOME/.nix-defexpr/channels
-
- mkdir -p ~/.config/nix-darwin
- cp modules/examples/simple.nix ~/.config/nix-darwin/configuration.nix
+ sudo mkdir -p /etc/nix-darwin
+ sudo cp modules/examples/simple.nix /etc/nix-darwin/configuration.nix
nixConfHash=$(shasum -a 256 /etc/nix/nix.conf | cut -d ' ' -f 1)
- /usr/bin/sed -i.bak \
- "s/# programs.fish.enable = true;/nix.settings.access-tokens = [ \"github.com=\${{ secrets.GITHUB_TOKEN }}\" ]; environment.etc.\"nix\/nix.conf\".knownSha256Hashes = [ \"$nixConfHash\" ];/" \
- ~/.config/nix-darwin/configuration.nix
+ sudo /usr/bin/sed -i.bak \
+ "s/# programs.fish.enable = true;/ \
+ imports = [ \
+ ({ options, ... }: { \
+ nix.settings.access-tokens = [ \"github.com=\${{ secrets.GITHUB_TOKEN }}\" ]; \
+ environment.etc.\"nix\/nix.conf\".knownSha256Hashes = [ \"$nixConfHash\" ]; \
+ nix.nixPath = \
+ [ { darwin = \"${PWD////\/}\"; } ] \
+ ++ options.nix.nixPath.default; \
+ }) \
+ ]; \
+ /" \
+ /etc/nix-darwin/configuration.nix
- nix run .#darwin-rebuild \
- -- switch \
- -I darwin-config=$HOME/.config/nix-darwin/configuration.nix
+ nix run .#darwin-rebuild -- switch \
+ -I darwin=. \
+ -I darwin-config=/etc/nix-darwin/configuration.nix
- name: Switch to new configuration
run: |
. /etc/bashrc
- /usr/bin/sed -i.bak \
+ sudo /usr/bin/sed -i.bak \
"s/pkgs.vim/pkgs.hello/" \
- ~/.config/nix-darwin/configuration.nix
+ /etc/nix-darwin/configuration.nix
- darwin-rebuild switch -I darwin=.
+ darwin-rebuild switch
hello
- name: Test uninstallation of nix-darwin
@@ -75,148 +81,54 @@ jobs:
# `cachix/install-nix-action` but not by our default config above
nix run .#darwin-uninstaller \
--extra-experimental-features "nix-command flakes" \
- --override-input nixpkgs nixpkgs/${{ env.CURRENT_STABLE_CHANNEL }}
+ --override-input nixpkgs nixpkgs/${{ env.NIXPKGS_BRANCH }}
nix run .#darwin-uninstaller.tests.uninstaller \
--extra-experimental-features "nix-command flakes" \
- --override-input nixpkgs nixpkgs/${{ env.CURRENT_STABLE_CHANNEL }}
+ --override-input nixpkgs nixpkgs/${{ env.NIXPKGS_BRANCH }}
- install-against-unstable:
+ install-flake:
runs-on: macos-13
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- - name: Install nix from current unstable channel
+ - name: Install Nix
uses: cachix/install-nix-action@v30
with:
- install_url: https://releases.nixos.org/nix/nix-2.24.9/install
- nix_path: nixpkgs=channel:nixpkgs-unstable
- - name: Install channels
- run: |
- nix-channel --add https://github.com/LnL7/nix-darwin/archive/master.tar.gz darwin
- nix-channel --add https://nixos.org/channels/nixpkgs-unstable nixpkgs
- nix-channel --update
+ install_url: https://releases.nixos.org/nix/nix-${{ env.NIX_VERSION }}/install
- name: Install nix-darwin
run: |
- export NIX_PATH=$HOME/.nix-defexpr/channels
-
- mkdir -p ~/.config/nix-darwin
- cp modules/examples/simple.nix ~/.config/nix-darwin/configuration.nix
-
- nixConfHash=$(shasum -a 256 /etc/nix/nix.conf | cut -d ' ' -f 1)
- /usr/bin/sed -i.bak \
- "s/# programs.fish.enable = true;/nix.settings.access-tokens = [ \"github.com=\${{ secrets.GITHUB_TOKEN }}\" ]; environment.etc.\"nix\/nix.conf\".knownSha256Hashes = [ \"$nixConfHash\" ];/" \
- ~/.config/nix-darwin/configuration.nix
-
- nix run .#darwin-rebuild \
- -- switch \
- -I darwin-config=$HOME/.config/nix-darwin/configuration.nix
- - name: Switch to new configuration
- run: |
- . /etc/bashrc
-
- /usr/bin/sed -i.bak \
- "s/pkgs.vim/pkgs.hello/" \
- ~/.config/nix-darwin/configuration.nix
-
- darwin-rebuild switch -I darwin=.
-
- hello
- - name: Test uninstallation of nix-darwin
- run: |
- # We need to specify `--extra-experimental-features` because `experimental-features` is set by
- # `cachix/install-nix-action` but not by our default config above
- nix run .#darwin-uninstaller \
- --extra-experimental-features "nix-command flakes" \
- --override-input nixpkgs nixpkgs/nixpkgs-unstable
- nix run .#darwin-uninstaller.tests.uninstaller \
- --extra-experimental-features "nix-command flakes" \
- --override-input nixpkgs nixpkgs/nixpkgs-unstable
-
- install-flake-against-stable:
- runs-on: macos-13
- steps:
- - uses: actions/checkout@v4
- - name: Install nix version corresponding to latest stable channel
- uses: cachix/install-nix-action@v30
- with:
- install_url: https://releases.nixos.org/nix/nix-2.18.8/install
- - name: Install nix-darwin
- run: |
- mkdir -p ~/.config/nix-darwin
+ sudo mkdir -p /etc/nix-darwin
darwin=$(pwd)
- pushd ~/.config/nix-darwin
- nix flake init -t $darwin
+ pushd /etc/nix-darwin
+ sudo nix flake init -t $darwin
nixConfHash=$(shasum -a 256 /etc/nix/nix.conf | cut -d ' ' -f 1)
- /usr/bin/sed -i.bak \
+ sudo /usr/bin/sed -i.bak \
"s/# programs.fish.enable = true;/nix.settings.access-tokens = [ \"github.com=\${{ secrets.GITHUB_TOKEN }}\" ]; environment.etc.\"nix\/nix.conf\".knownSha256Hashes = [ \"$nixConfHash\" ];/" \
flake.nix
- /usr/bin/sed -i.bak \
+ sudo /usr/bin/sed -i.bak \
+ 's/darwinConfigurations."simple"/darwinConfigurations."'$(scutil --get LocalHostName)'"/g' \
+ flake.nix
+ sudo /usr/bin/sed -i.bak \
's/nixpkgs.hostPlatform = "aarch64-darwin";/nixpkgs.hostPlatform = "'$(nix eval --expr builtins.currentSystem --impure --raw)'";/' \
flake.nix
popd
- nix run .#darwin-rebuild -- \
- switch --flake ~/.config/nix-darwin#simple \
+ nix run .#darwin-rebuild -- switch \
--override-input nix-darwin . \
- --override-input nixpkgs nixpkgs/${{ env.CURRENT_STABLE_CHANNEL }}
+ --override-input nixpkgs nixpkgs/${{ env.NIXPKGS_BRANCH }}
- name: Switch to new configuration
run: |
. /etc/bashrc
- /usr/bin/sed -i.bak \
+ sudo /usr/bin/sed -i.bak \
"s/pkgs.vim/pkgs.hello/" \
- ~/.config/nix-darwin/flake.nix
+ /etc/nix-darwin/flake.nix
- darwin-rebuild switch --flake ~/.config/nix-darwin#simple \
+ darwin-rebuild switch \
--override-input nix-darwin . \
- --override-input nixpkgs nixpkgs/${{ env.CURRENT_STABLE_CHANNEL }}
+ --override-input nixpkgs nixpkgs/${{ env.NIXPKGS_BRANCH }}
hello
- name: Test uninstallation of nix-darwin
run: |
- nix run .#darwin-uninstaller --override-input nixpkgs nixpkgs/${{ env.CURRENT_STABLE_CHANNEL }}
- nix run .#darwin-uninstaller.tests.uninstaller --override-input nixpkgs nixpkgs/${{ env.CURRENT_STABLE_CHANNEL }}
-
- install-flake-against-unstable:
- runs-on: macos-13
- timeout-minutes: 30
- steps:
- - uses: actions/checkout@v4
- - name: Install nix from current unstable channel
- uses: cachix/install-nix-action@v30
- with:
- install_url: https://releases.nixos.org/nix/nix-2.24.9/install
- - name: Install nix-darwin
- run: |
- mkdir -p ~/.config/nix-darwin
- darwin=$(pwd)
- pushd ~/.config/nix-darwin
- nix flake init -t $darwin
- nixConfHash=$(shasum -a 256 /etc/nix/nix.conf | cut -d ' ' -f 1)
- /usr/bin/sed -i.bak \
- "s/# programs.fish.enable = true;/nix.settings.access-tokens = [ \"github.com=\${{ secrets.GITHUB_TOKEN }}\" ]; environment.etc.\"nix\/nix.conf\".knownSha256Hashes = [ \"$nixConfHash\" ];/" \
- flake.nix
- /usr/bin/sed -i.bak \
- 's/nixpkgs.hostPlatform = "aarch64-darwin";/nixpkgs.hostPlatform = "'$(nix eval --expr builtins.currentSystem --impure --raw)'";/' \
- flake.nix
- popd
- nix run .#darwin-rebuild -- \
- switch --flake ~/.config/nix-darwin#simple \
- --override-input nix-darwin . \
- --override-input nixpkgs nixpkgs/nixpkgs-unstable
- - name: Switch to new configuration
- run: |
- . /etc/bashrc
-
- /usr/bin/sed -i.bak \
- "s/pkgs.vim/pkgs.hello/" \
- ~/.config/nix-darwin/flake.nix
-
- darwin-rebuild switch --flake ~/.config/nix-darwin#simple \
- --override-input nix-darwin . \
- --override-input nixpkgs nixpkgs/nixpkgs-unstable
-
- hello
- - name: Test uninstallation of nix-darwin
- run: |
- nix run .#darwin-uninstaller --override-input nixpkgs nixpkgs/nixpkgs-unstable
- nix run .#darwin-uninstaller.tests.uninstaller --override-input nixpkgs nixpkgs/nixpkgs-unstable
+ nix run .#darwin-uninstaller --override-input nixpkgs nixpkgs/${{ env.NIXPKGS_BRANCH }}
+ nix run .#darwin-uninstaller.tests.uninstaller --override-input nixpkgs nixpkgs/${{ env.NIXPKGS_BRANCH }}
diff --git a/CHANGELOG b/CHANGELOG
index b9a9adcc..74591eff 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,23 @@
+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
+ default for `darwin-rebuild switch` when using flakes. This
+ is implemented by setting `environment.darwinConfig` to
+ `"/etc/nix-darwin/configuration.nix"` by default when
+ `system.stateVersion` ≥ 6.
+
2024-09-10
- The default Nix build user group ID is now set to 350 when
`system.stateVersion` ≥ 5, to reflect the default for new Nix
diff --git a/README.md b/README.md
index d5373273..20447dec 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:
+
+ * To install the **recommended** vanilla upstream [Nix](https://nixos.org), you will need to explicitly say `no` when prompted to install `Determinate Nix`.
+
+ * 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.
@@ -33,12 +41,18 @@ Despite being an experimental feature in Nix currently, nix-darwin recommends th
Getting started from scratch
-If you don't have an existing `configuration.nix`, you can run the following commands to generate a basic `flake.nix` inside `~/.config/nix-darwin`:
+If you don't have an existing `configuration.nix`, you can run the following commands to generate a basic `flake.nix` inside `/etc/nix-darwin`:
```bash
-mkdir -p ~/.config/nix-darwin
-cd ~/.config/nix-darwin
-nix flake init -t nix-darwin
+sudo mkdir -p /etc/nix-darwin
+sudo chown $(id -nu):$(id -ng) /etc/nix-darwin
+cd /etc/nix-darwin
+
+# To use Nixpkgs unstable:
+nix flake init -t nix-darwin/master
+# To use Nixpkgs 24.11:
+nix flake init -t nix-darwin/nix-darwin-24.11
+
sed -i '' "s/simple/$(scutil --get LocalHostName)/" flake.nix
```
@@ -57,8 +71,10 @@ Add the following to `flake.nix` in the same folder as `configuration.nix`:
description = "John's darwin system";
inputs = {
- nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-24.05-darwin";
- nix-darwin.url = "github:LnL7/nix-darwin";
+ # Use `github:NixOS/nixpkgs/nixpkgs-24.11-darwin` to use Nixpkgs 24.11.
+ nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
+ # Use `github:LnL7/nix-darwin/nix-darwin-24.11` to use Nixpkgs 24.11.
+ nix-darwin.url = "github:LnL7/nix-darwin/master";
nix-darwin.inputs.nixpkgs.follows = "nixpkgs";
};
@@ -81,7 +97,10 @@ Make sure to set `nixpkgs.hostPlatform` in your `configuration.nix` to either `x
Unlike NixOS, `nix-darwin` does not have an installer, you can just run `darwin-rebuild switch` to install nix-darwin. As `darwin-rebuild` won't be installed in your `PATH` yet, you can use the following command:
```bash
-nix run nix-darwin -- switch --flake ~/.config/nix-darwin
+# To use Nixpkgs unstable:
+nix run nix-darwin/master#darwin-rebuild -- switch
+# To use Nixpkgs 24.11:
+nix run nix-darwin/nix-darwin-24.11#darwin-rebuild -- switch
```
### Step 3. Using `nix-darwin`
@@ -89,7 +108,7 @@ nix run nix-darwin -- switch --flake ~/.config/nix-darwin
After installing, you can run `darwin-rebuild` to apply changes to your system:
```bash
-darwin-rebuild switch --flake ~/.config/nix-darwin
+darwin-rebuild switch
```
#### Using flake inputs
@@ -117,13 +136,17 @@ nix-darwin.lib.darwinSystem {
### Step 1. Creating `configuration.nix`
-Copy the [simple](./modules/examples/simple.nix) example to `~/.config/nix-darwin/configuration.nix`.
+Copy the [simple](./modules/examples/simple.nix) example to `/etc/nix-darwin/configuration.nix`.
### Step 2. Adding `nix-darwin` channel
```bash
-nix-channel --add https://github.com/LnL7/nix-darwin/archive/master.tar.gz darwin
-nix-channel --update
+# If you use Nixpkgs unstable (the default):
+sudo nix-channel --add https://github.com/LnL7/nix-darwin/archive/master.tar.gz darwin
+# If you use Nixpkgs 24.11:
+sudo nix-channel --add https://github.com/LnL7/nix-darwin/archive/nix-darwin-24.11.tar.gz darwin
+
+sudo nix-channel --update
```
### Step 3. Installing `nix-darwin`
@@ -131,8 +154,8 @@ nix-channel --update
To install `nix-darwin`, you can just run `darwin-rebuild switch` to install nix-darwin. As `darwin-rebuild` won't be installed in your `PATH` yet, you can use the following command:
```bash
-nix-build https://github.com/LnL7/nix-darwin/archive/master.tar.gz -A darwin-rebuild
-./result/bin/darwin-rebuild switch -I darwin-config=$HOME/.config/nix-darwin/configuration.nix
+nix-build '' -A darwin-rebuild
+./result/bin/darwin-rebuild switch -I darwin-config=/etc/nix-darwin/configuration.nix
```
### Step 4. Using `nix-darwin`
@@ -145,10 +168,10 @@ darwin-rebuild switch
### Step 5. Updating `nix-darwin`
-You can update `nix-darwin` using the following command:
+You can update Nixpkgs and `nix-darwin` using the following command:
```bash
-nix-channel --update darwin
+sudo nix-channel --update
```
diff --git a/doc/known-files/3bd68ef979a42070a44f8d82c205cfd8e8cca425d91253ec2c10a88179bb34aa b/doc/known-files/3bd68ef979a42070a44f8d82c205cfd8e8cca425d91253ec2c10a88179bb34aa
new file mode 100644
index 00000000..dacf1689
--- /dev/null
+++ b/doc/known-files/3bd68ef979a42070a44f8d82c205cfd8e8cca425d91253ec2c10a88179bb34aa
@@ -0,0 +1,3 @@
+# Written by https://github.com/DeterminateSystems/nix-installer.
+# The contents below are based on options specified at installation time.
+
diff --git a/doc/known-files/53712b4335030e2dbfb46bb235f8cffcac83fea404bd32dc99417ac89e2dd7c5 b/doc/known-files/53712b4335030e2dbfb46bb235f8cffcac83fea404bd32dc99417ac89e2dd7c5
new file mode 100644
index 00000000..44b308a0
--- /dev/null
+++ b/doc/known-files/53712b4335030e2dbfb46bb235f8cffcac83fea404bd32dc99417ac89e2dd7c5
@@ -0,0 +1,14 @@
+
+# Generated by https://github.com/DeterminateSystems/nix-installer.
+# See `/nix/nix-installer --version` for the version details.
+
+!include nix.custom.conf
+
+experimental-features = nix-command flakes
+always-allow-substitutes = true
+extra-trusted-substituters = https://cache.flakehub.com
+extra-trusted-public-keys = cache.flakehub.com-3:hJuILl5sVK4iKm86JzgdXW12Y2Hwd5G07qKtHTOcDCM= cache.flakehub.com-4:Asi8qIv291s0aYLyH6IOnr5Kf6+OF14WVjkE6t3xMio= cache.flakehub.com-5:zB96CRlL7tiPtzA9/WKyPkp3A2vqxqgdgyTVNGShPDU= cache.flakehub.com-6:W4EGFwAGgBj3he7c5fNh9NkOXw0PUVaxygCVKeuvaqU= cache.flakehub.com-7:mvxJ2DZVHn/kRxlIaxYNMuDG1OvMckZu32um1TadOR8= cache.flakehub.com-8:moO+OVS0mnTjBTcOUh2kYLQEd59ExzyoW1QgQ8XAARQ= cache.flakehub.com-9:wChaSeTI6TeCuV/Sg2513ZIM9i0qJaYsF+lZCXg0J6o= cache.flakehub.com-10:2GqeNlIp6AKp4EF2MVbE1kBOp9iBSyo0UPR9KoR0o1Y=
+bash-prompt-prefix = (nix:$name)\040
+max-jobs = auto
+extra-nix-path = nixpkgs=flake:nixpkgs
+upgrade-nix-store-path-url = https://install.determinate.systems/nix-upgrade/stable/universal
diff --git a/doc/known-files/6787fade1cf934f82db554e78e1fc788705c2c5257fddf9b59bdd963ca6fec63 b/doc/known-files/6787fade1cf934f82db554e78e1fc788705c2c5257fddf9b59bdd963ca6fec63
new file mode 100644
index 00000000..74a863d8
--- /dev/null
+++ b/doc/known-files/6787fade1cf934f82db554e78e1fc788705c2c5257fddf9b59bdd963ca6fec63
@@ -0,0 +1,4 @@
+
+# Written by https://github.com/DeterminateSystems/nix-installer.
+# The contents below are based on options specified at installation time.
+
diff --git a/doc/known-files/6bb8d6b0dd16b44ee793a9b8382dac76c926e4c16ffb8ddd2bb4884d1ca3f811 b/doc/known-files/6bb8d6b0dd16b44ee793a9b8382dac76c926e4c16ffb8ddd2bb4884d1ca3f811
new file mode 100644
index 00000000..0973d2c6
--- /dev/null
+++ b/doc/known-files/6bb8d6b0dd16b44ee793a9b8382dac76c926e4c16ffb8ddd2bb4884d1ca3f811
@@ -0,0 +1,13 @@
+# Generated by https://github.com/DeterminateSystems/nix-installer.
+# See `/nix/nix-installer --version` for the version details.
+
+extra-experimental-features = nix-command flakes
+always-allow-substitutes = true
+extra-trusted-substituters = https://cache.flakehub.com
+extra-trusted-public-keys = cache.flakehub.com-3:hJuILl5sVK4iKm86JzgdXW12Y2Hwd5G07qKtHTOcDCM= cache.flakehub.com-4:Asi8qIv291s0aYLyH6IOnr5Kf6+OF14WVjkE6t3xMio= cache.flakehub.com-5:zB96CRlL7tiPtzA9/WKyPkp3A2vqxqgdgyTVNGShPDU= cache.flakehub.com-6:W4EGFwAGgBj3he7c5fNh9NkOXw0PUVaxygCVKeuvaqU= cache.flakehub.com-7:mvxJ2DZVHn/kRxlIaxYNMuDG1OvMckZu32um1TadOR8= cache.flakehub.com-8:moO+OVS0mnTjBTcOUh2kYLQEd59ExzyoW1QgQ8XAARQ= cache.flakehub.com-9:wChaSeTI6TeCuV/Sg2513ZIM9i0qJaYsF+lZCXg0J6o= cache.flakehub.com-10:2GqeNlIp6AKp4EF2MVbE1kBOp9iBSyo0UPR9KoR0o1Y=
+bash-prompt-prefix = (nix:$name)\040
+max-jobs = auto
+extra-nix-path = nixpkgs=flake:nixpkgs
+upgrade-nix-store-path-url = https://install.determinate.systems/nix-upgrade/stable/universal
+
+!include nix.custom.conf
diff --git a/doc/manual/default.nix b/doc/manual/default.nix
index d8e12f29..ef4b64d5 100644
--- a/doc/manual/default.nix
+++ b/doc/manual/default.nix
@@ -53,7 +53,7 @@ in rec {
substitute \
${optionsDoc.optionsJSON}/nix-support/hydra-build-products \
$out/nix-support/hydra-build-products \
- --replace \
+ --replace-fail \
'${optionsDoc.optionsJSON}/share/doc/nixos' \
"$out/share/doc/darwin"
'';
@@ -74,8 +74,8 @@ in rec {
cp -r ${pkgs.documentation-highlighter} $dst/highlightjs
substitute ${./manual.md} manual.md \
- --replace '@DARWIN_VERSION@' "${version}" \
- --replace \
+ --replace-fail '@DARWIN_VERSION@' "${version}" \
+ --replace-fail \
'@DARWIN_OPTIONS_JSON@' \
${optionsJSON}/share/doc/darwin/options.json
diff --git a/eval-config.nix b/eval-config.nix
index cd14493d..7c6d48ff 100644
--- a/eval-config.nix
+++ b/eval-config.nix
@@ -1,10 +1,72 @@
+let
+ nixDarwinVersion = builtins.fromJSON (builtins.readFile ./version.json);
+
+ checkRelease = lib:
+ # Avoid breaking configurations when the unstable Nixpkgs version
+ # rolls over.
+ #
+ # TODO: Something more refined than this would be ideal, as this
+ # still means you could be using unstable nix-darwin 25.05 with
+ # Nixpkgs 26.05, which would be unfortunate.
+ if nixDarwinVersion.isReleaseBranch then
+ lib.trivial.release == nixDarwinVersion.release
+ else
+ lib.versionAtLeast lib.trivial.release nixDarwinVersion.release;
+in
+
{ lib
, modules
, baseModules ? import ./modules/module-list.nix
, specialArgs ? { }
, check ? true
+, enableNixpkgsReleaseCheck ? true
}@args:
+assert enableNixpkgsReleaseCheck -> checkRelease lib || throw ''
+
+ nix-darwin now uses release branches that correspond to Nixpkgs releases.
+ The nix-darwin and Nixpkgs branches in use must match, but you are currently
+ using nix-darwin ${nixDarwinVersion.release} with Nixpkgs ${lib.trivial.release}.
+
+ On macOS, you should use either the `nixpkgs-unstable` or
+ `nixpkgs-YY.MM-darwin` branches of Nixpkgs. These correspond to the
+ `master` and `nix-darwin-YY.MM` branches of nix-darwin, respectively. Check
+ for the currently supported Nixpkgs releases.
+
+ If you’re using flakes, make sure your inputs look like this:
+
+ inputs = {
+ nixpkgs.url = "github:NixOS/nixpkgs/NIXPKGS-BRANCH";
+ nix-darwin.url = "github:LnL7/nix-darwin/NIX-DARWIN-BRANCH";
+ nix-darwin.inputs.nixpkgs.follows = "nixpkgs";
+ # …
+ };
+
+ If you’re using channels, you can check your current channels with:
+
+ $ sudo nix-channel --list
+ nixpkgs https://nixos.org/channels/NIXPKGS-BRANCH
+ darwin https://github.com/LnL7/nix-darwin/archive/NIX-DARWIN-BRANCH.tar.gz
+ …
+ $ nix-channel --list
+ …
+
+ If `darwin` or `nixpkgs` are present in `nix-channel --list` (without
+ `sudo`), you should delete them with `nix-channel --remove NAME`. These can
+ contribute to version mismatch problems.
+
+ You can then fix your channels like this:
+
+ $ sudo nix-channel --add https://nixos.org/channels/NIXPKGS-BRANCH nixpkgs
+ $ sudo nix-channel --add https://github.com/LnL7/nix-darwin/archive/NIX-DARWIN-BRANCH.tar.gz darwin
+ $ sudo nix-channel --update
+
+ After that, activating your system again should work correctly. If it
+ doesn’t, please open an issue at
+ and include as much
+ information as possible.
+'';
+
let
argsModule = {
_file = ./eval-config.nix;
@@ -15,7 +77,7 @@ let
};
};
- eval = lib.evalModules (builtins.removeAttrs args [ "lib" ] // {
+ eval = lib.evalModules (builtins.removeAttrs args [ "lib" "enableNixpkgsReleaseCheck" ] // {
class = "darwin";
modules = modules ++ [ argsModule ] ++ baseModules;
specialArgs = { modulesPath = builtins.toString ./modules; } // specialArgs;
diff --git a/flake.lock b/flake.lock
index 3ce8eac6..0f05e93e 100644
--- a/flake.lock
+++ b/flake.lock
@@ -2,16 +2,18 @@
"nodes": {
"nixpkgs": {
"locked": {
- "lastModified": 1718149104,
- "narHash": "sha256-Ds1QpobBX2yoUDx9ZruqVGJ/uQPgcXoYuobBguyKEh8=",
+ "lastModified": 1736241350,
+ "narHash": "sha256-CHd7yhaDigUuJyDeX0SADbTM9FXfiWaeNyY34FL1wQU=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "e913ae340076bbb73d9f4d3d065c2bca7caafb16",
+ "rev": "8c9fd3e564728e90829ee7dbac6edc972971cd0f",
"type": "github"
},
"original": {
- "id": "nixpkgs",
- "type": "indirect"
+ "owner": "NixOS",
+ "ref": "nixpkgs-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
}
},
"root": {
diff --git a/flake.nix b/flake.nix
index 2c1ae1b2..92569fa9 100644
--- a/flake.nix
+++ b/flake.nix
@@ -1,6 +1,10 @@
{
description = "A collection of darwin modules";
+ inputs = {
+ nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
+ };
+
outputs = { self, nixpkgs }: let
forAllSystems = nixpkgs.lib.genAttrs [ "aarch64-darwin" "x86_64-darwin" "aarch64-linux" "x86_64-linux" ];
forDarwinSystems = nixpkgs.lib.genAttrs [ "aarch64-darwin" "x86_64-darwin" ];
diff --git a/modules/environment/default.nix b/modules/environment/default.nix
index fc4db2ab..377a9594 100644
--- a/modules/environment/default.nix
+++ b/modules/environment/default.nix
@@ -67,8 +67,24 @@ in
};
environment.darwinConfig = mkOption {
- type = types.either types.path types.str;
- default = "$HOME/.nixpkgs/darwin-configuration.nix";
+ type = types.nullOr (types.either types.path types.str);
+ default =
+ if config.nixpkgs.flake.setNixPath then
+ # Don’t set this for flake‐based systems.
+ null
+ else if config.system.stateVersion >= 6 then
+ "/etc/nix-darwin/configuration.nix"
+ else
+ "$HOME/.nixpkgs/darwin-configuration.nix";
+ defaultText = literalExpression ''
+ if config.nixpkgs.flake.setNixPath then
+ # Don’t set this for flake‐based systems.
+ null
+ else if config.system.stateVersion >= 6 then
+ "/etc/nix-darwin/configuration.nix"
+ else
+ "$HOME/.nixpkgs/darwin-configuration.nix"
+ '';
description = ''
The path of the darwin configuration.nix used to configure the system,
this updates the default darwin-config entry in NIX_PATH. Since this
@@ -161,7 +177,7 @@ in
environment.systemPath = mkMerge [
[ (makeBinPath cfg.profiles) ]
- (mkOrder 1200 [ "/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin" ])
+ (mkOrder 1200 [ "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" ])
];
# Use user, default and system profiles.
diff --git a/modules/examples/flake/flake.nix b/modules/examples/flake/flake.nix
index 4520b8ff..447c468a 100644
--- a/modules/examples/flake/flake.nix
+++ b/modules/examples/flake/flake.nix
@@ -3,7 +3,7 @@
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
- nix-darwin.url = "github:LnL7/nix-darwin";
+ nix-darwin.url = "github:LnL7/nix-darwin/master";
nix-darwin.inputs.nixpkgs.follows = "nixpkgs";
};
@@ -27,7 +27,7 @@
# Used for backwards compatibility, please read the changelog before changing.
# $ darwin-rebuild changelog
- system.stateVersion = 5;
+ system.stateVersion = 6;
# The platform the configuration will be used on.
nixpkgs.hostPlatform = "aarch64-darwin";
diff --git a/modules/examples/hydra.nix b/modules/examples/hydra.nix
index f87ed5d0..d30f5c00 100644
--- a/modules/examples/hydra.nix
+++ b/modules/examples/hydra.nix
@@ -43,5 +43,5 @@ in
echo "ok"
'';
- system.stateVersion = 5;
+ system.stateVersion = 6;
}
diff --git a/modules/examples/lnl.nix b/modules/examples/lnl.nix
index 2204c2fa..8dff10cc 100644
--- a/modules/examples/lnl.nix
+++ b/modules/examples/lnl.nix
@@ -199,7 +199,7 @@
programs.zsh.enableFzfGit = true;
programs.zsh.enableFzfHistory = true;
- programs.zsh.variables.cfg = "$HOME/.config/nixpkgs/darwin/configuration.nix";
+ programs.zsh.variables.cfg = "/etc/nix-darwin/configuration.nix";
programs.zsh.variables.darwin = "$HOME/.nix-defexpr/darwin";
programs.zsh.variables.nixpkgs = "$HOME/.nix-defexpr/nixpkgs";
@@ -319,8 +319,7 @@
# 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 = 5;
+ system.stateVersion = 6;
}
diff --git a/modules/examples/simple.nix b/modules/examples/simple.nix
index 5771ec60..7751fb29 100644
--- a/modules/examples/simple.nix
+++ b/modules/examples/simple.nix
@@ -7,13 +7,10 @@
[ pkgs.vim
];
- # Use custom location for configuration.nix.
- environment.darwinConfig = "$HOME/.config/nix-darwin/configuration.nix";
-
# Enable alternative shell support in nix-darwin.
# programs.fish.enable = true;
# Used for backwards compatibility, please read the changelog before changing.
# $ darwin-rebuild changelog
- system.stateVersion = 5;
+ system.stateVersion = 6;
}
diff --git a/modules/homebrew.nix b/modules/homebrew.nix
index 7aee9e13..10764fbb 100644
--- a/modules/homebrew.nix
+++ b/modules/homebrew.nix
@@ -137,7 +137,7 @@ let
config = {
brewBundleCmd = concatStringsSep " " (
optional (!config.autoUpdate) "HOMEBREW_NO_AUTO_UPDATE=1"
- ++ [ "brew bundle --file='${brewfileFile}' --no-lock" ]
+ ++ [ "brew bundle --file='${brewfileFile}'" ]
++ optional (!config.upgrade) "--no-upgrade"
++ optional (config.cleanup == "uninstall") "--cleanup"
++ optional (config.cleanup == "zap") "--cleanup --zap"
@@ -396,6 +396,9 @@ let
no_binaries = mkNullOrBoolOption {
description = "Whether to disable linking of helper executables.";
};
+ ignore_dependencies = mkNullOrBoolOption {
+ description = "Ignore casks dependencies in case you manage them extrenally";
+ };
brewfileLine = mkInternalOption { type = types.nullOr types.str; };
};
@@ -705,9 +708,6 @@ in
description = ''
Applications to install from Mac App Store using {command}`mas`.
- When this option is used, `"mas"` is automatically added to
- [](#opt-homebrew.brews).
-
Note that you need to be signed into the Mac App Store for {command}`mas` to
successfully install and upgrade applications, and that unfortunately apps removed from this
option will not be uninstalled automatically even if
@@ -765,8 +765,7 @@ in
];
homebrew.brews =
- optional (cfg.masApps != { }) "mas"
- ++ optional (cfg.whalebrews != [ ]) "whalebrew";
+ optional (cfg.whalebrews != [ ]) "whalebrew";
homebrew.brewfile =
"# Created by `nix-darwin`'s `homebrew` module\n\n"
@@ -786,7 +785,8 @@ in
# Homebrew Bundle
echo >&2 "Homebrew bundle..."
if [ -f "${cfg.brewPrefix}/brew" ]; then
- PATH="${cfg.brewPrefix}":$PATH ${cfg.onActivation.brewBundleCmd}
+ PATH="${cfg.brewPrefix}:${lib.makeBinPath [ pkgs.mas ]}:$PATH" \
+ ${cfg.onActivation.brewBundleCmd}
else
echo -e "\e[1;31merror: Homebrew is not installed, skipping...\e[0m" >&2
fi
diff --git a/modules/misc/ids.nix b/modules/misc/ids.nix
index 34b36859..ddab290a 100644
--- a/modules/misc/ids.nix
+++ b/modules/misc/ids.nix
@@ -39,11 +39,13 @@ in
ids.uids = {
nixbld = lib.mkDefault 350;
_prometheus-node-exporter = 534;
+ _dnscrypt-proxy = 535;
};
ids.gids = {
nixbld = lib.mkDefault (if config.system.stateVersion < 5 then 30000 else 350);
_prometheus-node-exporter = 534;
+ _dnscrypt-proxy = 535;
};
};
diff --git a/modules/module-list.nix b/modules/module-list.nix
index aa190c7d..d01bbdb9 100644
--- a/modules/module-list.nix
+++ b/modules/module-list.nix
@@ -62,6 +62,7 @@
./services/chunkwm.nix
./services/cachix-agent.nix
./services/dnsmasq.nix
+ ./services/dnscrypt-proxy.nix
./services/emacs.nix
./services/eternal-terminal.nix
./services/github-runner
@@ -82,6 +83,7 @@
./services/nix-gc
./services/nix-optimise
./services/ofborg
+ ./services/openssh.nix
./services/postgresql
./services/privoxy
./services/redis
diff --git a/modules/networking/default.nix b/modules/networking/default.nix
index 7a81ca1c..8097e276 100644
--- a/modules/networking/default.nix
+++ b/modules/networking/default.nix
@@ -118,7 +118,6 @@ in
echo "configuring networking..." >&2
${optionalString (cfg.computerName != null) ''
- # shellcheck disable=SC1112
scutil --set ComputerName ${escapeShellArg cfg.computerName}
''}
${optionalString (cfg.hostName != null) ''
@@ -133,6 +132,11 @@ in
${optionalString (cfg.wakeOnLan.enable != null) ''
systemsetup -setWakeOnNetworkAccess '${onOff cfg.wakeOnLan.enable}' &> /dev/null
''}
+
+ if [ -e /etc/hosts.before-nix-darwin ]; then
+ echo "restoring /etc/hosts..." >&2
+ sudo mv /etc/hosts{.before-nix-darwin,}
+ fi
'';
};
diff --git a/modules/nix/default.nix b/modules/nix/default.nix
index 09e6e50d..e5d0801d 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 = {
@@ -49,13 +51,16 @@ let
mkKeyValuePairs = attrs: concatStringsSep "\n" (mapAttrsToList mkKeyValue attrs);
+ isExtra = key: hasPrefix "extra-" key;
+
in
pkgs.writeTextFile {
name = "nix.conf";
text = ''
# WARNING: this file is generated from the nix.* options in
# your nix-darwin configuration. Do not edit it!
- ${mkKeyValuePairs cfg.settings}
+ ${mkKeyValuePairs (filterAttrs (key: value: !(isExtra key)) cfg.settings)}
+ ${mkKeyValuePairs (filterAttrs (key: value: isExtra key) cfg.settings)}
${cfg.extraOptions}
'';
checkPhase =
@@ -134,6 +139,34 @@ 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
+ '';
+ })
+ ];
+
+ 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
{
@@ -144,7 +177,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 +189,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,29 +205,43 @@ in
nix = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = true;
+ description = ''
+ 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.
+ :::
+ '';
+ };
+
package = mkOption {
type = types.package;
- default = 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.
'';
};
- # Not in NixOS module
- useDaemon = mkOption {
- type = types.bool;
- default = false;
- 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.
- '';
- };
-
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`.
@@ -197,7 +251,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
@@ -212,7 +266,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.
@@ -340,7 +394,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`).
@@ -354,21 +408,13 @@ in
envVars = mkOption {
type = types.attrs;
internal = true;
- default = { };
+ inherit (managedDefault "nix.envVars" { }) default defaultText;
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;
+ inherit (managedDefault "nix.nrBuildUsers" 0) default defaultText;
description = ''
Number of `nixbld` user accounts created to
perform secure concurrent builds. If you receive an error
@@ -396,11 +442,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 [
@@ -422,7 +470,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.
@@ -483,7 +531,7 @@ in
};
}
));
- default = { };
+ inherit (managedDefault "nix.registry" { }) default defaultText;
description = ''
A system-wide flake registry.
'';
@@ -491,7 +539,7 @@ in
extraOptions = mkOption {
type = types.lines;
- default = "";
+ inherit (managedDefault "nix.extraOptions" "") default defaultText;
example = ''
keep-outputs = true
keep-derivations = true
@@ -617,7 +665,6 @@ in
trusted-users = mkOption {
type = types.listOf types.str;
- default = [ "root" ];
example = [ "root" "alice" "@admin" ];
description = ''
A list of names of users that have additional rights when
@@ -661,7 +708,7 @@ in
};
};
};
- default = { };
+ inherit (managedDefault "nix.settings" { }) default defaultText;
description = ''
Configuration for Nix, see
@@ -679,7 +726,7 @@ in
###### implementation
- config = {
+ config = handleUnmanaged {
environment.systemPackages =
[
nixPackage
@@ -703,6 +750,8 @@ in
"5d23e6d7015756c6f300f8cd558ec4d9234ca61deefd4f2478e91a49760b0747" # DeterminateSystems Nix installer 0.16.0
"e4974acb79c56148cb8e92137fa4f2de9b7356e897b332fc4e6769e8c0b83e18" # DeterminateSystems Nix installer 0.20.0
"966d22ef5bb9b56d481e8e0d5f7ca2deaf4d24c0f0fc969b2eeaa7ae0aa42907" # DeterminateSystems Nix installer 0.22.0
+ "53712b4335030e2dbfb46bb235f8cffcac83fea404bd32dc99417ac89e2dd7c5" # DeterminateSystems Nix installer 0.33.0
+ "6bb8d6b0dd16b44ee793a9b8382dac76c926e4c16ffb8ddd2bb4884d1ca3f811" # DeterminateSystems Nix installer 0.34.0
"24797ac05542ff8b52910efc77870faa5f9e3275097227ea4e50c430a5f72916" # lix-installer 0.17.1 with flakes
"b027b5cad320b5b8123d9d0db9f815c3f3921596c26dc3c471457098e4d3cc40" # lix-installer 0.17.1 without flakes
];
@@ -758,13 +807,13 @@ 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"; }
{
# Should be fixed in Lix by https://gerrit.lix.systems/c/lix/+/2100
- # As `isNixAtLeast "2.92.0" "2.92.0-devpre20241107" == false`, we need to explicitly check if the user is running Lix 2.92.0
- assertion = cfg.settings.auto-optimise-store -> (cfg.package.pname == "lix" && (isNixAtLeast "2.92.0-devpre20241107" || cfg.package.version == "2.92.0"));
+ # Lix 2.92.0 will set `VERSION_SUFFIX` to `""`; `lib.versionAtLeast "" "pre20241107"` will return `true`.
+ assertion = cfg.settings.auto-optimise-store -> (cfg.package.pname == "lix" && (isNixAtLeast "2.92.0" && versionAtLeast (strings.removePrefix "-" cfg.package.VERSION_SUFFIX) "pre20241107"));
message = "`nix.settings.auto-optimise-store` is known to corrupt the Nix Store, please use `nix.optimise.automatic` instead.";
}
];
@@ -784,21 +833,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
@@ -806,10 +845,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;
@@ -817,14 +856,62 @@ 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
+ # `/etc/nix/nix.conf` hash check so that we don’t accidentally
+ # clobber user configuration.
+ #
+ # TODO: Maybe this could use a more general file placement mechanism
+ # to express that we want it deleted and know only one hash?
+ system.activationScripts.etcChecks.text = mkAfter ''
+ nixCustomConfKnownSha256Hashes=(
+ # v0.33.0
+ 6787fade1cf934f82db554e78e1fc788705c2c5257fddf9b59bdd963ca6fec63
+ # v0.34.0
+ 3bd68ef979a42070a44f8d82c205cfd8e8cca425d91253ec2c10a88179bb34aa
+ )
+ if [[ -e /etc/nix/nix.custom.conf ]]; then
+ nixCustomConfSha256Output=$(shasum -a 256 /etc/nix/nix.custom.conf)
+ nixCustomConfSha256Hash=''${nixCustomConfSha256Output%% *}
+ nixCustomConfIsKnown=
+ for nixCustomConfKnownSha256Hash
+ in "''${nixCustomConfKnownSha256Hashes[@]}"
+ do
+ if
+ [[ $nixCustomConfSha256Hash == "$nixCustomConfKnownSha256Hash" ]]
+ then
+ nixCustomConfIsKnown=1
+ break
+ fi
+ done
+ if [[ ! $nixCustomConfIsKnown ]]; then
+ printf >&2 '\e[1;31merror: custom settings in `/etc/nix/nix.custom.conf`, aborting activation\e[0m\n'
+ printf >&2 'You will need to migrate these to nix-darwin `nix.*` settings if you\n'
+ printf >&2 'wish to keep them. Check the manual for the appropriate settings and\n'
+ printf >&2 'add them to your system configuration, then run:\n'
+ printf >&2 '\n'
+ printf >&2 ' $ sudo mv /etc/nix/nix.custom.conf{,.before-nix-darwin}\n'
+ printf >&2 '\n'
+ printf >&2 'and activate your system again.\n'
+ exit 2
+ fi
+ fi
+ '';
# Unrelated to use in NixOS module
- system.activationScripts.nix-daemon.text = mkIf cfg.useDaemon ''
+ system.activationScripts.nix-daemon.text = ''
+ # Follow up on the `/etc/nix/nix.custom.conf` check.
+ # TODO: Use a more generalized file placement mechanism for this.
+ if [[ -e /etc/nix/nix.custom.conf ]]; then
+ mv /etc/nix/nix.custom.conf{,.before-nix-darwin}
+ fi
+
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
@@ -835,12 +922,15 @@ in
done
'';
- # Legacy configuration conversion.
nix.settings = mkMerge [
{
trusted-public-keys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ];
+ 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" ] ++
@@ -856,8 +946,6 @@ in
(mkIf (isNixAtLeast "2.3pre") { sandbox-fallback = false; })
- # Not in NixOS module
- (mkIf cfg.useDaemon { build-users-group = "nixbld"; })
];
};
diff --git a/modules/nix/linux-builder.nix b/modules/nix/linux-builder.nix
index 2bcb62ea..36a41310 100644
--- a/modules/nix/linux-builder.nix
+++ b/modules/nix/linux-builder.nix
@@ -61,9 +61,16 @@ in
maxJobs = mkOption {
type = types.ints.positive;
- default = 1;
- example = 4;
+ default = cfg.package.nixosConfig.virtualisation.cores;
+ defaultText = ''
+ The `virtualisation.cores` of the build machine's final NixOS configuration.
+ '';
+ example = 2;
description = ''
+ Instead of setting this directly, you should set
+ {option}`nix.linux-builder.config.virtualisation.cores` to configure
+ the amount of cores the Linux builder should have.
+
The number of concurrent jobs the Linux builder machine supports. The
build machine will enforce its own limits, but this allows hydra
to schedule better since there is no work-stealing between build
@@ -153,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}
'';
diff --git a/modules/nix/nix-darwin.nix b/modules/nix/nix-darwin.nix
index 4a989d79..9c78f3a6 100644
--- a/modules/nix/nix-darwin.nix
+++ b/modules/nix/nix-darwin.nix
@@ -4,7 +4,7 @@ let
nix-tools = pkgs.callPackage ../../pkgs/nix-tools {
inherit (config.system) profile;
inherit (config.environment) systemPath;
- nixPackage = config.nix.package;
+ nixPath = lib.optionalString config.nix.enable (lib.concatStringsSep ":" config.nix.nixPath);
};
darwin-uninstaller = pkgs.callPackage ../../pkgs/darwin-uninstaller { };
diff --git a/modules/nix/nixpkgs-flake.nix b/modules/nix/nixpkgs-flake.nix
index bb7c1b0a..bc00c78d 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 {
diff --git a/modules/nix/nixpkgs.nix b/modules/nix/nixpkgs.nix
index ee999971..51bb1718 100644
--- a/modules/nix/nixpkgs.nix
+++ b/modules/nix/nixpkgs.nix
@@ -1,89 +1,96 @@
-{ config, options, lib, pkgs, ... }:
-
-with lib;
+{
+ config,
+ options,
+ lib,
+ pkgs,
+ ...
+}:
let
cfg = config.nixpkgs;
opt = options.nixpkgs;
- isConfig = x:
- builtins.isAttrs x || lib.isFunction x;
+ isConfig = x: builtins.isAttrs x || lib.isFunction x;
- optCall = f: x:
- if lib.isFunction f
- then f x
- else f;
+ optCall = f: x: if lib.isFunction f then f x else f;
- mergeConfig = lhs_: rhs_:
+ mergeConfig =
+ lhs_: rhs_:
let
lhs = optCall lhs_ { inherit pkgs; };
rhs = optCall rhs_ { inherit pkgs; };
in
- recursiveUpdate lhs rhs //
- optionalAttrs (lhs ? packageOverrides) {
- packageOverrides = pkgs:
- optCall lhs.packageOverrides pkgs //
- optCall (attrByPath [ "packageOverrides" ] { } rhs) pkgs;
- } //
- optionalAttrs (lhs ? perlPackageOverrides) {
- perlPackageOverrides = pkgs:
- optCall lhs.perlPackageOverrides pkgs //
- optCall (attrByPath [ "perlPackageOverrides" ] { } rhs) pkgs;
+ lib.recursiveUpdate lhs rhs
+ // lib.optionalAttrs (lhs ? packageOverrides) {
+ packageOverrides =
+ pkgs:
+ optCall lhs.packageOverrides pkgs // optCall (lib.attrByPath [ "packageOverrides" ] { } rhs) pkgs;
+ }
+ // lib.optionalAttrs (lhs ? perlPackageOverrides) {
+ perlPackageOverrides =
+ pkgs:
+ optCall lhs.perlPackageOverrides pkgs
+ // optCall (lib.attrByPath [ "perlPackageOverrides" ] { } rhs) pkgs;
};
- configType = mkOptionType {
+ configType = lib.mkOptionType {
name = "nixpkgs-config";
description = "nixpkgs config";
- check = x:
- let traceXIfNot = c:
- if c x then true
- else lib.traceSeqN 1 x false;
- in traceXIfNot isConfig;
- merge = args: foldr (def: mergeConfig def.value) {};
+ check =
+ x:
+ let
+ traceXIfNot = c: if c x then true else lib.traceSeqN 1 x false;
+ in
+ traceXIfNot isConfig;
+ merge = args: lib.foldr (def: mergeConfig def.value) { };
};
- overlayType = mkOptionType {
+ overlayType = lib.mkOptionType {
name = "nixpkgs-overlay";
description = "nixpkgs overlay";
check = lib.isFunction;
merge = lib.mergeOneOption;
};
- pkgsType = types.pkgs // {
+ pkgsType = lib.types.pkgs // {
# This type is only used by itself, so let's elaborate the description a bit
# for the purpose of documentation.
description = "An evaluation of Nixpkgs; the top level attribute set of packages";
};
- hasBuildPlatform = opt.buildPlatform.highestPrio < (mkOptionDefault {}).priority;
+ hasBuildPlatform = opt.buildPlatform.highestPrio < (lib.mkOptionDefault { }).priority;
hasHostPlatform = opt.hostPlatform.isDefined;
hasPlatform = hasHostPlatform || hasBuildPlatform;
# Context for messages
- hostPlatformLine = optionalString hasHostPlatform "${showOptionWithDefLocs opt.hostPlatform}";
- buildPlatformLine = optionalString hasBuildPlatform "${showOptionWithDefLocs opt.buildPlatform}";
+ hostPlatformLine = lib.optionalString hasHostPlatform "${lib.showOptionWithDefLocs opt.hostPlatform}";
+ buildPlatformLine = lib.optionalString hasBuildPlatform "${lib.showOptionWithDefLocs opt.buildPlatform}";
- legacyOptionsDefined =
- optional (opt.system.highestPrio < (mkDefault {}).priority) opt.system
- ;
+ legacyOptionsDefined = lib.optional (
+ opt.system.highestPrio < (lib.mkDefault { }).priority
+ ) opt.system;
defaultPkgs =
- if opt.hostPlatform.isDefined
- then
- let isCross = cfg.buildPlatform != cfg.hostPlatform;
- systemArgs =
- if isCross
- then {
+ if opt.hostPlatform.isDefined then
+ let
+ isCross = cfg.buildPlatform != cfg.hostPlatform;
+ systemArgs =
+ if isCross then
+ {
localSystem = cfg.buildPlatform;
crossSystem = cfg.hostPlatform;
}
- else {
+ else
+ {
localSystem = cfg.hostPlatform;
};
in
- import cfg.source ({
- inherit (cfg) config overlays;
- } // systemArgs)
+ import cfg.source (
+ {
+ inherit (cfg) config overlays;
+ }
+ // systemArgs
+ )
else
import cfg.source {
inherit (cfg) config overlays;
@@ -96,9 +103,9 @@ in
{
options.nixpkgs = {
- pkgs = mkOption {
+ pkgs = lib.mkOption {
type = pkgsType;
- example = literalExpression "import {}";
+ example = lib.literalExpression "import {}";
description = ''
If set, the pkgs argument to all nix-darwin modules is the value of
this option, extended with `nixpkgs.overlays`, if
@@ -120,53 +127,48 @@ in
'';
};
- config = mkOption {
- default = {};
- example = literalExpression
- ''
- { allowBroken = true; allowUnfree = true; }
- '';
+ config = lib.mkOption {
+ default = { };
+ example = lib.literalExpression ''
+ { allowBroken = true; allowUnfree = true; }
+ '';
type = configType;
description = ''
- The configuration of the Nix Packages collection. (For
- details, see the Nixpkgs documentation.) It allows you to set
- package configuration options.
+ Global configuration for Nixpkgs.
+ The complete list of [Nixpkgs configuration options](https://nixos.org/manual/nixpkgs/unstable/#sec-config-options-reference) is in the [Nixpkgs manual section on global configuration](https://nixos.org/manual/nixpkgs/unstable/#chap-packageconfig).
- Ignored when `nixpkgs.pkgs` is set.
+ Ignored when {option}`nixpkgs.pkgs` is set.
'';
};
- overlays = mkOption {
- default = [];
- example = literalExpression
- ''
- [
- (self: super: {
- openssh = super.openssh.override {
- hpnSupport = true;
- kerberos = self.libkrb5;
- };
- })
- ]
- '';
- type = types.listOf overlayType;
+ overlays = lib.mkOption {
+ default = [ ];
+ example = lib.literalExpression ''
+ [
+ (self: super: {
+ openssh = super.openssh.override {
+ hpnSupport = true;
+ kerberos = self.libkrb5;
+ };
+ })
+ ]
+ '';
+ type = lib.types.listOf overlayType;
description = ''
- List of overlays to use with the Nix Packages collection.
- (For details, see the Nixpkgs documentation.) It allows
- you to override packages globally. Each function in the list
- takes as an argument the *original* Nixpkgs.
- The first argument should be used for finding dependencies, and
- the second should be used for overriding recipes.
+ List of overlays to apply to Nixpkgs.
+ This option allows modifying the Nixpkgs package set accessed through the `pkgs` module argument.
- If `nixpkgs.pkgs` is set, overlays specified here
- will be applied after the overlays that were already present
- in `nixpkgs.pkgs`.
+ For details, see the [Overlays chapter in the Nixpkgs manual](https://nixos.org/manual/nixpkgs/stable/#chap-overlays).
+
+ If the {option}`nixpkgs.pkgs` option is set, overlays specified using `nixpkgs.overlays` will be applied after the overlays that were already included in `nixpkgs.pkgs`.
'';
};
- hostPlatform = mkOption {
- type = types.either types.str types.attrs; # TODO utilize lib.systems.parsedPlatform
- example = { system = "aarch64-darwin"; config = "aarch64-apple-darwin"; };
+ hostPlatform = lib.mkOption {
+ type = lib.types.either lib.types.str lib.types.attrs; # TODO utilize lib.systems.parsedPlatform
+ example = {
+ system = "aarch64-darwin";
+ };
# Make sure that the final value has all fields for sake of other modules
# referring to this. TODO make `lib.systems` itself use the module system.
apply = lib.systems.elaborate;
@@ -179,15 +181,24 @@ in
'';
};
- buildPlatform = mkOption {
- type = types.either types.str types.attrs; # TODO utilize lib.systems.parsedPlatform
+ buildPlatform = lib.mkOption {
+ type = lib.types.either lib.types.str lib.types.attrs; # TODO utilize lib.systems.parsedPlatform
default = cfg.hostPlatform;
- example = { system = "x86_64-darwin"; config = "x86_64-apple-darwin"; };
+ example = {
+ system = "x86_64-darwin";
+ };
# Make sure that the final value has all fields for sake of other modules
# referring to this.
- apply = lib.systems.elaborate;
- defaultText = literalExpression
- ''config.nixpkgs.hostPlatform'';
+ apply =
+ inputBuildPlatform:
+ let
+ elaborated = lib.systems.elaborate inputBuildPlatform;
+ in
+ if lib.systems.equals elaborated cfg.hostPlatform then
+ cfg.hostPlatform # make identical, so that `==` equality works; see https://github.com/NixOS/nixpkgs/issues/278001
+ else
+ elaborated;
+ defaultText = lib.literalExpression ''config.nixpkgs.hostPlatform'';
description = ''
Specifies the platform on which nix-darwin should be built.
By default, nix-darwin is built on the system where it runs, but you can
@@ -202,12 +213,11 @@ in
'';
};
- system = mkOption {
- type = types.str;
+ system = lib.mkOption {
+ type = lib.types.str;
example = "x86_64-darwin";
default =
- if opt.hostPlatform.isDefined
- then
+ if opt.hostPlatform.isDefined then
throw ''
Neither ${opt.system} nor any other option in nixpkgs.* is meant
to be read by modules and configurations.
@@ -232,9 +242,9 @@ in
# nix-darwin only
- source = mkOption {
- type = types.path;
- defaultText = literalMD ''
+ source = lib.mkOption {
+ type = lib.types.path;
+ defaultText = lib.literalMD ''
`` or nix-darwin's `nixpkgs` flake input
'';
description = ''
@@ -247,8 +257,8 @@ in
'';
};
- constructedByUs = mkOption {
- type = types.bool;
+ constructedByUs = lib.mkOption {
+ type = lib.types.bool;
internal = true;
description = ''
Whether `pkgs` was constructed by this module. This is false when any of
@@ -266,40 +276,51 @@ in
# which is somewhat costly for Nixpkgs. With an explicit priority, we only
# evaluate the wrapper to find out that the priority is lower, and then we
# don't need to evaluate `finalPkgs`.
- lib.mkOverride lib.modules.defaultOverridePriority
- finalPkgs.__splicedPackages;
+ lib.mkOverride lib.modules.defaultOverridePriority finalPkgs.__splicedPackages;
};
nixpkgs.constructedByUs =
# We set it with default priority and it can not be merged, so if the
# pkgs module argument has that priority, it's from us.
(lib.modules.mergeAttrDefinitionsWithPrio options._module.args).pkgs.highestPrio
- == lib.modules.defaultOverridePriority
+ == lib.modules.defaultOverridePriority
# Although, if nixpkgs.pkgs is set, we did forward it, but we did not construct it.
- && !opt.pkgs.isDefined;
+ && !opt.pkgs.isDefined;
assertions = [
(
let
pkgsSystem = finalPkgs.stdenv.targetPlatform.system;
- in {
+ in
+ {
assertion = cfg.constructedByUs -> !hasPlatform -> cfg.system == pkgsSystem;
- message = "The nix-darwin nixpkgs.pkgs option was set to a Nixpkgs invocation that compiles to target system ${pkgsSystem} but nix-darwin was configured for system ${darwinExpectedSystem} via nix-darwin option nixpkgs.system. The nix-darwin system settings must match the Nixpkgs target system.";
+ message = "The nix-darwin nixpkgs.pkgs option was set to a Nixpkgs invocation that compiles to target system ${pkgsSystem} but nix-darwin was configured for system ${config.nixpkgs.system} via nix-darwin option nixpkgs.system. The nix-darwin system settings must match the Nixpkgs target system.";
}
)
{
- assertion = cfg.constructedByUs -> hasPlatform -> legacyOptionsDefined == [];
+ assertion = cfg.constructedByUs -> hasPlatform -> legacyOptionsDefined == [ ];
message = ''
- Your system configures nixpkgs with the platform parameter${optionalString hasBuildPlatform "s"}:
- ${hostPlatformLine
- }${buildPlatformLine
- }
+ Your system configures nixpkgs with the platform parameter${lib.optionalString hasBuildPlatform "s"}:
+ ${hostPlatformLine}${buildPlatformLine}
However, it also defines the legacy options:
- ${concatMapStrings showOptionWithDefLocs legacyOptionsDefined}
+ ${lib.concatMapStrings lib.showOptionWithDefLocs legacyOptionsDefined}
For a future proof system configuration, we recommend to remove
the legacy definitions.
'';
}
+ {
+ assertion = opt.pkgs.isDefined -> cfg.config == { };
+ message = ''
+ Your system configures nixpkgs with an externally created instance.
+ `nixpkgs.config` options should be passed when creating the instance instead.
+
+ Current value:
+ ${lib.generators.toPretty { multiline = true; } cfg.config}
+
+ Defined in:
+ ${lib.concatMapStringsSep "\n" (file: " - ${file}") opt.config.files}
+ '';
+ }
];
};
}
diff --git a/modules/power/default.nix b/modules/power/default.nix
index a99905ff..c3e4974d 100644
--- a/modules/power/default.nix
+++ b/modules/power/default.nix
@@ -15,6 +15,8 @@ in
default = null;
description = ''
Whether to restart the computer after a power failure.
+
+ Option is not supported on all devices.
'';
};
diff --git a/modules/programs/fish.nix b/modules/programs/fish.nix
index 4b76e02e..65797ccd 100644
--- a/modules/programs/fish.nix
+++ b/modules/programs/fish.nix
@@ -57,6 +57,8 @@ in
type = types.bool;
};
+ package = lib.mkPackageOption pkgs "fish" { };
+
useBabelfish = mkOption {
type = types.bool;
default = false;
@@ -238,7 +240,7 @@ in
++ optional cfg.vendor.functions.enable "/share/fish/vendor_functions.d";
}
- { systemPackages = [ pkgs.fish ]; }
+ { systemPackages = [ cfg.package ]; }
];
};
diff --git a/modules/programs/ssh/default.nix b/modules/programs/ssh/default.nix
index 51c7796d..1e87732a 100644
--- a/modules/programs/ssh/default.nix
+++ b/modules/programs/ssh/default.nix
@@ -114,6 +114,15 @@ in
type = with types; attrsOf (submodule userOptions);
};
+ programs.ssh.extraConfig = lib.mkOption {
+ type = lib.types.lines;
+ default = "";
+ description = ''
+ Extra configuration text loaded in {file}`ssh_config`.
+ See {manpage}`ssh_config(5)` for help.
+ '';
+ };
+
programs.ssh.knownHosts = mkOption {
default = {};
type = types.attrsOf (types.submodule host);
@@ -151,6 +160,7 @@ in
+ (if h.publicKey != null then h.publicKey else readFile h.publicKeyFile)
)) + "\n";
};
+ "ssh/ssh_config.d/100-nix-darwin.conf".text = config.programs.ssh.extraConfig;
"ssh/sshd_config.d/101-authorized-keys.conf" = {
text = ''
# sshd doesn't like reading from symbolic links, so we cat
diff --git a/modules/programs/zsh/default.nix b/modules/programs/zsh/default.nix
index c6ec9175..65689bad 100644
--- a/modules/programs/zsh/default.nix
+++ b/modules/programs/zsh/default.nix
@@ -204,7 +204,7 @@ in
}
${optionalString cfg.enableFastSyntaxHighlighting
- "source ${pkgs.zsh-fast-syntax-highlighting}/share/zsh-fast-syntax-highlighting/zsh-fast-syntax-highlighting.zsh"
+ "source ${pkgs.zsh-fast-syntax-highlighting}/share/zsh/site-functions/fast-syntax-highlighting.plugin.zsh"
}
${optionalString cfg.enableFzfCompletion "source ${fzfCompletion}"}
diff --git a/modules/security/pam.nix b/modules/security/pam.nix
index 69b4c37e..e671e23f 100644
--- a/modules/security/pam.nix
+++ b/modules/security/pam.nix
@@ -1,69 +1,106 @@
{ config, lib, pkgs, ... }:
-with lib;
-
let
- cfg = config.security.pam;
-
- # Implementation Notes
- #
- # We don't use `environment.etc` because this would require that the user manually delete
- # `/etc/pam.d/sudo` which seems unwise given that applying the nix-darwin configuration requires
- # sudo. We also can't use `system.patchs` since it only runs once, and so won't patch in the
- # changes again after OS updates (which remove modifications to this file).
- #
- # As such, we resort to line addition/deletion in place using `sed`. We add a comment to the
- # added line that includes the name of the option, to make it easier to identify the line that
- # should be deleted when the option is disabled.
- mkSudoTouchIdAuthScript = isEnabled:
- let
- file = "/etc/pam.d/sudo";
- option = "security.pam.enableSudoTouchIdAuth";
- sed = "${pkgs.gnused}/bin/sed";
- in ''
- ${if isEnabled then ''
- # Enable sudo Touch ID authentication, if not already enabled
- if ! grep 'pam_tid.so' ${file} > /dev/null; then
- ${sed} -i '2i\
- auth sufficient pam_tid.so # nix-darwin: ${option}
- ' ${file}
- fi
- '' else ''
- # Disable sudo Touch ID authentication, if added by nix-darwin
- if grep '${option}' ${file} > /dev/null; then
- ${sed} -i '/${option}/d' ${file}
- fi
- ''}
- '';
+ cfg = config.security.pam.services.sudo_local;
in
-
{
+ imports = [
+ (lib.mkRemovedOptionModule [ "security" "pam" "enableSudoTouchIdAuth" ] ''
+ This option has been renamed to `security.pam.services.sudo_local.touchIdAuth` for consistency with NixOS.
+ '')
+ ];
+
options = {
- security.pam.enableSudoTouchIdAuth = mkEnableOption "" // {
- description = ''
- Enable sudo authentication with Touch ID.
+ security.pam.services.sudo_local = {
+ enable = lib.mkEnableOption "managing {file}`/etc/pam.d/sudo_local` with nix-darwin" // {
+ default = true;
+ example = false;
+ };
- When enabled, this option adds the following line to
- {file}`/etc/pam.d/sudo`:
+ text = lib.mkOption {
+ type = lib.types.lines;
+ default = "";
+ description = ''
+ Contents of {file}`/etc/pam.d/sudo_local`
+ '';
+ };
- ```
- auth sufficient pam_tid.so
- ```
+ touchIdAuth = lib.mkEnableOption "" // {
+ description = ''
+ Whether to enable Touch ID with sudo.
- ::: {.note}
- macOS resets this file when doing a system update. As such, sudo
- authentication with Touch ID won't work after a system update
- until the nix-darwin configuration is reapplied.
- :::
- '';
+ This will also allow your Apple Watch to be used for sudo. If this doesn't work,
+ you can go into `System Settings > Touch ID & Password` and toggle the switch for
+ your Apple Watch.
+ '';
+ };
+
+ watchIdAuth = lib.mkEnableOption "" // {
+ description = ''
+ Use Apple Watch for sudo authentication, for devices without Touch ID or
+ laptops with lids closed, consider using this.
+
+ When enabled, you can use your Apple Watch to authenticate sudo commands.
+ If this doesn't work, you can go into `System Settings > Touch ID & Password`
+ and toggle the switch for your Apple Watch.
+ '';
+ };
+
+ reattach = lib.mkEnableOption "" // {
+ description = ''
+ Whether to enable reattaching a program to the user's bootstrap session.
+
+ This fixes Touch ID for sudo not working inside tmux and screen.
+
+ This allows programs like tmux and screen that run in the background to
+ survive across user sessions to work with PAM services that are tied to the
+ bootstrap session.
+ '';
+ };
};
};
config = {
- system.activationScripts.pam.text = ''
+ security.pam.services.sudo_local.text = lib.concatLines (
+ (lib.optional cfg.reattach "auth optional ${pkgs.pam-reattach}/lib/pam/pam_reattach.so")
+ ++ (lib.optional cfg.touchIdAuth "auth sufficient pam_tid.so")
+ ++ (lib.optional cfg.watchIdAuth "auth sufficient ${pkgs.pam-watchid}/lib/pam_watchid.so")
+ );
+
+ environment.etc."pam.d/sudo_local" = {
+ inherit (cfg) enable text;
+ };
+
+ system.activationScripts.pam.text =
+ let
+ file = "/etc/pam.d/sudo";
+ marker = "security.pam.services.sudo_local";
+ deprecatedOption = "security.pam.enableSudoTouchIdAuth";
+ sed = lib.getExe pkgs.gnused;
+ in
+ ''
# PAM settings
echo >&2 "setting up pam..."
- ${mkSudoTouchIdAuthScript cfg.enableSudoTouchIdAuth}
+
+ # REMOVEME when macOS 13 no longer supported as macOS automatically
+ # nukes this file on system upgrade
+ # Always clear out older implementation if it is present
+ if grep '${deprecatedOption}' ${file} > /dev/null; then
+ ${sed} -i '/${deprecatedOption}/d' ${file}
+ fi
+
+ ${if cfg.enable then ''
+ # REMOVEME when macOS 13 no longer supported
+ # `sudo_local` is automatically included after macOS 14
+ if ! grep 'sudo_local' ${file} > /dev/null; then
+ ${sed} -i '2iauth include sudo_local # nix-darwin: ${marker}' ${file}
+ fi
+ '' else ''
+ # Remove include line if we added it
+ if grep '${marker}' ${file} > /dev/null; then
+ ${sed} -i '/${marker}/d' ${file}
+ fi
+ ''}
'';
};
}
diff --git a/modules/services/activate-system/default.nix b/modules/services/activate-system/default.nix
index 6a982fe8..df0b48e4 100644
--- a/modules/services/activate-system/default.nix
+++ b/modules/services/activate-system/default.nix
@@ -21,14 +21,15 @@
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}
${config.system.activationScripts.keyboard.text}
'';
serviceConfig.RunAtLoad = true;
- serviceConfig.KeepAlive.SuccessfulExit = false;
};
};
}
diff --git a/modules/services/aerospace/default.nix b/modules/services/aerospace/default.nix
index 50d47b3b..3080579d 100644
--- a/modules/services/aerospace/default.nix
+++ b/modules/services/aerospace/default.nix
@@ -9,7 +9,31 @@ let
cfg = config.services.aerospace;
format = pkgs.formats.toml { };
- configFile = format.generate "aerospace.toml" cfg.settings;
+ filterAttrsRecursive = pred: set:
+ lib.listToAttrs (
+ lib.concatMap (
+ name: let
+ v = set.${name};
+ in
+ if pred v
+ then [
+ (lib.nameValuePair name (
+ if lib.isAttrs v
+ then filterAttrsRecursive pred v
+ else if lib.isList v
+ then
+ (map (i:
+ if lib.isAttrs i
+ then filterAttrsRecursive pred i
+ else i) (lib.filter pred v))
+ else v
+ ))
+ ]
+ else []
+ ) (lib.attrNames set)
+ );
+ filterNulls = filterAttrsRecursive (v: v != null);
+ configFile = format.generate "aerospace.toml" (filterNulls cfg.settings);
in
{
@@ -36,7 +60,8 @@ in
after-startup-command = lib.mkOption {
type = listOf str;
default = [ ];
- description = "Do not use AeroSpace to run commands after startup. (Managed by launchd instead)";
+ description = "Add commands that run after AeroSpace startup";
+ example = [ "layout tiles" ];
};
enable-normalization-flatten-containers = lib.mkOption {
type = bool;
@@ -71,9 +96,84 @@ in
description = "Default orientation for the root container.";
};
on-window-detected = lib.mkOption {
- type = listOf str;
+ type = listOf (submodule {
+ options = {
+ "if" = lib.mkOption {
+ type = submodule {
+ options = {
+ app-id = lib.mkOption {
+ type = nullOr str;
+ default = null;
+ description = "The application ID to match (optional).";
+ };
+ workspace = lib.mkOption {
+ type = nullOr str;
+ default = null;
+ description = "The workspace name to match (optional).";
+ };
+ window-title-regex-substring = lib.mkOption {
+ type = nullOr str;
+ default = null;
+ description = "Substring to match in the window title (optional).";
+ };
+ app-name-regex-substring = lib.mkOption {
+ type = nullOr str;
+ default = null;
+ description = "Regex substring to match the app name (optional).";
+ };
+ during-aerospace-startup = lib.mkOption {
+ type = nullOr bool;
+ default = null;
+ description = "Whether to match during aerospace startup (optional).";
+ };
+ };
+ };
+ default = { };
+ description = "Conditions for detecting a window.";
+ };
+ check-further-callbacks = lib.mkOption {
+ type = nullOr bool;
+ default = null;
+ description = "Whether to check further callbacks after this rule (optional).";
+ };
+ run = lib.mkOption {
+ type = oneOf [str (listOf str)];
+ example = ["move-node-to-workspace m" "resize-node"];
+ description = "Commands to execute when the conditions match (required).";
+ };
+ };
+ });
default = [ ];
- description = "Commands to run every time a new window is detected.";
+ example = [
+ {
+ "if" = {
+ app-id = "Another.Cool.App";
+ workspace = "cool-workspace";
+ window-title-regex-substring = "Title";
+ app-name-regex-substring = "CoolApp";
+ during-aerospace-startup = false;
+ };
+ check-further-callbacks = false;
+ run = ["move-node-to-workspace m" "resize-node"];
+ }
+ ];
+ description = "Commands to run every time a new window is detected with optional conditions.";
+ };
+ workspace-to-monitor-force-assignment = lib.mkOption {
+ type = attrsOf (oneOf [int str (listOf str)]);
+ default = { };
+ description = ''
+ Map workspaces to specific monitors.
+ Left-hand side is the workspace name, and right-hand side is the monitor pattern.
+ '';
+ example = {
+ "1" = 1; # First monitor from left to right.
+ "2" = "main"; # Main monitor.
+ "3" = "secondary"; # Secondary monitor (non-main).
+ "4" = "built-in"; # Built-in display.
+ "5" = "^built-in retina display$"; # Regex for the built-in retina display.
+ "6" = ["secondary" "dell"]; # Match first pattern in the list.
+ };
};
on-focus-changed = lib.mkOption {
type = listOf str;
@@ -142,10 +242,6 @@ in
assertion = cfg.settings.after-login-command == [ ];
message = "AeroSpace will not run these commands as it does not start itself.";
}
- {
- assertion = cfg.settings.after-startup-command == [ ];
- message = "AeroSpace will not run these commands as it does not start itself.";
- }
];
environment.systemPackages = [ cfg.package ];
diff --git a/modules/services/buildkite-agents.nix b/modules/services/buildkite-agents.nix
index 69bc1f65..3c04d904 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/cachix-agent.nix b/modules/services/cachix-agent.nix
index d9e4a909..508261af 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}
diff --git a/modules/services/dnscrypt-proxy.nix b/modules/services/dnscrypt-proxy.nix
new file mode 100644
index 00000000..f0ba1d52
--- /dev/null
+++ b/modules/services/dnscrypt-proxy.nix
@@ -0,0 +1,81 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+
+let
+
+ cfg = config.services.dnscrypt-proxy;
+
+ format = pkgs.formats.toml { };
+
+ configFile = format.generate "dnscrypt-proxy.toml" cfg.settings;
+
+in
+
+{
+ options.services.dnscrypt-proxy = {
+
+ enable = lib.mkEnableOption "the dnscrypt-proxy service.";
+
+ package = lib.mkPackageOption pkgs "dnscrypt-proxy" { };
+
+ settings = lib.mkOption {
+ description = ''
+ Attrset that is converted and passed as TOML config file.
+ For available params, see:
+ '';
+ example = lib.literalExpression ''
+ {
+ sources.public-resolvers = {
+ urls = [ "https://download.dnscrypt.info/resolvers-list/v2/public-resolvers.md" ];
+ cache_file = "public-resolvers.md";
+ minisign_key = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3";
+ refresh_delay = 72;
+ };
+ }
+ '';
+ type = format.type;
+ default = { };
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ users.users._dnscrypt-proxy = {
+ uid = config.ids.uids._dnscrypt-proxy;
+ gid = config.ids.gids._dnscrypt-proxy;
+ home = "/var/lib/dnscrypt-proxy";
+ createHome = true;
+ shell = "/usr/bin/false";
+ description = "System user for dnscrypt-proxy";
+ };
+
+ users.groups._dnscrypt-proxy = {
+ gid = config.ids.gids._dnscrypt-proxy;
+ description = "System group for dnscrypt-proxy";
+ };
+
+ users.knownUsers = [ "_dnscrypt-proxy" ];
+ users.knownGroups = [ "_dnscrypt-proxy" ];
+
+ launchd.daemons.dnscrypt-proxy = {
+ script = ''
+ ${lib.getExe' cfg.package "dnscrypt-proxy"} -config ${configFile}
+ '';
+ serviceConfig =
+ let
+ logPath = config.users.users._dnscrypt-proxy.home + "/dnscrypt-proxy.log";
+ in
+ {
+ RunAtLoad = true;
+ KeepAlive = true;
+ StandardOutPath = logPath;
+ StandardErrorPath = logPath;
+ GroupName = "_dnscrypt-proxy";
+ UserName = "_dnscrypt-proxy";
+ };
+ };
+ };
+}
diff --git a/modules/services/github-runner/options.nix b/modules/services/github-runner/options.nix
index 8f98aa07..5152cc43 100644
--- a/modules/services/github-runner/options.nix
+++ b/modules/services/github-runner/options.nix
@@ -3,7 +3,9 @@
, ...
}:
-with lib;
+let
+ inherit (lib) literalExpression mkOption mkPackageOption types;
+in
{
options.services.github-runners = mkOption {
description = ''
@@ -88,6 +90,9 @@ with lib;
Changing this option or the `tokenFile`’s content triggers a new runner registration.
+ You can also manually trigger a new runner registration by deleting
+ {file}`/var/lib/github-runners//.runner` and restarting the service.
+
We suggest using the fine-grained PATs. A runner registration token is valid
only for 1 hour after creation, so the next time the runner configuration changes
this will give you hard-to-debug HTTP 404 errors in the configure step.
diff --git a/modules/services/github-runner/service.nix b/modules/services/github-runner/service.nix
index 21d908e0..3668a721 100644
--- a/modules/services/github-runner/service.nix
+++ b/modules/services/github-runner/service.nix
@@ -1,6 +1,10 @@
{ config, lib, pkgs, ... }:
-with lib;
+
let
+ inherit (lib) any attrValues boolToString concatStringsSep escapeShellArg
+ flatten flip getExe getExe' hasAttr hasPrefix mapAttrsToList mapAttrs' mkBefore
+ mkDefault mkIf mkMerge nameValuePair optionalAttrs optionalString replaceStrings;
+
mkSvcName = name: "github-runner-${name}";
mkStateDir = cfg: "/var/lib/github-runners/${cfg.name}";
mkLogDir = cfg: "/var/log/github-runners/${cfg.name}";
@@ -9,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";
@@ -51,15 +60,17 @@ in
(
umask -S u=rwx,g=rx,o= > /dev/null
- ${pkgs.coreutils}/bin/mkdir -p ${escapeShellArg (mkStateDir cfg)}
- ${pkgs.coreutils}/bin/chown ${user}:${group} ${escapeShellArg (mkStateDir cfg)}
+ ${getExe' pkgs.coreutils "mkdir"} -p ${escapeShellArg (mkStateDir cfg)}
+ ${getExe' pkgs.coreutils "chown"} ${user}:${group} ${escapeShellArg (mkStateDir cfg)}
- ${pkgs.coreutils}/bin/mkdir -p ${escapeShellArg (mkLogDir cfg)}
- ${pkgs.coreutils}/bin/chown ${user}:${group} ${escapeShellArg (mkLogDir cfg)}
+ ${getExe' pkgs.coreutils "mkdir"} -p ${escapeShellArg (mkLogDir cfg)}
+ # launchd will fail to start the service if the outer direction doesn't have sufficient permissions
+ ${getExe' pkgs.coreutils "chmod"} o+rx ${escapeShellArg (mkLogDir { name = ""; })}
+ ${getExe' pkgs.coreutils "chown"} ${user}:${group} ${escapeShellArg (mkLogDir cfg)}
${optionalString (cfg.workDir == null) ''
- ${pkgs.coreutils}/bin/mkdir -p ${escapeShellArg (mkWorkDir cfg)}
- ${pkgs.coreutils}/bin/chown ${user}:${group} ${escapeShellArg (mkWorkDir cfg)}
+ ${getExe' pkgs.coreutils "mkdir"} -p ${escapeShellArg (mkWorkDir cfg)}
+ ${getExe' pkgs.coreutils "chown"} ${user}:${group} ${escapeShellArg (mkWorkDir cfg)}
''}
)
'');
@@ -123,7 +134,7 @@ in
else
args+=(--token "$token")
fi
- ${package}/bin/config.sh "''${args[@]}"
+ ${getExe' package "config.sh"} "''${args[@]}"
'';
};
in
@@ -131,12 +142,12 @@ in
echo "Configuring GitHub Actions Runner"
# Always clean the working directory
- ${pkgs.findutils}/bin/find ${escapeShellArg workDir} -mindepth 1 -delete
+ ${getExe pkgs.findutils} ${escapeShellArg workDir} -mindepth 1 -delete
# Clean the $RUNNER_ROOT if we are in ephemeral mode
if ${boolToString cfg.ephemeral}; then
echo "Cleaning $RUNNER_ROOT"
- ${pkgs.findutils}/bin/find "$RUNNER_ROOT" -mindepth 1 -delete
+ ${getExe pkgs.findutils} "$RUNNER_ROOT" -mindepth 1 -delete
fi
# If the `.runner` file does not exist, we assume the runner is not configured
@@ -145,7 +156,7 @@ in
fi
# Start the service
- ${package}/bin/Runner.Listener run --startuptype service
+ ${getExe' package "Runner.Listener"} run --startuptype service
'';
serviceConfig = mkMerge [
diff --git a/modules/services/gitlab-runner.nix b/modules/services/gitlab-runner.nix
index 94c291ef..329fd727 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 fc3d9520..47368294 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}";
@@ -74,7 +82,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/lorri.nix b/modules/services/lorri.nix
index 0c123004..c4e1acee 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
+}
diff --git a/modules/services/nix-daemon.nix b/modules/services/nix-daemon.nix
index ffc7e651..404ca057 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 9fe8e86d..b8d5c4d9 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; }];
@@ -62,15 +56,18 @@ in
###### implementation
- config = mkIf cfg.automatic {
+ config = {
+ assertions = [
+ {
+ assertion = cfg.automatic -> config.nix.enable;
+ message = ''nix.gc.automatic requires nix.enable'';
+ }
+ ];
- launchd.daemons.nix-gc = {
+ 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;
};
-
};
}
diff --git a/modules/services/nix-optimise/default.nix b/modules/services/nix-optimise/default.nix
index c0ee0a38..addf0467 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; }];
@@ -58,17 +52,20 @@ in
###### implementation
- config = mkIf cfg.automatic {
+ config = {
+ assertions = [
+ {
+ assertion = cfg.automatic -> config.nix.enable;
+ message = ''nix.optimise.automatic requires nix.enable'';
+ }
+ ];
- launchd.daemons.nix-optimise = {
- environment.NIX_REMOTE = optionalString config.nix.useDaemon "daemon";
+ launchd.daemons.nix-optimise = mkIf cfg.automatic {
command = "${lib.getExe' config.nix.package "nix-store"} --optimise";
serviceConfig = {
RunAtLoad = false;
StartCalendarInterval = cfg.interval;
- UserName = cfg.user;
};
};
-
};
}
diff --git a/modules/services/ofborg/default.nix b/modules/services/ofborg/default.nix
index 8959cc84..acd6974f 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"
];
diff --git a/modules/services/openssh.nix b/modules/services/openssh.nix
new file mode 100644
index 00000000..859f79d8
--- /dev/null
+++ b/modules/services/openssh.nix
@@ -0,0 +1,33 @@
+{ config, lib, ... }:
+
+let
+ cfg = config.services.openssh;
+in
+{
+ options = {
+ services.openssh.enable = lib.mkOption {
+ type = lib.types.nullOr lib.types.bool;
+ default = null;
+ description = ''
+ Whether to enable Apple's built-in OpenSSH server.
+
+ The default is null which means let macOS manage the OpenSSH server.
+ '';
+ };
+ };
+
+ config = {
+ # We don't use `systemsetup -setremotelogin` as it requires Full Disk Access
+ system.activationScripts.launchd.text = lib.mkIf (cfg.enable != null) (if cfg.enable then ''
+ if [[ "$(systemsetup -getremotelogin | sed 's/Remote Login: //')" == "Off" ]]; then
+ launchctl enable system/com.openssh.sshd
+ launchctl bootstrap system /System/Library/LaunchDaemons/ssh.plist
+ fi
+ '' else ''
+ if [[ "$(systemsetup -getremotelogin | sed 's/Remote Login: //')" == "On" ]]; then
+ launchctl bootout system/com.openssh.sshd
+ launchctl disable system/com.openssh.sshd
+ fi
+ '');
+ };
+}
diff --git a/modules/system/activation-scripts.nix b/modules/system/activation-scripts.nix
index 5f8916cc..c8ad20ad 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,13 +66,12 @@ 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@
- _status=0
- trap "_status=1" ERR
-
# Ensure a consistent umask.
umask 0022
@@ -81,9 +106,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
-
- exit $_status
+ if [[ -d /nix/var/nix/gcroots ]]; then
+ ln -sfn /run/current-system /nix/var/nix/gcroots/current-system
+ fi
'';
# FIXME: activationScripts.checks should be system level
@@ -91,7 +116,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/base.nix b/modules/system/base.nix
index f20e2b64..40c3699b 100644
--- a/modules/system/base.nix
+++ b/modules/system/base.nix
@@ -2,50 +2,35 @@
{
system.activationScripts.createRun.text = ''
- IFS="." read -r -a macOSVersion <<< "$(sw_vers -productVersion)"
+ if [[ $(stat -c '%a' /etc/synthetic.conf) != "644" ]]; then
+ echo "fixing permissions on /etc/synthetic.conf..."
+ sudo chmod 644 /etc/synthetic.conf
+ fi
- if [[ ''${macOSVersion[0]} -gt 10 || ( ''${macOSVersion[0]} -eq 10 && ''${macOSVersion[1]} -ge 15 ) ]]; then
- if ! grep -q '^run\b' /etc/synthetic.conf 2>/dev/null; then
- echo "setting up /run via /etc/synthetic.conf..."
- printf 'run\tprivate/var/run\n' | sudo tee -a /etc/synthetic.conf >/dev/null
- fi
+ if [[ $(grep -c '^run\b' /etc/synthetic.conf) -gt 1 ]]; then
+ echo "found duplicate run entries in /etc/synthetic.conf, removing..."
+ sudo sed -i "" -e '/^run\tprivate\/var\/run$/d' /etc/synthetic.conf
+ fi
- if [[ ''${macOSVersion[0]} -gt 10 ]]; then
- sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t || true
- else
- sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -B || true
- fi
+ if ! grep -q '^run\b' /etc/synthetic.conf 2>/dev/null; then
+ echo "setting up /run via /etc/synthetic.conf..."
+ printf 'run\tprivate/var/run\n' | sudo tee -a /etc/synthetic.conf >/dev/null
+ fi
- if [[ ! -L /run ]]; then
- printf >&2 '[1;31merror: apfs.util failed to symlink /run, aborting activation[0m\n'
- printf >&2 'To create a symlink from /run to /var/run, please run:\n'
- printf >&2 '\n'
- printf >&2 "$ printf 'run\tprivate/var/run\n' | sudo tee -a /etc/synthetic.conf"
+ sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t || true
- if [[ ''${macOSVersion[0]} -gt 10 ]]; then
- printf >&2 '$ sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t\n'
- else
- printf >&2 '$ sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -B\n'
- fi
-
- printf >&2 '\n'
- printf >&2 'The current contents of /etc/synthetic.conf is:\n'
- printf >&2 '\n'
- sudo sed 's/^/ /' /etc/synthetic.conf >&2
- printf >&2 '\n'
- exit 1
- fi
- else
- echo "setting up /run..."
- sudo ln -sfn private/var/run /run
-
- if [[ ! -L /run ]]; then
- printf >&2 '[1;31merror: failed to symlink /run, aborting activation[0m\n'
- printf >&2 'To create a symlink from /run to /var/run, please run:\n'
- printf >&2 '\n'
- printf >&2 '$ sudo ln -sfn private/var/link /run\n'
- exit 1
- fi
+ if [[ ! -L /run ]]; then
+ printf >&2 '[1;31merror: apfs.util failed to symlink /run, aborting activation[0m\n'
+ printf >&2 'To create a symlink from /run to /var/run, please run:\n'
+ printf >&2 '\n'
+ printf >&2 "$ printf 'run\tprivate/var/run\n' | sudo tee -a /etc/synthetic.conf\n"
+ printf >&2 '$ sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t\n'
+ printf >&2 '\n'
+ printf >&2 'The current contents of /etc/synthetic.conf is:\n'
+ printf >&2 '\n'
+ sed 's/^/ /' /etc/synthetic.conf >&2
+ printf >&2 '\n'
+ exit 1
fi
'';
}
diff --git a/modules/system/checks.nix b/modules/system/checks.nix
index 796e7e4e..6afe796c 100644
--- a/modules/system/checks.nix
+++ b/modules/system/checks.nix
@@ -8,53 +8,54 @@ let
cfg = config.system.checks;
- darwinChanges = ''
- darwinChanges=/dev/null
- if test -e /run/current-system/darwin-changes; then
- darwinChanges=/run/current-system/darwin-changes
- fi
-
- darwinChanges=$(diff --changed-group-format='%>' --unchanged-group-format= /run/current-system/darwin-changes $systemConfig/darwin-changes 2> /dev/null) || true
- if test -n "$darwinChanges"; then
- echo >&2
- echo "[1;1mCHANGELOG[0m" >&2
- echo >&2
- echo "$darwinChanges" >&2
- echo >&2
+ macOSVersion = ''
+ IFS=. read -ra osVersion <<<"$(sw_vers -productVersion)"
+ if (( osVersion[0] < 11 || (osVersion[0] == 11 && osVersion[1] < 3) )); then
+ printf >&2 '\e[1;31merror: macOS version is less than 11.3, aborting activation\e[0m\n'
+ printf >&2 'Nixpkgs 25.05 requires macOS Big Sur 11.3 or newer, and 25.11 will\n'
+ printf >&2 'require macOS Sonoma 14.\n'
+ printf >&2 '\n'
+ printf >&2 'For more information on your options going forward, see the 25.05\n'
+ printf >&2 'release notes:\n'
+ printf >&2 '\n'
+ printf >&2 '\n'
+ printf >&2 'Nixpkgs 24.11 and nix-darwin 24.11 continue to support down to macOS\n'
+ printf >&2 'Sierra 10.12, and will be supported through June 2025.\n'
+ printf >&2 '\n'
+ printf >&2 'You can override this check by setting:\n'
+ printf >&2 '\n'
+ printf >&2 ' system.checks.verifyMacOSVersion = false;\n'
+ printf >&2 '\n'
+ printf >&2 'However, we are unable to provide support if you do so.\n'
+ exit 2
fi
'';
- runLink = ''
- if [[ ! -e /run ]]; then
- printf >&2 '[1;31merror: directory /run does not exist, aborting activation[0m\n'
- exit 1
+ 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
'';
-
- oldBuildUsers = ''
- if dscl . -list /Users | grep -q '^nixbld'; then
- echo "[1;31merror: Detected old style nixbld users, aborting activation[0m" >&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
- '';
-
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'
@@ -87,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 "[1;31merror: Using the nix-daemon requires build users, aborting activation[0m" >&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 = ''
@@ -118,7 +103,6 @@ let
printf >&2 'Possible causes include setting up a new Nix installation with an\n'
printf >&2 'existing nix-darwin configuration, setting up a new nix-darwin\n'
printf >&2 'installation with an existing Nix installation, or manually increasing\n'
- # shellcheck disable=SC2016
printf >&2 'your `system.stateVersion` setting.\n'
printf >&2 '\n'
printf >&2 'You can set the configured group ID to match the actual value:\n'
@@ -132,46 +116,21 @@ let
fi
'';
- nixDaemon = if config.nix.useDaemon then ''
- if ! dscl . -read /Groups/nixbld PrimaryGroupID &> /dev/null; then
- printf >&2 '[1;31merror: The daemon should not be enabled for single-user installs, aborting activation[0m\n'
- printf >&2 'Disable the nix-daemon service:\n'
+ nixDaemon = ''
+ if [[ "$(stat --format='%u' /nix)" != 0 ]]; then
+ printf >&2 '[1;31merror: single‐user install detected, aborting activation[0m\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'
- # shellcheck disable=SC2016
- 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 '[1;31merror: The daemon should be enabled for multi-user installs, aborting activation[0m\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 "[1;31merror: The ~/.nix-defexpr/channels symlink does not point your users channels, aborting activation[0m" >&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 = ''
@@ -196,7 +155,7 @@ let
darwinConfig=$(NIX_PATH=$nixPath nix-instantiate --find-file darwin-config) || true
if ! test -e "$darwinConfig"; then
echo "[1;31merror: Changed but target does not exist, aborting activation[0m" >&2
- echo "Create ''${darwinConfig:-~/.nixpkgs/darwin-configuration.nix} or set environment.darwinConfig:" >&2
+ echo "Create ''${darwinConfig:-/etc/nix-darwin/configuration.nix} or set environment.darwinConfig:" >&2
echo >&2
echo " environment.darwinConfig = \"$(nix-instantiate --find-file darwin-config 2> /dev/null || echo '***')\";" >&2
echo >&2
@@ -211,8 +170,8 @@ let
if ! test -e "$darwinPath"; then
echo "[1;31merror: Changed but target does not exist, aborting activation[0m" >&2
echo "Add the darwin repo as a channel or set nix.nixPath:" >&2
- echo "$ nix-channel --add https://github.com/LnL7/nix-darwin/archive/master.tar.gz darwin" >&2
- echo "$ nix-channel --update" >&2
+ echo "$ sudo nix-channel --add https://github.com/LnL7/nix-darwin/archive/master.tar.gz darwin" >&2
+ echo "$ sudo nix-channel --update" >&2
echo >&2
echo "or set" >&2
echo >&2
@@ -225,8 +184,8 @@ let
if ! test -e "$nixpkgsPath"; then
echo "[1;31merror: Changed but target does not exist, aborting activation[0m" >&2
echo "Add a nixpkgs channel or set nix.nixPath:" >&2
- echo "$ nix-channel --add http://nixos.org/channels/nixpkgs-unstable nixpkgs" >&2
- echo "$ nix-channel --update" >&2
+ echo "$ sudo nix-channel --add http://nixos.org/channels/nixpkgs-unstable nixpkgs" >&2
+ echo "$ sudo nix-channel --update" >&2
echo >&2
echo "or set" >&2
echo >&2
@@ -236,50 +195,12 @@ let
fi
'';
- nixStore = ''
- if test -w /nix/var/nix/db -a ! -O /nix/store; then
- echo >&2 "[1;31merror: the store is not owned by this user, but /nix/var/nix/db is writable[0m"
- 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 "[1;31merror: A single-user install can't run gc as root, aborting activation[0m" >&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 "[1;31merror: A single-user install can't run optimiser as root, aborting activation[0m" >&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 = ''
if [[ -d /etc/ssh/authorized_keys.d ]]; then
printf >&2 '\e[1;31merror: /etc/ssh/authorized_keys.d exists, aborting activation\e[0m\n'
printf >&2 'SECURITY NOTICE: The previous implementation of the\n'
- # shellcheck disable=SC2016
printf >&2 '`users.users..openssh.authorizedKeys.*` options would not delete\n'
printf >&2 'authorized keys files when the setting for a given user was removed.\n'
printf >&2 '\n'
@@ -302,36 +223,47 @@ let
echo "Homebrew doesn't seem to be installed. Please install homebrew separately." >&2
echo "You can install homebrew using the following command:" >&2
echo >&2
- # shellcheck disable=SC2016
echo ' /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"' >&2
echo >&2
exit 2
fi
'';
+
+ # some mac devices, notably notebook do not support restartAfterPowerFailure option
+ restartAfterPowerFailureIsSupported = ''
+ if sudo /usr/sbin/systemsetup -getRestartPowerFailure | grep -q "Not supported"; then
+ printf >&2 "\e[1;31merror: restarting after power failure is not supported on your machine\e[0m\n" >&2
+ printf >&2 "Please ensure that \`power.restartAfterPowerFailure\` is not set.\n" >&2
+ exit 2
+ fi
+ '';
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.";
};
+ system.checks.verifyMacOSVersion = mkOption {
+ type = types.bool;
+ default = true;
+ description = "Whether to run the macOS version check.";
+ };
+
system.checks.text = mkOption {
internal = true;
type = types.lines;
@@ -342,21 +274,16 @@ in
config = {
system.checks.text = mkMerge [
- darwinChanges
- runLink
- (mkIf (cfg.verifyBuildUsers && !config.nix.configureBuildUsers) oldBuildUsers)
- (mkIf cfg.verifyBuildUsers buildUsers)
+ (mkIf cfg.verifyMacOSVersion macOSVersion)
+ (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
(mkIf config.homebrew.enable homebrewInstalled)
+ (mkIf (config.power.restartAfterPowerFailure != null) restartAfterPowerFailureIsSupported)
];
system.activationScripts.checks.text = ''
diff --git a/modules/system/default.nix b/modules/system/default.nix
index a1862fae..8351dcc6 100644
--- a/modules/system/default.nix
+++ b/modules/system/default.nix
@@ -135,7 +135,10 @@ in
chmod u+x $out/activate-user
unset activationUserScript
- shellcheck $out/activate $out/activate-user
+ # We exclude the warnings for `…` in single‐quote strings and
+ # non‐ASCII quotation marks as they are noisy and lead to a lot
+ # of false positives in our user‐facing output:
+ shellcheck --exclude=SC2016,SC1112 $out/activate $out/activate-user
echo -n "$systemConfig" > $out/systemConfig
diff --git a/modules/system/defaults-write.nix b/modules/system/defaults-write.nix
index 87b179b8..a00b0e42 100644
--- a/modules/system/defaults-write.nix
+++ b/modules/system/defaults-write.nix
@@ -9,6 +9,9 @@ let
"defaults write ${domain} '${key}' $'${strings.escape [ "'" ] (generators.toPlist { } value)}'";
defaultsToList = domain: attrs: mapAttrsToList (writeDefault domain) (filterAttrs (n: v: v != null) attrs);
+ # Filter out options to not pass through
+ # dock has alias options that we need to ignore
+ dockFiltered = (builtins.removeAttrs cfg.dock ["expose-group-by-app"]);
# defaults
alf = defaultsToList "/Library/Preferences/com.apple.alf" cfg.alf;
@@ -21,7 +24,7 @@ let
LaunchServices = defaultsToList "com.apple.LaunchServices" cfg.LaunchServices;
NSGlobalDomain = defaultsToList "-g" cfg.NSGlobalDomain;
menuExtraClock = defaultsToList "com.apple.menuextra.clock" cfg.menuExtraClock;
- dock = defaultsToList "com.apple.dock" cfg.dock;
+ dock = defaultsToList "com.apple.dock" dockFiltered;
finder = defaultsToList "com.apple.finder" cfg.finder;
hitoolbox = defaultsToList "com.apple.HIToolbox" cfg.hitoolbox;
magicmouse = defaultsToList "com.apple.AppleMultitouchMouse" cfg.magicmouse;
@@ -39,7 +42,7 @@ let
CustomSystemPreferences = flatten (mapAttrsToList (name: value: defaultsToList name value) cfg.CustomSystemPreferences);
- mkIfAttrs = list: mkIf (any (attrs: attrs != { }) list);
+ mkIfLists = list: mkIf (any (attrs: attrs != [ ]) list);
in
{
@@ -54,7 +57,7 @@ in
else types.float.check x;
};
- system.activationScripts.defaults.text = mkIfAttrs [
+ system.activationScripts.defaults.text = mkIfLists [
alf
loginwindow
smb
@@ -71,7 +74,7 @@ in
${concatStringsSep "\n" CustomSystemPreferences}
'';
- system.activationScripts.userDefaults.text = mkIfAttrs
+ system.activationScripts.userDefaults.text = mkIfLists
[
GlobalPreferences
LaunchServices
diff --git a/modules/system/defaults/WindowManager.nix b/modules/system/defaults/WindowManager.nix
index 38fbaa37..7b9048cc 100644
--- a/modules/system/defaults/WindowManager.nix
+++ b/modules/system/defaults/WindowManager.nix
@@ -57,6 +57,38 @@ with lib;
'';
};
+ system.defaults.WindowManager.EnableTilingByEdgeDrag = mkOption {
+ type = types.nullOr types.bool;
+ default = null;
+ description = ''
+ Enable dragging windows to screen edges to tile them. The default is true.
+ '';
+ };
+
+ system.defaults.WindowManager.EnableTopTilingByEdgeDrag = mkOption {
+ type = types.nullOr types.bool;
+ default = null;
+ description = ''
+ Enable dragging windows to the menu bar to fill the screen. The default is true.
+ '';
+ };
+
+ system.defaults.WindowManager.EnableTilingOptionAccelerator = mkOption {
+ type = types.nullOr types.bool;
+ default = null;
+ description = ''
+ Enable holding alt to tile windows. The default is true.
+ '';
+ };
+
+ system.defaults.WindowManager.EnableTiledWindowMargins = mkOption {
+ type = types.nullOr types.bool;
+ default = null;
+ description = ''
+ Enable window margins when tiling windows. The default is true.
+ '';
+ };
+
system.defaults.WindowManager.StandardHideWidgets = mkOption {
type = types.nullOr types.bool;
default = null;
diff --git a/modules/system/defaults/dock.nix b/modules/system/defaults/dock.nix
index 8c43830b..53b63b35 100644
--- a/modules/system/defaults/dock.nix
+++ b/modules/system/defaults/dock.nix
@@ -6,6 +6,10 @@ let
# Should only be used with options that previously used floats defined as strings.
inherit (config.lib.defaults.types) floatWithDeprecationError;
in {
+ imports = [
+ (mkRenamedOptionModule [ "system" "defaults" "dock" "expose-group-by-app" ] [ "system" "defaults" "dock" "expose-group-apps" ])
+ ];
+
options = {
system.defaults.dock.appswitcher-all-displays = mkOption {
@@ -67,11 +71,11 @@ in {
'';
};
- system.defaults.dock.expose-group-by-app = mkOption {
+ system.defaults.dock.expose-group-apps = mkOption {
type = types.nullOr types.bool;
default = null;
description = ''
- Whether to group windows by application in Mission Control's Exposé. The default is true.
+ Whether to group windows by application in Mission Control's Exposé. The default is false.
'';
};
@@ -124,16 +128,72 @@ in {
};
system.defaults.dock.persistent-apps = mkOption {
- type = types.nullOr (types.listOf (types.either types.path types.str));
+ type = let
+ taggedType = types.attrTag {
+ app = mkOption {
+ description = "An application to be added to the dock.";
+ type = types.str;
+ };
+ file = mkOption {
+ description = "A file to be added to the dock.";
+ type = types.str;
+ };
+ folder = mkOption {
+ description = "A folder to be added to the dock.";
+ type = types.str;
+ };
+ spacer = mkOption {
+ description = "A spacer to be added to the dock. Can be small or regular size.";
+ type = types.submodule {
+ options.small = mkOption {
+ description = "Whether the spacer is small.";
+ type = types.bool;
+ default = false;
+ };
+ };
+ };
+ };
+
+ simpleType = types.either types.str types.path;
+ toTagged = path: { app = path; };
+ in
+ types.nullOr (types.listOf (types.coercedTo simpleType toTagged taggedType));
default = null;
- example = [ "/Applications/Safari.app" "/System/Applications/Utilities/Terminal.app" ];
+ example = [
+ { app = "/Applications/Safari.app"; }
+ { spacer = { small = false; }; }
+ { spacer = { small = true; }; }
+ { folder = "/System/Applications/Utilities"; }
+ { file = "/User/example/Downloads/test.csv"; }
+ ];
description = ''
- Persistent applications in the dock.
+ Persistent applications, spacers, files, and folders in the dock.
'';
- apply = value:
- if !(isList value)
- then value
- else map (app: { tile-data = { file-data = { _CFURLString = app; _CFURLStringType = 0; }; }; }) value;
+ apply =
+ let
+ toTile = item: if item ? app then {
+ tile-data.file-data = {
+ _CFURLString = item.app;
+ _CFURLStringType = 0;
+ };
+ } else if item ? spacer then {
+ tile-data = { };
+ tile-type = if item.spacer.small then "small-spacer-tile" else "spacer-tile";
+ } else if item ? folder then {
+ tile-data.file-data = {
+ _CFURLString = "file://" + item.folder;
+ _CFURLStringType = 15;
+ };
+ tile-type = "directory-tile";
+ } else if item ? file then {
+ tile-data.file-data = {
+ _CFURLString = "file://" + item.file;
+ _CFURLStringType = 15;
+ };
+ tile-type = "file-tile";
+ } else item;
+ in
+ value: if value == null then null else map toTile value;
};
system.defaults.dock.persistent-others = mkOption {
@@ -230,7 +290,6 @@ in {
Magnified icon size on hover. The default is 16.
'';
};
-
system.defaults.dock.wvous-tl-corner = mkOption {
type = types.nullOr types.ints.positive;
diff --git a/modules/system/defaults/screencapture.nix b/modules/system/defaults/screencapture.nix
index 80dcaabb..351ca5f2 100644
--- a/modules/system/defaults/screencapture.nix
+++ b/modules/system/defaults/screencapture.nix
@@ -48,5 +48,20 @@ with lib;
Show thumbnail after screencapture before writing to file. The default is true.
'';
};
+
+ system.defaults.screencapture.target = mkOption {
+ type = types.nullOr (types.enum [ "file" "clipboard" "preview" "mail" "messages" ]);
+ default = null;
+ description = ''
+ Target to which screencapture should save screenshot to. The default is "file".
+ Valid values include:
+
+ * `file`: Saves as a file in location specified by `system.defaults.screencapture.location`
+ * `clipboard`: Saves screenshot to clipboard
+ * `preview`: Opens screenshot in Preview app
+ * `mail`
+ * `messages`
+ '';
+ };
};
}
diff --git a/modules/system/defaults/universalaccess.nix b/modules/system/defaults/universalaccess.nix
index 8a2de90f..996f23b6 100644
--- a/modules/system/defaults/universalaccess.nix
+++ b/modules/system/defaults/universalaccess.nix
@@ -28,7 +28,6 @@ with lib;
default = null;
description = ''
Disable transparency in the menu bar and elsewhere.
- Requires macOS Yosemite or later.
The default is false.
'';
};
diff --git a/modules/system/version.nix b/modules/system/version.nix
index 826ad352..3fac46ef 100644
--- a/modules/system/version.nix
+++ b/modules/system/version.nix
@@ -51,7 +51,7 @@ in
system.maxStateVersion = mkOption {
internal = true;
type = types.int;
- default = 5;
+ default = 6;
};
system.darwinLabel = mkOption {
@@ -59,11 +59,18 @@ in
description = "Label to be used in the names of generated outputs.";
};
+ system.darwinRelease = mkOption {
+ readOnly = true;
+ type = types.str;
+ default = (lib.importJSON ../../version.json).release;
+ description = "The nix-darwin release (e.g. `24.11`).";
+ };
+
system.darwinVersion = mkOption {
internal = true;
type = types.str;
- default = "darwin${toString cfg.stateVersion}${cfg.darwinVersionSuffix}";
- description = "The full darwin version (e.g. `darwin4.2abdb5a`).";
+ default = cfg.darwinRelease + cfg.darwinVersionSuffix;
+ description = "The full nix-darwin version (e.g. `24.11.2abdb5a`).";
};
system.darwinVersionSuffix = mkOption {
@@ -72,7 +79,7 @@ in
default = if cfg.darwinRevision != null
then ".${substring 0 7 cfg.darwinRevision}"
else "";
- description = "The short darwin version suffix (e.g. `.2abdb5a`).";
+ description = "The short nix-darwin version suffix (e.g. `.2abdb5a`).";
};
system.darwinRevision = mkOption {
@@ -86,14 +93,15 @@ in
readOnly = true;
type = types.str;
default = lib.trivial.release;
- description = "The nixpkgs release (e.g. `16.03`).";
+ description = "The nixpkgs release (e.g. `24.11`).";
};
+ # TODO: Shouldn’t mismatch the Darwin release, rethink all this…
system.nixpkgsVersion = mkOption {
internal = true;
type = types.str;
default = cfg.nixpkgsRelease + cfg.nixpkgsVersionSuffix;
- description = "The full nixpkgs version (e.g. `16.03.1160.f2d4ee1`).";
+ description = "The full nixpkgs version (e.g. `24.11.1160.f2d4ee1`).";
};
system.nixpkgsVersionSuffix = mkOption {
@@ -124,7 +132,7 @@ in
config = {
# This default is set here rather than up there so that the options
# documentation is not reprocessed on every commit
- system.darwinLabel = mkDefault "${cfg.nixpkgsVersion}+${cfg.darwinVersion}";
+ system.darwinLabel = mkDefault cfg.darwinVersion;
assertions = [
{
diff --git a/modules/users/default.nix b/modules/users/default.nix
index 574f5a4e..706abbfa 100644
--- a/modules/users/default.nix
+++ b/modules/users/default.nix
@@ -147,9 +147,8 @@ in
homeDirectory=''${homeDirectory#NFSHomeDirectory: }
if ! sudo dscl . -change /Users/nobody NFSHomeDirectory "$homeDirectory" "$homeDirectory" &> /dev/null; then
- if [[ -n "$SSH_CONNECTION" ]]; then
+ if [[ "$(launchctl managername)" != Aqua ]]; then
printf >&2 '\e[1;31merror: users cannot be %s over SSH without Full Disk Access, aborting activation\e[0m\n' "$2"
- # shellcheck disable=SC2016
printf >&2 'The user %s could not be %s as `darwin-rebuild` was not executed with Full Disk Access over SSH.\n' "$1" "$2"
printf >&2 'You can either:\n'
printf >&2 '\n'
@@ -157,7 +156,6 @@ in
printf >&2 '\n'
printf >&2 'or\n'
printf >&2 '\n'
- # shellcheck disable=SC2016
printf >&2 ' run `darwin-rebuild` in a graphical session.\n'
printf >&2 '\n'
printf >&2 'The option "Allow full disk access for remote users" can be found by\n'
@@ -171,12 +169,10 @@ in
if ! sudo dscl . -change /Users/nobody NFSHomeDirectory "$homeDirectory" "$homeDirectory" &> /dev/null; then
printf >&2 '\e[1;31merror: permission denied when trying to %s user %s, aborting activation\e[0m\n' "$2" "$1"
- # shellcheck disable=SC2016
printf >&2 '`darwin-rebuild` requires permissions to administrate your computer,\n'
printf >&2 'please accept the dialog that pops up.\n'
printf >&2 '\n'
- # shellcheck disable=SC2016
- printf >&2 'If you do not wish to be prompted every time `darwin-rebuild updates your users,\n'
+ printf >&2 'If you do not wish to be prompted every time `darwin-rebuild` updates your users,\n'
printf >&2 'you can grant Full Disk Access to your terminal emulator in System Settings.\n'
printf >&2 '\n'
printf >&2 'This can be found in System Settings > Privacy & Security > Full Disk Access.\n'
@@ -224,7 +220,6 @@ in
if [ "$u" -gt 501 ]; then
# TODO: add `darwin.primaryUser` as well
if [[ ${name} == "$USER" ]]; then
- # shellcheck disable=SC2016
printf >&2 '\e[1;31merror: refusing to delete the user calling `darwin-rebuild` (%s), aborting activation\e[0m\n', ${name}
exit 1
fi
diff --git a/pkgs/darwin-uninstaller/configuration.nix b/pkgs/darwin-uninstaller/configuration.nix
index 295477a6..ce6be6ca 100644
--- a/pkgs/darwin-uninstaller/configuration.nix
+++ b/pkgs/darwin-uninstaller/configuration.nix
@@ -12,16 +12,16 @@ 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 ''
- if [[ -L ~/.nix-defexpr/channels/darwin ]]; then
- nix-channel --remove darwin || true
- fi
+ nix-channel --remove darwin || true
'';
system.activationScripts.postActivation.text = mkAfter ''
+ nix-channel --remove darwin || true
+
if [[ -L /Applications/Nix\ Apps ]]; then
rm /Applications/Nix\ Apps
fi
@@ -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 da58682e..6b43bcfc 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
@@ -56,7 +59,6 @@ in writeShellApplication {
if [[ -L /run ]]; then
if [[ -e /etc/synthetic.conf ]]; then
sudo sed -i -E '/^run[[:space:]]/d' /etc/synthetic.conf
- sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -B &>/dev/null || true
sudo /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t &>/dev/null || true
echo >&2 "NOTE: the /run symlink will be removed on reboot"
else
@@ -78,7 +80,7 @@ in writeShellApplication {
echo >&2
echo >&2 "checking darwin channel"
- test -e ~/.nix-defexpr/channels/darwin && exit 1
+ nix-instantiate --find-file darwin && exit 1
echo >&2 "checking /etc"
test -e /etc/static && exit 1
echo >&2 "checking /run/current-system"
@@ -88,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/pkgs/nix-tools/darwin-option.sh b/pkgs/nix-tools/darwin-option.sh
index 8e40e93c..79ecee91 100755
--- a/pkgs/nix-tools/darwin-option.sh
+++ b/pkgs/nix-tools/darwin-option.sh
@@ -1,7 +1,9 @@
#! @shell@
set -e
set -o pipefail
-export PATH=@path@:$PATH
+
+export PATH=@path@
+export NIX_PATH=${NIX_PATH:-@nixPath@}
evalNix() {
nix-instantiate --eval --strict "${extraEvalFlags[@]}" -E "with import {}; $*" 2>/dev/null
diff --git a/pkgs/nix-tools/darwin-rebuild.sh b/pkgs/nix-tools/darwin-rebuild.sh
index 7824913d..8f207a7a 100644
--- a/pkgs/nix-tools/darwin-rebuild.sh
+++ b/pkgs/nix-tools/darwin-rebuild.sh
@@ -1,8 +1,9 @@
#! @shell@
set -e
set -o pipefail
-export PATH=@path@:$PATH
+export PATH=@path@
+export NIX_PATH=${NIX_PATH:-@nixPath@}
showSyntax() {
echo "darwin-rebuild [--help] {edit | switch | activate | build | check | changelog}" >&2
@@ -22,15 +23,9 @@ showSyntax() {
}
sudo() {
- # REMOVEME when support for macOS 10.13 is dropped
- # macOS 10.13 does not support sudo --preserve-env so we make this conditional
- if command sudo --help | grep -- --preserve-env= >/dev/null; then
- # We use `env` before our command to ensure the preserved PATH gets checked
- # when trying to resolve the command to execute
- command sudo -H --preserve-env=PATH --preserve-env=SSH_CONNECTION env "$@"
- else
- command sudo -H "$@"
- fi
+ # We use `env` before our command to ensure the preserved PATH gets checked
+ # when trying to resolve the command to execute
+ command sudo -H --preserve-env=PATH --preserve-env=SSH_CONNECTION env "$@"
}
# Parse the command line.
@@ -177,8 +172,8 @@ if [ "$action" != build ]; then
fi
if [ "$action" = edit ]; then
- darwinConfig=$(nix-instantiate --find-file darwin-config)
if [ -z "$flake" ]; then
+ darwinConfig=$(nix-instantiate "${extraBuildFlags[@]}" --find-file darwin-config)
exec "${EDITOR:-vi}" "$darwinConfig"
else
exec nix "${flakeFlags[@]}" edit "${extraLockFlags[@]}" -- "$flake#$flakeAttr"
diff --git a/pkgs/nix-tools/default.nix b/pkgs/nix-tools/default.nix
index 5fdc3821..8d6b89b7 100644
--- a/pkgs/nix-tools/default.nix
+++ b/pkgs/nix-tools/default.nix
@@ -5,12 +5,31 @@
, substituteAll
, stdenv
, profile ? "/nix/var/nix/profiles/system"
-, nixPackage ? "/nix/var/nix/profiles/default"
-, systemPath ? "$HOME/.nix-profile/bin:/etc/profiles/per-user/$USER/bin:/run/current-system/sw/bin:/nix/var/nix/profiles/default/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin"
+, # This should be kept in sync with the default
+ # `environment.systemPath`. We err on side of including conditional
+ # things like the profile directories, since they’re more likely to
+ # help than hurt, and this default is mostly used for fresh
+ # installations anyway.
+ systemPath ? lib.concatStringsSep ":" [
+ "$HOME/.nix-profile/bin"
+ "/etc/profiles/per-user/$USER/bin"
+ "/run/current-system/sw/bin"
+ "/nix/var/nix/profiles/default/bin"
+ "/usr/local/bin"
+ "/usr/bin"
+ "/bin"
+ "/usr/sbin"
+ "/sbin"
+]
+, # This should be kept in sync with the default `nix.nixPath`.
+ nixPath ? lib.concatStringsSep ":" [
+ "darwin-config=/etc/nix-darwin/configuration.nix"
+ "/nix/var/nix/profiles/per-user/root/channels"
+]
}:
let
- extraPath = lib.makeBinPath [ nixPackage coreutils jq git ];
+ extraPath = lib.makeBinPath [ coreutils jq git ];
writeProgram = name: env: src:
substituteAll ({
@@ -25,14 +44,14 @@ in
{
darwin-option = writeProgram "darwin-option"
{
- inherit path;
+ inherit path nixPath;
inherit (stdenv) shell;
}
./darwin-option.sh;
darwin-rebuild = writeProgram "darwin-rebuild"
{
- inherit path profile;
+ inherit path nixPath profile;
inherit (stdenv) shell;
postInstall = ''
mkdir -p $out/share/zsh/site-functions
diff --git a/release.nix b/release.nix
index b3e2df7e..eaf30044 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;
@@ -103,6 +103,7 @@ in {
tests.sockets-nix-daemon = makeTest ./tests/sockets-nix-daemon.nix;
tests.services-aerospace = makeTest ./tests/services-aerospace.nix;
tests.services-dnsmasq = makeTest ./tests/services-dnsmasq.nix;
+ tests.services-dnscrypt-proxy = makeTest ./tests/services-dnscrypt-proxy.nix;
tests.services-eternal-terminal = makeTest ./tests/services-eternal-terminal.nix;
tests.services-nix-gc = makeTest ./tests/services-nix-gc.nix;
tests.services-nix-optimise = makeTest ./tests/services-nix-optimise.nix;
diff --git a/tests/checks-nix-gc.nix b/tests/checks-nix-gc.nix
deleted file mode 100644
index e3dccd7f..00000000
--- 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/environment-path.nix b/tests/environment-path.nix
index 0bb9a055..b5e4754d 100644
--- a/tests/environment-path.nix
+++ b/tests/environment-path.nix
@@ -30,8 +30,8 @@ with lib;
"afterProfile/bin"
"/usr/local/bin"
"/usr/bin"
- "/usr/sbin"
"/bin"
+ "/usr/sbin"
"/sbin"
"afterPath"
]}"
diff --git a/tests/fixtures/system-defaults-write/activate-user.txt b/tests/fixtures/system-defaults-write/activate-user.txt
index f6e9bbaa..7162a414 100644
--- a/tests/fixtures/system-defaults-write/activate-user.txt
+++ b/tests/fixtures/system-defaults-write/activate-user.txt
@@ -235,6 +235,11 @@ defaults write com.apple.dock 'autohide-delay' $'
0.240000
'
+defaults write com.apple.dock 'expose-group-apps' $'
+
+
+
+'
defaults write com.apple.dock 'orientation' $'
@@ -250,7 +255,7 @@ defaults write com.apple.dock 'persistent-apps' $'file-data
_CFURLString
- MyApp.app
+ /Applications/MyApp.app
_CFURLStringType
0
@@ -262,12 +267,56 @@ defaults write com.apple.dock 'persistent-apps' $'file-data
_CFURLString
- Cool.app
+ /Applications/Cool.app
_CFURLStringType
0
+
+ tile-data
+
+
+
+ tile-type
+ small-spacer-tile
+
+
+ tile-data
+
+
+
+ tile-type
+ spacer-tile
+
+
+ tile-data
+
+ file-data
+
+ _CFURLString
+ file:///Applications/Utilities
+ _CFURLStringType
+ 15
+
+
+ tile-type
+ directory-tile
+
+
+ tile-data
+
+ file-data
+
+ _CFURLString
+ file:///Users/example/Downloads/test.csv
+ _CFURLStringType
+ 15
+
+
+ tile-type
+ file-tile
+
'
defaults write com.apple.dock 'persistent-others' $'
@@ -421,6 +470,11 @@ defaults write com.apple.screencapture 'location' $'
/tmp
'
+defaults write com.apple.screencapture 'target' $'
+
+
+file
+'
defaults write com.apple.screensaver 'askForPassword' $'
@@ -509,6 +563,26 @@ defaults write com.apple.WindowManager 'EnableStandardClickToShowDesktop' $'
'
+defaults write com.apple.WindowManager 'EnableTiledWindowMargins' $'
+
+
+
+'
+defaults write com.apple.WindowManager 'EnableTilingByEdgeDrag' $'
+
+
+
+'
+defaults write com.apple.WindowManager 'EnableTilingOptionAccelerator' $'
+
+
+
+'
+defaults write com.apple.WindowManager 'EnableTopTilingByEdgeDrag' $'
+
+
+
+'
defaults write com.apple.WindowManager 'GloballyEnabled' $'
@@ -568,4 +642,4 @@ defaults write ~/Library/Preferences/ByHost/com.apple.controlcenter 'Sound' $'
24
-'
\ No newline at end of file
+'
diff --git a/tests/nix-enable.nix b/tests/nix-enable.nix
new file mode 100644
index 00000000..e052aa2f
--- /dev/null
+++ b/tests/nix-enable.nix
@@ -0,0 +1,16 @@
+{ config, ... }:
+
+{
+ nix.enable = false;
+
+ 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-aerospace.nix b/tests/services-aerospace.nix
index 8cbd292f..088c92d9 100644
--- a/tests/services-aerospace.nix
+++ b/tests/services-aerospace.nix
@@ -8,6 +8,7 @@ in
services.aerospace.enable = true;
services.aerospace.package = aerospace;
services.aerospace.settings = {
+ after-startup-command = [ "layout tiles" ];
gaps = {
outer.left = 8;
outer.bottom = 8;
@@ -20,6 +21,32 @@ in
alt-k = "focus up";
alt-l = "focus right";
};
+ on-window-detected = [
+ {
+ "if" = {
+ app-id = "Another.Cool.App";
+ during-aerospace-startup = false;
+ };
+ check-further-callbacks = false;
+ run = "move-node-to-workspace m";
+ }
+ {
+ "if".app-name-regex-substring = "finder|calendar";
+ run = "layout floating";
+ }
+ {
+ "if".workspace = "1";
+ run = "layout h_accordion";
+ }
+ ];
+ workspace-to-monitor-force-assignment = {
+ "1" = 1;
+ "2" = "main";
+ "3" = "secondary";
+ "4" = "built-in";
+ "5" = "^built-in retina display$";
+ "6" = [ "secondary" "dell" ];
+ };
};
test = ''
@@ -31,6 +58,35 @@ in
${config.out}/user/Library/LaunchAgents/org.nixos.aerospace.plist`
echo >&2 "checking config in $conf"
- if [ `cat $conf | wc -l` -eq "27" ]; then echo "aerospace.toml config correctly contains 27 lines"; else return 1; fi
+ grep 'after-startup-command = \["layout tiles"\]' $conf
+
+ grep 'bottom = 8' $conf
+ grep 'left = 8' $conf
+ grep 'right = 8' $conf
+ grep 'top = 8' $conf
+
+ grep 'alt-h = "focus left"' $conf
+ grep 'alt-j = "focus down"' $conf
+ grep 'alt-k = "focus up"' $conf
+ grep 'alt-l = "focus right"' $conf
+
+ grep 'check-further-callbacks = false' $conf
+ grep 'run = "move-node-to-workspace m"' $conf
+ grep 'app-id = "Another.Cool.App"' $conf
+ grep 'during-aerospace-startup = false' $conf
+
+ grep 'run = "layout floating"' $conf
+ grep 'app-name-regex-substring = "finder|calendar"' $conf
+ (! grep 'window-title-regex-substring' $conf)
+
+ grep 'workspace = "1"' $conf
+ grep 'run = "layout h_accordion"' $conf
+
+ grep '1 = 1' $conf
+ grep '2 = "main"' $conf
+ grep '3 = "secondary"' $conf
+ grep '4 = "built-in"' $conf
+ grep '5 = "^built-in retina display$"' $conf
+ grep '6 = \["secondary", "dell"\]' $conf
'';
}
diff --git a/tests/services-dnscrypt-proxy.nix b/tests/services-dnscrypt-proxy.nix
new file mode 100644
index 00000000..15d59739
--- /dev/null
+++ b/tests/services-dnscrypt-proxy.nix
@@ -0,0 +1,23 @@
+{
+ config,
+ pkgs,
+ ...
+}:
+
+let
+ dnscrypt-proxy = pkgs.runCommand "dnscrypt-proxy-0.0.0" { } "mkdir $out";
+in
+{
+ services.dnscrypt-proxy.enable = true;
+ services.dnscrypt-proxy.package = dnscrypt-proxy;
+
+ test = ''
+
+ echo >&2 "checking dnscrypt-proxy service in /Library/LaunchDaemons"
+ grep -q "org.nixos.dnscrypt-proxy" -- ${config.out}/Library/LaunchDaemons/org.nixos.dnscrypt-proxy.plist
+ grep -q "dnscrypt-proxy-start" -- ${config.out}/Library/LaunchDaemons/org.nixos.dnscrypt-proxy.plist
+
+ echo >&2 "checking dnscrypt-proxy system user in /Library/LaunchDaemons"
+ grep -q "_dnscrypt-proxy" -- ${config.out}/Library/LaunchDaemons/org.nixos.dnscrypt-proxy.plist
+ '';
+}
diff --git a/tests/services-nix-daemon.nix b/tests/services-nix-daemon.nix
index 3a217cbb..f8f06e5d 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 6d7cdef8..9c8ba817 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 4108eb0f..acdc1dce 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 606b7b6f..bafd6c10 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
diff --git a/tests/system-defaults-write.nix b/tests/system-defaults-write.nix
index 078cf82f..19ce3c4f 100644
--- a/tests/system-defaults-write.nix
+++ b/tests/system-defaults-write.nix
@@ -46,10 +46,18 @@
system.defaults.menuExtraClock.Show24Hour = false;
system.defaults.menuExtraClock.ShowDayOfWeek = true;
system.defaults.menuExtraClock.ShowDate = 2;
+ system.defaults.dock.expose-group-apps = true;
system.defaults.dock.appswitcher-all-displays = false;
system.defaults.dock.autohide-delay = 0.24;
system.defaults.dock.orientation = "left";
- system.defaults.dock.persistent-apps = ["MyApp.app" "Cool.app"];
+ system.defaults.dock.persistent-apps = [
+ "/Applications/MyApp.app"
+ { app = "/Applications/Cool.app"; }
+ { spacer = { small = true; }; }
+ { spacer = { small = false; }; }
+ { folder = "/Applications/Utilities"; }
+ { file = "/Users/example/Downloads/test.csv"; }
+ ];
system.defaults.dock.persistent-others = ["~/Documents" "~/Downloads/file.txt"];
system.defaults.dock.scroll-to-open = false;
system.defaults.finder.AppleShowAllFiles = true;
@@ -73,6 +81,7 @@
system.defaults.finder.ShowRemovableMediaOnDesktop = false;
system.defaults.hitoolbox.AppleFnUsageType = "Show Emoji & Symbols";
system.defaults.screencapture.location = "/tmp";
+ system.defaults.screencapture.target = "file";
system.defaults.screencapture.include-date = true;
system.defaults.screensaver.askForPassword = true;
system.defaults.screensaver.askForPasswordDelay = 5;
@@ -94,6 +103,10 @@
system.defaults.WindowManager.AppWindowGroupingBehavior = true;
system.defaults.WindowManager.StandardHideDesktopIcons = false;
system.defaults.WindowManager.HideDesktop = false;
+ system.defaults.WindowManager.EnableTilingByEdgeDrag = true;
+ system.defaults.WindowManager.EnableTopTilingByEdgeDrag = true;
+ system.defaults.WindowManager.EnableTilingOptionAccelerator = true;
+ system.defaults.WindowManager.EnableTiledWindowMargins = true;
system.defaults.WindowManager.StandardHideWidgets = true;
system.defaults.WindowManager.StageManagerHideWidgets = true;
system.defaults.CustomUserPreferences = {
diff --git a/version.json b/version.json
new file mode 100644
index 00000000..1d2863a0
--- /dev/null
+++ b/version.json
@@ -0,0 +1,4 @@
+{
+ "release": "25.05",
+ "isReleaseBranch": false
+}