Мои приключения с NixOS, часть 1: начало работы
Sergey, 01 February 2019
Недавно у меня стало заканчиваться место на диске, в связи с экспериментами с виртуализацией, и я решил попробовать включить сжатие на всю ФС. Беглый гуглёж показал, что связка LVM + ext4 сжатие не поддерживает, и чтобы получить возможность компрессии ФС, нужно мигрировать на другую ФС, я выбрал btrfs, поскольку она поддерживает компрессию. Самый простой способ сменить разметку диска - переразметить его с переустановкой системы, так что я решил воспользоваться поводом и поставить NixOS в качестве эксперимента, благо времени на настройку у меня в данный момент достаточно.
NixOS - дистрибутив GNU/Linux, основанный на пакетном менеджере Nix, использующем свой функциональный DSL. Вот некоторые из её преимуществ, которые и заинтересовали меня:
- Возможность полностью декларативной настройки системы.
Вся конфигурация системы описывается в едином файле
/etc/nixos/configuration.nix
. Это касается и загрузчика, и initramfs, и запускаемых сервисов, и их настроек. Более того, поскольку конфигурация пишется на чистом функциональном языке, результат сборки системы из файла/etc/nixos/configuration.nix
не зависит от текущего состояния системы и всегда один и тот же, что подводит ко второму достоинству. - Надёжные обновления. Из сказанного в предыдущем пункте также следует, что обновление системы так же надёжно, как установка системы с нуля.
- Все изменения конфигурации атомарны. Каждое изменение конфигурационного файла с последующей перестройкой системы порождает новое поколение, при этом система всегда остаётся в консистентном состоянии, отвечающем текущему состоянию конфигурационного файла, и всегда есть возможность откатиться на любое предыдущее состояние системы.
- Интеграция nix с пакетными менеджерами различных языков. Более того, его можно использовать как менеджер зависимостей для C++.
Более полное завлекалово можно посмотреть здесь. Для меня одним из сигналов стало то, что на NixOS Wiki я нашёл более актуальную информацию по GVT-g, чем на Arch Wiki.
Теперь, когда мы разобрались, зачем это нам может быть нужно, посмотрим, что здесь с установкой. Скачать образ NixOS можно здесь. Доступны различные варианты загрузки, как классические образы дисков, так и VirtualBox appliances, AMI для Amazon EC2 и образы для Microsoft Azure. Рассмотрим установку с образа LiveCD. Записать образ на диск/флешку можно с помощью dd
.
После загрузки мы получим в управление консоль, откуда можно либо запустить графический интерфейс с помощью systemctl start display-manager
, либо провести установку прямо из консоли. Графического установщика пока нет. На tty8(Alt-F8) доступен мануал NixOS. В принципе, весь порядок установки описан в нём достаточно подробно, поэтому я лишь кратко перескажу порядок установки:
- Настроить сеть в установщике с помощью NetworkManager, либо вручную.
- Разбить диск на разделы и отформатировать их.
- Примонтировать все разделы системы в
/mnt
и поддиректории. - Сгенерировать начальный файл конфигурации:
# nixos-generate-config --root /mnt
- Поправить файл конфигурации
/etc/nixos/configuration.nix
. Он прокомментирован, поэтому с начальной настройкой проблем быть не должно. Если настраиваете Wi-Fi с помощьюnetworkmanager
, нужно не забыть его добавить вenvironment.systemPackages
и сказать NixOS, что используется он, а неwpa_supplicant
:# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. networking.networkmanager.enable = true;
Также имеет смысл сразу включить в список системных пакетов
w3m
илиlinks
для просмотра документации, либо какой-нибудь DM. Настройка для разных DE и DM отличается, поэтому здесь я не буду на ней останавливаться. Также стоит заметить, что помимо системного набора пакетов, у каждого пользователя есть свой собственный набор пакетов, задаваемый в переменнойusers.user.<username>.packages
. Кроме того, пакеты можно устанавливать, не прописывая их в системной конфигурации, с помощью командыnix-env -i <package>
. Удалять, соответственноnix-env -e <package>
. Эти команды можно выполнять, как от имени суперпользователя, так и от имени обычного пользователя. В первом случае пакет устанавливается общесистемно, во втором - локально для установившего пользователя. При этом также используются различные каналы установки, т. е. система у вас может обновляться из каналаnixos-stable
, а пользовательские пакеты - изnixos-unstable
. Можно включить автообновление:system.autoUpgrade.enable = true;
В силу атомарности обновлений, если что-то вдруг сломается, всегда можно будет загрузиться в предыдущее поколение системы.
- Собственно установка:
# nixos-install
В конце установки вас попросят установить пароль для root. После этого шага, если вы где-то напартачили в конфигурации,
nixos-install
после правок можно будет запустить заново. - Система установлена, можно перезагружаться.
Теперь несколько слов об опыте использования. Останавливаться на том, как выполняется администрирование системы, я не буду, это описано в мануале, да и я сам с этим не до конца разобрался. Поэтому просто напишу о некоторых особенностях, с которыми мне довелось столкнуться.
Как я уже упоминал ранее, каждая пересборка системы с помощью nixos-rebuild switch
генерирует новую запись в загрузчике. Если конфиг часто меняется, это приводит к захламлению меню загрузчика, что может мешать в случае, если загрузчиком является systemd-boot
. Почистить мусор от старых поколений можно командами:
# nix-collect-garbage -d
# nix-rebuild switch
В этом случае, удалится всё, что относится ко всем поколениям, кроме последнего. Первую команду можно также выполнить от имени пользователя, но в этом случае удалится не всё, например, останутся лишние записи в загрузчике.
Также мне понадобилось использовать программу, не вошедшую в репозитории NixOS - acpilight. Эта программа позволяет рулить подсветкой дисплея и клавиатуры через ACPI. В мануале NixOS(да и nixpkgs) предлагается не совсем удобный способ создания локального хранилища пакетов, который подразумевает скачивание всего дерева пакетов NixOS. Более удобный способ состоит в использовании оверлеев. Пример оверлея можно посмотреть у меня в репозитории.
Из интересных фич, на которые я наткнулся при чтении мануала по nixpkgs, можно отметить возможность создания кастомных пакетов для Vim и Emacs, включающих в себя уже готовую конфигурацию и набор плагинов.
Также можно отметить возможность создания отдельных окружений для разработки с помощью nix-shell. Например, вот так выглядит создание окружения для этого блога:
Создаём файл shell.nix для nix-shell:
$(nix-build '<nixpkgs>' -A bundix)/bin/bundix
Полученный файл shell.nix
будет иметь вид вроде:
with (import <nixpkgs> {});
let
env = bundlerEnv {
name = "setser.github.io-bundler-env";
inherit ruby;
gemfile = ./Gemfile;
lockfile = ./Gemfile.lock;
gemset = ./gemset.nix;
groups = [ "default" "jekyll_plugins" ];
};
in stdenv.mkDerivation {
name = "setser.github.io";
buildInputs = [ env ];
}
Теперь можно запустить nix-shell
, и в нём собирать проект. С помощью nix-build
можно собрать пакет с приложением(в данном случае блогом), он будет лежать в result
.
Похожим образом можно сделать окружение для проектов, например, на Haskell, но перед этим стоит внимательно ознакомиться с соответствующим разделом мануала nixpkgs. Вот некоторые грабли, которые могут подстерегать на этом пути:
- https://nixos.org/nixpkgs/manual/#users-guide-to-the-haskell-infrastructure
- https://github.com/commercialhaskell/stack/issues/2586
- https://github.com/commercialhaskell/stack/issues/4362
- https://github.com/commercialhaskell/stack/issues/2975
Кроме того, у меня так и не получилось добиться того, чтобы проект собирался с помощьюnix-build
, даже с использованиемcabal2nix
.
Что касается количества пакетов и их свежести, repology.org говорит, что у NixOS с этим всё очень даже неплохо: по количеству пакетов и по их свежести она входит в первые пять репозиториев. Необходимость освоения нового языка для конфигурации несколько повышает порог вхождения.
NixOS - весьма перспективная система, но в данный момент есть всё ещё некоторые шероховатости, особенно при работе с проектами на Haskell. Некоторые её особенности, такие как, например, воспроизводимость сборки системы, будут полезны в CI/CD и при отладке. Декларативная конфигурация полезна для облачных приложений, а атомарные обновления - крайне полезная вещь для десктопа, да и не только.
UPD: залил свой конфиг на GitHub. Также добавил в статью пример оверлея.