[Из песочницы] Компактная инсталляция FreeBSD 10 для центра сертификации

Однажды возникла необходимость в подчинённом, в рамках имеющейся инфраструктуры центре сертификации для 'выездного' использования — создания временных технологических сертификатов во время различных разъездов. Необходимо было сделать его мобильным и разумно, для данных целей, защищённым. Приемлемым был признан вариант с загрузочной флешкой с каким-нибудь *nix + openssl и типовым сценарием использования — имеющийся под рукой компьютер перезагружаем, вставляем флешку, загружаемся с неё, работаем, вытаскиваем флешку, перезагружаем компьютер. Секретные ключи данного ЦС, его файлы конфигурации, ключевые файлы для двухфакторной аутентификации могут быть вынесены на отдельные носители.

Начался выбора дистрибутива *nix. Требования были следующие:

  • дистрибутив должен быть поддерживаемым в актуальном состоянии, в том числе и OpenSSL
  • наличие i386 версии. Гигабайты памяти нам не понадобятся, а вот возможность запуска на нетбуке с x86 Intel Atom будет полезна
  • запуск системы из оперативной памяти, либо корректный запуск и работа с r/o разделов. В идеале, корректная работа с флешки при включенной защите от записи (при использовании Qumo серии Yin & Yan)
  • возможность компактной инсталляции
  • желателен достаточно большой срок поддержки релиза


В результате в финал вышли два дистрибутива — Alpine Linux и OpenBSD. Всё бы хорошо, и не было бы смысла писать эту статью, как ВНЕЗАПНО уточнились требования к операционной системе — потребовалась полная поддержка русского текста в Unicode в системной консоли. На ввод и на вывод.

Ну всё, приплыли. Оба финалиста выбыли из соревнования. Alpine Linux в силу используемой в нём компактной библиотеки C, а OpenBSD… ну, у неё другие сильные стороны. Однако это требование позволило иначе взглянуть на доступные дистрибутивы, и в фаворитах неожиданно оказалась FreeBSD. Консольный драйвер vt (ранее известный как newcons) поддерживает Unicode «из коробки», русские шрифты идут в комплекте, вышеописанные критерии в сумме исполняются достаточно полно. Бонусом можно реализовать возможность оффлайнового бинарного обновления системы на флешке.

Началось изучение возможности компактной инсталляции стандартными способами. Готовые наборы — tinybsd, nanobsd, picobsd произвели впечатление «старый, древний, ещё древнее». Одни только расчёты секторов, головок, цилиндров для разных типов флешек в picobsd… Прям времена MFM, RLL, ST-506…

Творения отдельных энтузиастов, различные miniBSD, easyBSD, mfsBSD выглядели поинтереснее, но в итоге всё равно было решено поиграть в доброго доктора Франкенштейна.

В данном примере мы сделаем загрузочную флешку с:

  • компактной инсталляцией FreeBSD 10.1
  • русифицированной системной консолью в Unicode
  • корневым разделом, монтирующимся в памяти
  • разделом для скриптов и файлов конфигурации нашего ЦС
  • шифрованным разделом для секретных ключей ЦС
  • FAT разделом для обмена с внешними системами запросами на сертификат и подписанными сертификатами
  • возможностью оффлайнового обновления системы
  • возможностью выбора ядра при загрузке (минимальное + GENERIC)
  • возможностью выбора образа системы при загрузке (эталонный + обновлённый до последней версии FreeBSD)

Подчеркну — пример демонстрационный, в него включено всё что можно. В реальной жизни вышеуказанные возможности применяются, естественно, выборочно. Нет особого смысла один раздел монтировать в памяти, а другой, с той же флешки — вживую. И да, это будет не слишком похоже на «ядро + systemd + шелл + openssl», но не ставилась же цель уместить всё на дискету. Времена не те. И с fdformat.com и 800.com не влезет… Поэтому помимо программ, без которых не обойтись, были оставлены программы, которые могут пригодиться — по работе с текстом, с дисками, с архивами. К тому же, для обеспечения заявленной возможности обновления системы, сильно её уродовать (свернуть всё в один crunchgen бинарник и засунуть в ядро) нельзя —, а то freebsd-update не признает.

Забегая вперёд — размер системы в максимальной конфигурации (два ядра + два образа) у нас составит 48 Мб, а в минимальной (одно ядро + один образ) — 7⅓ Мб. Без установленных пакетов.

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


Итак, начнём.

Нашу флешку будем делать на основе FreeBSD 10.1-RELEASE. Можно, конечно, -STABLE, но тогда не будет работать freebsd-update с бинарными обновлениями. В процессе работы мы скомпилируем мир и ядро, установим их в отдельный каталог, настроим систему, удалим ненужные файлы, после чего сделаем .iso и .img. Ничего сложного.

Создадим рабочее окружение. Можно в железе, но проще в виртуальной машине. Скачиваем FreeBSD-10.1-RELEASE-i386, устанавливаем, при выборе системных компонент включив установку исходных текстов. Дерево портов и игры не нужны. Загружаемся, заходим как root.

Подготовка


Всё будем делать из-под root.

Для удобства установим несколько переменных окружения, они будут использоваться далее по тексту. У пользователя root шелл по умолчанию csh, поэтому в /root/.login добавляем:

$ echo "setenv BASE /root/caBSD" >> /root/.login
$ echo "setenv WORKDIR /root/caBSD/_work" >> /root/.login


Да, нашу поделку назовём ЦСДПБ caBSD

Обновим систему до последнего patchlevel

$ freebsd-update fetch
$ freebsd-update install

$ reboot


Ядро, мир и исходники обновились. Перезагружаемся.

Создадим каталог /root/caBSD и рабочие подкаталоги в нём.

$ mkdir -p ${BASE}/{conf,tools,pkg.local}
$ mkdir -p ${WORKDIR}/{vanilla,custom,mnt}


/root/caBSD/_work/ — основной рабочий каталог, ${WORK}. Подкаталоги в нём:
vanilla/ — тут мы настраиваем корень будущей системы, installworld, installkernel
mnt/ — временная точка монтирования
custom/ — из содержимого этого каталога будем создавать .iso/.img образы


Компилируем мир и ядро


Создаём файл конфигурации для нашего ядра. На этапе отладки используем конфигурацию, базирующуюся на GENERIC и состоящую из нескольких строчек:

tools/CABSD-DEV
#
# tools/CABSD-DEV

include         GENERIC

ident           CABSD-DEV

