Введение
Nix - это функциональный менеджер пакетов, который кардинально отличается по принципу работы от классических пакетных менеджеров, таких как dnf, apt, pacman и т.п.
На данный момент репозиторий пакетов nixpkgs насчитывает около 120 тысяч пакетов, являясь неоспоримым лидером. Для сравнения репозиторий AUR содержит около 90 тысяч пакетов.
В традиционных пакетных менеджерах во время установки какого-либо ПО, состояние системы меняется на ходу, то есть файлы новых версий программ записываются поверх существующих, заменясь новыми. Как следствие, невозможно иметь несколько версий одной и той же программы в одной системе.
Конечно, существуют способы сделать это (контейнеры, виртуальные оболочки), но они слишком сложны или ресурсозатратны, чтобы использовать их.
Хоть такой подход и проще в плане архитектуры и работы, он вызывает множество проблем связанных с различными версиями пакетов и их взаимодействием между собой. В традиционных пакетных менеджерах часто возникает ситуация, когда одно приложение зависит от более старой версии библиотеки, в то время как другие требуют установки новой версии.
В сообществе такую проблему называют адом зависимостей (dependency hell).
Что же делать в такой ситуации? Пакетный менеджер Nix элегантно решает эти и другие проблемы путем нескольких решений, речь о которых пойдет далее.
Изолирование пакетов
Начнем с того, что Nix изолирует каждый пакет в системе в свою отдельную директорию, название которой содержит свое уникальное криптографическое hash-значение, имя пакета и его версию.
На самом деле для пакетного менеджера Nix имеет значение только само hash-значение, а все остальное пишется для удобства пользователей.
Директория пакета содержит в себе все необходимые данные собираемого пакета, а также ссылки на его зависимости. При этом сами зависимости также изолированы. Благодаря этой особенности можно использовать сразу нескольких версий одной и той же программы или библиотеки, не вызывая при этом никаких проблем с совместимостью.
Все пакеты Nix являются неизменяемыми (immutable), и при обновлении старые пакеты остаются как есть, а для новых создаются директории как было описано ранее.
Стоит отметить, что пока существуют поколения которые ссылаются на старые версии пакетов, они не будут удалены из общего хранилища. После ручной или же автоматической очистки старых поколений, директории старых пакетов на которые не будут ссылаться будут удалены.
По умолчанию директории всех пакетов Nix находятся по пути /nix/store/
. К примеру так может выглядеть полный путь для программы GNU Hello: /nix/store/bwacc7a5c5n3qx37nz5drwcgd2lv89w6-hello-2.1.1/bin/hello
Атомарные обновления и откаты
Поскольку операции по управлению пакетами никгода не перезаписывают пакеты в хранилище, а просто добавляет новые версии по новым путям, они являются атомными. Это значит, что при обновлениях системы нет состояние "между" - вы либо обновились, либо нет. При резком прерывании обновления, вы всегда сможете продолжить его без каких либо ошибок.
А поскольку пакеты не перезаписываются, это значит, что вы всегда можете откатиться к старым версиям:
$ nix-env --upgrade --attr nixpkgs.some-package
$ nix-env --rollback
Сборка мусора
Когда вы удаляете пакет из системы, он не пропадает из нее насовсем, оставаясь в хранилище. Если вас это раздражает, или вам не хватает места вы можете запустить сборщик мусора:
$ nix-collect-garbage
Это удаляет все пакеты, которые в данный момент не используются в системе.
Декларативность
Nix использует декларативную парадигму управления системой. То есть пользователь описывает желаемое состояние системы, а пакетник делает все необходимое в соответствии с ранее определенной схемой.
Например, для установки какого-либо ПО или же настройки системы императивным способом нам может понадобиться вводить по очередности команды, изменять конфигурационные файлы и так далее. В случае же с декларативным подходом мы заранее определяем что нужно сделать и в какой последовательности, а Nix следует инструкциям для установки или настройки системы/программы как то было задумано. Для определения деклараций пакетов используется одноименный функциональный язык Nix.
Nix всеми силами старается убедиться, что выражения детерминированы: выполнение выражения дважды должно дать идентичный результат.
Управление средами сборки
Nix чрезвычайно полезен всем разработчикам, так как позволяет автоматически настраивать окружение для сборки пакета. Принимая выражение Nix, которое описывает зависимости вашего пакета, команда nix-shell
создает эти зависимости, если их нет в хранилище, а затем запускает среду с установленными переменными окружения (такие как пути поиска компилятора).
Например, следующая команда получает все зависимости Pan Newsreader:
$ nix-shell '<nixpkgs>' --attr pan
После чего вы попадаете в оболочку, в которой вы можете редактировать, собирать и проверять пакет:
[nix-shell]$ unpackPhase
[nix-shell]$ cd pan-*
[nix-shell]$ configurePhase
[nix-shell]$ buildPhase
[nix-shell]$ ./pan/gui/pan
Портативность
Пакетный менеджер Nix может быть также установлен и использован на других дистрибутивах Linux и системах MacOS.