NixOS: решение повседневных задач и выход из трудных ситуаций

nixos

Мы уже делали обзор NixOS, весьма необычном и удобном Linux-дистрибутиве, позволяющем описать всю конфигурацию системы в одном файле и развернуть ее на любой машине в любой момент. В той статье мы познакомили вас лишь с особенностями системы. Сегодня я расскажу о том, как пользоваться NixOS, решать повседневные задачи и выходить из трудных ситуаций.

Упомяну, что значит NixOS для меня. Долгие время я использовал Gentoo, и NixOS стал для меня Gentoo done right, когда, несмотря на гибкость системы и возможность простой сборки всего необходимого из исходных кодов, я получил глобальный бинарный кеш для аналогичных базовым пакетов, а также простоту развертывания.

NixOS также служит отличным примером того, как нужно работать с комьюнити, — запросы на слияние (pull request) рассматриваются намного быстрее и качественнее всех существующих на данный момент дистрибутивов. Даже если вы не занимаетесь непосредственно разработкой, вы не столкнетесь со старыми бюрократами из таких проектов, как Debian и Gentoo.

Из последнего следует один немаловажный и крайне приятный факт: ни оверлеи (overlay — сторонние репозитории, содержащие сценарии сборки ebuild для пакетов), ни их аналоги из других дистрибутивов больше не являются необходимостью. Вы можете отправлять свои патчи сразу в апстрим!

Готовые конфигурации

Так как дистрибутив NixOS предоставляет простую возможность распространять настройки своих машин так же, как и уже ставшая обычной традиция делиться своими конфигурациями для GNU Emacs, мы можем использовать подготовленные другими пользователями конфигурации в качестве базы для своей, тем самым не решая те проблемы, которые уже кто-то решал.

Для NixOS существует проект Simple Nixos Mailserver, который предоставляет готовую конфигурацию для почтового сервера. Я использую этот проект, а полный пример конфигурации можно посмотреть на моем Git-сервере.

Мы можем включить чужую конфигурацию, забрав ее с любого ресурса (добавь эти строки в configuration.nix):

SHA-256 позволяет быть уверенным в аутентичности используемого архива.

Также вместо fetchTarball можно использовать fetchGit. Далее мы уже работаем с конфигурацией mailserver таким же образом, как если бы это было просто локальное включение файлов:

Далее нам остается только (тут я намеренно опускаю настройку DNS, она не касается непосредственно настроек системы, и подобным придется заниматься что на NixOS, что на Ubuntu, что на других дистрибутивах) указать пользователей, alias’ы et cetera.

Таким же образом мы можем распространять что угодно, например управлять базовым слоем конфигурации для компании — настройкой домена, стандартных плагинов для браузера и так далее. Большой плюс данного подхода — он не ограничивает свободу пользователей, работающих в компании, так как нет чувства, что вашим компом управляет кто-то другой: человек может посмотреть на обновленную конфигурацию, изменив URL «перейти на нее», и продолжать работать.

Или, быть может, вам нужно работать со звуком и понадобилось реалтайм-аудио? Просто воспользуйтесь готовой конфигурацией от musnix.

Сборка пакета из исходников

Система сборки пакетов Nix немного напоминает систему ebuild для Gentoo, когда большую часть работы выполняет сам пакетный менеджер, который содержит информацию о том, как собирать при наличии Makefile, CMakeLists et cetera.

Сборочный файл для GNU Hello совсем не будет содержать указаний на то, как собирать:

Для сборки и установки необходимо только записать эти строки в файл (hello.nix, например) и выполнить следующую команду:

Если понадобится совершить какие-либо нестандартные действия (частично это будет рассмотрено на примере работы с бинарными пакетами далее), достаточно переопределить конкретные этапы.

В этой статье мы не будем подробно рассматривать все случаи сборки различных приложений, ибо вариантов бесчисленное множество. Не смотря на это, я советую посмотреть своими глазами на то, каким образом составляются описания для сборки различного ПО в репозитории nixpkgs. Я крайне редко (буду честным — никогда) пишу описания сборки с нуля, в nixpkgs легко найти пример для разных систем сборки, а также великолепный набор костылей на для любой ситуации.

Бинарные пакеты и FHS

