FreeBSD virtual environment management and repository

2020-10 upd: we reached the first fundraising goal and rented a server in Hetzner for development! Thank you for donating !

FreeBSD in packages

Дистрибьюция FreeBSD в виде монолитной базы является предметом ненависти у одной группы системных инженеров и в то же время предметом гордости у другой. Доводы обоих весьма понятны.

Довольно грустно, когда в процессе работы внезапно и срочно необходимы утилиты вроде ping, finger, ssh, telnet, traceroute и их нет под рукой. И довольно весело, когда одной командой можно поставить все необходимое без лишнего хлама.

Между тем не многие критики "толстой базы" FreeBSD знают, что с крайне бородадых времен разработчиками ОС ведутся KNOBS-ы — определенные переменные, специфичные для того или иного приложения.

С помощью них, например, собирают кастомайженные базы через src.conf. Остается лишь решить вопрос построения репозитория в автоматическом режиме и методов его дистрибьюции, с чем нам может помочь pkgng. Следующими парой строчек sh-сценария ( сырцы тут: base2pkg ) решается один из самых наистрашнейших минусов FreeBSD, которым десятилетиями пугают молодежь камрады с Ubuntu.

Всю работу по автоматическому построению списка файлов, соответствующих тому или иному KNOBs и построению файлов MANIFEST, необходимые для создания pkg, выполняет скрипт makepkg.

Алгоритм работы не идеален (ввиду большого количества циклов installworld), но прост: один раз собирается FreeBSD база с опциями по-умолчанию (или со всеми возможными опциями вообще), после чего в цикле из всех возможных KNOBs выполняется installworld WITHOUT_KNOBS и сравниваются файлы с оригиналом. Список файлов, присутствующие в инсталляции по-умолчанию и отсутствующие в базе с WITHOUT_KNOBS и используются для создания пекеджа с именем knobs. Для того, чтобы операция не изнашивала циклами installworld диск, все операции по-умолчанию выполняются на md(4) диске, что требует ~basesize x 2 (окола 1 Гб).

Список всех возможных KNOBS описан в файле /usr/share/mk/bsd.own.mk в __DEFAULT_YES_OPTIONS и __DEFAULT_NO_OPTIONS переменных, отражающие все опции и с какими именно создается база по-умолчанию. Этот список нам понадобятся, поэтому выпишем их в отдельном файле knobs.inc.

Перед запуском подразумевается, что в /usr/src находятся исходные коды FreeBSD и имеются объектные файлы сборки (стадия buildworld), те, операция

                % make -C /usr/src buildworld 
                

прошла успешно.

Запуск скрипта:

          % /makepkg.sh 
        * WIP: defaultbase. Knobs 0 from 114
        * WIP: acct. Knobs 0 from 114
        * WIP: acpi. Knobs 1 from 114
        * WIP: amd. Knobs 2 from 114
        * WIP: apm. Knobs 3 from 114
        * WIP: arm_eabi. Knobs 4 from 114
        ...
                

По окончанию отработки, в текущем каталоге со скриптом, в txz/ каталоге будут сфомированы соотетствующие пакеты:

          % ls -1 txz/
        freebsd-acct-9.2.258493.txz
        freebsd-acpi-9.2.258493.txz
        freebsd-amd-9.2.258493.txz
        freebsd-apm-9.2.258493.txz
        freebsd-at-9.2.258493.txz
        freebsd-atm-9.2.258493.txz
        freebsd-audit-9.2.258493.txz
        freebsd-authpf-9.2.258493.txz
        ..
                

Примечание: Третья цифра в версии соответствует ревизии SVN дерева исходных кодов. Если утилиты svn нет в системе, будет подставлен результат data %s.

Таким образом, вы можете обеспечить свои сервера, которые находятся на промежуточных версиях ( например STABLE_X или вовсе на HEAD-ветках ) бинарным обновлением.

Примечание2: поскольку пакетов много, имеет смысл сделать кумулятивный Meta-пакет freebsd-base, содержащий в качестве зависимостей все другие пекеджи базы.

Последним шагом создадим pkg-каталог через pkg repo и закинем результат на доступный HTTP WEB сервер для раздачи.

                % cd txz/
                % pkg repo .
                

Эпилог