# Без модулей
makeoptions     NO_MODULES=1

# Без драйвера консоли sc
nodevice        sc
nodevice        vga

# Так как модули не компилируем, то включаем необходимые в ядро
options         TMPFS           # Efficient memory filesystem
options         GEOM_ELI        # Disk encryption.
device          crypto          # core crypto support

options         NO_SWAPPING     # Disable swapping of stack pages



Здесь мы берём GENERIC ядро, отключаем syscons (vt становится драйвером консоли по умолчанию), включаем три модуля — для тестирования загрузки системы вполне хватит.

Потом, когда всё заработает можно использовать минимальное ядро. Для него берём файл GENERIC ядра, удаляем всё лишнее (периодически компилируя и проверяя — грузится .iso или нет), оставляем необходимое и непонятное. Файл конфигурации нашего рабочего ядра стал выглядеть так:

tools/CABSD
#
# tools/CABSD

cpu             I486_CPU
cpu             I586_CPU
cpu             I686_CPU

ident           CABSD

makeoptions     NO_MODULES=1            # Don't compile modules

options         SCHED_ULE               # ULE scheduler
options         PREEMPTION              # Enable kernel thread preemption

options         FFS                     # Berkeley Fast Filesystem
#options        SOFTUPDATES             # Enable FFS soft updates support
#options        UFS_ACL                 # Support for access control lists
options         MD_ROOT                 # MD is a potential root device
options         ROOTDEVNAME=\"ufs:/dev/md0\"  # The root device and filesystem type can be compiled in
options         MSDOSFS                 # MSDOS Filesystem
options         CD9660                  # ISO 9660 Filesystem
options         TMPFS                   # Efficient memory filesystem
#options        NULLFS                  # NULL filesystem
#options        PROCFS                  # Process filesystem (requires PSEUDOFS)
#options        PSEUDOFS                # Pseudo-filesystem framework

options         GEOM_PART_GPT           # GUID Partition Tables.
options         GEOM_LABEL              # Provides labelization
options         GEOM_ELI                # Disk encryption.

options         COMPAT_FREEBSD4         # Compatible with FreeBSD4
options         COMPAT_FREEBSD5         # Compatible with FreeBSD5
options         COMPAT_FREEBSD6         # Compatible with FreeBSD6
options         COMPAT_FREEBSD7         # Compatible with FreeBSD7
#options        SCSI_DELAY=5000         # Delay (in ms) before probing SCSI
#options        SYSVSHM                 # SYSV-style shared memory
options         SYSVMSG                 # SYSV-style message queues
options         SYSVSEM                 # SYSV-style semaphores
options         _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
options         KBD_INSTALL_CDEV        # install a CDEV entry in /dev
options         PROCDESC                # Support for process descriptors
#options        INCLUDE_CONFIG_FILE     # Include this file in kernel
options         NO_SWAPPING             # Disable swapping of stack pages

# To make an SMP kernel, the next two lines are needed
options         SMP                     # Symmetric MultiProcessor Kernel
device          apic                    # I/O APIC

device          cpufreq                 # CPU frequency control

# Bus support.
device          acpi
device          pci
#device         eisa

# Floppy drives
#device         fdc

# USB support https://www.freebsd.org/doc/en/books/handbook/usb-disks.html
device          scbus                   # SCSI bus (required for ATA/SCSI)
device          da                      # Direct Access (disks)

device          uhci                    # UHCI PCI->USB interface
device          ohci                    # OHCI PCI->USB interface
device          ehci                    # EHCI PCI->USB interface (USB 2.0)
device          xhci                    # XHCI PCI->USB interface (USB 3.0)
device          usb                     # USB Bus (required)
device          umass                   # Disks/Mass storage - Requires scbus and da

device          cd                      # CD

device          ukbd                    # Keyboard

device          ahci                    # AHCI-compatible SATA controllers
device          ata                     # Legacy ATA/SATA controllers
options         ATA_STATIC_ID           # Static device numbering
#device         mvs                     # Marvell 88SX50XX/88SX60XX/88SX70XX/SoC SATA
#device         siis                    # SiliconImage SiI3124/SiI3132/SiI3531 SATA

# atkbdc0 controls both the keyboard and the PS/2 mouse
device          atkbdc                  # AT keyboard controller
device          atkbd                   # AT keyboard

# Без этого не будет работать kbdcontrol (keymap, keyrate)
device          kbdmux                  # keyboard multiplexer

# vt is the new video console driver
device          vt
device          vt_vga

options         TERMINAL_NORM_ATTR=(FG_GREEN|BG_BLACK)

options         MAXCONS=4               # number of virtual consoles

# Number of initial kernel page table pages used for early bootstrap.
# This number should include enough pages to map the kernel, any
# modules or other data loaded with the kernel by the loader, and data
# structures allocated before the VM system is initialized such as the
# vm_page_t array.  Each page table page maps 4MB (2MB with PAE).
# Может понадобиться увеличить, но вроде работает и так
#options                NKPT=31

device          crypto                  # core crypto support

# Pseudo devices.
device          loop                    # Network loopback
device          random                  # Entropy device
#device         padlock_rng             # VIA Padlock RNG
device          rdrand_rng              # Intel Bull Mountain RNG
#device         ether                   # Ethernet support
device          md                      # Memory "disks"

# EOF



Создаём файл настроек для компиляции мира. Читаем man src.conf, выписываем все WITHOUT_ в файл и вдумчиво изучаем. Приходит понимание, что понадобится не один, а целых два файла настроек — один для buildworld, второй плюсом для installworld.

