NixOS - 带参数的模块导入

时间:2017-12-05 10:06:13

标签: nixos

假设我的NixOS configuration.nix设置如下:

{config, pkgs, ...}:
{
  services.openssh.enable = true;
}

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

{config, pkgs, hostname, ...}:
{
  networking.hostName = hostname
}

这可能吗?我该如何包含该文件。我已经尝试过使用imports = [ ./networking.nix { hostname = "helloworld"; } ];,但这不起作用。

感谢。

3 个答案:

答案 0 :(得分:4)

A' NixOS配置文件'只是一个module,它没有定义选项,所以实际上没有区别。 configuration.nix文件只是一个模块,通常它不定义任何选项,因此可以用abbreviated form编写。

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

然而,如果你真的必须,出于一些非常特殊的原因,因为你在NixOS上做了非常不寻常的事情,你可以在imports中放置任意函数。但是你不应该这样做,因为它不能很好地处理模块系统的自定义错误消息以及可能依赖于知道模块定义位置的其他方面。如果这样做,请确保它是实际功能。在你的情况下,这意味着修改networking.nix的第一行以使其成为一个curried函数:

hostname: {config, pkgs, ...}:

在我看来并不是很漂亮。虽然它对于发生的事情非常明确,但它与NixOS模块的预期不同。

答案 1 :(得分:4)

您应该可以使用_module.args选项[1]来执行此操作。所以你的configuration.nix就像:

{config, pkgs, ...}:
{
  _module.args.hostname = "ahostname";
  services.openssh.enable = true;
}

然而,在值非常简单的情况下,直接设置它们可能要容易得多,例如:只需在networking.hostname中定义configuration.nix即可。本部分手册重新介绍。合并和优先事项也可能有所帮助[2]

进一步讨论:

_module.args的值确实应用于所有导入的配置(尽管该值仅用于直接引用它的模块,例如pkgs值,...表示未引用的所有值。

对于将参数传递给模块,对我来说这似乎是一个很好的方法,但是根据你的评论,也许一种不同的方法可能更合适。

另一种解决方案可能是翻转导入中的关系:而不是传递多个不同参数的单个公共配置,而是多个不同的配置导入公共配置。 E.g。

$cat ./common.nix
{ services.openssh.enable = true; }
$cat ./ahostname.nix
{ imports = [ ./common.nix ]; networking.hostname = "ahostname"; }

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

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

答案 2 :(得分:0)

我今天遇到了这个问题,并在手册中提出了一个相当简单的解决方案recommended

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 ...
];

{
  # ...
}

configuration.nix

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

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