NixOS отличается от других дистрибутивов тем, что разработчикам дистрибутива пришлось отказаться от совместимости с FHS — стандартом, определяющим местоположение библиотек, исполняемых файлов, конфигурации и прочего. Из-за этого бинарные утилиты, собранные для других дистрибутивов, без изменений работать не смогут: каталогов /usr/share и /usr/lib в NixOS попросту нет.

При этом, если разработчик проприетарного программного обеспечения будет собирать для Nix, ему это будет только в плюс, так как сам пакетный менеджер Nix на данный момент работает на всех дистрибутивах (включая Ubuntu, Fedora, Debian), а простая работа с зависимостями позволит не беспокоиться о том, заработает ли оно на конкретном.

Например, для создания пакета для BinaryNinja нам необязательно костылить с изменением бинарных файлов и зависимостей вручную (за исключением libpython, но это уже не зависит непосредственно от Nix).

Пояснения излишни — мы имеем некоторый бойлерплейт описания сборки, а также список зависимостей.

Далее достаточно выполнить команду

После чего binaryninja будет установлен на уровне пользователя, но с управлением через менеджер пакетов.

nixos использование

Но есть нюанс, который нужно помнить: в том случае, если это бинарное ПО, которое хочет обновляться самостоятельно (как binaryninja), оно это сделать не сможет, так как каталог приложения при установке через пакетный менеджер доступен только для чтения.

Приятные мелочи

Для Chromium существует возможность управлять плагинами со стороны системы (небольшое описание есть тут).

NixOS позволяет управлять плагинами для Chromium прямо в конфигурации для системы. Например, чтобы установить по умолчанию HTTPS Everywhere и блокировщик рекламы uBlock Origin, достаточно всего лишь определить их в списке extensions:

Hardened

Для NixOS существует профиль Hardened, который объединяет в себе полезные для безопасности настройки системы. И у вас есть возможность откатить некоторые из них. Например, я делаю так:

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

Значительно большего уровня защищенности можно достигнуть использованием специализированного hardened-ядра.

Все hardened-ядра в NixOS имеют постфикс _hardened, соответственно, возможные варианты можно найти простым поиском по пакетам (также я добавляю .kernel, так как по умолчанию nix search покажет и модули ядра):

К примеру, на момент написания статьи были доступны следующие ядра:

Подобным образом можно искать и обычные ядра:

Стоит отметить, что hardened-ядра не включают опции из профиля Hardened по умолчанию, тем самым гибкость снижается только для той конфигурации ядра, которую невозможно изменять после загрузки посредством интерфейсов ядра.

Далее в configuration.nix указываем необходимое нам ядро, например:

После чего ставший уже привычным nixos-rebuild switch и в случае со сменой ядра — перезагрузка (или kexec).

Хранение секретов для публичных конфигураций

Самый простой способ для того случая, когда вы распространяете конфигурацию, — использовать включение конфигурации через import. Например:

Декларативные контейнеры

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

Что меня восхищает в контейнерах в NixOS — возможность использовать те же самые декларации, которые использовались ранее для хостовой системы. По сути, единственное, что отличает контейнер от основной системы, — другое пространство имен (namespace) в конфигурационном файле.

В качестве примера покажу одну из деклараций контейнера, которая у меня осталась где-то в конфигурациях. В данном случае определен контейнер с версией Chromium из релиза NixOS 18.03.

То есть, как вы уже могли заметить, только небольшой «контейнерный бойлерплейт», и мы получаем логически изолированную среду. При этом стоит отметить, что контейнеры в NixOS не предполагают изоляцию с целью усиления безопасности.

Декларативная генерация виртуальных машин

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

Использование виртуальных машин в рамках только пакетного менеджера Nix в других дистрибутивах и использование Nix в рамках NixOS в данном случае ничего не изменит. Тут можно продолжить оды Nix за внесение универсальности не только в рамках «материнского дистрибутива», но и в общем в экосистеме GNU/Linux, но буду придерживаться главной цели этой статьи и показывать больше непосредственно примеры использования в повседневной жизни.

Стабильность

