NixOS - 带参数的模块导入

lsc*_*ann 6 nixos

假设我的 NixOSconfiguration.nix设置如下:

{config, pkgs, ...}:
{
  services.openssh.enable = true;
}
Run Code Online (Sandbox Code Playgroud)

我现在想要调用第二个文件networking.nix,它根据参数设置我的主机名。

{config, pkgs, hostname, ...}:
{
  networking.hostName = hostname
}
Run Code Online (Sandbox Code Playgroud)

这可能吗?我怎样才能包含文件。我已经尝试通过使用来做到这一点,imports = [ ./networking.nix { hostname = "helloworld"; } ];但这没有用。

谢谢。

Rob*_*ing 7

“NixOS 配置文件”只是一个没有定义选项的模块,因此实际上没有区别。一个configuration.nix文件只是一个模块,并且通常不定义任何选项,因此它可以在写缩写形式

定义选项是 NixOS 模块传递信息的正常方式,因此这是最惯用的方式。

但是,如果您真的必须,出于某些非常特殊的原因,因为您正在使用 NixOS 做非常不寻常的事情,您可以将任意函数放入imports. 但是您不应该这样做,因为它不适用于模块系统的自定义错误消息以及可能依赖于了解模块定义位置的其他方面。如果这样做,请确保它是一个实际的函数。在您的情况下,这意味着修改第一行networking.nix以使其成为柯里化函数:

hostname: {config, pkgs, ...}:
Run Code Online (Sandbox Code Playgroud)

在我看来不是很漂亮。尽管它对正在发生的事情非常明确,但它偏离了 NixOS 模块的预期。


bro*_*ing 5

您应该能够使用_module.args选项[1]来做到这一点。所以你configuration.nix会像:

{config, pkgs, ...}:
{
  _module.args.hostname = "ahostname";
  services.openssh.enable = true;
}
Run Code Online (Sandbox Code Playgroud)

然而,在值非常简单的情况下,直接设置它们可能会容易得多,例如只需定义networking.hostnamein configuration.nix。本节手册重新。合并和优先级也可能有帮助[2]


进一步讨论:

的值_module.args确实适用于所有导入的配置(尽管该值只会在直接引用它的模块中使用,例如pkgs值,the...表示所有未引用的值)。

对于将参数传递给模块,这对我来说似乎是一种很好的方法,但从您的评论来看,也许另一种方法可能更合适。

另一种解决方案可能是翻转导入中的关系:而不是传递多个不同参数的单个通用配置,而是多个不同的配置导入通用配置。例如

$cat ./common.nix
{ services.openssh.enable = true; }
$cat ./ahostname.nix
{ imports = [ ./common.nix ]; networking.hostname = "ahostname"; }
Run Code Online (Sandbox Code Playgroud)

Reddit 评论中的 NixOS 配置看起来像是使用了这种方法。人们在网上公开分享了许多其他 NixOS 配置,因此您可能会在其中找到一些有用的想法。Robert Hensing 的回答中的要点也非常有用,值得牢记。

但是,如果不了解更多关于您想要使用它的上下文,就很难说在您的情况下什么可能是更好的解决方案。您可以创建一个新的 SO 问题,其中包含有关该问题的更多信息,这可能会使您更容易看到更合适的解决方案。


nrd*_*dxp 5

我今天遇到了这个问题,并想出了手册中推荐的一个相当简单的解决方案。

foobar.nix

{ lib, withFoo ? "bar", ... }:

# simple error checking to ensure garbage isn't passed in
assert lib.asserts.assertOneOf "withFoo" withFoo [
  "bar"
  "baz"
  # other valid choices ...
];

{
  # ...
}

Run Code Online (Sandbox Code Playgroud)

configuration.nix

args@{ ... }:
{
  imports = [
    # ...
    (
      import ./foobar.nix (
        args
        // { withFoo = "baz"; }
      )
    )
    # ...
  ];
}
Run Code Online (Sandbox Code Playgroud)

这是配置中“一次性”选项的理想选择。