缘起#
一台电脑的NixOS配置写好之后,如果还想把另一台电脑也换成NixOS,最容易想到的办法就是把配置复制过去,再改一下硬件相关的部分。
这种方式适合最初配置,但公共设置需要在多份文件中维护。例如,增加一个Shell设置或常用软件时,需要分别修改每台电脑的配置。如果遗漏了其中一份,配置就会出现差异。
所以我把几台电脑放进同一个flake里,公共配置写一份,每台电脑只保留自己的差异。这里用笔记本laptop、工作站workstation和服务器server三个示例说明,名字和路径都需要换成自己的。
这个系列最初从三台电脑的配置写起,现在同一套flake已经管理四台电脑。下面仍用三个虚构角色说明目录组织,实际配置并不限制主机数量。
如果还不熟悉flake,可以先看上一篇的概念介绍。
配置仓库的存放位置#
安装NixOS之后,一般会在/etc/nixos里看到安装器生成的配置。不过日常使用时,配置仓库也可以放在其他位置,只要重建时指定它的路径:
| |
这样,这次构建使用的就是指定仓库里的flake。如果修改的是另一份配置,除非它被当前flake导入,否则不会影响这次构建。
我把配置单独放进Git仓库,方便查看历史、修改文件和同步到其他电脑。修改前需要确认重建命令使用的仓库路径。如果编辑的是/etc/nixos,重建时却指定了另一个目录,就需要检查这些文件是否由当前flake导入。
配置文件分类#
一个简单的目录结构可以是:
| |
其中flake.nix是入口,flake.lock记录依赖版本。其余的文件主要分成下面几类。
公共配置#
几台电脑都会用到的设置,可以放在modules/common.nix。例如常用命令行工具、语言和时区、一些通用服务设置等。
公共模块只放几台电脑都需要的内容。例如,笔记本的桌面和电源设置不一定适合服务器,工作站的显卡驱动也应当保留在相应主机的配置中。
每台电脑的配置#
每台电脑建立一个目录,例如hosts/laptop/。它的configuration.nix保存这台电脑自己的设置,后面会在flake里把它与公共模块组合起来。
显示器、笔记本合盖后的行为、特殊硬件支持等,通常放在这里。这样看到某台机器的配置时,就比较容易知道它和其他机器有什么区别。
硬件配置#
hardware-configuration.nix是安装器生成的硬件描述,包含文件系统、swap和检测到的硬件模块等信息。这里可能有本机磁盘的UUID,不能把另一台电脑的文件直接拿来用。
如果存储布局发生了变化,可以在对应机器上重新生成一份,和仓库里的文件比较:
| |
上面的做法先把结果写到临时文件,方便检查后再决定替换哪些内容。这里假设正在运行安装后的目标系统;如果还在安装U盘的环境中,就需要指定正确的目标根目录。
配置flake的主机输出#
每台电脑都需要一个nixosConfigurations输出。由于创建输出的写法很相似,可以用一个函数省掉重复内容。例如,下面这段可以放在flake的outputs中(假设已经取得nixpkgs输入):
| |
这里的mkHost接收一个主机模块,再把它与公共模块一起交给nixosSystem。这是一个简化片段,不是完整的flake.nix。各主机模块还需要导入自己的硬件配置。
需要注意,上面的例子由mkHost统一导入公共模块,所以主机文件里不用再重复导入。也可以选择在主机文件中导入公共模块,只要整个仓库的写法保持清楚就行。
之后,在笔记本上就可以选择laptop输出:
| |
在服务器上则选择server。修改公共模块会影响所有导入它的主机,所以只在一台电脑上重建成功,还不足以说明其他主机的配置也没有问题。
使用Home Manager管理用户配置#
Shell、编辑器、终端等用户环境,可以交给Home Manager管理。它也可以像系统配置一样拆分:公共偏好放在一起,显示器布局等机器相关设置分别保存。
把Home Manager作为NixOS模块集成后,用户配置可以随nixos-rebuild一起应用,不需要再单独运行一次home-manager switch。
如果原来已经手动创建了配置文件,首次交给Home Manager管理时可能出现文件冲突。需要先备份已有文件,再检查如何处理;设置了自动备份扩展名时,也需要检查同名备份是否已经存在。后面介绍Home Manager时会详细说明这些操作,这里主要介绍用户配置的组织方式。
修改与检查配置#
例如要修改笔记本的配置,可以先在仓库里看一下已有改动:
| |
编辑相应文件之后,再检查并构建:
| |
如果新建了模块,记得把文件加入Git索引,否则本地Git flake可能看不到它。构建成功后,可以先用test试用,再根据结果执行switch:
| |
内核和启动相关的修改,还需要重启验证。各条命令的具体区别见第五篇。
依赖更新可以单独做:运行nix flake update,看一下flake.lock的diff,再检查和构建。这样如果出了问题,比较容易分清是配置修改造成的,还是依赖版本发生了变化。
构建与运行记录#
Git记录的是配置文件的修改,查看机器的实际运行状态还需要另外记录。例如,配置已经提交,构建仍然可能失败;执行了switch之后,如果尚未重启,也可能还在运行之前的内核。这些信息不能只通过Git日志判断。
因此,我会在构建和更新笔记中记录使用的提交、实际代次、是否激活、是否重启,以及仍需处理的问题。文件可以放在docs/里,按机器分别记录,方便以后查阅。
代次链接的时间只能作为线索,不能单凭它判断系统已经运行过。需要时还可以查看:
| |
旧代次被垃圾回收后,历史笔记仍然有用,不过笔记里存在的代次不一定还能回滚。当前可用的代次要另外检查。
这些记录自己以后会用到,交给AI继续维护时也有帮助。下一篇就介绍怎么把仓库里的约定告诉AI。
