NixOS - модуль импорта с аргументами

Допустим, у меня есть мой NixOS configuration.nix настроить следующим образом:

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

Теперь я хочу иметь второй файл с именем networking.nix который устанавливает мое имя хоста на основе аргумента.

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

Это возможно? Как я могу включить файл. Я уже пытался сделать это с помощью imports = [ ./networking.nix { hostname = "helloworld"; } ]; но это не сработало.

Благодарю.

2 ответа

Сегодня я столкнулся с этой проблемой и нашел довольно простое решение, рекомендованное в руководстве.

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"; }
      )
    )
    # ...
  ];
}

Это идеально подходит для "разовых" вариантов в ваших конфигурациях.

"Файл конфигурации NixOS" - это просто модуль, который не определяет параметры, поэтому на самом деле нет никаких различий. configuration.nix Файл - это просто модуль, и, как правило, он не определяет какие-либо параметры, поэтому его можно записать в сокращенной форме.

Определение опций - это обычный способ для модулей NixOS передавать информацию, так что это самый идиоматичный способ.

Однако, если вам действительно необходимо по какой-то особой причине, потому что вы делаете очень необычные вещи с NixOS, вы можете поместить произвольные функции в imports, Но вы не должны этого делать, потому что он плохо работает с пользовательскими сообщениями об ошибках системы модулей и, возможно, с другими аспектами, которые зависят от знания, где определен модуль. Если вы это сделаете, убедитесь, что это фактическая функция. В вашем случае это будет означать изменение первой строки networking.nix сделать функцию карри:

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

Не очень красиво, на мой взгляд. Несмотря на то, что он очень четко описывает происходящее, он отличается от того, что следует ожидать от модуля NixOS.

Вы должны быть в состоянии использовать _module.argsвариант [1], чтобы сделать это. Так что ваши configuration.nix было бы как:

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

Однако, если значения очень просты, вероятно, будет гораздо проще просто установить их напрямую, например, просто определить networking.hostname в configuration.nix, Этот раздел руководства повторно. Слияние и приоритеты могут быть полезны также [2].


Дальнейшее обсуждение:

Значение _module.args действительно применяется ко всем импортированным конфигурациям (хотя значение будет использоваться только в модулях, которые непосредственно на него ссылаются, таких как pkgs значение, ... представляет все значения, на которые нет ссылок).

Для передачи аргументов модулям это кажется хорошим подходом для меня, но из ваших комментариев, возможно, другой подход может быть более подходящим.

Другим решением может быть изменение отношения в импорте: вместо единой общей конфигурации, которая передает несколько разных аргументов, вместо нескольких разных конфигураций импортируется общая конфигурация. Например

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

Конфигурация NixOS в этом комментарии Reddit выглядит так, как будто он использует этот подход. Существует довольно много других конфигураций NixOS, которыми люди публично делятся в сети, поэтому вы можете найти там несколько полезных идей. Пункты в ответе Роберта Хенсинга также очень полезны для понимания.

Однако трудно сказать, что может быть лучшим решением в вашем случае, не зная немного больше о контексте, в котором вы хотите его использовать. Вы можете создать новый вопрос SO с дополнительной информацией о том, что может помочь найти более подходящее решение.

Другие вопросы по тегам