tools/worldbuild.conf
#
# tools/worldbuild.conf
#
WITHOUT_ACCT=
WITHOUT_ACPI=
WITHOUT_AMD=
WITHOUT_APM=
WITHOUT_ARM_EABI=
WITHOUT_ASSERT_DEBUG=
WITHOUT_AT=
WITHOUT_ATM=
WITHOUT_AUDIT=
WITHOUT_AUTHPF=
# Эту опцию включаем в tools/worldinstall.conf
# На этапе компиляции она бесполезна
# WITHOUT_BINUTILS=
WITHOUT_BLUETOOTH=
WITHOUT_BMAKE=
WITHOUT_BSD_CPIO=
WITHOUT_BSNMP=
WITHOUT_CALENDAR=
WITHOUT_CAPSICUM=
WITHOUT_CDDL=
WITHOUT_CLANG=
WITHOUT_CLANG_EXTRAS=
WITHOUT_CLANG_FULL=
WITHOUT_CPP=
# Не включаем, так как на libcrypt завязаны geli и openssl
# WITHOUT_CRYPT=
WITHOUT_CTM=
WITHOUT_CXX=
WITHOUT_DICT=
WITHOUT_EXAMPLES=
WITHOUT_FDT=
WITHOUT_FLOPPY=
WITHOUT_FMTREE=
# Не вкючаем, иначе сломается загрузочное меню
# WITHOUT_FORTH=
# Не включаем, понадобится по условиям задачи
# WITHOUT_FREEBSD_UPDATE=
WITHOUT_GAMES=
WITHOUT_GCC=
WITHOUT_GCOV=
WITHOUT_GDB=
WITHOUT_GNU=
WITHOUT_GNUCXX=
WITHOUT_GNU_SUPPORT=
WITHOUT_GPIB=
WITHOUT_GPIO=
WITHOUT_GROFF=
WITHOUT_GSSAPI=
WITHOUT_HTML=
WITHOUT_HYPERV=
WITHOUT_ICONV=
WITHOUT_INET=
WITHOUT_INET_SUPPORT=
WITHOUT_INET6=
WITHOUT_INET6_SUPPORT=
WITHOUT_INFO=
# Эту опцию включаем в tools/worldinstall.conf
# WITHOUT_INSTALLLIB=
WITHOUT_IPFILTER=
WITHOUT_IPFW=
WITHOUT_IPX=
WITHOUT_IPX_SUPPORT=
WITHOUT_JAIL=
WITHOUT_KDUMP=
WITHOUT_KERBEROS=
WITHOUT_KERBEROS_SUPPORT=
WITHOUT_KERNEL_SYMBOLS=
WITHOUT_LDNS=
WITHOUT_LDNS_UTILS=
# Не включаем, системная консоль нужна
# WITHOUT_LEGACY_CONSOLE=
# А это имеет смысл только для amd64, а у нас i386
# WITHOUT_LIB32=
WITHOUT_LIBCPLUSPLUS=
# Не включаем, несколько локалей нам понадобятся.
# Лишние потом удалим, оставим только нужные
# WITHOUT_LOCALES=
WITHOUT_LOCATE=
WITHOUT_LPR=
WITHOUT_LS_COLORS=
WITHOUT_MAIL=
WITHOUT_MAILWRAPPER=
WITHOUT_MAKE=
WITHOUT_MAN=
WITHOUT_MAN_UTILS=
# libncurces используется редакторами /usr/bin/vi и jupp из пакетов.
# WITHOUT_NCURSESW=
WITHOUT_NDIS=
WITHOUT_NETCAT=
WITHOUT_NETGRAPH=
WITHOUT_NETGRAPH_SUPPORT=
WITHOUT_NIS=
WITHOUT_NLS=
WITHOUT_NLS_CATALOGS=
WITHOUT_NMTREE=
WITHOUT_NS_CACHING=
WITHOUT_NTP=
WITHOUT_OPENSSH=
# Если включить опцию, то openssl компилироваться не будет,
# придётся его ставить из пакетов. Но в нашем случае
# используем openssl из комплекта
# WITHOUT_OPENSSL=
WITHOUT_PAM_SUPPORT=
WITHOUT_PC_SYSINSTALL=
WITHOUT_PF=
WITHOUT_PKGBOOTSTRAP=
WITHOUT_PMC=
WITHOUT_PORTSNAP=
WITHOUT_PPP=
WITHOUT_PROFILE=
WITHOUT_QUOTAS=
WITHOUT_RCMDS=
WITHOUT_RCS=
# Тема /rescue будет рассмотрена отдельно
WITHOUT_RESCUE=
WITHOUT_ROUTED=
WITHOUT_SENDMAIL=
WITHOUT_SHAREDOCS=
WITHOUT_SOURCELESS=
WITHOUT_SOURCELESS_UCODE=
WITHOUT_SOURCELESS_HOST=
WITHOUT_SSP=
WITHOUT_SVNLITE=
# syscons нам не нужен, мы будем использовать newcons - vt(4)
WITHOUT_SYSCONS=
WITHOUT_SYSINSTALL=
# В качестве шелла используем tcsh
# WITHOUT_TCSH=
WITHOUT_TELNET=
WITHOUT_TESTS=
WITHOUT_TEXTPROC=
# Эту опцию включаем в tools/worldinstall.conf
# На этапе компиляции она бесполезна
# WITHOUT_TOOLCHAIN=
WITHOUT_UNBOUND=
WITHOUT_USB=
WITHOUT_UTMPX=
# Не включаем, vt нам как раз и нужен
# WITHOUT_VT=
WITHOUT_WIRELESS=
WITHOUT_WIRELESS_SUPPORT=
WITHOUT_WPA_SUPPLICANT_EAPOL=
WITHOUT_ZFS=
# Не включаем, файлы tz нам понадобятся.
# Лишние потом удалим, оставим только нужные
# WITHOUT_ZONEINFO=


tools/worldinstall.conf
#
# tools/worldinstall.conf
#

# Set to not install binutils (as, c++-filt, gconv, ld, nm, objcopy, objdump, readelf, size and strip)
WITHOUT_BINUTILS=

# Set this if you do not want to install optional libraries. For example when creating a nanobsd(8) image.
WITHOUT_INSTALLLIB=

# Set to not install programs used for program development, compilers, debuggers etc. The option does not work for build targets.
# When set, it also enforces the following options:
# WITHOUT_BINUTILS, WITHOUT_CLANG, WITHOUT_CLANG_EXTRAS, WITHOUT_CLANG_FULL, WITHOUT_GCC, WITHOUT_GDB
WITHOUT_TOOLCHAIN=



С такими опциями мы отключаем компиляцию как clang, так и gcc.


Приступаем к компиляции. На первом же шаге немного схитрим. При компиляции мира очень много времени уходит на компиляцию компилятора, но у нас же есть готовый, в базовой системе. К тому же только что обновлённый. Им мы и воспользуемся. Устанавливаем переменные

$ setenv CC `whereis -bq clang`
$ setenv CPP `whereis -bq clang-cpp`
$ setenv CXX `whereis -bq clang++`


Создаём символьную ссылку на файл конфигурации ядра CABSD в соответствующий каталог (в данном примере пропустим отладочный этап с CABSD-DEV, сразу будем делать конечный вариант ядра).

$ ln -sf ${BASE}/tools/CABSD /usr/src/sys/i386/conf


Компилируем. Дополнительные опции вида '-j N' по желанию

