NixOS 中管理 generation(系统世代)主要通过 nixos-rebuild、nix-env 和 nix-collect-garbage 三组命令完成,核心操作是查看、切换、删除、清理,配合 configuration.nix 中的自动维护选项可实现无人值守。以下是维护示例,执行前确认目标 profile 和回滚窗口。
一、Generation 生命周期总览#
flowchart LR
A["修改 configuration.nix<br/>或 flake.nix"] --> B["nixos-rebuild switch"]
B --> C["生成新 Generation<br/>旧版本保留在 /nix/store"]
C --> D{系统是否正常?}
D -- 正常 --> E["继续使用"]
D -- 异常 --> F["nixos-rebuild switch --rollback<br/>或 GRUB 菜单选择旧世代"]
F --> E
E --> G["定期清理旧世代<br/>nix-collect-garbage"]
G --> H["nix-store --gc<br/>回收未引用的 store 对象"]switch/boot 更新系统 profile 时可以记录新 generation;仅 build 或 test 不等于建立新的系统 profile 世代,旧 generation 通常保留,直到手动或自动维护删除;能否回滚取决于保留的 profile 和产物;只有显式删除 generation 并执行垃圾回收后,对应的 /nix/store 路径才会被真正释放。
二、常用命令速查表#
| 操作 | 命令 | 说明 |
|---|---|---|
| 列出所有系统世代 | sudo nixos-rebuild list-generations |
NixOS 较新版本自带,输出最清晰 |
| 列出所有系统世代(通用) | sudo nix-env --list-generations --profile /nix/var/nix/profiles/system |
传统 profile 的通用接口 |
| 列出当前用户环境世代 | nix-env --list-generations |
用户级 profile |
| 回滚到上一个世代 | sudo nixos-rebuild switch --rollback |
立即切换,无需重启 |
| 切换到指定世代(如 204) | 先 sudo nix-env --profile /nix/var/nix/profiles/system --switch-generation 204,再 sudo /nix/var/nix/profiles/system/bin/switch-to-configuration switch |
更改 profile 与激活是两个步骤 |
| 删除指定世代 | sudo nix-env --profile /nix/var/nix/profiles/system --delete-generations 205 206 |
删除 205、206 号 |
| 只保留最近 5 个 | sudo nix-env --profile /nix/var/nix/profiles/system --delete-generations +5 |
+N 表示保留最新 N 个 |
| 删除 30 天前的世代 | sudo nix-env --profile /nix/var/nix/profiles/system --delete-generations 30d |
按时间清理 |
| 删除旧世代并回收空间 | sudo nix-collect-garbage -d |
删除所有旧世代 + GC,最常用 |
| 按时间清理并回收 | sudo nix-collect-garbage --delete-older-than 30d |
保留近 30 天,更安全 |
| 仅回收未被引用的 store 对象 | sudo nix-store --gc |
不删世代,只清未引用路径 |
| 预览将被删除的内容 | sudo nix-store --gc --print-dead |
列出"死"对象,不实际删除 |
| 开机时通过 GRUB 回滚 | 启动菜单选 "NixOS - All configurations" | 选择任意历史世代启动 |
提示:
nix-collect-garbage -d相当于先对工具找到的 profiles 执行nix-env --delete-generations old,再执行nix-store --gc,执行后将无法回滚到已被删除的世代。
三、清理 /nix/store 空间#
1. 标准两步清理流程
# 第一步:删除 14 天前的系统世代
sudo nix-env --delete-generations --profile /nix/var/nix/profiles/system 14d
# 第二步:只回收未引用的 store 对象,不再扩大历史删除范围
sudo nix-store --gc此流程将历史删除范围限定在指定系统 profile,先删世代再 GC,否则被世代引用的包不会被回收。
2. 优化存储(硬链接去重)
sudo nix-store --optimise对相同的 store 文件内容进行硬链接去重,节省量取决于重复内容,可配合 GC 定期执行。
四、在 configuration.nix 中配置自动维护#
把这些选项写进 /etc/nixos/configuration.nix,rebuild 后即可实现自动清理,无需手动跑命令:
{ config, pkgs, ... }:
{
# 限制 GRUB 启动菜单中保留的世代数量(建议 10-20)
boot.loader.grub.configurationLimit = 20;
# 自动垃圾回收
nix.gc = {
automatic = true;
dates = "weekly"; # 每周执行,也可用 "03:30" 指定时间
options = "--delete-older-than 30d"; # 只删 30 天前的世代
};
# 自动优化存储(硬链接去重)
nix.settings.auto-optimise-store = true;
# 设置构建时尝试自动 GC 的可用空间阈值(不是 store 容量硬限制)
nix.extraOptions = ''
min-free = ${toString (5 * 1024 * 1024 * 1024)}
max-free = ${toString (10 * 1024 * 1024 * 1024)}
'';
}nix.gc.automatic 是官方推荐做法,可以避免 /nix/store 无限膨胀;boot.loader.grub.configurationLimit 则从源头限制 GRUB 菜单条目数量,避免启动列表过长。
五、进阶技巧#
1. 用 nh 简化操作
nh(nix helper)是社区流行的封装工具,提供 nh os switch、nh os generations 等更友好的命令,并能在 rebuild 后显示配置 diff。
2. 新一代 nix 命令
新 CLI 提供用 nix profile 系列命令管理世代:
sudo nix profile history --profile /nix/var/nix/profiles/system # 查看历史
sudo nix profile wipe-history --profile /nix/var/nix/profiles/system --older-than 7d # 清理 7 天前社区配置仓库中常见这种写法。
3. 系统无法启动时的回滚
即使系统进不去桌面,NixOS 默认在 GRUB 菜单保留 "NixOS - All configurations" 子菜单,列出未删除且在启动菜单保留范围内的历史世代,直接选择即可回到上一个可用状态;这是最后一道保险。
4. 安全清理建议
- 执行
nix-collect-garbage -d前确认当前世代稳定,因为删除后无法回滚。 - 生产服务器建议用
--delete-older-than 30d而非-d,保留一段时间的回滚窗口。 - 大版本升级后先验证运行和回滚方案,再按保留策略清理;菜单条目限制不会自动删除 profile 历史或释放全部 store 空间。
把上述命令和配置组合起来,基本能覆盖从日常回滚到长期磁盘维护的全部场景:nixos-rebuild list-generations 看状态、--rollback 救急、nix-collect-garbage --delete-older-than 定期清,再配 nix.gc.automatic 自动兜底。
参考与延伸
根据技术笔记重新整理,示例使用通用名称。