一、/dataset 里还能放哪些实例类型
你已知的 docker / podman / kvm / lxc / microvm 之外,NixOS 这套生态里可落进 /dataset 的实例类型还有这些。按「隔离强度从弱到强」排,同时标出它在 NixOS 里的声明式入口(选项名视版本略有差异)。
| 类型 | 内核 | NixOS 声明式入口 | 典型用途 | 要点 |
|---|---|---|---|---|
| systemd 服务 + DynamicUser | 宿主共享 | systemd.services | 数据库、中间件、守护进程 | 不算容器,但往往是最优解:零虚拟化开销 |
| bubblewrap / firejail 沙箱 | 宿主共享 | security.* / programs.firejail | 单进程隔离(浏览器、外来二进制) | 只隔离进程,不隔离系统 |
| nixos-container(声明式 nspawn) | 宿主共享 | containers.<name> | 要独立 NixOS 用户空间但不要独立内核 | NixOS 一等公民,改配置即重建 |
| OCI 容器 podman(rootless) | 宿主共享 | virtualisation.podman + systemd/quadlet | 绝大多数服务 | 比 docker 更 native:无守护进程、systemd 原生集成 |
| OCI 容器 docker | 宿主共享 | virtualisation.oci-containers(后端 docker) | 依赖 compose 生态的栈 | 多一层 dockerd,能不用就不用 |
| Incus / LXD 系统容器 | 宿主共享 | services.incus(LXD 已改名 Incus) | 类 VM 体验、容器开销;同一套还能管 VM | 适合「想要 VM 手感但不想吃 VM 成本」 |
| microVM(microvm.nix) | 独立内核 | microvm.nix 的 nixosModules | 单服务强隔离、秒级启动 | 后端可选 firecracker / cloud-hypervisor / qemu |
| KVM 全虚机(libvirt) | 独立内核 | virtualisation.libvirtd | Windows、需独立内核 / 设备直通 | 最重但最硬,Win 生态的唯一正解 |
| distrobox | 宿主共享 | environment.systemPackages | 跑其他发行版的用户空间(含 GUI) | 外来闭源工具的最佳容器 |
| Flatpak | 宿主共享 | services.flatpak | 桌面 GUI 应用分发 | 自带沙箱与权限模型 |
| wine / proton | 宿主共享 | programs.wine / steam | 个别 Windows 小程序 | 不能替代 Win VM(网银 UKey、Office 重度场景必翻车) |
| Kata Containers / gVisor | 独立内核 / 用户态内核 | 无官方 NixOS 模块 | 强隔离容器 | 生态偏 k8s,本地场景收益不大 |
| WASM 运行时(wasmtime 等) | 无内核 | 包 + systemd | 插件、边缘函数 | 与上面不同维度:隔离的是代码,不是系统 |
另外还有一类东西同样要占 /dataset,但属于「数据面」而不是「实例」:只读镜像库(iso、rootfs、cloud image)、共享卷(virtiofsd / NFS 导出点)、备份(ZFS snapshot 与 zfs send 的落点)、以及 git 工作区。这一类不要和实例目录混在一起。
二、怎么选:三个判据 + 一条成本线
选型按顺序问三句话,能问出答案就不用纠结:
- 信任边界:这个服务会被不受信的人或网络碰到吗?越暴露越往外层关(Web 应用 → 独立 VM)。
- 内核需求:需要独立内核吗?不同 OS、不同内核版本 / 参数、需要设备直通 → 只能是 VM;否则共享宿主内核就够。
- 显示需求:需要 GUI 吗?谁渲染?宿主 GPU 直用 → 原生 / flatpak / distrobox;远程看 → microVM + waypipe;Windows GUI → KVM。
然后是成本线——每加一层隔离,就多一份运维成本和一层 IO 栈:
原生 systemd + DynamicUser ← 最省,默认选它
→ podman quadlet / oci-containers
→ nixos-container
→ microVM
→ KVM 全虚机
→ KVM 内再 docker ← 只在「必须 Win + 必须容器化」时才用三个反模式,见到就停手:把数据库塞进 KVM(白吃两层 IO);把 tailscale 塞进容器(它必须动宿主网络栈);为了「架构统一」把所有东西都容器化(多一层却零收益)。
三、逐业务归属建议
| 业务 | 建议落点 | 理由 |
|---|---|---|
| 数据库(postgres / mysql / redis) | 宿主原生 systemd + DynamicUser,ZFS dataset 直挂 | 无中间层、延迟最低;ZFS 快照能与 DB 备份对齐;容器化零收益 |
| 对象存储(minio)、消息(nats / redis) | 宿主原生,或 podman quadlet(要版本隔离时) | 同上,除非需要多版本并存 |
| 中间件(向量库 qdrant、搜索等) | podman quadlet | 这类常需多版本、多实例并存,容器化换来干净隔离 |
| git 自托管(forgejo / gitea) | 宿主原生 | NixOS 有现成服务模块,升级与备份路径最短 |
| tailscale | 宿主原生 | 必须接触宿主网络栈;塞进容器是自虐 |
| wireguard / 其他 VPN | 宿主原生 | 同上,网络控制面天然属于宿主 |
| frp(frpc) | 看暴露面:大 → microVM;小 → 宿主 | 穿透工具的对外暴露面大,适合用 microVM 关起来;frps 一般直接放公网 VPS |
| 私有文件服务中心 | 分两种:只服务本机 VM/容器 → 宿主原生 + ZFS 共享(NFS / virtiofsd);要对外开 → 专用 Linux KVM,KVM 内 docker 跑 Web 应用 | 这是「KVM 内再 docker」唯一真正合理的用法:把攻击面关进最大一层隔离 |
| 反向代理与证书(caddy / traefik) | 宿主原生 | 要占 80/443,必须收口在宿主一处 |
| 日常文件处理 GUI(压缩 / PDF / 重命名) | 宿主原生(nixpkgs 首选)或 flatpak | 要直连文件系统与 GPU,套层只会变慢 |
| 浏览器 | 宿主原生 / flatpak;要隔离 → firejail 或 bubblewrap;要强隔离 → 专用 KVM | GPU 加速路径最短;日常放 KVM 里等于自找麻烦 |
| Win 残留应用(微信 / QQ / Office / 网银 UKey / 游戏) | Win KVM + USB 透传 | 就是本项目计 1 的目标机;wine 只适合个别小工具 |
| GPU 计算与编码 | 宿主用 780M 做显示与轻负载;重活给 4060 | 你这台是 780M + 4060 双 GPU,天然可分;但 eGPU 掉链未结案前,4060 不做直通 |
四、IDE(Trae / VSCode)四种形态的取舍
| 方案 | 隔离 | 显示路径 | 维护成本 | 结论 |
|---|---|---|---|---|
| A. 宿主原生(nixpkgs vscode) | 无 | 原生 GPU,最快 | 极低 | 首选。VSCode 在 nixpkgs 有包 |
| B. distrobox 或 flatpak 跑 Trae | 中 | 原生(X11 / Wayland 直通) | 低 | 闭源 Trae 的首选;还能钉住旧版本不被自动更新 |
| C. microVM + code-server / waypipe | 高 | 远程(浏览器或 waypipe) | 中 | 想把 IDE 也隔离又不牺牲太多体验时用 |
| D. docker 化 Trae + VNC | 高 | 远程 VNC | 高 | 最别扭:GUI 走 VNC 体验差,不推荐 |
一句话结论:该下沉的是「开发环境」(编译器、工具链、项目依赖),不是 IDE 本身。IDE 留在一个有原生显示的层(宿主或 distrobox),把项目依赖丢给容器 / microVM / 远端编译机。只有当你的目标明确是「IDE 也不许看到宿主文件系统」时,才把 IDE 一起关进 microVM。
五、/dataset 目录骨架建议
按「实例类型」与「业务域」两个维度分层:实例目录只放运行态产物,数据目录按业务域分包,这样 ZFS 快照与备份策略能按域独立设置。
/dataset
kvm/ ← libvirt 域磁盘(win/、linux/),qcow2
microvm/ ← microvm.nix 实例卷
nspawn/ ← nixos-container 卷
podman/ ← quadlet 实例卷
docker/ ← oci-containers / compose 卷
incus/ ← 若上 Incus
data/ ← 服务数据,按业务域分包,ZFS dataset 级快照
pg/ redis/ gitea/ minio/ qdrant/ ...
share/ ← 共享给 VM 的导出点(virtiofsd / NFS)
iso/ ← 安装镜像(virtio-win.iso、OVMF、发行版 iso)
img/ ← 只读 rootfs / cloud image
repos/ ← git 工作区注意与计 1 的命名冲突:计 1 里写的是 /dataset/vms/,本文用的是 kvm/。两者指的是同一个东西,需要挑一个定稿并同步改另一处(我建议保留 kvm/,因为未来 microVM 与 nixos-container 的卷不是 VM)。
六、网络平面(与实例类型正交,别混在一起谈)
- tailscale 只跑宿主一份,其余实例通过宿主路由 + subnet router 暴露;不要每个实例装一个 tailscale 节点。
- libvirt 默认 virbr0 NAT;microVM 与容器走宿主桥或 slirp;对外一律经宿主 caddy 收口 443。
- frp / 公网暴露只出现在宿主或公网 VPS,本地实例不直连公网。
- 原则:网络出口收口在宿主一处,实例只暴露局部端口,不各自开对外通道。
七、与计 1(偷天换日)的衔接
- Win KVM 落
/dataset/kvm/win;用 virtiofsd 把/dataset/share/win共享给 Win VM(比 SMB 更 native,也符合你 configuration.nix 里已在声明的 virtiofsd)。 - 统一
vms/与kvm/的命名(见第五节)。 - 宿主 NixOS 用 780M 负责显示与轻负载;4060 在 eGPU 掉链问题结案前不做直通,只留给宿主。
- 嵌套虚拟化(VM 内再跑容器 / KVM)在这台机器上可行,但要显式打开 nested;Win VM 内跑 WSL2 或 docker 属于这一类,性能折损明显,非必要不做。