Программирование

NixOS: Как эффективно настроить несколько точек монтирования NFS

Узнайте, как эффективно объявлять несколько точек монтирования NFS в NixOS с общими параметрами с помощью builtins.listToAttrs и функций map. Полное руководство с примерами.

NixOS: Как объявить несколько NFS-монтирований с общими параметрами в цикле

У меня в системе NixOS настроено несколько NFS-монтирований, и для них используются практически одинаковые параметры конфигурации. Я пытаюсь использовать цикл, чтобы не повторять одни и те же параметры монтирования для каждого ресурса, но мой текущий подход работает только для первой записи. Вот что я уже пробовал:

nix
fileSystems =
let attrs = builtins.listToAttrs [
  { mount = "/mnt/Foo"; dev = "192.168.0.1:/mnt/Foo"; }
  { mount = "/mnt/Bar"; dev = "192.168.0.1:/mnt/Bar"; }
];
in {
  mount = {
    depends = ["/"];
    device = dev;
    fsType = "nfs";
    options = [
        "rsize=8192"
        "wsize=8192"
        "_netdev"
        "nfsvers=4"
        "x-systemd.automount"
        "noauto"
        "x-systemd.idle-timeout=600"
        "nofail"
        "x-systemd.automount"
    ];
  };
};

Есть ли идеи, как можно модифицировать эту конфигурацию, чтобы правильно объявить несколько NFS-монтирований в цикле с сохранением одинаковых параметров для каждой точки монтирования?

Понимание проблемы

В вашем конфиге есть две основные ошибки:

  1. Неправильная структура builtins.listToAttrs – функция ожидает, что каждый элемент списка будет иметь атрибуты name и value, а не mount и dev.

  2. Проблема области видимости переменных – переменная dev недоступна в том месте, где вы пытаетесь её использовать в наборе fileSystems.

Согласно Nix Reference Manual, builtins.listToAttrs строит атрибутный набор из списка, где каждый элемент должен содержать name и value.

Правильное решение с builtins.listToAttrs

Вот как правильно оформить конфигурацию:

nix
{
  fileSystems = builtins.listToAttrs [
    {
      name = "/mnt/Foo";
      value = {
        depends = [ "/" ];
        device = "192.168.0.1:/mnt/Foo";
        fsType = "nfs";
        options = [
          "rsize=8192"
          "wsize=8192"
          "_netdev"
          "nfsvers=4"
          "x-systemd.automount"
          "noauto"
          "x-systemd.idle-timeout=600"
          "nofail"
        ];
      };
    }
    {
      name = "/mnt/Bar";
      value = {
        depends = [ "/" ];
        device = "192.168.0.1:/mnt/Bar";
        fsType = "nfs";
        options = [
          "rsize=8192"
          "wsize=8192"
          "_netdev"
          "nfsvers=4"
          "x-systemd.automount"
          "noauto"
          "x-systemd.idle-timeout=600"
          "nofail"
        ];
      };
    }
  ];
}

Альтернативный подход с map

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

nix
{
  fileSystems = builtins.listToAttrs (map 
    (mount: {
      name = mount.path;
      value = {
        depends = [ "/" ];
        device = "${mount.host}:${mount.remote}";
        fsType = "nfs";
        options = mount.options;
      };
    })
    [
      {
        path = "/mnt/Foo";
        host = "192.168.0.1";
        remote = "/mnt/Foo";
        options = [
          "rsize=8192"
          "wsize=8192"
          "_netdev"
          "nfsvers=4"
          "x-systemd.automount"
          "noauto"
          "x-systemd.idle-timeout=600"
          "nofail"
        ];
      }
      {
        path = "/mnt/Bar";
        host = "192.168.0.1";
        remote = "/mnt/Bar";
        options = [
          "rsize=8192"
          "wsize=8192"
          "_netdev"
          "nfsvers=4"
          "x-systemd.automount"
          "noauto"
          "x-systemd.idle-timeout=600"
          "nofail"
        ];
      }
    ]
  );
}

Такой подход упрощает добавление новых точек монтирования – достаточно просто добавить новый элемент в список, а общие параметры объявлены в одном месте.

Частые ошибки и их решения

1. Дублирующиеся имена опций

У вас в списке опций встречается "x-systemd.automount" дважды. Это, скорее всего, опечатка, и дубли могут вызвать конфликт. Уберите лишние элементы.

2. Проблемы области видимости

При использовании let‑привязок убедитесь, что переменные находятся в нужной области видимости. Альтернативный подход с map избавляет от этой проблемы, так как все ссылки обрабатываются внутри функции‑карты.

3. Отсутствие зависимостей

Убедитесь, что модули ядра NFS загружены в конфигурации. Добавьте в configuration.nix:

nix
boot.initrd.supportedFilesystems = [ "nfs" "nfsv4" ];

Согласно NixOS Wiki о NFS, это необходимо для корректной работы монтирования NFS во время загрузки.

Продвинутые шаблоны конфигурации

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

nix
{ config, lib, pkgs, ... }:

let
  commonNfsOptions = [
    "rsize=8192"
    "wsize=8192"
    "_netdev"
    "nfsvers=4"
    "x-systemd.automount"
    "noauto"
    "x-systemd.idle-timeout=600"
    "nofail"
  ];

  nfsMounts = [
    { path = "/mnt/Foo"; host = "192.168.0.1"; remote = "/mnt/Foo"; }
    { path = "/mnt/Bar"; host = "192.168.0.1"; remote = "/mnt/Bar"; }
    { path = "/mnt/Data"; host = "192.168.0.2"; remote = "/volume1/data"; }
  ];

  generateNfsMount = mount: {
    name = mount.path;
    value = {
      depends = [ "/" ];
      device = "${mount.host}:${mount.remote}";
      fsType = "nfs";
      options = commonNfsOptions;
    };
  };

in
{
  boot.initrd.supportedFilesystems = [ "nfs" "nfsv4" ];

  fileSystems = builtins.listToAttrs (map generateNfsMount nfsMounts);
}

Такой шаблон обеспечивает отличную поддерживаемость: добавлять новые точки монтирования или менять общие параметры становится проще.

Проверка конфигурации

После внесения изменений проверьте конфиг:

bash
# Проверка синтаксиса
nix-instantiate --eval --strict configuration.nix

# Сборка системы
sudo nixos-rebuild test

Если всё настроено правильно, вы сможете вручную смонтировать любой раздел:

bash
# Тестируем монтирование
sudo mount /mnt/Foo
df -h /mnt/Foo

Опция x-systemd.automount обеспечит автоматическое монтирование при первом обращении к каталогу.

Источники

  1. Nix Reference Manual – builtins.listToAttrs
  2. Stack Overflow – NixOS declare mounts in loop
  3. NFS – NixOS Wiki
  4. NixOS Discourse – Abstract fileSystems NFS mount
  5. Nixpkgs/lib/attrsets.nix
Авторы
Проверено модерацией
Модерация