Skip to main content

Конфигурация и модули

Модуль

Модуль — это блок, описывающий настройку одной из частей системы, используя параметрыопции как способ взаимодействия с другими блоками, настройкой системы в целом или отдельными её частями.

Объявление этих параметровопций является его основным отличием от других блоков с настройками. Модули позволяют разбивать настройку системы на части, делая ее более структурированной, повторно используемой и масштабируемой.

Функции модуля

  1. Абстракция. Модули скрывают детали реализации, предоставляя стандартизированный интерфейс для настройки компонентов системы. В этом смысле он больше похож на описание функциикласса в языке программирования.
  2. Повторное использование. Один и тот же модуль может использоваться в разных частях системы или в разных конфигурациях для однотипных настроек.
  3. Использование других модулей. Модули могут импортировать другие модули, позволяя создавать иерархическую структуру конфигурации.

Структура модуля

  1. Импорт других модулей (модулей(imports).
  2. Объявление параметров(опций(options). 
  3. Определение параметров,опций аи такжеописание другиенастроек настройки(модуля(config).
{
  imports = [
    # Пути к другим модулям.
    # Модули могут импортировать другие модули, позволяя
    # создавать иерархическую структуру настроек.
  ];

  options = {
    # Объявление параметров.опций.
    # Объявляет какие настройки пользователь этого модуля может устанавливать.
    # Обычно это включает общий пункт "enable" изначально установленный в ложное значение.
  };

  config = {
    # Определение параметров.опций.
    # Определяет какие другие настройки, службы и ресурсы должны быть задействованы.
    # Обычно это зависит от того выбрал ли пользователь этого модуля 
    # пункт "enable" используя объявление выше.
    # ПараметрыОпции для модулей импортированных в секции "imports" могут быть установлены здесь.
  };
}

Каждый модуль может объявлять новые параметры,опции, которые являются настройками для других частей системы. Например, модуль для настройки веб-сервера может иметь параметрыопции порта и директории сайта.

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

Поскольку модули описывают желаемое состояние системы, а не шаги по его достижению, NixOS является декларативной системой, где настройка системы осуществляется средствами модулей.

Пример:
Вот как может выглядеть упрощенный модуль для гипотетической службы my-service:

# ./my-module.nix
{ config, lib, pkgs, ... }: # Это функция, принимающая аргументы

{
  # 1. Объявляем опции, которые можно использовать в configuration.nix
  options = {
    services.my-service = {
      enable = lib.mkEnableOption "My cool service"; # Создает опцию enable с описанием
      port = lib.mkOption {
        type = lib.types.port;
        default = 8080;
        description = "Port for my-service";
      };
    };
  };

  # 2. Определяем, что делать, если служба включена
  config = lib.mkIf config.services.my-service.enable {
    # Это "вклад" модуля в общую конфигурацию системы
    environment.systemPackages = [ pkgs.my-service-pkg ]; # Добавляем пакет в окружение
    systemd.services.my-service = { # Создаем systemd юнит
      description = "My Service";
      after = [ "network.target" ];
      wantedBy = [ "multi-user.target" ];
      serviceConfig = {
        ExecStart = "${pkgs.my-service-pkg}/bin/my-service --port ${toString config.services.my-service.port}";
      };
    };
  };
}

Теперь в configuration.nix мы можем импортировать этот модуль и использовать его опции:

 

# /etc/nixos/configuration.nix
{ config, pkgs, ... }:

{
  imports = [ ./my-module.nix ]; # Импортируем модуль

  # Используем опции, объявленные в модуле
  services.my-service = {
    enable = true;
    port = 9000;
  };

  # ... остальная конфигурация системы
}

 

Теперь в configuration.nix мы можем включить этот модуль и использовать его опции:

# /etc/nixos/configuration.nix
{ config, pkgs, ... }:

{
  imports = [ ./my-module.nix ]; # Импортируем модуль

  # Используем опции, объявленные в модуле
  services.my-service = {
    enable = true;
    port = 9000;
  };

  # ... остальная конфигурация системы
}

Примеры использования модулей

Модули могут использоваться для:

  1. Управления службами. Модуль может описывать настройку и запуск службы, например, веб-сервера nginx, включая его зависимости.
  2. Настройки пользователя. NixOS home-manager использует модули для управления настройками пользователя и содержимым его домашнего каталога, например, настройками оболочки или приложения.
  3. Описание пакетов. Модули могут описывать сборку и установку пакетов, а также управлять их зависимостями.

Преимущества модулей

  1. Воспроизводимость. Модули упрощают создание воспроизводимых настроек, которые можно легко применить на разных машинах.
  2. Управление. Разбиение настроек на модули делает ее более управляемой и понятной, даже для сложных систем.
  3. Повторное использование. Модули могут быть повторно использованы в разных настройках, что сокращает дублирование кода.

Вложенные модули

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

При использовании lib.types.submodule вы создаёте новыйновую параметр,опцию, значением которого будет набор атрибутов, соответствующих другому, вложенному модулю. Этот вложенный модуль имеет свой собственный набор параметров,опций, как и обычный модуль NixOS.

Пример:
Допустим, вы создаёте модуль для веб-сервиса, и хотите, чтобы опции для базы данных были сгруппированы.

  1. Объявление типа submodule:
    Вы определяете параметропцию database с типом submodule. Внутри submodule вы задаёте собственные параметры,опции, например, host, port и user.


    # module.nix
    { config, lib, ... }:
    
    let
      types = lib.types;
    in
    {
      options.database = lib.mkOption {
        type = types.submodule {
          options = {
            host = lib.mkOption {
              type = types.str;
              default = "localhost";
            };
            port = lib.mkOption {
              type = types.int;
              default = 5432;
            };
            user = lib.mkOption {
              type = types.str;
              default = "admin";
            };
          };
        };
        description = "Настройки для базы данных.";
      };
    }
  2. Использование в настройке:
    Затем в вашей настройке вы можете определить значения для этих вложенных параметров.опций.
    # configuration.nix
    { ... }:
    
    {
      imports = [
        ./module.nix
      ];
    
      database = {
        host = "db.example.com";
        port = 5433;
        user = "web_user";
      };
    }

В результате вы получите настройки, где config.database.host будет "db.example.com", config.database.port будет 5433 и config.database.user будет "web_user".

Преимущества вложенных модулей

  • Модульность: Позволяет разбивать сложные настройки на логические, повторно используемые блоки.
  • Структурирование: Повышает читаемость и удобство управления настройками.
  • Типобезопасность: КаждыйКаждая параметропция внутри submodule имеет свой тип и проверяется, что предотвращает ошибки настройки.
  • Совместимость с другими типами: Часто используется в сочетании с lib.types.attrsOf или lib.types.listOf для создания списков или наборов подмодулей. Например, можно создать listOf submodules для определения нескольких веб-сервисов с похожими настройками.

Конфигурация

Конфигурация – это блок, описывающий настройку системы в целом или отдельной её части.

В NixOS файл конфигурации /etc/nixos/configuration.nix предназначен для описания всех настроек системы. Он может включать другие файлы конфигурации, описывающие только часть настроек общей системы, а также модули, задействоватьизменять настройки которых можно через их параметры.опции. Конфигурация описывает заданное, статическое состояние системы, в то время как модули могут изменять свое поведение в зависимости от значения, передаваемое их опциям.


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

Определения

  • Опция — необязательная возможность, меняющий поведение функции.

Список используемых источников

  1. NixOS modules
  2. Understanding NixOS Modules and Declaring Options