系统更新翻车后的自救:回退 flake.lock 是恢复可复现状态的常见手段,但不等于系统已经回滚。
flake.lock 的本质#
flake.lock 是给 nix 读的纯文本 JSON——nix 只认内容不认来源。你可以:
- 手动编辑(改 rev、改 URL、改 narHash)
git checkout回退(优先考虑)- 从别处复制一个 lock 文件
只要 narHash 和 rev 对得上、包能构建,nix 就会采用。
回退方式一:git checkout(保留当前改动后使用)#
配置仓库本身是 git 仓库时,回退 flake.lock 可优先从已知好的 Git 版本恢复:
# 1. 查看提交历史,找到更新前的 commit
cd ~/nixos-config
git status --short
# 先备份当前锁文件,保留尚未提交的更新
cp flake.lock /tmp/flake.lock.before-rollback
git log --oneline -5 flake.lock
# 2. 回退 flake.lock 到某个 commit 的版本(<known-good-commit> 是更新前)
git restore --source=<known-good-commit> -- flake.lock
# 3. 验证配置能评估(不实际构建)
nix flake check --no-build
nixos-rebuild dry-build --flake .#my-host
# 4. 检查差异;dry-build 不会构建或激活系统
git diff -- flake.lock
# 确认需要保存本次回退后再提交
git add flake.lock
git commit -m "revert(flake): roll back flake.lock to <known-good-commit>"为什么它最安全:
- 指定 commit 是已知能工作的版本(更新前)
- 不用猜 narHash
- 有 git 历史可追溯
回退方式二:系统代际回退#
如果问题出在系统本身(不只是依赖锁定),可以回退整个 generation:
# 列出所有历史系统代际(按时间倒序)
ls -l /nix/var/nix/profiles/system-*-link
# 回到上一个代际(立即生效)
sudo nixos-rebuild switch --rollback
# 回到指定代际(如第 5 个)
sudo /nix/var/nix/profiles/system-5-link/bin/switch-to-configuration switch完整教程见 Generation 管理指南。新系统完全进不去时,重启在 GRUB 菜单选旧代际("NixOS - All configurations")即可。
GC 警示#
NixOS 代际是"堆叠"的:每次 switch 生成新代际,旧的不会自动删除,直到显式删除代际。GC 只回收不再被根引用的 Store 路径。重要配置更新前别跑 nix-collect-garbage——普通 GC 不会删除仍被代际引用的路径;nix-collect-garbage -d 会删除旧代际并回收不再引用的内容,可能失去回退路径。
手动编辑的坑#
- narHash 必须准确:nix 用 narHash 校验下载内容。rev 改了但 narHash 是旧的 → 报
hash mismatch。手动改 rev 通常要配新的 narHash。 - 有专门命令,不一定要手改:
- 回退到指定 commit:
在 flake.nix 中将 nixpkgs.url 固定到 github:NixOS/nixpkgs/<rev>,再运行 nix flake update nixpkgs - 但通过声明输入并由 Nix 生成 lock 通常比手改 JSON 更容易检查,因为配置本身就是 git 仓库。
- 回退到指定 commit:
- flake.lock 是版本锁定文件:锁住每个 input 的确切版本,保证可复现。手动编辑 = 手动改变锁定版本,完全合法。
操作对照表#
| 操作 | 方式 |
|---|---|
| 回退到已知好的旧版本 | git restore --source=<commit> -- flake.lock(会覆盖工作树中的该文件,先备份) |
| 更新到最新 | nix flake update |
| 更新单个 input | nix flake update nixpkgs |
| 手动改特定 rev | 手编辑,但需配 narHash(麻烦,少用) |
核心:只要配置是 git 仓库,回退 flake.lock 可优先从已知好的 Git 版本恢复,不用手改。手动编辑更像"高级技巧",多数时候不需要。
参考与延伸
根据技术笔记重新整理,示例使用通用名称。