缘起#
在上一篇中,我们介绍了通过Home Manager安装用户软件的方法。不过,个人环境里除了软件,还有Shell别名、编辑器设置、终端主题等配置。换一台电脑时,通常希望这些设置也能一起使用。
之前我在介绍Shell和Neovim配置时,使用过脚本和配置文件来整理个人环境。Home Manager可以把软件和这些设置放进同一套Nix配置中,方便一起记录和更新。
这里介绍Home Manager的配置组织和文件管理方法,重点说明第一次接管已有文件时的处理方式。示例使用虚构的用户alice和主机laptop,不包含私人配置。
前置条件#
- 已有可以正常构建的NixOS flake配置;
- 了解模块和选项的基本用法,可以参考第六篇;
- 已备份准备交给Home Manager管理的现有配置文件。
下面主要使用Home Manager的NixOS模块方式。示例假设系统中已经有普通用户alice,实际使用时需要替换成自己的用户名。Home Manager用户配置不会代替NixOS的用户账户设置。
Home Manager简介#
Home Manager采用与NixOS类似的模块系统,可以管理用户的软件、配置文件、环境变量和部分用户服务。例如,启用Bash模块后,可以用选项定义别名,而不必另外维护完整的.bashrc。
它常见的使用方式有两种:
| 方式 | 配置应用方式 | 适用情况 |
|---|---|---|
| 作为NixOS模块 | 随nixos-rebuild构建和应用 | 系统与用户配置放在同一个仓库 |
| 独立使用 | 使用home-manager build和home-manager switch | 用户配置单独维护,也可用于其他支持Nix的系统 |
两种方式都可以管理用户环境,但输入和更新流程需要分别安排。本系列已经用一个flake管理系统,因此下面继续采用第一种方式。相关说明可以参看Home Manager的NixOS模块文档。
Home Manager管理的是声明给它的软件和设置,不是整个家目录的快照。文档、浏览器历史、程序缓存和数据库等数据仍然需要另外保存。
配置Home Manager#
添加flake输入#
对于使用NixOS 26.05的示例配置,可以在已有flake.nix中加入相应输入:
| |
这里的follows让Home Manager跟随本flake的Nixpkgs输入。分支需要与自己的配置相匹配;如果已有这些输入,就检查现有设置,不要另外重复添加,也不要为了照抄示例而更换整个系统的分支。
导入NixOS模块#
在outputs函数中接收home-manager输入,然后在主机的模块列表里加入它。例如,下面是outputs返回的属性集中的相关部分:
| |
这段不是完整的flake,原有公共模块和其他主机输出要保留。如果使用第三篇的mkHost函数,也可以在那个函数的modules列表中加入Home Manager模块。
两个选项的作用分别是:
useGlobalPkgs:让Home Manager使用系统的pkgs,方便统一软件包配置;启用后,Home Manager自身的nixpkgs.*选项不再用于单独配置包集合。useUserPackages:通过NixOS的用户软件包机制提供Home Manager的软件,用户profile位于/etc/profiles/per-user/<用户>/。
它们与输入的follows作用不同:follows统一输入来源,useGlobalPkgs复用已经配置好的包集合。这里把两者都写出来,避免用户和系统环境使用不同的包设置。
组织用户配置#
可以沿用第三篇的目录结构,将公共用户配置和个人入口分开:
| |
先创建home/alice.nix:
| |
home.stateVersion用于选择与旧配置兼容的行为和默认值,不是指定软件版本。这里为新建的示例环境使用"26.05";已有环境应保留原来的值,更新Home Manager时不要顺便修改它。确实需要调整时,应先阅读对应版本的变更说明。
这个NixOS集成例子会根据系统账户提供用户名和家目录。独立使用Home Manager时,通常还要在用户配置中设置home.username和home.homeDirectory。
软件与Shell配置#
在home/common.nix中,可以先写几项简单设置:
| |
这里安装jq,为Bash添加ll别名,并启用fzf模块。启用Bash配置并不会自动把系统账户的登录Shell换成Bash;如果平时使用Zsh,应选择相应的Home Manager模块,账户的默认Shell则由NixOS配置。
已有programs.*模块时,优先用它提供的选项,通常比把整份配置文件作为文本维护更方便。对于模块没有覆盖的部分,再使用相应的额外配置选项或文件管理功能。
公共文件里适合放多个用户或多台电脑都需要的设置。屏幕布局、设备路径等专属内容,仍然可以分别保存在用户或主机对应的模块中,不必为了统一配置而全部放在一起。
配置文件管理#
home.file与xdg.configFile#
Home Manager通常通过符号链接,将家目录中的目标文件连接到store中的配置。home.file的目标相对于家目录;xdg.configFile的目标相对于XDG配置目录,默认是~/.config。
上面的例子会管理~/.config/nixos-user-demo/settings.ini。这是用于观察文件管理过程的演示文件,应用之后可以直接读取它的内容。
如果希望保留单独的配置文件,也可以将这个文件选项改成:
| |
这个路径相对于home/common.nix,对应前面目录结构中的home/files/settings.ini。文件可以写成:
| |
text和这里的source是两种替代写法,改成source时需要移除之前同一目标的text。新建的Nix文件和源配置文件都要加入Git索引,才会被本地Git flake读取。
修改托管文件#
配置应用后,通常应修改仓库中的Nix设置或源文件,再重新应用,而不是直接编辑家目录中的链接目标。链接指向store时,编辑器或程序可能因为目标只读而无法保存,也可能自行替换链接,导致下次激活出现冲突。
因此,不建议直接把整个~/.config目录交给Home Manager。这个目录里可能同时有配置、缓存和程序运行时写入的状态,最好只管理明确需要保存的文件。
密码、令牌和私钥也不要直接写进text,或作为普通source复制进store。下一篇会单独介绍运行时机密的管理方法。
构建与应用配置#
创建文件并检查修改后,可以先构建目标系统:
| |
如果采用了source写法,还需要将home/files/settings.ini加入索引。首次加入Home Manager输入时,Nix可能需要更新flake.lock,应检查它的diff并一并记录;已经锁定输入的日常修改,可以继续使用第五篇中的--no-update-lock-file。
构建成功表示配置可以生成,不代表家目录中的现有文件不会冲突。检查并处理下面介绍的文件冲突后,再按第五篇的流程应用。例如,确认要立即应用并设置默认启动配置时运行:
| |
在这里采用的默认系统服务激活方式下,可以检查用户配置的服务和文件:
| |
文件检查应在对应用户的会话中执行。还可以打开一个新的Bash终端,运行type ll和jq --version检查别名与软件。已有Shell会话不一定自动加载新设置,桌面会话中的环境变量也可能需要重新登录才会更新。
问题解决#
已有文件冲突#
首次启用Home Manager时,常见的问题是目标位置已经有手动创建的文件,例如原来的.bashrc。这类冲突通常在激活时检查,单独构建不会替我们检查实际家目录。
例如,演示文件已经存在时,可以先检查它:
| |
确认文件属于原来的手动配置后,先备份它,再把其中仍然需要的内容合并到仓库。移开冲突文件后重新应用配置。不要直接删除整个配置目录;错误信息通常已经指出具体冲突目标,逐个处理即可。
如果希望Home Manager在激活时自动备份冲突文件,可以在NixOS模块中设置:
| |
这样,原文件会被移到带.hm-backup后缀的位置。这个选项属于NixOS集成层,不要写进home/common.nix。独立使用Home Manager时,对应的是CLI的-b备份参数,不能直接照搬两种方式的命令。
同名备份已经存在时,激活仍然可能失败。需要检查并另外保存已有备份,而不是每次报错都删除它。home.file.*.force可以跳过某些目标的保护检查并替换文件,但不适合当作首次迁移的默认处理方法。文件冲突和备份的实现可以参看Home Manager文件模块及NixOS集成选项。
配置未生效#
如果重建后没有看到预期设置,可以先确认用户模块是否被导入,以及命令选择的主机输出是否正确。接着检查Home Manager服务的状态和日志,最后再检查实际文件与当前会话。
服务激活失败时,系统的其他部分可能已经应用了新配置,需要结合日志判断实际状态。系统回滚也不会恢复家目录里的所有数据,更不会自动撤销备份、程序写入或者手动移动文件的操作。
桌面设置与可变数据#
用户设置不一定都是store中的只读文件。例如,GNOME的一些偏好保存在dconf数据库中,Home Manager可以在激活时写入它们。
在使用GNOME并已启用系统dconf支持的配置中,可以在Home Manager模块里设置:
| |
对应的programs.dconf.enable = true;属于NixOS系统模块。这类设置在激活时写入用户数据库,之后仍可能通过图形界面修改;下次激活时,配置中声明的值又可能被重新应用。它和通过符号链接管理文件的方式不同,也不能把GNOME的选项直接套用到其他桌面。
对于经常需要在程序界面里调整的设置,可以先决定哪些值长期由配置管理,哪些保留给程序自己保存。例如,统一字体和固定快捷键可以写进配置,最近打开的文件和临时窗口状态则通常没有必要纳入其中。
推荐的使用方法#
我建议先从少量工具、Shell别名和一个简单配置文件开始,构建并确认实际效果后,再逐步接管其他dotfiles。这样每次出现冲突,都比较容易知道是哪项设置造成的。
公共设置和专属设置分别保存,已有文件先备份,再决定如何导入。对于会在运行时修改配置的程序,需要查清它的保存方式,再选择使用Home Manager模块、文件链接,还是保留可变文件。
让AI帮忙迁移个人环境时,可以要求它先列出准备管理的目标文件,并解释已有内容怎样保留。修改完成后,检查用户服务、文件内容和新的Shell或桌面会话。这样记录的是可以继续维护的个人环境,而不是仅仅把一批文件搬进仓库。
下一篇将介绍Nix store中的信息可见性,以及密码、令牌等机密怎样在运行时提供给服务。
