Мой опыт использования NixOS

NixOS - это дистрибутив linux с декларативной конфигурацией. Вы можете задать настройки системы в виде кода, и она приведёт себя в требуемое состояние. Почти как ansible, только на уровне системы.

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

Первая установка

Начать работать с NixOS довольно легко, местная wiki проведёт вас по всем этапам установки, а система сама сгенерирует стартовые настройки. Они послужат вам хорошей отправной точкой. Полезной идеей будет создание репозитория для настроек.

Настройки nixos охватывают практически все аспекты системы. Можно настраивать пользователей, программы, сервисы, накопители. Сначала, конечно, придётся привыкнуть к необычному синтаксису nix, но в большинстве случаев он не вызовет проблем.

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

# Пример был немного упрощён, проверьте доступные настройки перед запуском.
{ config, ... }:
{
  services.forgejo = {
    enable = true;
    settings = {
      server = {
        ROOT_URL = "https://git.example.org";
        PROTOCOL = "http+unix";
        DOMAIN = "git.example.org";
      };
    };
    database = {
      type = "postgres";
      socket = "/run/postgresql";
    };
  };
  services.nginx.virtualHosts."git.example.org" = {
    useACMEHost = "example.org";
    forceSSL = true;
    locations."/" = {
      proxyPass = "http://unix:${config.services.forgejo.settings.server.HTTP_ADDR}";
    };
  };
}

Выглядит несложно? Так и есть. И если бы моя история заканчивалась здесь, то я бы сказал, что NixOS прекрасна. Но есть одно но…

Продвинутая работа

Допустим, нужной программы нет в NixOS, или же программа есть, но нет необходимых параметров. Что делать в таком случае?

Бежать. Если же отвечать чуть более серьёзно, то не всё так страшно, конечно, но слабонервным лучше не приближаться. Синтаксис настроек nixos воистину необычен и сложен для обывателей.

Создать свой пакет более чем реально, на данных момент в официальных репозиториях уже 80,000+ пакетов. Но буду честен, я так в них до конца и не разобрался. В интернете есть инструкции и примеры, но полного рецепта для своей ситуации вы можете так и не найти. Иногда достаточно небольших правок готового пакета, что значительно облегчает задачу.

Самый простой вариант запуска собственного сервиса - docker, podman и их приятели. Настроить k3s можно буквально при помощи 12 строчек кода. Свой выбор я остановил на podman, хоть не исключаю, что перейду на nix, если разберусь с настройками.

Стоит ли?

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

NixOS потребует много внимания. Вы сможете легко начать работу, но в какой-то момент можете найти себя за чтением книги о nix flakes. И всё это лишь для того, чтобы настроить систему. Стоит ли результат усилий в случае NixOS? Я не уверен.

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

Мне кажется, что проекту не стоило пытаться быть настолько всеобъемлющим и необычным. Например, можно было оставить настройки программ в виде текстовых файлов, это облегчило бы жизнь разработчикам пакетов, а пользователи получили бы более привычный инструмент настройки. Вот как это могло бы быть реализовано:

{ config, ... }:
{
  services.forgejo = {
    enable = true;
  };
  dotfiles."/etc/forgejo/app.ini" = ''
    ROOT_URL=https://git.example.org
    PROTOCOL=http+unix
    DOMAIN=git.example.org
  '';
}

Помимо этого, можно было бы выбрать куда более известные языки, тот же toml, как вариант:

[services.forgejo]
enable = true

[dotfiles."/etc/forgejo/app.ini"]
content = '''
  ROOT_URL=https://git.example.org
  PROTOCOL=http+unix
  DOMAIN=git.example.org
'''

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