NixOS: Как эффективно настроить несколько точек монтирования NFS
Узнайте, как эффективно объявлять несколько точек монтирования NFS в NixOS с общими параметрами с помощью builtins.listToAttrs и функций map. Полное руководство с примерами.
NixOS: Как объявить несколько NFS-монтирований с общими параметрами в цикле
У меня в системе NixOS настроено несколько NFS-монтирований, и для них используются практически одинаковые параметры конфигурации. Я пытаюсь использовать цикл, чтобы не повторять одни и те же параметры монтирования для каждого ресурса, но мой текущий подход работает только для первой записи. Вот что я уже пробовал:
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-монтирований в цикле с сохранением одинаковых параметров для каждой точки монтирования?
Понимание проблемы
В вашем конфиге есть две основные ошибки:
-
Неправильная структура
builtins.listToAttrs– функция ожидает, что каждый элемент списка будет иметь атрибутыnameиvalue, а неmountиdev. -
Проблема области видимости переменных – переменная
devнедоступна в том месте, где вы пытаетесь её использовать в набореfileSystems.
Согласно Nix Reference Manual, builtins.listToAttrs строит атрибутный набор из списка, где каждый элемент должен содержать name и value.
Правильное решение с builtins.listToAttrs
Вот как правильно оформить конфигурацию:
{
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 для генерации конфигураций монтирования:
{
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:
boot.initrd.supportedFilesystems = [ "nfs" "nfsv4" ];
Согласно NixOS Wiki о NFS, это необходимо для корректной работы монтирования NFS во время загрузки.
Продвинутые шаблоны конфигурации
Для ещё большей организации можно вынести генерацию монтирования в отдельную функцию:
{ 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);
}
Такой шаблон обеспечивает отличную поддерживаемость: добавлять новые точки монтирования или менять общие параметры становится проще.
Проверка конфигурации
После внесения изменений проверьте конфиг:
# Проверка синтаксиса
nix-instantiate --eval --strict configuration.nix
# Сборка системы
sudo nixos-rebuild test
Если всё настроено правильно, вы сможете вручную смонтировать любой раздел:
# Тестируем монтирование
sudo mount /mnt/Foo
df -h /mnt/Foo
Опция x-systemd.automount обеспечит автоматическое монтирование при первом обращении к каталогу.