$ cd /usr/src

# rm -rf /usr/obj

# Мир
$ make buildworld USER=IT HOSTNAME=hq.example.net SRCCONF=${BASE}/tools/worldbuild.conf __MAKE_CONF=/dev/null

# Ядро
$ make buildkernel USER=IT HOSTNAME=hq.example.net SRCCONF=${BASE}/tools/worldbuild.conf __MAKE_CONF=/dev/null KERNCONF=CABSD

$ cd ${BASE}


Параметры USER и HOSTNAME декоративные — можно указать что-то своё, чтобы в новой системе при загрузке, при uname -a, да и в других местах выводилось гордое «IT@hq.example.net», а не «root@localhost».

Теперь устанавливаем систему в рабочий каталог. Обратите внимание — между этапами компиляции и установки не стоит посредством freebsd-update обновлять систему или выключать параметры в файле worldbuild.conf.

$ cd /usr/src

# Устанавливаем мир. Второй файл с параметрами мы указываем через параметр __MAKE_CONF - фактически он приплюсуется к первому.
$ make installworld DESTDIR=${WORKDIR}/vanilla SRCCONF=${BASE}/tools/worldbuild.conf __MAKE_CONF=${BASE}/tools/worldinstall.conf

# Устанавливаем etc
$ make distribution DESTDIR=${WORKDIR}/vanilla SRCCONF=${BASE}/tools/worldbuild.conf __MAKE_CONF=${BASE}/tools/worldinstall.conf

# Устанавливаем наше минимальное ядро
$ make installkernel DESTDIR=${WORKDIR}/vanilla SRCCONF=${BASE}/tools/worldbuild.conf __MAKE_CONF=${BASE}/tools/worldinstall.conf KERNCONF=CABSD

# Копируем второе ядро, GENERIC - берём его из /boot/kernel базовой системы
# Устанавливаем во временный каталог
$ mkdir -p ${WORKDIR}/vanilla/tmp/boot/kernel
# И почти 800 модулей в придачу. Потом удалим лишние.
$ cp -p /boot/kernel/{kernel,*.ko} ${WORKDIR}/vanilla/tmp/boot/kernel/

$ chflags -R noschg ${WORKDIR}/vanilla

$ cd ${BASE}


Если не включать опцию WITHOUT_RESCUE= при компиляции мира, то мы можем заменить файлы в bin, sbin, usr/bin, usr/sbin на их аналоги из rescue, хотя целесообразность этого не очевидна. Вся система у нас находится на одном разделе, при загрузке монтирующемся в памяти — поэтому варианты с несмонтировавшемся usr практически исключены, и смысл замены может быть лишь в возможности уменьшить размер системы за счёт удаления библиотек, ставших ненужными из-за того, что использующие их программы заменены на слинкованный статически rescue. Впрочем, экономию надо просчитывать, а в нашем примере мы rescue компилировать не будем.

Если будете заменять, то можно использовать скрипт (подсмотрен в mfsBSD)

tools/_linkrescue.sh
#!/bin/csh

#
# tools/_linkrescue.sh

cd ${WORKDIR}/vanilla

echo "Before:"

du -hc bin sbin usr/bin usr/sbin rescue

foreach FILE (`ls rescue`)
        if ( -f bin/${FILE} ) then
                ln -f rescue/${FILE} bin/${FILE}
        else if ( -f sbin/${FILE} ) then
                ln -f rescue/${FILE} sbin/${FILE}
        else if ( -f usr/bin/${FILE} ) then
                ln -f rescue/${FILE} usr/bin/${FILE}
        else if ( -f usr/sbin/${FILE} ) then
                ln -f rescue/${FILE} usr/sbin/${FILE}
        endif
end

echo "After:"

du -hc bin sbin usr/bin usr/sbin rescue

cd ${BASE}



Устанавливаем пакеты


Для удобства операторов нашего ЦС мы установим файловый менеджер. Популярный mc занимает 158 Мб, mc-light — 6 Мб, deco — 217 Mb со всеми зависимостями. Если ставить из портов, то, вероятно, можно было бы немного уменьшить размер с помощью опций компиляции, но в пакетах нашелся компактный консольный файловый менеджер clex — 0.3 Мб, который мы и установим.

Второй момент — редактор с поддержкой Unicode. Формально, по букве задания, поддержка была обеспечена — русский текст ввести в консоли в командной строке csh можно (echo привет), вывести на экран тоже (cat /usr/bin/help), но хотелось обеспечить более комфортную работу с текстами — отредактировать какой-нибудь файл, вести записи, мало ли. Комплектный /usr/bin/ee русский текст в Unicode файле показывает как »-PM-7M-PM-? M», /usr/bin/vi всё показывает корректно (правда он требует библиотеку libncursesw, поэтому придётся выключить опцию WITHOUT_NCURSESW= в tools/worldbuild.conf), /rescue/vi — »\xd0\xb7\xd0\xb0».

В пакетах нашлись несколько небольших редакторов с поддержкой Unicode, в частности: puff, отображающий текст как «запи~Аи в об~@аз» (в оригинале «записи в образ»); le — всем хорош, но требует библиотеки C++; и jupp, который всё показывает корректно, и, как и vi требует libncurses. Причём jupp представляет собой переработанную версию редактора joe, но если оригинальный joe из пакетов тянет за собой 49 Мб зависимостей, то jupp размером с vi.

Причём все проблемы у редакторов ee и puff лишь с отображением русских букв, при вводе «вслепую» всё сохраняется корректно.

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

Устанавливаем misc/clex и editors/jupp. Какие-то пользовательские пакеты можно положить в каталог ${BASE}/pkg.local/, при установке они добавятся.

# Пакеты устанавливаем в два захода - сначала скачиваем их, добавляем
# свои, если есть, а затем устанавливаем в chroot окружении.

# Устанавливаем pkg в базовую систему
$ pkg -N || env ASSUME_ALWAYS_YES=YES pkg bootstrap

# БД пакетов держим в каталоге внутри ${WORKDIR}, чтобы не пересекалась с БД из базовой системы
$ mkdir -p ${WORKDIR}/pkg.db
$ setenv PKG_DBDIR ${WORKDIR}/pkg.db

# Обновим БД
$ pkg-static update

# Пакеты пока будут внутри ${WORKDIR}/vanilla, устанавливать их будем в chroot
$ mkdir -p ${WORKDIR}/vanilla/tmp/pkg.files/All