Чисто теоретически, в pkgng таким образом можно обернуть абсолютно всю базу, включая разные ядра ОС и обеспечить альтернативу бинарного обновления через FreeBSD update server, однако привычное поведение pkg при любой ошибке делать deinstall устанавливаемого пакета по манифесту, делает не очень надеждым данный способ: неприятно будет потерять файлы в каталоге /lib/* если что-то пойдет не так. Конечно, через pkg hold package можно заморозить состояние пакета, поставив иммунитет на обновления и тп.

Однако гораздо лучшим решением будет создание микро-базы (например средствами picobsd, которая идет в составе FreeBSD, или mfsBSD. Оба инструмента по-умолчанию создают рабочую базу FreeBSD объемем ~20-30 Мб, не подверженную обновлению в pkg, которая будет проливаться на ваш хостинг/парк серверов, а уже сверху через pkg доставлять все, что заблагорассудится.

Наслаждаемся результатом:

          % pkg install freebsd-openssh freebsd-zoneinfo freebsd-examples freebsd-games
        Updating repository catalogue
        The following 4 packages will be installed:

                Installing freebsd-openssh: 9.2.258493
                Installing freebsd-zoneinfo: 9.2.258493
                Installing freebsd-examples: 9.2.258493
                Installing freebsd-games: 9.2.258493

        The installation will require 9 MB more space

        2 MB to be downloaded

        Proceed with installing packages [y/N]: y
        freebsd-openssh-9.2.258493.txz        100%  886KB 886.0KB/s 886.0KB/s   00:00
        freebsd-zoneinfo-9.2.258493.txz       100%  108KB 108.3KB/s 108.3KB/s   00:00    
        freebsd-examples-9.2.258493.txz       100%  378KB 378.5KB/s 378.5KB/s   00:00
        freebsd-games-9.2.258493.txz          100%  868KB 867.8KB/s 867.8KB/s   00:00
        Checking integrity... done
        [1/4] Installing freebsd-openssh-9.2.258493... done
        [2/4] Installing freebsd-zoneinfo-9.2.258493... done
        [3/4] Installing freebsd-examples-9.2.258493... done
        [4/4] Installing freebsd-games-9.2.258493... done
                
          % pkg info
        freebsd-acct-9.2.258493        FreeBSD base
        freebsd-acpi-9.2.258493        FreeBSD base
        freebsd-amd-9.2.258493         FreeBSD base
        freebsd-apm-9.2.258493         FreeBSD base
        freebsd-at-9.2.258493          FreeBSD base
        freebsd-atm-9.2.258493         FreeBSD base
        freebsd-audit-9.2.258493       FreeBSD base
        freebsd-authpf-9.2.258493      FreeBSD base
        freebsd-binutils-9.2.258493    FreeBSD base
        freebsd-bluetooth-9.2.258493   FreeBSD base
        freebsd-boot-9.2.258493        FreeBSD base
        freebsd-bsd_cpio-9.2.258493    FreeBSD base
        freebsd-bsnmp-9.2.258493       FreeBSD base
        freebsd-calendar-9.2.258493    FreeBSD base
        freebsd-cddl-9.2.258493        FreeBSD base
        freebsd-cpp-9.2.258493         FreeBSD base
        freebsd-crypt-9.2.258493       FreeBSD base
        freebsd-ctm-9.2.258493         FreeBSD base
        freebsd-cxx-9.2.258493         FreeBSD base
        freebsd-dict-9.2.258493        FreeBSD base
        freebsd-examples-9.2.258493    FreeBSD base
        freebsd-floppy-9.2.258493      FreeBSD base
        freebsd-forth-9.2.258493       FreeBSD base
        freebsd-freebsd_update-9.2.258493 FreeBSD base
        freebsd-games-9.2.258493       FreeBSD base
        freebsd-gcov-9.2.258493        FreeBSD base
        freebsd-gdb-9.2.258493         FreeBSD base
        freebsd-gpib-9.2.258493        FreeBSD base
        freebsd-gpio-9.2.258493        FreeBSD base
        freebsd-groff-9.2.258493       FreeBSD base
        freebsd-html-9.2.258493        FreeBSD base
        freebsd-inet6-9.2.258493       FreeBSD base
        freebsd-info-9.2.258493        FreeBSD base
        freebsd-installlib-9.2.258493  FreeBSD base
        freebsd-ipfilter-9.2.258493    FreeBSD base
        freebsd-ipfw-9.2.258493        FreeBSD base
        freebsd-ipx-9.2.258493         FreeBSD base
        freebsd-jail-9.2.258493        FreeBSD base
        freebsd-kerberos-9.2.258493    FreeBSD base
        freebsd-legacy_console-9.2.258493 FreeBSD base
        freebsd-lib32-9.2.258493       FreeBSD base
        freebsd-locales-9.2.258493     FreeBSD base
        freebsd-locate-9.2.258493      FreeBSD base
        freebsd-lpr-9.2.258493         FreeBSD base
        freebsd-mail-9.2.258493        FreeBSD base
        freebsd-mailwrapper-9.2.258493 FreeBSD base
        freebsd-make-9.2.258493        FreeBSD base
        freebsd-man-9.2.258493         FreeBSD base
        freebsd-ndis-9.2.258493        FreeBSD base
        freebsd-netcat-9.2.258493      FreeBSD base
        freebsd-netgraph-9.2.258493    FreeBSD base
        freebsd-nis-9.2.258493         FreeBSD base
        freebsd-nls-9.2.258493         FreeBSD base
        freebsd-ns_caching-9.2.258493  FreeBSD base
        freebsd-ntp-9.2.258493         FreeBSD base
        freebsd-openssh-9.2.258493     FreeBSD base
        freebsd-openssl-9.2.258493     FreeBSD base
        freebsd-pc_sysinstall-9.2.258493 FreeBSD base
        freebsd-pf-9.2.258493          FreeBSD base
        freebsd-pmc-9.2.258493         FreeBSD base
        freebsd-portsnap-9.2.258493    FreeBSD base
        freebsd-ppp-9.2.258493         FreeBSD base
        freebsd-profile-9.2.258493     FreeBSD base
        freebsd-quotas-9.2.258493      FreeBSD base
        freebsd-rcmds-9.2.258493       FreeBSD base
        freebsd-rcs-9.2.258493         FreeBSD base
        freebsd-rescue-9.2.258493      FreeBSD base
        freebsd-routed-9.2.258493      FreeBSD base
        freebsd-sendmail-9.2.258493    FreeBSD base
        freebsd-sharedocs-9.2.258493   FreeBSD base
        freebsd-syscons-9.2.258493     FreeBSD base
        freebsd-sysinstall-9.2.258493  FreeBSD base
        freebsd-tcsh-9.2.258493        FreeBSD base
        freebsd-telnet-9.2.258493      FreeBSD base
        freebsd-textproc-9.2.258493    FreeBSD base
        freebsd-usb-9.2.258493         FreeBSD base
        freebsd-utmpx-9.2.258493       FreeBSD base
        freebsd-wireless-9.2.258493    FreeBSD base
        freebsd-zfs-9.2.258493         FreeBSD base
        freebsd-zoneinfo-9.2.258493    FreeBSD base
                
          %  which mail portsnap gdb
        /usr/bin/mail
        /usr/sbin/portsnap
        /usr/bin/gdb

          % pkg which /usr/bin/mail
        /usr/bin/mail was installed by package freebsd-mail-9.2.258493

          % pkg which /usr/bin/gdb
        /usr/bin/gdb was installed by package freebsd-gdb-9.2.258493

          % pkg remove freebsd-mail freebsd-gdb freebsd-portsnap
        Deinstallation has been requested for the following 3 packages:

                        freebsd-mail-9.2.258493
                        freebsd-gdb-9.2.258493
                        freebsd-portsnap-9.2.258493

        The deinstallation will free 11 MB

        Proceed with deinstalling packages [y/N]: y
        [1/3] Deleting freebsd-mail-9.2.258493... done
        [2/3] Deleting freebsd-gdb-9.2.258493... done
        [3/3] Deleting freebsd-portsnap-9.2.258493... done

          % which mail portsnap gdb
        mail: Command not found.
        portsnap: Command not found.
        gdb: Command not found.
                

PS: В данной реализации не учтены возможные конфликты по устанавливаемым файлам ( поскольку сборка сделана из общей базы, то при установке пакета freebsd-examples всегда будет выдаваться руганть о коллизиях некоторых файлов ), а также не учтены зависимости. Например, пакет freebsd-openssh и freebsd-openssl зависят от пакета freebsd-crypto.