Как-то раз я случайно обнаружил, что поставил новую систему из unstable-ветви. В NixOS unstable-ветвь собирается из тех пакетов, которые добавили непосредственно в Git-репозиторий nixpgs на GitHub и которые после успешно собрались. Тем самым я оказался на весьма суровом bleeding edge.

Очевидным результатом стало то, что однажды (на самом деле это было в первый день) я все-таки отхватил баг — virt-manager не работал.

nixos использовать

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

В случае NixOS подобных проблем быть не может. Вопрос решился добавлением стабильной ветки:

где tarball-base определяется ранее:

После чего в списке используемых пакетов мне достаточно использовать префикс stable. для того, чтобы устанавливать пакеты из стабильных ветвей, например:

Для простоты понимания того, какая версия используется, есть возможность указывать симлинки явно, например:

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

Например, мы хотим найти версию снимка состояния репозитория nixpgs, в котором virt-manager имел версию 2.0.

Для этого нам достаточно перейти в каталог с нужным пакетом:

После чего, запустив git log, найти коммит (простым поиском по номеру версии), в котором данная версия была добавлена. Например, virt-manager 2.0 был добавлен в коммите db7e9408a1b5c0d7d103c28b91646b374968b045:

Следовательно, для получения virt-manager версии 2.0 нам достаточно использовать архив с этого коммита:

После мы можем таким же образом, как и ранее, добавить в bin исполняемый файл для определенной версии.

Итого мы имеем virt-manager из последней стабильной ветки 18.09, той версии, которая на данный момент находится в Git, а также версии 2.0.0.

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

Альтернативный вариант — установка Nix-пакета от пользователя, в этом случае достаточно просто запустить команду в каталоге с описанием для сборки.

Или же можно вернуться на стабильную ветку из unstable. Предположим, мы хотим переключиться на следующий релиз 19.03, для этого достаточно сделать так:

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

Каналы также можно использовать напрямую, например если мы добавим каналы для стабильного релиза, нестабильного и следующего планируемого стабильного.

Тот, что назван nixos, будет использоваться по умолчанию.

Далее мы можем определить каналы и использовать их для установки программ:

Для того чтобы не пропустить улучшения в плане работы с тем, что было описано выше, советую заглянуть в статью на NixOS Wiki.

Более радикальное решение проблем с FHS

Проблема несовместимости NixOS с FHS в основном затрагивает бинарные пакеты (суть проблемы я описал в соответствующем разделе), но часто бывает, что написанный очень странными людьми код собирается, только если в системе есть условный /usr/lib/libastral.so по жестко заданному пути, и вне FHS-совместимого окружения собирать становится невыносимо.

Решение с использованием Docker в этом случае довольно очевидно и приземленно, поэтому оставим его хипстерам. Для своих задач я предпочитаю использовать обычное chroot-окружение с Debian, и я покажу, как его готовить таким образом, чтобы он не доставлял проблем.

Для начала просто генерируем chroot с Debian или любым другим дистрибутивом, который мы будем использовать для FHS окружения (я использую Debian и Gentoo):

После чего добавляем в configuration.nix сервис с mount-костылями, который будет монтировать все нужные нам каталоги. Самое важное из этого — привязка (bind) домашнего каталога хостовой системы к системе в chroot.

Далее добавляем в скрипт инициализацию используемого шелла (у меня это .zshrc):

Теперь достаточно набрать команду fhs, и мы окажемся в окружении Debian, использующем наш родной домашний каталог. Разве не круто?

Далее, для того чтобы не перепутать окружения, я советую добавить небольшую проверку в тот же файл инициализации шелла.

Что мы получили в итоге?

Home manager

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

Например, Nix + home-manager можно использовать на macOS.

Чем вы можете помочь NixOS?

На данный момент активна инициатива Zero Hydra Failures, которая предполагает устранение всех ошибок к следующему релизу 19.03.

Где получить помощь?

Англоязычную поддержку можно получить в канале #nixos на freenode, полный список каналов можно найти в списке c NixOS wiki.

Если вам нужна поддержка на русском языке, можете создать треды с тегами nix и nixos на ЛОРе, где на данный момент отвечают некоторые из русскоязычных разработчиков NixOS.

Вместо заключения

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

Понравилась статья? Поделиться с друзьями:
Добавить комментарий