NixOS 中的 NixOS?

NixOS within NixOS?

我开始尝试 NixOS 部署。为此,我有一个定义了一些包的回购协议,以及一个用于服务器的 configuration.nix

看来我应该能够在本地测试此配置(我也是 运行 NixOS)。我认为将我的 global configuration.nix 更改为指向部署服务器的 configuration.nix 是个坏主意(谁知道那会破坏什么);但是有没有一种安全方便的方法可以在本地 "try out" 服务器 - 即构建它并启动它,或者更好的是,将它作为一个单独的进程启动?

当然,我可以看到 docker 是一种方式;也许没有别的了。但我有一种模糊的感觉,尼克斯可以独自完成。

您可能已经知道,系统配置可以在 Nix 商店中毫无问题地共存。这里的问题是运行同时多个系统。为此,您需要隔离或虚拟化工具,例如 Docker、VirtualBox 等

NixOS 容器

NixOS provides 容器概念的高效实现,由 systemd-nspawn 支持,而不是基于图像的容器 运行time.

这些可以在 configuration.nix 中以声明方式指定,或者如果您需要更大的灵活性,则可以使用 nixos-container 命令强制指定。

Docker

Docker 并非设计用于 运行 容器内的整个操作系统,因此它可能不是测试 Nix 的最佳选择OS-based deployments,期望并在其部署单元内提供 systemd 和一些服务。 虽然你不会得到好的 NixOS Docker, Nix 和 Docker 很合适。 更新:'raw' Nix 包和 Docker 中的 NixOS 运行。例如,Arion 支持来自普通 Nix、NixOS 模块和 'normal' Docker 图像的图像。

NixOps

要在 NixOS 中部署 NixOS,最好使用旨在 运行 完整 Linux系统里面.

拥有一个为您管理集成的程序会很有帮助。在 Nix 生态系统中,NixOps 是第一个候选者。您可以使用 NixOps with its multiple backends, such as QEMU/KVM、VirtualBox、(目前处于实验阶段)NixOS 容器后端,或者您可以使用 none 后端部署到您使用其他工具创建的机器。

这里是a complete example of using NixOps with QEMU/KVM

测试

如果您的目标是 运行 自动化集成测试,您可以使用 NixOS VM testing framework。这使用 Linux KVM 虚拟化(在沙箱中公开 /dev/kvm)到虚拟机网络上的 运行 集成测试,并且 运行 将它们作为派生。它非常高效,因为它 而不是 必须创建虚拟机映像,因为它在 VM 中安装了 Nix 存储。这些测试像任何其他推导一样“构建”,使它们易于 运行.

拒绝商店优化

Nix 的一个独特功能是您可以经常重用主机 Nix 存储,因此能够在 container/vm 中安装主机文件系统是您解决方案中的一个很好的功能。如果您正在创建自己的解决方案,根据您的需要,您可能希望推迟此优化,因为如果您希望 container/vm 能够修改商店,它会变得更加复杂。 NixOS 测试通过虚拟机中的覆盖文件系统解决了这个问题。另一种方法可能是将 Nix 存储转发到 Nix 守护程序套接字。

默认系统中内置了一种相当标准的方法来执行此操作。

nixos-rebuild build-vm。这将获取您当前的配置文件(默认情况下 /etc/nixos/configuration.nix,构建它并创建一个脚本,允许您将配置引导到虚拟机中。

脚本完成后,它会在当前目录中留下一个符号链接。然后您可以通过 运行 ./result/bin/run-$HOSTNAME-vm 启动,这将启动您的虚拟机供您使用。

TLDR;

  1. nixos-rebuild build-vm
  2. ./result/bin/run-$HOSTNAME-vm
然而,

nixos-rebuild build-vm 是最简单的方法;您还可以将配置导入 NixOS 容器(请参阅 Chapter 47. Container Management in the NixOS manualnixos-container 命令)。

这将通过类似的方式完成:

containers.mydeploy = {
  privateNetwork = true;
  config = import ../mydeploy-configuration.nix;
};

请注意,您不想mydeploy-configuration.nix中指定网络配置,如果它是静态的,因为这可能会导致与为容器创建的网络子网发生冲突。