业务场景与虚拟化技术选择的native方案

一、/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.libvirtdWindows、需独立内核 / 设备直通最重但最硬,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;要强隔离 → 专用 KVMGPU 加速路径最短;日常放 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 属于这一类,性能折损明显,非必要不做。