从 Proxmox 迁移到 NixOS 和 Incus
摘要
作者描述了将其家庭实验室从 Proxmox 迁移到使用 Incus 的 NixOS 的过程,强调了声明式配置和可重现性相对于命令式系统的优势。
暂无内容
查看缓存全文
缓存时间: 2026/06/25 23:14
# 我已全面转向 Nix:从 Proxmox 到 NixOS + Incus
来源:https://www.nijho.lt/post/proxmox-to-nixos/
## 我已全面转向 Nix:从 Proxmox 到 NixOS + Incus
我已正式退役我的 Proxmox 集群。在 Proxmox 上运行了我的家庭实验室多年——从一台 NUC 起步,扩展到多节点集群——现在我已将所有内容迁移到运行 Incus 的 NixOS。
## 从怀疑者到信徒# (https://www.nijho.lt/post/proxmox-to-nixos/#from-skeptic-to-believer)
我并非一直都是 Nix 的布道者。事实上,我最初厌恶这门语言及其语法。我搞不懂它是如何工作的,而且我已有自己特定的方式来设置我的点文件。我使用Dotbot (https://www.nijho.lt/post/dotfiles/)进行符号链接,并使用我编写的一个名为dotbins (https://www.nijho.lt/post/dotbins/)的工具来管理二进制文件。我觉得大多数工具并不需要 Nix。我曾在 Mac 上长期使用nix-darwin (https://github.com/basnijholt/dotfiles/blob/4f534bf32fb4396dd86ce631dec00717eab7656d/configs/nix-darwin/configuration.nix),但仅用于指定 Homebrew 包和应用设置。
真正的转变发生在我购买游戏 PC 时,如我在本地 LLM 文章 (https://www.nijho.lt/post/local-ai-journey/)中所描述。我最初安装了 Pop!_OS,因为我想玩游戏,并且绝对想避免使用 Windows。我让一些游戏能运行,但不断遇到 NVIDIA 驱动程序问题,需要运行随机、命令式的命令来修复。我感觉这是糟糕的解决方案,因为之后永远无法重现这些调试步骤。然后我做了件蠢事:更新了 NVIDIA 驱动程序,没有意识到命令式地管理驱动版本和存储库是灾难的配方,结果卡在了 GRUB 启动循环中。沮丧之下,我安装了 NixOS,希望其原子更新的承诺能解决这个问题。结果非常棒。直到我将该系统迁移到新磁盘时,我才真正相信所有内容会字节级等价。我没有克隆驱动器,只是将我的 Nix 配置应用到一次全新安装。它启动了,我复制了数据,一切完全相同。那一刻我彻底明白了。
## 命令式系统的摩擦# (https://www.nijho.lt/post/proxmox-to-nixos/#the-friction-of-imperative-systems)
Proxmox 是非常棒的软件。它降低了我的入门门槛,教会了我关于虚拟化、LXC 容器和 ZFS 的几乎所有知识。但本质上,Proxmox 建立在**点击按钮**之上。它是 GUI 优先的范式。虽然你*可以*用 Terraform 或 Ansible 来自动化它,但这往往感觉像是在与工具对抗。状态漂移是真实存在的。你在 UI 中更改某个设置来调试问题,然后忘记了,六个月后你的“基础设施即代码”就与现实不同步了。对于手动维护系统的人来说,这很烦人。但当你引入 AI 代理时,这对操作员来说就成了灾难。一个以“YOLO 模式”运行的代理可能会执行数百条命令式命令来修复一个问题。它可能成功,但会使你的系统处于未定义、不可复现的状态,之后没有人——甚至代理自己——能完全理解或重现。
这种摩擦也体现在硬件管理上。在我的 HP EliteDesk 上,Intel I219-LM 网卡有一个已知错误:启用硬件卸载时会挂死。我隐约记得几年前在 Proxmox 上修复过,但忘记了细节。当我设置 NixOS 时,遇到了同样的问题:网络会随机断开。然而这次,修复方法不再是 root shell 历史记录中一条被遗忘的命令。它是我配置中的一个**被文档化的 systemd 服务** (https://github.com/basnijholt/dotfiles/blob/4f534bf32fb4396dd86ce631dec00717eab7656d/configs/nixos/hosts/hp/networking.nix#L16-L31)。我添加了一条注释,精确解释了*为什么*需要 `tso off gso off`,并引用了论坛帖子。如果我重新安装这台机器,修复会自动应用。而在 Proxmox 上,我将不得不重新经历这痛苦的一切。
另一个例子是我的 Intel NUC。由于我的家庭实验室放在电视后面,我好奇是否也能将其用作家庭影院 PC (HTPC)。在 Proxmox 上,这需要将 GPU 直通给一个虚拟机以获取视频输出。但这样做意味着 Proxmox 宿主机完全失去对 GPU 的访问,意味着如果出问题就无法使用本地控制台。这是一个严格取舍:要么是媒体播放器,要么是可调试的虚拟机管理程序。我尝试过,但麻烦太多,很快就回退了。使用 NixOS,我不必选择。宿主机系统直接运行Kodi (https://github.com/basnijholt/dotfiles/blob/4f534bf32fb4396dd86ce631dec00717eab7656d/configs/nixos/hosts/nuc/kodi.nix),提供原生硬件加速和视频输出。同时,`incus` 在后台运行,托管我的容器。我可以在同一台硬件上既拥有 HTPC 又拥有服务器,无需虚拟化开销,也没有“无头宿主机”的限制。
还有更深的哲学差异。像 Proxmox 或 TrueNAS 这样的系统被设计为设备。你不应该随意在宿主机上运行命令;安装软件包或修改配置文件是不被鼓励的,因为可能破坏中间件或在升级时丢失更改。你实际上被锁在了自己硬件的全部潜力之外。而使用 NixOS,宿主机完全属于我。我可以随意折腾它——安装 Kodi、调整网络驱动、运行本地 LLM——而无需担心。因为状态是声明式的,它 100% 明显且可复现。我可以破坏宿主机配置,然后在几秒内恢复到正常工作状态,即使机器正在运行关键服务。
## 代理乘数效应# (https://www.nijho.lt/post/proxmox-to-nixos/#the-agentic-multiplier)
我之前写过关于我转向基于代理的编程 (https://www.nijho.lt/post/agentic-coding/)的文章。在 AI 代理执行任务的当下,**CLI 优先**和**声明式**系统是王道。AI 代理无法可靠地在 Web 界面中“点击按钮”来配置 VLAN 标签或调整磁盘大小。它需要文本,需要确定性。
通过迁移到 NixOS,我的整个基础设施都定义在文本文件中。这意味着我的 AI 代理可以读取、理解,甚至安全地修改我的基础设施。Proxmox 不透明的数据库和 UI 驱动的工作流对我的代理来说是一个黑盒。而 NixOS 是一本打开的书。如果我希望我的代理“在端口 9000 上部署一个 Faster Whisper API 服务器并暴露给 LAN”,它不需要先导航到“服务”菜单,然后“网络”菜单,再然后“防火墙”菜单。它只需编写一个 systemd 服务定义 (https://github.com/basnijholt/dotfiles/blob/fa890fa22ee608be2d11ab4f705550337092c414/configs/nixos/hosts/pc/ai.nix#L385),并在同一文件中添加 `networking.firewall.allowedTCPPorts = [ 9000 ];`。代理甚至可以通过检查 git diff 或活动配置来验证更改是否成功。这正是我所经历的“基于代理的编程”革命在基础设施领域的对应物。
一位使用 NixOS 多年的朋友最近称赞我的配置结构良好,尤其是管理 8 台不同的机器。有趣的是,我的配置几乎没有一行是我自己写的。我全部使用基于代理的 AI 在多次会话中完成。我重构和重组了好几次,从单台机器发展到 2 台,最终到 9 台。AI 处理了重构的繁重工作,确保我的PC、NUC 和 HP (https://github.com/basnijholt/dotfiles/blob/4f534bf32fb4396dd86ce631dec00717eab7656d/configs/nixos/flake.nix)共享公共模块,同时保持各自独特的个性。
## 架构:Incus 与模拟# (https://www.nijho.lt/post/proxmox-to-nixos/#the-architecture-incus--simulation)
我仍然希望有一种纯粹的“Nix”方式来管理持久、有状态的 LXC 容器和虚拟机。有一些项目如 `nixos-containers` 或 `microvm.nix`,但它们往往缺乏成熟的操作特性或像健壮虚拟机管理程序那样的实时迁移功能。Incus (https://linuxcontainers.org/incus/)(LXD 的社区分支)完美填补了这一空白。它让我拥有 NixOS 对宿主机“牲畜”式的管理,同时允许我在稳定、可管理的环境中运行“宠物”遗留工作负载(如旧版 Ubuntu 容器或 Home Assistant 虚拟机)。关键是,Incus 完全通过干净的 CLI 控制,使其在我的代理工作流中成为完美公民。
随着时间的推移,我已经将大部分遗留的 LXC 容器——如 DNS 或媒体管理器等服务——迁移到了在虚拟机内运行的声明式 Docker Compose 文件。但我仍然有一个主要的坚持者:**Home Assistant OS**。我没有好的替代方案。我以为需要像 Proxmox 这样的专用设备系统才能可靠地运行它。我没有意识到,在 NixOS 上使用 Incus,为 Home Assistant 运行一个完整的虚拟机是小事一桩。它只是另一个 QEMU 进程,但以与容器相同的简便方式进行管理。
我做的另一件巧妙的事是创建了复制我物理机器完全相同配置的 Incus 虚拟机。在我真正关闭最后一台 Proxmox 宿主机之前,我已经确信完整配置可以工作,因为我已经有一台运行相同设置的虚拟机。我只有一个小文件包含覆盖项 (https://github.com/basnijholt/dotfiles/blob/4f534bf32fb4396dd86ce631dec00717eab7656d/configs/nixos/hosts/hp/incus-overrides.nix)。然后我可以验证虚拟机是否工作。这消除了“摧毁并重建”我物理服务器的恐惧。
## 迁移过程# (https://www.nijho.lt/post/proxmox-to-nixos/#the-migration)
迁移过程出奇地直接,多亏了 `vzdump` 和 `qemu-img`。以下是我如何移动 7 年以上的数字历史而不丢失数据。
我还保留了一些详细的迁移笔记 (https://github.com/basnijholt/dotfiles/blob/fa890fa22ee608be2d11ab4f705550337092c414/configs/nixos/archive/PROXMOX_MIGRATION.md)在我的点文件中。这些笔记应该足以让任何想进行相同操作的人使用。如果不是,将它们交给 AI(我使用了 Gemini 3 Pro)肯定能让你弄清楚。
### 1. 迁移 LXC 容器# (https://www.nijho.lt/post/proxmox-to-nixos/#1-migrating-lxc-containers)
对于我的 LXC 容器(运行 Docker、DNS 等),我基本上是“瞬移”它们。我将 Proxmox 上运行的容器转储为标准化 tarball,复制过来,然后直接流式传输到一个新的 Incus 容器中。
在 Proxmox 上:
```
# 将容器 101 转储为压缩存档
vzdump 101 --dumpdir /var/lib/vz/dump --mode suspend --compress zstd
```
在 NixOS 上(使用我的 `migrate-lxc.sh` (https://github.com/basnijholt/dotfiles/blob/4f534bf32fb4396dd86ce631dec00717eab7656d/configs/nixos/archive/migrate-lxc.sh) 脚本):
```
# 将备份流式传输到新的 Incus 容器
./migrate-lxc.sh vzdump-lxc-101-*.tar.zst ubuntu-container
```
这个脚本会创建一个新容器,挂载其根文件系统,并用 Proxmox 转储覆盖它。它自动处理了麻烦的部分——比如映射 UID 和修复 `machine-id`。
### 2. 迁移虚拟机# (https://www.nijho.lt/post/proxmox-to-nixos/#2-migrating-virtual-machines)
对于虚拟机(如 Home Assistant OS),就是转换磁盘格式。Proxmox 使用 LVM-thin 或 ZFS zvol;Incus 可以使用 QCOW2 或原始 ZFS。
在 Proxmox 上:
```
# 将 ZFS 卷导出为 QCOW2 文件
qemu-img convert -p -O qcow2 /dev/zvol/rpool/data/vm-100-disk-0 vm-100.qcow2
```
在 NixOS 上(使用 `migrate-vm.sh` (https://github.com/basnijholt/dotfiles/blob/4f534bf32fb4396dd86ce631dec00717eab7656d/configs/nixos/archive/migrate-vm.sh)):
```
# 导入磁盘并创建虚拟机
./migrate-vm.sh vm-100.qcow2 home-assistant
```
## 结果# (https://www.nijho.lt/post/proxmox-to-nixos/#the-result)
我现在从单个 git 仓库管理我的整个舰队——包括宿主操作系统、网络、存储和虚拟机管理程序配置。我做到了两全其美:在我需要的地方有持久、有状态的服务,以及可复现、坚不可摧的宿主操作系统。我可以擦除我的宿主机,重新安装 NixOS,运行恢复脚本,然后在几分钟内恢复在线。最重要的是,我再也不用记得三年前在 Web UI 中点击了哪个复选框。一切都在代码中。而因为是代码,我的代理可以帮助我管理它。
## 参考与配置# (https://www.nijho.lt/post/proxmox-to-nixos/#references--configuration)
本文提到的所有配置文件都可在我的点文件仓库 (https://github.com/basnijholt/dotfiles) 中找到。
1. **flake.nix** (https://github.com/basnijholt/dotfiles/blob/fa890fa22ee608be2d11ab4f705550337092c414/configs/nixos/flake.nix):定义我的整个舰队(PC、NUC、HP)的入口点。
2. **networking.nix** (https://github.com/basnijholt/dotfiles/blob/fa890fa22ee608be2d11ab4f705550337092c414/configs/nixos/hosts/hp/networking.nix#L16-L31):用于 Intel I219-LM 网络挂起的声明式修复。
3. **kodi.nix** (https://github.com/basnijholt/dotfiles/blob/4f534bf32fb4396dd86ce631dec00717eab7656d/configs/nixos/hosts/nuc/kodi.nix):NUC HTPC 配置,直接在宿主机上运行 Kodi。
4. **ai.nix** (https://github.com/basnijholt/dotfiles/blob/fa890fa22ee608be2d11ab4f705550337092c414/configs/nixos/hosts/pc/ai.nix#L385):Faster Whisper 的声明式服务定义。
5. **incus-overrides.nix** (https://github.com/basnijholt/dotfiles/blob/4f534bf32fb4396dd86ce631dec00717eab7656d/configs/nixos/hosts/hp/incus-overrides.nix):用于在 Incus 虚拟机内模拟物理机器的覆盖项。
6. **migrate-lxc.sh** (https://github.com/basnijholt/dotfiles/blob/4f534bf32fb4396dd86ce631dec00717eab7656d/configs/nixos/archive/migrate-lxc.sh):将 Proxmox `vzdump` 存档导入 Incus 容器的脚本。
7. **migrate-vm.sh** (https://github.com/basnijholt/dotfiles/blob/4f534bf32fb4396dd86ce631dec00717eab7656d/configs/nixos/archive/migrate-vm.sh):将 QCOW2 磁盘镜像导入 Incus 虚拟机的脚本。
8. **PROXMOX_MIGRATION.md** (https://github.com/basnijholt/dotfiles/blob/fa890fa22ee608be2d11ab4f705550337092c414/configs/nixos/archive/PROXMOX_MIGRATION.md):详细的原始笔记和迁移清单。
相似文章
将我的 NAS 从 CoreOS/Flatcar Linux 迁移到 NixOS
Michael Stapelberg 详细介绍了他将一台 NAS 从 CoreOS/Flatcar Linux 迁移到 NixOS 的过程,涵盖了从 Docker 容器逐步过渡到原生 NixOS 模块的步骤,并附有实际示例。
我喜欢的 NixOS 声明式安装方式
一份关于使用 nixos-anywhere 等工具通过网络声明式安装 NixOS 的指南,重点强调在版本控制下管理配置文件。
使用Nix构建系统软件
一篇博客文章,讨论Nix如何帮助解决构建系统软件时的依赖和可重现性问题,特别是针对像BPF和io_uring这样快速演进的子系统。
Guix Nix 的怪异融合:在 Nix 中利用 Guix 派生
一项技术探索,展示了 Nix 如何构建 Guix 派生项,强调了共享底层“输入输出机”架构以及跨生态系统互操作的可能性。
Derivations to Deployments: Practical Nix in Production
这篇演讲介绍了如何用 Nix 实现从开发环境、构建到云部署的全面可复现性,并展示了 Antithesis 基于 Nix 的“命令集”框架来替代杂乱脚本。