Tetsuya 的多设备 Nix / NixOS / macOS Flake 配置
. 的项目说明。先看下方摘要,再按需展开具体专题。展开完整 README 原文
Tetsuya 的多设备 Nix / NixOS / macOS Flake 配置
打开中文配置学习手册 · 学习配置架构 · 更新与故障排查
用一份 flake 管理多台 NixOS 机器和一台 macOS:公共配置抽成 modules/,每台
机器只保留自己的硬件或平台差异项。NixOS 使用 nixosConfigurations,macOS
使用独立的 darwinConfigurations;两者共享锁文件,但不直接共享 Linux 专用模块。
本仓库负责 NixOS 和 macOS 系统层:系统包和服务、硬件或平台差异、启动和
用户组,以及 本地桌面的 NixOS 系统接线。用户级私人编排由 ~/chezmoi 管理,
可公开复用的通用配置由 ~/dotfiles 管理;详细边界见 AGENTS.md。
目录结构
nixos-config/
├── flake.nix # 入口:注册所有主机,锁定 nixpkgs 版本
├── flake.lock # nixpkgs 的精确版本锁定(换机后照常使用)
├── modules/ # 系统与平台模块
│ ├── core.nix # 基础系统:引导、内核、网络、 locale、输入法、zram……
│ ├── desktop.nix # 桌面:SDDM + Hyprland、PipeWire、字体……
│ ├── home-manager/ # NixOS/Darwin 用户级 Home Manager 配置
│ ├── darwin/ # macOS / nix-darwin 模块
│ └── zsh.nix # NixOS 全局 Zsh
└── hosts/ # 每台机器一个目录
├── aarch64/ # ARM64 虚拟机
├── hx90/ # HX90 工作站
└── macbook-m1-max/ # Apple Silicon macOS
主机现状
| 主机 | flake 名 | 状态 | 说明 |
|---|---|---|---|
| ARM64 虚拟机 | aarch64 |
可用 | QEMU aarch64-linux,GNOME、PipeWire、SPICE |
| HX90 工作站 | hx90 |
可用 | x86_64,休眠和桌面环境 |
| WSL2 | wsl |
可用 | x86_64,Windows 11 终端环境 |
| Apple Silicon Mac | macbook-m1-max |
配置已加入,待首次安装 Nix/激活 | aarch64-darwin,nix-darwin |
macOS 的配置和第一次激活步骤见
docs/macos-nix-darwin.md。
想系统学习这次迁移的设计、日常操作、边界、回滚和扩展方式,见
docs/macos-nix-darwin/README.md。
HX90 的 networking.hostName 与 flake 输出名统一为 hx90,nixos-update
据此选中正确配置;omarchy update 转发到同一快照更新流程。
每台主机的 configuration.nix 只包含:主机名、时区(Asia/Tokyo)、用户
tetsuya、以及该机特有的服务;其余全部 import 共享模块。
模块都在干什么
modules/core.nix — 所有机器共用的底座
- 引导/内核:systemd-boot + EFI,
linuxPackages_latest最新内核。 - 网络:NetworkManager。
- 本地化:默认 locale
zh_CN.UTF-8,时间/货币等格式用ja_JP.UTF-8。 - 输入法:Fcitx5 + Rime(
fcitx5-rime),走 Wayland text-input 协议 (waylandFrontend),GTK 不设GTK_IM_MODULE,Qt/SDL 仍走显式 IM module。 - sudo:
tetsuya免密码(单用户工作站)。 - 服务:打印 (CUPS)、SSH、nix-ld(跑非 Nix 打包的二进制)、Firefox。
- 键盘映射:keyd 服务由独立的
modules/keyd.nix公共业务模块声明,所有主机 使用同一份 MINILA-R 配置;详见docs/keyd.md。 - zram:zstd 压缩、占内存 50%、优先级 100(高于磁盘 swap),配
vm.swappiness=180。解决 14G 内存机器冷页换出到 NVMe 后切窗口卡半秒的问题。 - 基础包:git、curl、jq、ripgrep、python3、fnm 等。
modules/desktop.nix — 桌面环境
- 登录:SDDM(Wayland 模式),Shizuka 主题。主题依赖 KDE QML 模块,所以 同时启用了 Plasma 6——这台机器上 Plasma 也作为备用会话存在。
- HX90 默认会话:Labwc + Anchor Shell;保留本地 Hyprland 和 Plasma 备用会话。
- 更新入口:
nixos-update从~/nixos-config创建快照、构建候选并切换;omarchy update转发到它。 - 图形栈:Hyprland(含 XWayland)、xdg portal、polkit、gnome-keyring、 power-profiles-daemon。
- 音频:PipeWire(兼容 ALSA / 32 位 / PulseAudio 客户端)。
- 蓝牙:blueman。
- 字体:Noto CJK、JetBrains Mono Nerd Font、emoji、图标字体。
- 桌面工具:Labwc 使用 Anchor Shell(
modules/anchor-shell,Quickshell 顶栏);Hyprland 使用本仓库打包的 Omarchy 兼容 shell。另有 grim/slurp/swappy (截图)、foot/kitty(终端)、pamixer、brightnessctl、nautilus 等。 - 两处针对性修补:
QML2_IMPORT_PATH指向 kirigami/qt5compat 的.unwrapped,确保 polkit 图形代理正常工作。amdgpu-dpm服务:AC 供电时把 Cezanne iGPU 显存频率锁high、电池时auto(auto 会在 4K@scale2 合成时每秒在 400/1750MHz 之间跳,表现为掉帧), 并用 udev 规则在电源插拔时重跑。
modules/zsh.nix
全局启用 Zsh 和补全。用户 shell 在各主机 configuration.nix 里指定。
HX90 主机特有的部分
- 休眠:
boot.resumeDevice指向 NVMe swap 分区。因为 zram 里的页在内存 里,直接休眠会 ENOMEM 失败,所以装了systemd/system-sleep/10-hibernate-zram.sh: 休眠前把 zram swap 整个 swapoff 到磁盘、把 image_size 调到最小;唤醒后 重置 zram0 并重启 zram-setup 服务恢复优先级配置。 - logind:电源键/(若存在的)盖子动作按主机配置处理,但禁用"无人值守空闲挂起", 以保证 SSH 任务不会因空闲而中断。
- snapper:
/和/home各一套自动快照(小时/天/周/月保留策略), 用于本地回滚。注释里写明:这不是加密 NAS 备份的替代品。 - Docker + Windows VM 工具链:docker、docker-compose、freerdp(RDP)、 cifs-utils(SMB)、restic、btrfs-progs。
日常操作
重装后的 SSH 接管
新系统启动后,如果 Agent 要通过 SSH 接管,可以先把本仓库复制到新系统,并确认 安装时已经为用户设置密码,然后执行:
cd ~/nixos-config
./scripts/enable-ssh-bootstrap.sh
脚本会临时叠加 SSH、22 端口防火墙规则和密码登录配置,执行一次
nixos-rebuild switch,最后打印本机 IP。它不会修改仓库或 /etc/nixos/configuration.nix。
SSH 使用用户密码登录,禁止 root 直接登录;接管完成后建议改回密钥登录或关闭 SSH。
# 应用配置(在本机上,<name> 换成当前机器的 flake 名)
sudo nixos-rebuild switch --flake ~/nixos-config#hx90 # HX90
sudo nixos-rebuild switch --flake ~/nixos-config#aarch64 # ARM64 虚拟机
# 更新 nixpkgs 锁定(谨慎:当前刻意钉在 nixos-26.05 迁移基线)
nix flake update
sudo nixos-rebuild switch --flake ~/nixos-config#<name>
# 只检查并更新 Shizuka SDDM 主题
nix flake update shizuka --flake ~/nixos-config
sudo nixos-rebuild switch --flake ~/nixos-config#<name>
# 测试构建(不切换)
nixos-rebuild build --flake ~/nixos-config#<name>
# 回滚
sudo nixos-rebuild switch --rollback
omarchy update 已转发到本机 nixos-update,更新独立 flake 输入前创建
root/home 快照,构建候选后切换。不会更新 chezmoi 或 dotfiles。
操作与恢复见 docs/nixos-update-snapshots.md。
Nixarchy 外部依赖已移除,接管清单见 docs/nixarchy-removal.md。
全局 AI 环境与 skills 接线见 docs/agent-environment.md。
Shizuka 登录主题的源码、flake.lock 锁定版本、NixOS generation 和 SDDM 实际加载
路径之间的关系,见该文档中的「Shizuka 的版本到底由哪里管理」章节。注销登录不会
自动更新 Shizuka;更新 GitHub 后必须更新 flake.lock 并重新构建切换。
想系统学习 NixOS 的设计取舍和本仓库的实践方式,可从
docs/nixos-learning-notes.md 开始。
更新前自动快照、NixOS generation、/home 恢复和 Omarchy 插件更新的完整设计见
docs/nixos-update-snapshots.md。
统一更新命令是 nixos-update;正式更新请使用它,以确保更新前自动创建 / 与
/home 快照,并同时更新 Omarchy 插件。
NixOS 与 chezmoi 的用户配置边界
本仓库通过 Home Manager 管理 NixOS 专属的用户配置,入口是
modules/home-manager/nixos-user.nix。这里适合放:
- 依赖 Nix store 软件包的用户配置、用户级 systemd service;
- Labwc / Anchor Shell 与 Omarchy 兼容资源的 NixOS 接线;
- 只在 NixOS 上使用的用户环境变量、GUI 默认值和配置文件。
跨发行版或跨平台的用户偏好继续由 ~/chezmoi 管理,例如 Fcitx5、终端、tmux、
Voxtype 和通用脚本。macOS 专属的 AeroSpace、Karabiner、Hammerspoon、skhd 则由
本仓库的 Darwin Home Manager 管理。一个具体文件只能由一个系统管理:迁移到 Home Manager
后必须从 chezmoi 删除对应文件,反之亦然。NixOS 的用户配置通过
sudo nixos-rebuild switch --flake ~/nixos-config#<主机名> 生效;chezmoi 配置仍通过
chezmoi apply 生效。这样在 Fedora、Arch、Debian 或 macOS 上使用 chezmoi 时,
不会依赖 NixOS 的模块或 Nix store 路径。
仓库地图
换机时“配置回来”不等于只部署本仓库。主要配置由以下三个仓库组成:
| 仓库 | 地址 | 管什么 | 换机时的动作 |
|---|---|---|---|
| nixos-config(本仓库) | iamcheyan/nixos-config |
系统层和桌面组件 | clone + 生成 hardware 文件 + 注册主机 + rebuild |
| chezmoi(PRIVATE) | iamcheyan/chezmoi |
用户级私人软件与自动化编排 | 认证 clone + chezmoi apply |
| dotfiles(PUBLIC) | iamcheyan/dotfiles |
通用 Zsh、Neovim 与公开 CLI 配置 | clone + dotlink link |
不会自动回来的(换机前自行处理):
~/.ssh/、~/.gitconfig—— chezmoi 刻意不管(密钥不入库)。新机器第一件事 是手动迁移 SSH key(或先用 HTTPS + token 克隆),否则git@github.com:全部拉不动。- 桌面运行时状态 —— 生成物,按需重新设置。
- 浏览器数据、keyring 密码、Docker 卷等机器本地数据 —— 与配置仓库无关。
换一台新机器怎么用
场景 A:全新安装 NixOS
- 装系统:用官方 ISO 正常安装(分区时参考现有机器的布局:btrfs,
root, home, and nix 三个子卷 + ESP + swap 分区,这样 hardware 文件结构一致,
nix 子卷还能让
/nix/store在重装后保留缓存)。 - 把仓库弄到新机器上(U 盘、SSH 或先装 git):
git clone <你的仓库地址> ~/nixos-config - 生成新主机的硬件文件——这是唯一必须在本机生成的部分:
# 已 chroot 进新系统时: nixos-generate-config --root /mnt # 新系统已能启动时(文件在 /etc/nixos/ 下): cp /etc/nixos/hardware-configuration.nix ~/nixos-config/hosts/<新名字>/ - 建主机目录:复制一份现有的
hosts/nixos-new/configuration.nix当模板, 改三处:networking.hostName- imports 里硬件文件名(
hardware-configuration.nixvshardware.nix) - 删掉新机器没有的功能(比如不是 AMD 核显就删 amdgpu 相关注释参考,
不休眠就删
boot.resumeDevice和 sleep 脚本;反过来笔记本要加)
- 在 flake.nix 注册,照抄现有条目:
新名字 = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ ./hosts/新名字/configuration.nix ]; }; - 首次构建并切换:
sudo nixos-rebuild switch --flake ~/nixos-config#新名字 - 重启后:在 SDDM 中选择 Labwc(或所需备用会话)登录。
场景 B:把现有机器纳入这套配置管理
和场景 A 相同,只是第 3 步直接:
mkdir -p ~/nixos-config/hosts/旧机器名
cp /etc/nixos/hardware-configuration.nix ~/nixos-config/hosts/旧机器名/
然后按 4-6 步走。旧机器的 system.stateVersion 保持它当初安装时的
版本不要改(本仓库三台都是 26.05,因为都是 26.05 时代装的)。
休眠(Hibernate)跨机器的注意点
休眠是这套配置里最"机器绑定"的功能。内存大小本身不是问题——zram 按
百分比(50%)分配,钩子里的 image_size 恢复值是运行时从 /proc/meminfo
算的,没有任何写死的内存数值。真正的绑定点:
| 检查项 | 要求 | 不满足时会发生什么 |
|---|---|---|
| swap 分区大小 | ≳ 物理内存(swap ≥ RAM 是可靠规则) | 重负载时镜像写不下,写盘阶段失败、解冻弹回 |
boot.resumeDevice UUID |
必须是这台机器的 swap 分区 UUID | 休眠能正常写入镜像,但开机恢复不了:直接全新启动、会话丢失(数据不坏,但等于白休眠) |
| zram 刷盘钩子 | 有 zram 就必须带 10-hibernate-zram.sh |
zram 里的页在内存里,快照算不下会 ENOMEM 弹回(nixos-new 实测踩过) |
| Secure Boot lockdown | 关闭(或内核未进 lockdown) | lockdown 开启时内核直接禁止休眠,与本配置无关 |
HX90 台式机策略
HX90 是需要长期通过 SSH 运行任务的台式机,因此配置为:
- 空闲时不自动 suspend 或 hibernate:
services.logind.settings.Login.IdleAction = "ignore"。 - 手动 suspend 和 hibernate 仍然可用;例如
systemctl hibernate。 - 禁用 hybrid sleep 与 suspend-then-hibernate,避免后台策略自行改变电源状态。
- hibernate 写入磁盘后使用
HibernateMode = "shutdown"。这台机器的固件在 ACPI S4 阶段会因为 USB 控制器返回EBUSY导致恢复失败,所以采用快照后正常关机。 - 休眠目标是独立 NVMe swap 分区,不是 EXT4/Btrfs 文件系统里的 swapfile。当前 HX90
的 swap UUID 是
cfceef33-5044-4a72-8c01-c8d1f4444f00,必须同时出现在hardware-configuration.nix的swapDevices和configuration.nix的boot.resumeDevice。
这套台式机策略不应原样复制到笔记本:笔记本通常需要保留合盖动作,并可能需要
suspend-then-hibernate。复制时应按笔记本的电源管理需求单独设置 logind,并使用
笔记本自己的 swap UUID。
新机器要启用休眠的检查清单:
- 装机时留出 ≥ 内存的 swap 分区(HX90 使用约 68.4 GiB swap / 约 62 GiB RAM)。
nixos-generate-config生成 hardware 文件后,从里面的swapDevices拿到 swap 分区 UUID,填进该主机configuration.nix的boot.resumeDevice。- 把 HX90 里
environment.etc."systemd/system-sleep/10-hibernate-zram.sh"那一整块复制过去——zram 在modules/core.nix是共享启用的,所以只要用 zram 就需要这个钩子(钩子和 resumeDevice 同在 host 文件里,结构上保证同进退)。 - 验证顺序:
swapon --show确认两个 swap(zram0 优先级 100 + 磁盘分区 -1) →nixos-rebuild build --flake .#主机名→ 真点一次休眠按钮走完整断电循环 → 唤醒后确认会话还在、zram 优先级恢复 100。
电源面板只在内核支持 disk 休眠且存在非 zram 的磁盘 swap 分区时显示 Hibernate 按钮,没配 swap 的机器会自动隐藏。
注意事项 / 坑
- hardware 文件绝不跨机器复制。里面的磁盘 UUID、initrd 内核模块
(
kvm-intelvskvm-amd)、CPU 微码(intelvsamd)都是机器专属。 system.stateVersion不要动。它只表示"当初安装时的 NixOS 版本", 升级它不会升级系统,反而可能触发一次性迁移逻辑。- nixpkgs 钉在
nixos-26.05。这是刻意的迁移基线,新机器稳定运行之前 不要顺手nix flake update。 - 免密 sudo:
tetsuya在所有机器上NOPASSWD: ALL。多用户环境不适用, 需要时改modules/core.nix。 - HX90 的空闲挂起被禁用(logind
IdleAction=ignore),因为它是需要保持 SSH 在线的台式机;手动挂起/休眠仍可用,电源键和(若存在的)合盖动作仍按各自的Handle*设置处理。
各主机 rebuild 速查
sudo nixos-rebuild switch --flake ~/nixos-config#hx90
sudo nixos-rebuild switch --flake ~/nixos-config#aarch64