[Из песочницы] Компактная инсталляция 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
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
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
#
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
#
# 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)
#!/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' для выполнения некоторых действий в домашнем каталоге пользователя с его правами.
#!/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
##
/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
##
[localrules=5]
# Правило для нашей мультифлешки
# '/dev/' не указываем
add path 'gpt/*' group operator mode 0660
# Правило для обычных флешек
add path 'da*' group operator mode 0660
Флешку будем разбивать с использованием GPT, её разделы адресовать по меткам вида /dev/gpt/label
##
# conf/sysctl.conf
##
# allow regular users to mount file systems
vfs.usermount=1
Устанавливаем переменную в sysctl.conf
##
# 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
##
# $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, поэтому часики будем при необходимости устанавливать вручную. Благо, для данного ЦС точность плюс-минус минута абсолютно не критична.
====^^^=^^=^^=^^=^^==
== Проверьте время ==
Берём файл etc/defaults/rc.conf, копируем в наш 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
##
127.0.0.1 localhost
Пусть будет.
#
# 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
##
# $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, создадим ещё несколько файлов:
Для вызова справки введите 'help'
Переключение раскладки клавиатуры - Ctrl+Shift
И два файла — help и manpath, которые мы потом разместим в usr/bin
#!/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
#!/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
- ядро caBSD с первым образом системы
- ядро GENERIC с модулями и первым образом системы
- ядро GENERIC с модулями и вторым образом системы
Первый вариант и будет конфигурацией по умолчанию, и предполагаем, что обычно в ней и будет работать пользователь.
У нас будет три файла конфигурации для загрузчика — loader.conf для первой конфигурации, loader_gen1.conf и loader_gen2.conf — для GENERIC ядра с первым и вторым образом соответственно, отличающиеся лишь именем файла образа. Итак,
##
# conf/loader.conf
##
# Задержка перед автозагрузкой (сек)
autoboot_delay="5"
# Эти два параметра обязательные
mfs_load="YES"
mfs_type="md_image"
# Указываем загрузку с