macOS 纳入 Nix 管理
macOS 纳入 Nix 管理
本章说明如何把当前这台 Apple Silicon Mac 纳入本仓库,以及为什么 macOS 配置和 NixOS 配置必须分开。它既是操作手册,也是以后排查和迁移时的学习笔记。
当前目标主机:
| 项目 | 当前值 |
|---|---|
| flake 输出名 | macbook-m1-max |
| 当前主机 | MacBook Pro M1 Max |
| 架构 | aarch64-darwin |
| 内存 | 64 GB |
| macOS | 26.6.2 |
| 配置入口 | darwinConfigurations.macbook-m1-max |
| 应用命令 | sudo darwin-rebuild switch --flake .#macbook-m1-max |
1. 这次到底引入了什么
本仓库原来只有 NixOS 输出,现在增加一个独立的 Darwin 输出:
nixosConfigurations
├── aarch64
├── hx90
└── wsl
darwinConfigurations
└── macbook-m1-max
它们共享同一个 flake.lock 和 nixpkgs 基线,但不是同一套模块:
NixOS
├── systemd / systemd-boot
├── SDDM / Hyprland
├── PipeWire / Fcitx5 Wayland
├── keyd
└── Btrfs / zram / Linux 硬件
macOS / nix-darwin
├── launchd / macOS activation
├── Homebrew formulae/casks
├── macOS defaults
├── aarch64-darwin packages
└── Apple kernel / APFS / Recovery 仍由 macOS 管理
nix-darwin 是 macOS 的系统模块层。它需要先有 Nix,然后通过 darwinSystem
生成配置、通过 darwin-rebuild 激活。macOS 没有 NixOS 那种
hardware-configuration.nix:Apple 的硬件、APFS 分区、Recovery 和启动链不
由本仓库接管。
2. 为什么不能复用 modules/workstation.nix
modules/workstation.nix 是 NixOS 工作站模块,它导入了 core、keyd、desktop、
zsh、cli、dev 和 NixOS Home Manager。里面包含很多 macOS 不存在的选项:
- NixOS systemd 服务、systemd-boot 和 zramSwap
- SDDM、Hyprland、PipeWire
- Fcitx5 Wayland text-input 接线
- Linux keyd 服务
- AMD GPU 的
/sys/class/drm和 udev 规则 - Btrfs、休眠和 NixOS 硬件配置
所以本次新增 modules/darwin/,只把 macOS 需要的部分单独声明,而不是把
Linux 工作站模块改造成一个两边都能用的巨大条件分支。
3. 当前文件结构
hosts/macbook-m1-max/configuration.nix
modules/darwin/base.nix
modules/darwin/packages.nix
modules/darwin/homebrew.nix
modules/darwin/defaults.nix
modules/home-manager/darwin-user.nix
主机入口
hosts/macbook-m1-max/configuration.nix 只声明:
aarch64-darwin- 主机名
- Darwin 模块
- Darwin 版 Home Manager
system.stateVersion = 6
这里的 system.stateVersion 是 nix-darwin 的配置 schema 版本,不是 macOS
版本,也不是 NixOS 的 26.05。日常更新不要修改它。
Darwin 基础模块
modules/darwin/base.nix 负责:
- Nix daemon
- flakes 和
nix-command - Zsh
- Git、SSH、Neovim、chezmoi、ripgrep 等基础命令
EDITOR和VISUAL
这里不启用 macOS Remote Login。以后如果需要 SSH 进入 Mac,再单独设计和验证,
不要因为 NixOS 的 services.openssh.enable = true 就照搬过来。当前 nix-darwin
版本会在 Nix 启用时自动管理 Nix daemon,不再需要旧式的
services.nix-daemon.enable。
软件包模块
modules/darwin/packages.nix 负责第一批开发和诊断工具:Python、Make、bat、
eza、btop、htop 和 Starship。它不是当前 Homebrew formula 列表的完整复制;
Homebrew 安装出来的大量底层库不应该逐项写进配置。
Homebrew 模块
modules/darwin/homebrew.nix 保留当前已安装的主要 GUI cask,例如 Kitty、
Ghostty、Hammerspoon、AeroSpace、Android Studio、Bitwarden、OrbStack、VLC、
Godot 和 MonitorControl。
当前只把 mas 和 ntfs-3g-mac 保留为 Homebrew formula。普通 CLI 优先由 Nix
提供,避免同一个命令同时存在于 /nix/store 和 /opt/homebrew/bin。
主机入口中的 system.primaryUser = "tetsuya" 也很重要:当前 nix-darwin 的系统
激活以 root 执行,而 Homebrew 这类需要用户上下文的选项必须明确知道主要用户。
第一次激活使用:
homebrew.onActivation.cleanup = "none";
这表示配置不会自动删除还没有分类的旧软件。确认软件清单之后,才可以考虑收紧
清理策略。不要在不了解 brew list 的情况下开启清理。
macOS defaults 模块
modules/darwin/defaults.nix 目前是一个空的安全边界模块。Finder、Dock、时间/单位、
Mission Control、辅助功能、输入法权限等暂时不写进去,应该先读取当前状态再逐项
声明,避免第一次激活时改变用户可见设置。
Darwin Home Manager 模块
modules/home-manager/darwin-user.nix 声明 home.stateVersion、
BROWSER = "open",并管理 macOS 专属的 AeroSpace、Karabiner、Hammerspoon、
skhd 配置以及零动画脚本。配置按文件链接,不接管 Karabiner/Hammerspoon 的整个
运行目录,因此应用自己产生的 assets、备份和 Spoons 仍可写入。
4. 第一次安装和激活
当前这台 Mac 还没有 nix 命令,因此仓库代码已经准备好,但还没有完成系统激活。
请在 Mac 的 Terminal.app 中亲自执行 Nix 安装器;它需要登录密码来创建 /nix、
Nix build users 和 LaunchDaemon,不能由无交互的 Agent 代填:
curl -L https://nixos.org/nix/install | sh -s -- --daemon
安装完成后重新打开终端,再执行:
cd ~/nixos-config
nix --version
nix flake check --no-build
darwin-rebuild build --flake .#macbook-m1-max
sudo darwin-rebuild switch --flake .#macbook-m1-max
如果 darwin-rebuild 尚未进入 PATH,可以使用临时入口:
sudo nix run nix-darwin/nix-darwin-26.05#darwin-rebuild -- \
switch --flake .#macbook-m1-max
第一次切换完成后检查:
command -v nix
command -v darwin-rebuild
command -v git
command -v nvim
command -v chezmoi
brew list --cask
然后重新打开一个登录 shell,确认 Nix profile 和 Homebrew PATH 顺序符合预期。
5. 日常操作
# 求值检查
nix flake check --no-build
# 只构建,不切换
darwin-rebuild build --flake .#macbook-m1-max
# 应用配置
sudo darwin-rebuild switch --flake .#macbook-m1-max
# 查看和回滚 Darwin generations
darwin-rebuild --list-generations
sudo darwin-rebuild switch --rollback
Darwin generation 只回滚 nix-darwin 管理的系统配置。Homebrew 应用数据、用户 目录、浏览器 profile、Agent session 和外部模型不会随它自动回滚。
6. 三个仓库的边界
| 内容 | 归属 |
|---|---|
| Nix、Darwin 系统包、Homebrew 声明、macOS defaults | nixos-config |
| NixOS 内核、硬件、systemd、Hyprland、Fcitx5、keyd | nixos-config |
| 跨平台 Shell、Neovim、终端配置、Rime、Voxtype、Agent | chezmoi / dotfiles |
| macOS 专属 AeroSpace、Karabiner、Hammerspoon、skhd | Darwin Home Manager |
密钥、Token、.env、Bitwarden session |
不进本仓库 |
| 浏览器 profile、模型、缓存、项目构建产物 | 不进系统 flake |
同一个目标文件只能有一个所有者。例如:
软件包由 nix-darwin 管
~/.config/nvim/init.lua 由 dotfiles 管
~/.config/omarchy/... 由 chezmoi 管
~/.config/aerospace/aerospace.toml 由 Darwin Home Manager 管
~/.config/karabiner/karabiner.json 由 Darwin Home Manager 管
~/.hammerspoon/init.lua 由 Darwin Home Manager 管
Hammerspoon/Karabiner 权限由 macOS Settings 管
不能让 Home Manager 和 chezmoi 同时生成 ~/.config/nvim/init.lua。
7. 目前明确不迁移的内容
keyd
modules/keyd.nix 是 Linux 服务。macOS 继续使用现有 Karabiner、Hammerspoon
或其他 macOS 原生方案,不应该尝试通过 nix-darwin 启动 keyd。
Fcitx5
NixOS 中的 Fcitx5 依赖 Wayland text-input、GTK/Qt bridge 和 Linux 会话。macOS 的输入法、Rime 数据和权限继续由现有 chezmoi/macOS 流程管理。
Voxtype、本地模型和 Agent
这些内容涉及用户级权限、模型路径、音频输入、密钥和私有编排。先保持现状,等 软件包和权限边界明确后,再决定是 Homebrew、Nix package 还是 chezmoi user service。
本次已迁移的 macOS 用户配置
以下内容已从 ~/chezmoi 移到 modules/home-manager/darwin-files/:
- AeroSpace:
~/.config/aerospace/aerospace.toml; - Karabiner:
~/.config/karabiner/karabiner.json; - Hammerspoon:
~/.hammerspoon/init.lua; - skhd:
~/.skhdrc; - 零动画脚本:
~/.local/bin/macos-zero-animation。
这些是 macOS 专属内容,不应再通过 chezmoi apply 生成。Karabiner/Hammerspoon
运行目录中的缓存、自动备份和 Spoons 不进入 Git,也不由 Home Manager 覆盖。
8. Homebrew 与 Nix 的重复问题
迁移期间可能看到两个相同命令:
which -a git
which -a nvim
which -a python3
处理顺序应该是:
- 确认配置实际调用的是哪个路径;
- 确认版本满足项目需求;
- 确认 chezmoi、dotfiles 和脚本没有硬编码 Homebrew 路径;
- 再决定是否删除重复的 Homebrew formula。
公共 dotfiles 应优先使用 PATH 查找程序,不要写个人机器的绝对路径。Apple Silicon
Homebrew 前缀是 /opt/homebrew,Intel Mac 通常是 /usr/local,共享脚本应该
兼容两者。
9. 以后增加 macOS 配置的规则
新增设置前先问:
- 这是系统能力、用户偏好,还是秘密?
- 它是否依赖 macOS 权限或 GUI 当前状态?
- 它是否会和 chezmoi/dotfiles 生成同一个文件?
- 出错时能否通过上一个 Darwin generation 回滚?
推荐分类:
系统包 / Homebrew / launchd / defaults -> nix-darwin
用户文件 / shell / Neovim / Agent -> chezmoi 或 dotfiles
密码 / Token / session -> 加密存储或手工恢复
浏览器 / 模型 / 缓存 / 数据库 -> 单独备份和迁移
10. 故障排查
nix 不存在
说明 Nix 还没有安装,仓库配置还没有机会求值。先安装 Nix,再运行本章第 4 节。
darwin-rebuild 不存在
使用上面的 nix run nix-darwin/...#darwin-rebuild 临时入口。
Homebrew 想删除旧应用
确认 homebrew.onActivation.cleanup 是 "none"。第一次迁移不应该自动清理;
先把 brew list --formula 和 brew list --cask 分成 Nix、Homebrew、手工安装三类。
配置求值时报 Linux 选项错误
检查 hosts/macbook-m1-max/configuration.nix 的 imports,只保留 modules/darwin/
和 home-manager.darwinModules,不要导入 modules/workstation.nix 或
modules/desktop.nix。
应用本身无法启动
Nix 成功安装软件不代表 macOS 已授予 Accessibility、Input Monitoring、麦克风、 屏幕录制或网络扩展权限。权限必须在 macOS 的 Privacy & Security 中逐项验证, 不能把“能 build”当成“用户功能完成”。
11. 后续阶段
- 在 macOS 上完成 Nix 安装、flake lock 更新和首次 Darwin build;
- 验证 CLI、Homebrew cask、chezmoi 和 dotfiles 的协作;
- 将确实需要声明式管理的 macOS defaults 加入
defaults.nix; - 评估 launchd 服务,不把 Linux systemd 服务照搬过来;
- 对重复的 Homebrew formula 做逐项清理;
- 最后再考虑把少量跨平台用户配置迁移到 Home Manager。
在这些步骤完成以前,不要删除现有 Homebrew 软件、chezmoi 模板、Rime 数据、 浏览器 profile 或 Agent 配置。
12. 本次接入的实际验证记录
本次接入在 2026-09-07 进行了以下验证:
Nix: 2.35.2
Darwin build: 通过
Darwin output: .#darwinConfigurations.macbook-m1-max.system
首次 switch: 已完成;macOS 专属配置迁移与运行时目录恢复已完成
Darwin build 实际生成了 nix-darwin 26.05 的 system derivation,并验证了:
aarch64-darwin平台求值成功;- Home Manager Darwin module 求值成功;
- Homebrew Brewfile 生成成功;
- Nix、Zsh、基础 CLI 和开发工具的 system path 求值成功;
- nix-darwin 的 launchd、Nix daemon 和 activation derivation 生成成功。
完整的:
nix flake check --no-build
目前还会在原有 NixOS/Nixarchy 配置上遇到失效的 /nix/store/...-source 路径,
错误位于既有的 modules/home-manager/nixos-user.nix / Nixarchy 求值链,不是
本次 Darwin 模块的错误。Darwin 专用 build 已单独通过,因此后续应分别记录:
# macOS 接入的直接验证
nix build .#darwinConfigurations.macbook-m1-max.system --no-link
# 全仓库验证;如果旧 NixOS store 缓存问题仍存在,按错误单独修复
nix flake check --no-build
首次 switch 已经由用户在本机 Terminal.app 中完成。Homebrew、Home Manager
和 launchd activation 都已执行成功。Karabiner、AeroSpace、Hammerspoon 和
skhd 的静态配置已由 Darwin Home Manager 接管;Karabiner/Hammerspoon 的运行时
目录已从迁移备份恢复。更详细的学习材料见
macos-nix-darwin/README.md。
以后如果需要重新激活,使用:
sudo nix run nix-darwin/nix-darwin-26.05#darwin-rebuild -- \
switch --flake .#macbook-m1-max
切换完成后,再验证 darwin-rebuild --list-generations、command -v nvim、
brew list --cask、新开登录 shell,以及现有 chezmoi/dotfiles 配置是否仍正常。