本篇文章,主要是研究快照替代/nix,导致无法开机。

NixOS + Btrfs 快照隔离
在 NixOS 中使用 Btrfs 作为文件管理系统时,Btrfs 的快照功能可以帮助我们隔离 nixos 目录。
为了提高系统的稳定性和可靠性,我通常会创建两个子卷来分别管理不同的 /nix 配置版本:@nix、@nix.bak。
为什么要创建两个子卷?
- nix 子卷:这是当前活动的
/nix。它代表了当前活跃的系统环境。 - nix.bak 子卷:这个子卷用于保存上一个稳定的配置备份,通常在系统更新或变更前创建快照。这样可以确保在出现问题时,可以快速回滚至上一个已知的良好状态。
这种隔离方案的好处是,当系统出现故障时,能够迅速回滚到一个健康的配置,从而提高系统的可靠性和恢复能力。
NixOS Rebuild Switch 的限制
尽管官方文档没有提到,实际测试表明,NixOS 文件系统并不支持在运行时动态切换不同的目录。因此,当我们通过 sudo nixos-rebuild switch 工具切换配置时,必须特别注意当前活跃卷的路径。
1. 动态切换的验证
首先,我们检查当前系统中 Btrfs 子卷的挂载情况:
# 别想多,单纯验证而已
⋈┈◎ sudo btrfs subvolume list / /etc/nixos 12:04
ID 270 gen 2428 top level 5 path @nix_store
ID 271 gen 2427 top level 5 path @nix.bak
# 为接下来实验做准备
⋈┈◎ sudo mkdir /nix_store
# 通过`sudo nixos-rebuild switch`,我们尝试按顺序动态挂载`@nix`和`@nix.bak`到`/nix_store`。
# 结果发现`@nix`可以正常挂载,但`@nix.bak`无法挂载且没有任何提示。
fileSystems."/nix_store" = {
device = ...;
fsType = "btrfs";
options = ["subvol=@nix"];
# options = ["subvol=@nix.bak"];
};
使用 sudo nixos-rebuild switch构建,切换子卷,查看当前挂载情况:
⋈┈◎ mount | grep /nix /etc/nixos 12:04
/dev/nvme0n1p2 on /nix_store type btrfs (rw,relatime,sync,compress=zstd:3,ssd,discard,space_cache=v2,subvolid=270,subvol=/@nix)
通过这些命令输出,我们可以确认子卷一直都是@nix。
结论一:NixOS 文件系统并不支持在运行时动态切换不同的目录。
什么,你想使用 sudo umount /nix,这大概率不行,/nix是 nixos 的核心,只要系统还在运行,就无法卸载。
2. 子卷替代 /nix,重启后出现异常
假设你有两个卷:@nix 和 @nix.bak,当前活跃卷为 @nix。执行 sudo nixos-rebuild switch 时,
系统会基于当前活跃卷生成配置文件并应用到系统中。
问题出现了:当前活跃卷,当前活跃卷是哪个?是@nix,不是@nix.bak,生成的配置都在@nix中。
接下来,重启后,系统会根据 /etc/fstab 挂载 @nix 卷,系统没有找 @nix 找到了 @nix.bak,导致启动失败。
示例:
-
在
@nix卷下,sudo nixos-rebuild switch生成了相关的配置文件:# 当前在 /mnt/@nix 目录 ◎ ls /nix/store/ | rg -v '.drv' | rg 'system-nixos-' | rg '20250712.650e572' ahmkks0fx6c6rf144pmxl82wkhhjp1z0-nixos-system-nixos-25.05.20250712.650e572 l8090dqwbb9zq1s0akycl8m5zakwdraf-nixos-system-nixos-25.05.20250712.650e572 ... -
在
@nix.bak卷下,缺少n9pdhhv997jc0x8xpz4s9fdrx105c5rr启动文件:# 当前在 /mnt/@nix.bak 目录 ◎ ls store/ | rg -v '.drv' | rg 'system-nixos-' | rg '20250712.650e572' 504k4jq5d49a44fa7dyrc1n7kmr1lki8-nixos-system-nixos-25.05.20250712.650e572 ... # 没有对应的启动文件:n9pdhhv997jc0x8xpz4s9fdrx105c5rr
由于没有 n9pdhhv997jc0x8xpz4s9fdrx105c5rr 启动文件,重启后系统无法启动。
结论二:nixos 与 btrfs 搭配不和谐
图示说明
在 NixOS 中,/etc/fstab 文件在 stage1 阶段被加载(某些 Linux 系统则在 stage2 阶段加载)。这就意味着,如果系统在 stage2 阶段加载了不完整的配置文件,就会导致启动失败。下图说明了这个过程:

如何避免该问题?
没有办法避免。一旦nix目录出现问题,我们只能通过 liveCD 环境辅助本机构建。
Live CD 拯救脆弱的本质:如何通过 NixOS Live CD 辅助构建
开源项目通常指的是公开的代码,任何人都可以自由使用、修改和分发。这种开放性给开发者带来了巨大的便利,但也暴露出了一些潜在问题:开源项目的代码质量往往参差不齐。很多项目尽管“能用”,但其稳定性和复现能力可能不如预期。某些强大功能,虽然在理论上很完美,但在实际复现过程中却容易不经意地崩溃。
这时,我们需要借助像 NixOS 官方提供的 Live CD 环境 来帮助我们在完全清洁的环境中进行构建和复现,避免本地环境的不稳定或配置问题。
# 目录结构
/
|- @
|- @nix
|- @nix.bak
sudo mount -o subvol=@ /dev/nvme1n1p2 /mnt
sudo mount /dev/nvme1n1p1 /mnt/boot
sudo mount -o subvol=@nix.bak /dev/nvme1n1p2 /mnt/nix/
# 进入一个简易的 chroot 环境(默认全局sudo权限)
sudo nixos-enter --root /mnt
# 注意可能会出现 systemd,dbus ... 异常。但是,我们只需要nixos构建文件,这一点已经完成
# 本机能不能开机,那是本机的问题,liveCD 已经完成任务。
nixos-rebuild boot
1262

被折叠的 条评论
为什么被折叠?