# Скачиваем пакеты, зависимости разрешаются автоматически.
$ pkg-static fetch --output ${WORKDIR}/vanilla/tmp/pkg.files --dependencies --yes misc/clex editors/jupp
$ unsetenv PKG_DBDIR

# Добавляем пакеты из локального каталога (${BASE}/pkg.local).
# Удовлетворение зависимостей - на совести пользователя
$ install -m 0644 ${BASE}/pkg.local/* ${WORKDIR}/vanilla/tmp/pkg.files/All

# Если это не первый запуск, то удалим БД с информацией об установленных пакетах
$ rm -f ${WORKDIR}/vanilla/var/db/pkg/local.sqlite

# Устанавливаем пакеты
$ cd ${WORKDIR}/vanilla
$ find tmp/pkg.files/All/* -type f -exec pkg-static -c ${WORKDIR}/vanilla add {} \;

$ cd ${BASE}


Настраиваем систему


В chroot окружении создаём пользователя 'ca'. Для возможности монтирования устройств добавляем в группу operator. В качестве шелла используем csh, опция WITHOUT_TCSH в tools/worldbuild.conf не включена.

$ chroot ${WORKDIR}/vanilla pw useradd ca -c "Certification authority operator" -m -G operator -s /bin/csh

# Получаем и сохраняем в файл числовые UID и GID (по идее 1001:1001, но мало ли...)
$ chroot ${WORKDIR}/vanilla id -u ca > ${WORKDIR}/ca.uid
$ chroot ${WORKDIR}/vanilla id -g ca > ${WORKDIR}/ca.gid

# Включаем пользователю UTF-8 в системной консоли
$ echo "setenv MM_CHARSET UTF-8" >> ${WORKDIR}/vanilla/home/ca/.login
$ echo "setenv LANG en_US.UTF-8" >> ${WORKDIR}/vanilla/home/ca/.login

# Добавляем в конец path каталог со скриптами ЦС (раздел с ними будем монтировать в каталог /ca)
# Необходимо убедиться, что в системе установлен лишь один openssl - либо из пакетов, либо системный.
$ echo "set path = (/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin /ca)" >> ${WORKDIR}/vanilla/home/ca/.cshrc

# vi мы не используем, устанавливаем свою переменную EDITOR
$ echo "setenv EDITOR jupp" >> ${WORKDIR}/vanilla/home/ca/.cshrc

# Можно добавить переменные, используемые в конфигурации ЦС
$ echo "setenv OPENSSL_CONF /ca/conf/ca.conf" >> ${WORKDIR}/vanilla/home/ca/.login
$ echo "setenv CA_OID 1.3.6.1.4.1.nnnnn" >> ${WORKDIR}/vanilla/home/ca/.login


Ещё у нас есть скрипт conf/ca.sh, который мы запустим в chroot окружении из-под пользователя 'ca' для выполнения некоторых действий в домашнем каталоге пользователя с его правами.

conf/ca.sh
#!/bin/sh -ex
##
# conf/ca.sh
##

cd ~

# Здесь мы из-под пользователя 'ca' делаем какие-нибудь вещи

# 1. Создадим файл конфигурации для файлового менеджера clex

mkdir -p ~/.config/clex

cat << EOF > ~/.config/clex/config
#
# CLEX configuration file
#
CMD_F3=more -- $f
CMD_F4=puff -- $f
CMD_F5=cp -ir -- $f $2
CMD_F6=mv -i -- $f $2
CMD_F7=mkdir -- 
CMD_F8=rm -- $f
EOF

# 2. Создадим файл конфигурации для vi

#cat << EOF > ~/.nexrc
#set verbose showmode
#set nomesg
#EOF

# 3. Создадим файл .logout, он потребуется позже
touch .logout



Данный скрипт необходимо запустить до чистки системы, пока в ${WORKDIR}/vanilla ещё есть su.

# Устанавливаем conf/ca.sh с правами r-xr-xr-x в ${WORKDIR}/vanilla/home/ca
$ install -m 0555 -o root -g wheel conf/ca.sh ${WORKDIR}/vanilla/home/ca/

# Запускаем
$ chroot ${WORKDIR}/vanilla su - ca -c /home/ca/ca.sh

# Удаляем
$ rm -f ${WORKDIR}/vanilla/home/ca/ca.sh


Создаём файлы конфигурации. Все файлы лежат в каталоге ${BASE}/conf, откуда мы их потом установим в нужные места.

conf/fstab
##
# conf/fstab
##
/dev/md0                /       ufs     rw                                      0 0

# 50 Мб на /tmp.
tmpfs                   /tmp    tmpfs   rw,mode=1777,size=50m,noexec            0 0

# noauto
/dev/gpt/ca             /ca             ufs     rw,noauto,noatime               0 0
/dev/gpt/keys.eli       /ca.keys        ufs     ro,noauto,noatime               0 0
/dev/gpt/exchange       /ca.certs       msdosfs rw,longnames,-u=ca,-g=ca,-m=0640,-M=0750,noauto,noatime 0 0



Корневой раздел у нас монтируется из mfs, а /tmp в tmpfs. Можно /tmp отдельно не монтировать, оставить в корневом разделе, но тогда при создании флешки необходимо выделить больше свободного места для него внутри образа системы. При обновлении системы /tmp используется freebsd-update для извлечения файлов, самый большой из них в нашей конфигурации это GENERIC ядро, около 17 Мб, поэтому сильно маленьким этот раздел лучше не делать.

Раздел /dev/gpt/ca предназначен для скриптов и файлов конфигурации нашего ЦС, /dev/gpt/keys.eli — шифрованный с помощью geli раздел /dev/gpt/keys с секретными ключами, /dev/gpt/exchange — FAT раздел для обмена с внешними системами. Его мы монтируем с поддержкой длинных имён, но без поддержки их перекодировки — принято принципиальное решение об использовании лишь ASCII символов в именах файлов на этом разделе. Поэтому и систему, и ядро компилируем без поддержки iconv.

Эти разделы мы автоматически при старте не монтируем (параметр noauto), так как при каких-то неполадках (трижды неправильно введённый пароль для geli, например, что не позволит создать раздел keys.eli) нас выкинет в однопользовательский режим. У оператора будет шок и моральная травма. Поэтому эти разделы будем монтировать в userspace пользователя 'ca', для чего при создании включим его в группу operator и настройками devfs и sysctl (ниже) предоставим необходимые полномочия.

Обратите внимание — в fstab раздел с ключами для ЦС монтируется в режиме только для чтения, поэтому перед созданием ключей надо не забыть перемонтировать его для записи (mount -u -o rw /dev/gpt/keys.eli).

# Добавляем автоматическое монтирование разделов ЦС. Применимо только для флешки,
# при загрузке с CD будут выскакивать ошибки об отсутствующих разделах
$ echo "mount /dev/gpt/ca" >> ${WORKDIR}/vanilla/home/ca/.login
$ echo "mount /dev/gpt/keys.eli" >> ${WORKDIR}/vanilla/home/ca/.login
$ echo "mount /dev/gpt/exchange" >> ${WORKDIR}/vanilla/home/ca/.login

# И размонтирование
$ echo "umount /dev/gpt/ca" >> ${WORKDIR}/vanilla/home/ca/.logout
$ echo "umount /dev/gpt/keys.eli" >> ${WORKDIR}/vanilla/home/ca/.logout
$ echo "umount /dev/gpt/exchange" >> ${WORKDIR}/vanilla/home/ca/.logout


Обратите внимание — если файлы .login и .cshrc уже существовали в каталоге пользователя 'ca', и мы могли дописывать туда без опасения порчи владельца или прав, то файл .logout при заведении пользователя не создавался. Поэтому, если мы не хотим, чтобы его владельцем оказался root: ca, необходимо создать его из-под пользователя ca, хотя бы с помощью скрипта conf/ca.sh


Теперь мы предоставим возможность нашему пользователю 'ca' возможность монтировать сторонние флешки и разделы на нашей флешке (с настройками ЦС, ключами, разделом обмена).

conf/devfs.rules
##
# conf/devfs.rules
##
[localrules=5]
# Правило для нашей мультифлешки
# '/dev/' не указываем
add path 'gpt/*' group operator mode 0660
# Правило для обычных флешек
add path 'da*' group operator mode 0660



Флешку будем разбивать с использованием GPT, её разделы адресовать по меткам вида /dev/gpt/label

conf/sysctl.conf
##
# conf/sysctl.conf
##

# allow regular users to mount file systems
vfs.usermount=1



Устанавливаем переменную в sysctl.conf

conf/ttys
##
# conf/ttys
##

#
# $FreeBSD: releng/10.1/etc/etc.i386/ttys 267236 2014-06-08 17:50:07Z nwhitehorn $
#       @(#)ttys        5.1 (Berkeley) 4/17/89
#
console none                            unknown off secure

# Терминал с автологином 'ca'
ttyv0   "/usr/libexec/getty CA"               xterm   on  secure

# Терминал для 'root'
ttyv1   "/usr/libexec/getty Pc"               xterm   on  secure



Для системной консоли при старте запускаем два терминала (оба должны быть xterm). Первый — с автологином пользователя 'ca' (см. описание gettytab ниже), второй для 'root', обычный вход с запросом пароля.

conf/gettytab
##
# conf/gettytab
##

# $FreeBSD: releng/10.1/etc/gettytab 241708 2012-10-18 22:20:02Z peterj $
#       from: @(#)gettytab      5.14 (Berkeley) 3/27/91
#
default:\
        :cb:ce:ck:lc:fd#1000:im=\r\n%s/%m (%h) (%t)\r\n\r\n:sp#1200:\
        :if=/etc/issue:

P|Pc|Pc console:\
        :ht:np:sp#9600:

# Прописываем автологин для пользователя 'ca'
CA:\
        :al=ca:tc=Pc:



В настройках оставляем лишь несколько секций — default, Pc — для пользователя 'root' и создаём новую секцию CA, в которой прописываем автологин пользователя 'ca', а остальное наследуется из Pc и default.

Далее создаём файл issue, в котором сделаем напоминание о необходимости проверить установленное время на том компьютере, с которого загрузились. Интернет не предусмотрен by design, поэтому часики будем при необходимости устанавливать вручную. Благо, для данного ЦС точность плюс-минус минута абсолютно не критична.

conf/issue
====^^^=^^=^^=^^=^^==
== Проверьте время ==



Берём файл etc/defaults/rc.conf, копируем в наш conf/ и начинаем отключать всё лишнее.

conf/rc.conf
##
# conf/rc.conf
##

#
# $FreeBSD: releng/10.1/etc/defaults/rc.conf 273188 2014-10-16 22:00:24Z hrs $

##############################################################
###  Important initial Boot-time options  ####################
##############################################################

rc_debug="NO"         # Set to YES to enable debugging output from rc.d
rc_info="YES"         # Enables display of informational messages at boot.
devd_enable="NO"      # Run devd, to trigger programs on device tree changes.
devd_flags=""         # Additional flags for devd(8).

gptboot_enable="YES"  # GPT boot success/failure reporting.

# GELI disk encryption configuration.
geli_devices="gpt/keys"       # List of devices to automatically attach in addition to
                        # GELI devices listed in /etc/fstab.
geli_tries=""         # Number of times to attempt attaching geli device.
                        # If empty, kern.geom.eli.tries will be used.
geli_default_flags="" # Default flags for geli(8).
geli_autodetach="YES" # Automatically detach on last close.
                        # Providers are marked as such when all file systems are
                        # mounted.
# Example use.
#geli_devices="da1 mirror/home"
#geli_da1_flags="-p -k /etc/geli/da1.keys"
#geli_da1_autodetach="NO"
#geli_mirror_home_flags="-k /etc/geli/home.keys"

fsck_y_enable="NO"    # Set to YES to do fsck -y if the initial preen fails.
fsck_y_flags=""               # Additional flags for fsck -y
# Разделы на флешке создали без поддержки снапшотов, поэтому параметр устанавливаем в "NO"
background_fsck="NO"  # Attempt to run fsck in the background where possible.

##############################################################
###  Network configuration sub-section  ######################
##############################################################

### Basic network and firewall/security options: ###
hostname="root2sub1"          # Set this!
hostid_enable="NO"            # Set host UUID.

#network_interfaces="lo0"     # List of network interfaces (or "auto").
#ifconfig_lo0="inet 127.0.0.1"        # default loopback device configuration.
network_interfaces=""         # List of network interfaces (or "auto").

### Network daemon (miscellaneous) ###
hostapd_enable="NO"           # Run hostap daemon.
syslogd_enable="NO"           # Run syslog daemon (or NO).

### IPv6 options: ###
ip6addrctl_enable="NO"                # Set to YES to enable default address selection
ipv6_network_interfaces="none"        # List of IPv6 network interfaces
                                # (or "auto" or "none").

##############################################################
###  Mail Transfer Agent (MTA) options  ######################
##############################################################

# Settings for /etc/rc.sendmail and /etc/rc.d/sendmail:
sendmail_enable="NO"  # Run the sendmail inbound daemon (YES/NO).

##############################################################
###  Miscellaneous administrative options  ###################
##############################################################

# Это для того, чтоб юзер 'ca' мог монтировать флешки
devfs_rulesets="/etc/defaults/devfs.rules /etc/devfs.rules" # Files containing
                                                            # devfs(8) rules.
devfs_system_ruleset="localrules"     # The name (NOT number) of a ruleset to apply to /dev
devfs_set_rulesets="" # A list of /mount/dev=ruleset_name settings to
                        # apply (must be mounted already, i.e. fstab(5))
devfs_load_rulesets="YES"     # Enable to always load the default rulesets

cron_enable="NO"      # Run the periodic job daemon.
crashinfo_enable="NO" # Automatically generate crash dump summary.

kern_securelevel_enable="NO"  # kernel security level (see security(7))
kern_securelevel="-1" # range: -1..3 ; `-1' is the most insecure
                        # Note that setting securelevel to 0 will result
                        # in the system booting with securelevel set to 1, as
                        # init(8) will raise the level when rc(8) completes.

update_motd="NO"      # update version info in /etc/motd (or NO)
entropy_file="NO"     # Set to NO to disable caching entropy through reboots.
                        # /var/db/entropy-file is preferred if / is not avail.
dmesg_enable="YES"    # Save dmesg(8) to /var/run/dmesg.boot

newsyslog_enable="NO" # Run newsyslog at startup.
mixer_enable="NO"     # Run the sound mixer.


##############################################################
###  System console options  #################################
##############################################################

#keyboard=""          # keyboard device to use (default /dev/kbd0).
keymap="ru.win"               # keymap in /usr/share/{syscons,vt}/keymaps/* (or NO).
keyrate="fast"                # keyboard rate to: slow, normal, fast (or NO).
#keybell="NO"                 # See kbdcontrol(1) for options.  Use "off" to disable.
#keychange="NO"               # function keys default values (or NO).
#cursor="NO"          # cursor type {normal|blink|destructive} (or NO).
#scrnmap="NO"         # screen map in /usr/share/syscons/scrnmaps/* (or NO).
#font8x14="NO"                # font 8x14 from /usr/share/{syscons,vt}/fonts/* (or NO).
#font8x8="NO"         # font 8x8 from /usr/share/{syscons,vt}/fonts/* (or NO).
blanktime="NO"                # blank time (in seconds) or "NO" to turn it off.
moused_nondefault_enable="NO" # Treat non-default mice as enabled unless
                               # specifically overriden in rc.conf(5).

# Сюда, при наличии своих шрифтов будет дописана строка font8x16="xxx.fnt"



Секция с параметрами geli_ понадобится позже. Прописываем hostname. Указываем параметры для devfs — чтобы подтягивались наши локальные правила для монтирования флешек. Стоит иметь в виду, что freebsd-update не работает при установке kern.securelevel > 0. И, напоследок, в секции System console options настроим переключение на русский и свойства клавиатуры. Файл русского шрифта здесь мы не указываем — если есть свой, то добавим позже, если своего нету — то пусть используется системный

conf/hosts
##
# conf/hosts
##
127.0.0.1       localhost



Пусть будет.

conf/termcap
#
# conf/termcap
#

#       @(#)termcap.src 8.2 (Berkeley) 11/17/93
# $FreeBSD: releng/10.1/share/termcap/termcap.src 267734 2014-06-22 16:48:21Z gavin $

xterm|X11 terminal emulator:\
        :tc=xterm-new:
# To add a termcap entry under FreeBSD for a new terminal type, insert
# the entry in the appropriate location in /etc/termcap then issue this
# command:
#
#  cap_mkdb /etc/termcap
#
xterm-clear:\
        :te=\E[?1049l:ti=\E[?1049h:\
        :tc=xterm-new:
xterm-new|modern xterm:\
        :@7=\EOF:@8=\EOM:F1=\E[23~:F2=\E[24~:K2=\EOE:Km=\E[M:\
        :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\E[15~:k6=\E[17~:\
        :k7=\E[18~:k8=\E[19~:k9=\E[20~:k;=\E[21~:kI=\E[2~:\
        :kN=\E[6~:kP=\E[5~:kd=\EOB:kh=\EOH:kl=\EOD:kr=\EOC:ku=\EOA:\
        :tc=xterm-basic:
#
# This chunk is used for building the VT220/Sun/PC keyboard variants.
xterm-basic|modern xterm common:\
        :am:bs:km:mi:ms:ut:xn:AX:\
        :Co#8:co#80:kn#12:li#24:pa#64:\
        :AB=\E[4%dm:AF=\E[3%dm:AL=\E[%dL:DC=\E[%dP:DL=\E[%dM:\
        :DO=\E[%dB:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:ae=\E(B:al=\E[L:\
        :as=\E(0:bl=^G:cd=\E[J:ce=\E[K:cl=\E[H\E[2J:\
        :cm=\E[%i%d;%dH:cs=\E[%i%d;%dr:ct=\E[3g:dc=\E[P:dl=\E[M:\
        :ei=\E[4l:ho=\E[H:im=\E[4h:is=\E[!p\E[?3;4l\E[4l\E>:\
        :kD=\E[3~:kb=^H:ke=\E[?1l\E>:ks=\E[?1h\E=:kB=\E[Z:le=^H:md=\E[1m:\
        :me=\E[m:ml=\El:mr=\E[7m:mu=\Em:nd=\E[C:op=\E[39;49m:\
        :rc=\E8:rs=\E[!p\E[?3;4l\E[4l\E>:sc=\E7:se=\E[27m:sf=^J:\
        :so=\E[7m:sr=\EM:st=\EH:\
        :ue=\E[24m:up=\E[A:us=\E[4m:ve=\E[?12l\E[?25h:vi=\E[?25l:vs=\E[?12;25h:

#
# END OF TERMCAP
# ------------------------



Сделаем урезанную версию файла termcap, оставим там только xterm* терминалы — это позволит значительно уменьшить размер termcap.db.

conf/freebsd-update.conf
##
# conf/freebsd-update.conf
##
# $FreeBSD: releng/10.1/etc/freebsd-update.conf 258121 2013-11-14 09:14:33Z glebius $

# Trusted keyprint.
KeyPrint 800651ef4b4c71c27e60786d7b487188970f4b4169cc055784e21eb71d410cc5

# Server or server pool from which to fetch updates.
ServerName update.FreeBSD.org

# Components of the base system which should be kept updated.
Components world kernel

# Directory in which to store downloaded updates and temporary
# files used by FreeBSD Update.
WorkDir /mnt

# When installing a new kernel perform a backup of the old one first
# so it is possible to boot the old kernel in case of problems.
BackupKernel no



В нашем случае флешку с обновлениями мы будем монтировать в /mnt. При обновлении ядра старое не сохраняем.

Движимые человеколюбием к потенциальным операторам системы, которые вовсе не профессиональные пользователи FreeBSD, создадим ещё несколько файлов:

conf/motd
Для вызова справки введите 'help'

Переключение раскладки клавиатуры - Ctrl+Shift



И два файла — help и manpath, которые мы потом разместим в usr/bin

conf/help
#!/bin/sh
##
# conf/help
##

cat << EOF
Для записи изменений в образ mfs2:
$ mount /dev/gpt/system /mnt
$ mdconfig -a -t vnode -f /mnt/mfs2 -u 1
$ mount /dev/md1 /media
... Записываем в /mеdia ...
$ umount /media
$ mdconfig -d -u 1
$ umount /mnt

Для монтирования MS DOS
(as root) $ mount_msdosfs -u ca -g ca -m 0640 -M 0750 -l /dev/da1s1 /mnt
(as user) $ mount_msdosfs -m 0640 -M 0750 -l /dev/da1s1 ~/mnt

Для конвертации DOS строк (CR/LF) в Unix формат:
$ tr -d '\r' < in.txt > out.txt

Для установки времени
(as root) $ date ГГММДДччмм.сс
и проверить временную зону

Создать memory disk
$ mount -t tmpfs -o size=100m tmpfs ~/mnt
EOF



Так как man страниц в комплекте не будет, то сделаем небольшой help

conf/manpath
#!/bin/sh
##
# conf/manpath
##

# Так как систему компилировали с WITHOUT_MAN=, то утилита manpath отсутствует, а без неё не работает whereis

echo ""



Второй файл, manpath — это заглушка для обхода неправильного поведения утилиты whereis, которая, даже при указании поиска только по двоичным файлам ('-b') завершается с ошибкой при безуспешной попытке вызова утилиты manpath, которой нет в нашей системе в силу компиляции мира с опцией WITHOUT_MAN=.

Итак, устанавливаем наши файлы из conf/ в ${WORKDIR}/vanilla и продолжаем настройку

# в etc
# Разбито на две строки для лучшей читаемости
$ install -m 0644 -o root -g wheel conf/{devfs.rules,freebsd-update.conf,fstab,gettytab} ${WORKDIR}/vanilla/etc/
$ install -m 0644 -o root -g wheel conf/{hosts,issue,motd,rc.conf,sysctl.conf,ttys} ${WORKDIR}/vanilla/etc/

# в usr/bin
$ install -m 0555 -o root -g wheel conf/{help,manpath} ${WORKDIR}/vanilla/usr/bin/

# в usr/share/misc
$ install -m 0644 -o root -g wheel conf/termcap ${WORKDIR}/vanilla/usr/share/misc/

# Устанавливаем временную зону.
$ tzsetup -s -C ${WORKDIR}/vanilla Asia/Yekaterinburg

# Так как загружаться с флешки мы будем на компьютерах, у которых основная
# система Windows, то часы на них установлены по местному времени, а не UTC.
# Empty file. Its presence indicates that the machine's CMOS clock is set to local time.
$ touch ${WORKDIR}/vanilla/etc/wall_cmos_clock

# Устанавливаем пароль для root (по желанию)
$ pw -V ${WORKDIR}/vanilla/etc usermod root -h 0


Если хочется видеть в консоли другой шрифт, например старый добрый keyrus, то по ссылке с habrahabr.ru/post/137544 можно взять keyrus.bdf и добавить его в нашу систему.

$ vtfontcvt tools/keyrus.bdf keyrus.fnt
$ install -m 0444 -o root -g wheel keyrus.fnt ${WORKDIR}/vanilla/usr/share/vt/fonts/
$ echo 'font8x16="keyrus.fnt"' >> ${WORKDIR}/vanilla/etc/rc.conf


Настройка загрузки


Теперь настал черёд ответственного этапа по настройки загрузки системы. Ядра, модули, загрузчик, загрузочное меню. Последовательность загрузки описана в соответствующих разделах handbook, поэтому здесь подробно её освещать нет смысла. Важно то, что загрузчику — loader’у мы должны предъявить ядро, а ядру уже файл с образом нашей системы. Система в ${WORKDIR}/vanilla почти готова, поэтому переносим оттуда ядра и загрузочные файлы в каталог ${WORKDIR}/custom.

# Создаём каталоги в custom/boot/ для файла настроек loader_default.conf и два каталога для ядер
# boot/kernel/ - каталог для GENERIC ядра, а boot/kernel.cabsd/ - для нашего самодельного
$ mkdir -p ${WORKDIR}/custom/boot/{defaults,kernel,kernel.cabsd}

# Переносим ядра

# Основное (мини) ядро
$ cp -p ${WORKDIR}/vanilla/boot/kernel/kernel ${WORKDIR}/custom/boot/kernel.cabsd/

# Запасное (GENERIC) ядро
$ cp -p ${WORKDIR}/vanilla/tmp/boot/kernel/kernel ${WORKDIR}/custom/boot/kernel/


Нам придётся нарисовать загрузочное меню. У нас два ядра и будет два образа системы. В меню мы включим три варианта: mff, mmf, ffmm

  1. ядро caBSD с первым образом системы
  2. ядро GENERIC с модулями и первым образом системы
  3. ядро GENERIC с модулями и вторым образом системы


Первый вариант и будет конфигурацией по умолчанию, и предполагаем, что обычно в ней и будет работать пользователь.

У нас будет три файла конфигурации для загрузчика — loader.conf для первой конфигурации, loader_gen1.conf и loader_gen2.conf — для GENERIC ядра с первым и вторым образом соответственно, отличающиеся лишь именем файла образа. Итак,

conf/loader.conf
##
# conf/loader.conf
##

# Задержка перед автозагрузкой (сек)
autoboot_delay="5"

# Эти два параметра обязательные
mfs_load="YES"
mfs_type="md_image"

# Указываем загрузку с
    
            

© Habrahabr.ru