缘起#
我大约在四五年前第一次认真尝试过NixOS。当时的印象是:它的理念非常好——整个操作系统声明式地描述在几个文件里,用Git管理,每次变更都可以原子地切换和回滚——但写配置本身太难了。Nix语言的学习曲线很陡,nixpkgs的选项浩如烟海,找一个正确的写法往往要在网上翻很多帖子,而且很多帖子针对的还是几年前的版本。没有现成的答案时,只能自己试错:改一行、构建一遍、等很久、看报错、再改。这种"写起来比用起来难"的成本,抵消了NixOS的大部分优点,于是我在折腾了一阵之后放弃了,主力机器继续用Fedora。
今年情况变了。AI编码助手(比如Codex、OpenCode这类工具)可以阅读整个配置文件、理解nixpkgs的选项结构、生成并修正Nix代码,而且NixOS的"声明式+可验证"特性恰好是AI最擅长处理的形式:配置是一个完整的、机器可检查的声明,nix flake check和构建过程会直接告诉你它对不对,改坏了可以立刻回滚。人和AI的分工因此变得非常清晰:人负责决定"我要什么",AI负责把"我要什么"翻译成正确的Nix代码并验证它。写配置的困难消失了,NixOS的优点——可复现、可回滚、Git化管理多机器——就重新凸显出来了。
于是我们开始了这次迁移:把家里大部分电脑从Fedora换成NixOS,并且把整个系统配置(包括用户环境、机密文件、自托管服务)都放进Git仓库里声明式地管理。这个系列的文章就是记录这次迁移和后续维护过程,作为我自己和朋友的参考资料。
前提#
- 有一台或多台x86_64电脑,原来运行Fedora或其他发行版(本文的机器是Surface Pro 6、AMD Strix Halo台式机、ThinkPad T460s)
- 熟悉基本的Linux和Git操作
- 有一个可用的AI编码助手(终端里的Codex CLI、OpenCode等,或者网页版的也可以)
- 愿意花一点时间阅读后面的系列文章
迁移范围#
这次迁移涉及三台机器,全部在2026年8月到9月初的不到一个月里完成:
| 主机 | 机器 | 角色 | 现状 |
|---|---|---|---|
surface-pro-6 | Surface Pro 6二合一平板 | 日常主力机(写作、开发) | 2026-08-06从Fedora安装,115个系统代次 |
halo | AMD Strix Halo台式机(“霄”) | 本地AI推理与游戏机 | 2026-08-20加入,44个代次,无头远程桌面 |
t460s | ThinkPad T460s笔记本 | 合盖运行的自托管服务器 | 2026-08-31安装,15个代次,约18个自托管服务 |
“代次(generation)“是NixOS的概念:每次用新配置激活系统都会产生一个可回滚的代次。三台机器加起来174个代次、280多个Git提交,就是这一个多月里人和AI一起迭代出来的。
声明式管理覆盖的范围比"操作系统本身"更广:
- 系统配置:内核、服务、防火墙、用户账号,由一个flake仓库管理(
modules/放共享策略,hosts/<主机>/放各机器的硬件和专属设置); - 用户环境:Shell(Zsh + Oh My Posh)、输入法(Fcitx5 + Rime)、桌面环境(KDE Plasma、Niri + Noctalia)、终端(WezTerm)、编辑器(Neovim/LazyVim)、字体等,全部用Home Manager声明;
- 机密:SSH密钥、服务密码等用SOPS加密后存放在Git里,各机器用自己的主机密钥解密,明文不进仓库也不进Nix store;
- 自托管服务:t460s上约18个Docker/Compose服务(Authelia、Headscale、Nextcloud、Immich、SearXNG等)加上Traefik/Cloudflared边缘栈,用自研的
containerctl工具从"服务清单 + 加密机密 + 主机清单"渲染出运行时配置,开机自动重建; - 远程访问:SSH仅密钥认证、Tailscale、自建NetBird、KRDP/Sunshine共享桌面、无头Halo的EDID虚拟输出。
这些工作里既有"按部就班"的部分(安装系统、装软件),也有一些真正有意思的工程(比如containerctl的v2迁移,前后经历了十几个阶段的逐服务切换)。它们各自对应后面几篇文章。
为什么NixOS的优点现在才成立#
回顾一下NixOS的几个核心优点,以及为什么"AI维护配置"让它们第一次真正可用:
- 可复现:同一个flake在另一台机器上构建出完全相同的系统(同一份
flake.lock锁定所有依赖版本)。过去要维护这个仓库,得自己保证每次更新都是深思熟虑的;现在AI可以帮你审查flake.lock的diff、估算重建成本(比如Surface要重编Linux内核时,先清理旧代次腾出50GiB磁盘)。 - 原子切换与回滚:一次
nixos-rebuild switch要么完整成功、要么不生效,失败的配置可以从启动菜单或--rollback退回。AI可以放心地做较大胆的修改,因为"改坏了"的代价被系统本身兜住了——这也是我们在一个月里敢迭代出174个代次的原因。 - Git即文档:仓库里的README、docs/下的操作手册和逐代次的发布记录(release notes),是人和AI共同维护的"第二大脑”。AI接手任何一台机器的维护前,先读这些文档就能恢复到完整上下文。
- 机器可验证:
nix flake check、构建、test/switch构成了完整的验证闭环,AI不需要"猜"配置对不对,跑一遍就知道了。
第3点其实是最关键的转变:以前NixOS配置库的维护成本主要在"写"上,而"写"依赖人的经验;现在"写"的成本被AI大幅压低,剩下的"验证、记录、回滚"恰恰是NixOS原生就做好的事。
这个系列的结构#
后面几篇文章按下面的顺序展开(本系列共11篇,本文是第1篇):
- 为什么现在重新选择NixOS(本文)
- 核心概念:声明式配置、nixpkgs、flake与
flake.lock、代次与回滚——给没用过NixOS的朋友的概念入门 - 仓库架构:一个flake如何管理三台机器——目录结构、共享模块与主机模块的划分、日常变更流程、逐代次的发布记录
- 用AI维护配置:我们把标准工作流写成"维护者技能(maintainer skill)“交给AI,包括验证顺序、激活交接、失败与安全规则
- 迁移Surface Pro 6:从Fedora安装、生成硬件文件、Linux Surface内核的漫长构建与磁盘预算、开机后验证
- 接入新机器:可复用的新机器安装指南(以T460s为例),包括合盖服务器模式和故障恢复
- 用户环境:Home Manager、Shell、输入法、Plasma/Niri双桌面、Conky的迭代故事
- 网络与远程访问:仅密钥SSH、Tailscale/NetBird、KRDP/Sunshine、无头Halo的EDID方案
- 机密管理:SOPS + sops-nix,用各主机自己的SSH密钥做解密身份
- 自托管服务v2:containerctl架构、分阶段迁移约18个服务、边缘栈与MebTTY web终端
- Halo上的本地AI:Ollama、ROCm容器q38rocm、给AI代理用的本地模型,以及Steam/Proton
其中第5到11篇会引用本仓库里现成的文档和Git历史;如果你也是"先被NixOS劝退过、现在想再来一次"的人,建议从第2、3篇读起。
相关文章#
- “本地运行大语言模型(一):使用ollama和LobeChat在本地或者服务器上部署”:迁移前我们在Fedora上用Docker跑本地LLM的旧方案,后面第11篇会对比NixOS原生管理的方式
- “OpenClaw AI助手设置总结”:AI助手本身的配置,这次迁移中它从Docker容器变成了NixOS原生用户服务
- “容器(1):容器相关知识简介——容器化、docker、docker-compose、Kubernetes / K8s等”:自托管服务的背景知识
