nixos-vm-template
在 libvirt (KVM) 或 Proxmox VE (KVM 或 LXC) 上构建和管理不可变的 NixOS 虚拟机。
[!NOTE] 此代码使用 Claude Code 和其他 AI 工具编写。它经过 人类审查和测试。
为什么选择不可变虚拟机?
虚拟机随时间推移会积累状态。安装软件包、更新 配置、添加数据——最终你会得到一个独特的雪花, 难以复现或推理。快照和备份有所帮助, 但它们捕获一切——操作系统、配置和数据全部混 在一起。
更好的方法:将操作系统与你的数据分离。
两个磁盘而非一个:
- 启动磁盘 - 操作系统(只读)
- 数据磁盘 - 你的文件和应用状态(
/var,/home)
优势:
- 快照和备份仅针对重要内容——你的数据
- 操作系统是不可变的——没有配置漂移,没有意外变更
- 升级是原子的——重建镜像,交换启动磁盘,重启
- 多个虚拟机可以共享相同的基镜像(精简配置)
- 抗损坏——根文件系统无法在运行时被修改
权衡: 你无法在运行时安装软件包。如果你想要
添加软件包,你需要重建镜像。这是因为
根文件系统——包括 /nix——被设计为以只读方式挂载。
这强制实施基础设施即代码实践,并确保每个虚拟机都
可以从源代码复现。
本项目使用此架构构建 NixOS 镜像。NixOS 非常适合此用途,因为整个系统配置均以代码声明并离线构建。结果是一个启动迅速、运行可预测且可随时完全重建的虚拟机。
特性
- 适用于任何 Linux 主机发行版(例如 NixOS、Fedora、Debian、 Arch Linux 等)
- 三种后端:本地 libvirt/KVM、远程 Proxmox VE(KVM)或 Proxmox LXC 容器
- 它是一个用于创建自定义 NixOS 虚拟机镜像的构建脚本
- 不可变的、类似容器的根文件系统(只读)
- 即使
/etc也是只读的,你需要重新构建镜像才能重新配置它 - 为所有可变状态提供独立的
/var磁盘 - 将
/home绑定挂载到/var/home,将/root绑定挂载到/var/root(持久化) - 可选的可变模式:标准读写 NixOS 以实现完全灵活性
- 快照和备份
- 可组合的虚拟机配置文件以自定义虚拟机角色(docker、podman、dev、claude 等)
- 使用 systemd-boot 进行 UEFI 启动
- 仅使用 SSH 密钥进行身份验证
- QEMU 客户机代理用于 IP 检测和客户机命令
- 桥接虚拟机的静态 IP 或 DHCP(交互式或批处理)
- 交互式网桥管理(创建、添加端口、激活)
- 可选的 zram 压缩交换空间用于内存超额分配
后端
本项目支持三种后端,通过 BACKEND 环境变量进行选择:
| 后端 | 来宾类型 | 根文件系统 | 存储 / 镜像 | 指南 |
|---|---|---|---|---|
libvirt | KVM 虚拟机 | 不可变(或可变) | 带 backing file 的 QCOW2 启动磁盘 | LIBVIRT.md |
proxmox | KVM 虚拟机 | 不可变(或可变) | 通过 SSH 导入的 QCOW2 | PROXMOX.md |
proxmox-lxc | LXC 容器 | 仅可变 | rootfs tarball + 主机 ZFS 绑定挂载 | PROXMOX_LXC.md |
# Use libvirt (default)
just create myvm
# Use Proxmox (KVM)
BACKEND=proxmox just create myvm
# Use Proxmox LXC (containers)
BACKEND=proxmox-lxc just create myct
您可以在项目根目录的 .env 文件中设置 BACKEND,以避免
重复输入:
echo "BACKEND=proxmox" >> .env
[!NOTE]
proxmox-lxc与两种 KVM 后端不同。 容器共享 宿主内核,因此没有引导加载程序,且其根文件系统为读写模式——它 仅可变(nixos-rebuild在其中运行;没有不可变或 半可变模式)。作为交换,它可以将宿主 ZFS 数据集直接绑定挂载 到客户机中(pct set -mpN),这是 KVM 虚拟机无法做到的。这使得它成为 NAS 的正确后端:LXC 专用的nas配置文件通过 NFS + Samba 提供宿主 ZFS 数据集服务。参见 PROXMOX_LXC.md.
两种使用方式
根据你是想运行 已发布的虚拟机镜像还是构建自己的镜像,有两种不同的工作流:
| 生产部署 | 开发 | |
|---|---|---|
| 目标 | 部署官方的预构建镜像 | 自定义系统并构建自己的镜像 |
| 入口点 | bootstrap.bb(bb 单行命令) | 克隆仓库中的 just 配方 |
| 镜像来源 | 从二进制镜像仓库下载 | 使用 Nix 在本地构建 |
| 需要 Nix 吗? | 否 | 是 |
| 所需工具 | bb + 几个标准 CLI 工具 | nix、just、qemu-img、guestfish、… |
对于生产环境,你不需要 Nix、just 构建工具链,甚至
本地克隆——单个 bb 单行命令即可下载预构建镜像并从中创建
虚拟机,当存在 Nix 时,同一单行命令会切换到开发构建
工作流。参见 BOOTSTRAP.md 了解
单行命令及其如何适应每种角色。
要自定义镜像——添加软件包、更改配置、创建新的
配置文件——你需要使用 Nix 和 just 从克隆的仓库自行构建。
这是本文档其余部分所记录的工作流程,从以下
要求开始。要从你的
分支发布你自己的二进制镜像仓库,请参阅 CI.md。
要求(通用,用于本地构建)
[!NOTE] 这些要求适用于开发 / 本地构建工作流程。如果 你只想部署预构建的镜像,请参阅 BOOTSTRAP.md — 它不需要 Nix 或
just。
-
支持 KVM 的 Linux 构建机器
-
nix包管理器(已启用 flakes) -
just(命令运行器)
这些是你唯一需要手动安装的东西。所有其他构建工具——
bb(babashka,用于运行
虚拟机管理命令)、qemu-img 和 guestfish——都由此
flake 的开发环境提供,并且 just 配方会在其中自动运行
(nix develop --command …)。因此,一个干净的克隆加上 Nix 和 just
就足够了;无需通过发行版的包
管理器安装其余部分,也无需手动进入 nix develop。
文档
详细的设置和使用说明位于专门的指南中:
| 指南 | 内容 |
|---|---|
| BOOTSTRAP.md | bb 单行命令 — 生产环境(无 Nix)和开发环境(含 Nix)角色 |
| INSTALL.md | 安装 Nix + just,vm/pve shell 别名,Tab 补全 |
| LIBVIRT.md | Libvirt/KVM 后端:要求,主机防火墙,网络,网桥,存储 |
| PROXMOX.md | Proxmox VE (KVM) 后端:SSH 设置,环境变量,VMID,身份同步,磁盘格式 |
| PROXMOX_LXC.md | Proxmox LXC 后端:容器,主机 ZFS 绑定挂载,nas 配置文件,特权模式 |
| COMMANDS.md | 完整的 just 命令参考(生命周期,克隆,调整大小,快照,备份) |
| MODES.md | 不可变、可变和半可变虚拟机 |
| PROFILES.md | 可用配置文件,常见组合,zram 压缩交换空间 |
| CONFIGURATION.md | machines/<name>/ 配置文件,防火墙端口,root 密码 |
| ARCHITECTURE.md | 磁盘布局和每个后端的内部结构 |
| TROUBLESHOOTING.md | 常见问题及解决方法 |
| CLAUDE_CODE.md | 用于引导式虚拟机管理的 Claude Code 斜杠命令技能 |
| CI.md | 发布你自己的二进制镜像仓库(Woodpecker CI → S3) |
| DEVELOPMENT.md | Fedora Atomic 上的 Nix,distrobox,开发笔记 |