Full Stack in The Wild

. . . или проекты старого сисадмина

Инструменты пользователя

Инструменты сайта


astra:os-setup-iso

Установка ОС с собственного загрузочного носителя

Собственный загрузочный носитель - это ISO-образ, который можно записать на CD/USB/HDD, загрузить с них устройство и запустить процедуру установки.

ISO-образ должен содержать:

  • специальный вариант операционной системы, который способен загрузить устройство и обеспечить работоспособность процедуры установки
  • локальный репозиторий или возможность сетевого доступа к необходимым для установки пакетам (netinstall)

Операционная система (vmlinuz, initrd)

Операционная система состоит из ядра (vmlinuz) и архива с файлами корневого раздела (initrd)
В качестве сборочной платформы для получения этих файлов подойдет устройство с минимальным образом и установленными дополнительными пакетами:

apt install debootstrap cpio zstd

Сборка выполняется в пустом временном каталоге из-под пользователя root, например в /tmp/media:

rm -rfv /tmp/media; mkdir -pvm 0777 /tmp/media; cd /tmp/media
pwd

vmlinuz

Указать расположение главного репозитория (версия ОС в котором может отличаться от сборочной платформы):

REPOMAIN="https://download.astralinux.ru/astra/stable/1.8_x86-64/repository-main/"

Выбрать необходимые пакеты, например:

PACKAGES="chrony,console-setup,debootstrap,fdisk,isc-dhcp-client,linux-latest-generic,openssh-server"

Собрать систему в подкаталоге (например, в ./os) и перейти в него:

rm -rfv os
debootstrap --variant=minbase --include $PACKAGES $(basename $(echo $REPOMAIN | sed 's/x86-64.*$/x86-64/')) os $REPOMAIN
cd os

«Забрать» файл ядра системы (vmlinuz):

cp -fv boot/vmlinuz* ../vmlinuz
chmod -v 0644 ../vmlinuz

initrd (подготовка)

Распаковать initrd, созданный debootstrap. Его содержимое пригодится в дальнейшем:

zcat boot/initrd.img* | cpio -idmv --no-absolute-filenames --directory=boot --unconditional

Обеспечить поддержку русского языка (консоль и файловая система FAT):

rm -rfv etc/console-setup/*
mv -fv usr/share/consolefonts/CyrSlav-Fixed16.psf.gz etc/console-setup/
cat > etc/default/console-setup << EOF
CHARMAP="UTF-8"
CODESET="CyrSlav"
FONTFACE="Fixed"
FONTSIZE="8x16"
EOF
find usr/lib/modules/*/kernel/fs/nls/*1251* -exec mv -fv {} boot/{} \;

Удалить из образа все «ненужное» (трюк):

find . -mindepth 1 -maxdepth 1 -type d \
     ! -name 'boot' \
     ! -name 'etc' \
     ! -name 'usr' \
       -exec rm -rfv {} \;
 
find etc -mindepth 1 -maxdepth 1 -type d \
     ! -name 'alternatives' \
     ! -name 'astra' \
     ! -name 'chrony' \
     ! -name 'console-setup' \
     ! -name 'default' \
     ! -name 'dhcp' \
     ! -name 'ld.so.conf.d' \
     ! -name 'modprobe.d' \
     ! -name 'pam.d' \
     ! -name 'security' \
     ! -name 'ssh' \
     ! -name 'udev' \
       -exec rm -rfv {} \;
 
find usr -mindepth 1 -maxdepth 1 \
     ! -name 'bin' \
     ! -name 'lib' \
     ! -name 'lib64' \
     ! -name 'sbin' \
     ! -name 'share' \
       -exec rm -rfv {} \;
 
find usr/lib -mindepth 1 -maxdepth 1 -type d \
     ! -name 'console-setup' \
     ! -name 'init' \
     ! -name 'lsb' \
     ! -name 'modprobe.d' \
     ! -name 'openssh' \
     ! -name 'systemd' \
     ! -name 'terminfo' \
     ! -name 'udev' \
     ! -name 'x86_64-linux-gnu' \
       -exec rm -rfv {} \;
 
find usr/lib/systemd -mindepth 1 -maxdepth 1 -type d \
     ! -name 'network' \
       -exec rm -rfv {} \;
 
find usr/lib/x86_64-linux-gnu -mindepth 1 -maxdepth 1 -type d \
     ! -name 'security' \
       -exec rm -rfv {} \;
 
find usr/share -mindepth 1 -maxdepth 1 \
     ! -name 'debootstrap' \
       -exec rm -rfv {} \;

Воспользоваться содержимым распакованного ранее initrd и получить минимальный набор модулей/драйверов:

mv -fv boot/usr/lib/modules usr/lib/

Удалить /boot и «поломанные ссылки»:

rm -rfv boot
find . -xtype l -delete

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

echo "localhost" > etc/hostname
 
echo "echo 1 > /proc/sys/kernel/sysrq" > usr/bin/reboot
echo "echo b > /proc/sysrq-trigger"   >> usr/bin/reboot
 
echo "echo 1 > /proc/sys/kernel/sysrq" > usr/bin/poweroff
echo "echo o > /proc/sysrq-trigger"   >> usr/bin/poweroff
 
chmod a+x -v usr/bin/reboot usr/bin/poweroff

Выйти из подкаталога с файлами операционной системы:

cd ..

В результате текущий каталог /tmp/media будет содержать:

/tmp/media/os/*    - подкаталог с файлами операционной системы (которые нужно будет упаковать в архив "initrd")
/tmp/media/vmlinuz - ядро Linux

init

После загрузки ядра операционной системы первым запускаемым модулем, как правило, является /init
Минимальный пример, инициализирующий систему и стартующий командную оболочку (bash):

init
#!/bin/bash
 
#
# Disabling console flood
#
dmesg --console-off
 
#
# Creating VFS
#
mkdir -p /dev /proc /run /sys /tmp /var/lib/dhcp /var/lock
 
mount -t devtmpfs udev  /dev
mount -t proc     proc  /proc
mount -t tmpfs    tmpfs /run
mount -t sysfs    sysfs /sys
 
ln -sfn /proc/self/fd   /dev/fd
ln -sfn /proc/self/fd/0 /dev/stdin
ln -sfn /proc/self/fd/1 /dev/stdout
ln -sfn /proc/self/fd/2 /dev/stderr
 
mkdir /dev/pts
mount -t devpts devpts /dev/pts
 
/lib/systemd/systemd-udevd --daemon --resolve-names=never
udevadm trigger --action=add
udevadm settle
depmod
 
#
# Enabling Russian language support
#
setupcon
 
#
# Shell script execution
#
/usr/bin/bash
 
#
# Reboot
#
read -t 5 -p "Перезагрузка..."
reboot

Разместить этот скрипт в корне подкаталога с файлами будущего initrd и установить ему атрибут «исполняемый/executable»:

chmod a+x -v /tmp/media/os/init

initrd (упаковка)

Упаковать содержимое подкаталога с файлами операционной системы и получить результирующий initrd:

cd /tmp/media/os
find . | cpio -o -H newc -v | zstd -19 > ../initrd
cd ..

В итоге:

# du -h /tmp/media/{vmlinuz,initrd} 
15M	/tmp/media/vmlinuz
60M	/tmp/media/initrd

Проверить «работоспособность» этих файлов, загрузив с них виртуальную машину (через прямую загрузку ядра)

Локальный репозиторий

Если носитель предполагается использовать для инсталляции минимальной версии ОС, то достаточно сформировать репозиторий из установленных пакетов.

Загрузить все пакеты текущей (минимальной) системы:

cd /tmp/media
for p in $(apt list --installed | cut -d / -f 1 -s); do apt download $p; done

В /tmp/media/repo создать репозиторий и наполнить его загруженными пакетами:

apt install reprepro
 
mkdir -pv repo/conf
 
cat > repo/conf/distributions << EOF
Origin: Debian
Codename: 1.8_x86-64
Suite: stable
Version: 1.8
Architectures: amd64
Components: main non-free
EOF
 
reprepro -b repo export
reprepro -b repo includedeb 1.8_x86-64 ./*.deb
 
rm -rfv *.deb repo/{conf,db}

Создание ISO-образа

Подготовить структуру подкаталогов содержимого ISO-образа и сформировать гибридные загрузочные конфигурации:

cd /tmp/media
 
mkdir -pv iso/EFI/BOOT
cat > iso/EFI/BOOT/grub.cfg << EOF
set timeout=0
menuentry "setup" {
  linux  /isolinux/vmlinuz
  initrd /isolinux/initrd
}
EOF
 
mkdir -pv iso/isolinux
cat > iso/isolinux/isolinux.cfg << EOF
DEFAULT setup
LABEL setup
  KERNEL /isolinux/vmlinuz
  APPEND initrd=/isolinux/initrd
EOF
 
mv -fv vmlinuz initrd iso/isolinux/

Добыть некоторые SYSLINUX-файлы (потребуется расширенный репозиторий):

apt download grub-efi-amd64-bin isolinux syslinux-common
for p in *.deb; do dpkg -x $p .; rm -fv $p; done
for f in grubx64.efi isohdpfx.bin isolinux.bin ldlinux.c32; do find usr -name $f -exec mv -fv {} iso/isolinux \;; done
rm -rfv usr

Сформировать ESP-раздел:

apt install dosfstools
dd if=/dev/zero of=iso/isolinux/esp.img bs=5M count=1
mkfs.fat -F 12 iso/isolinux/esp.img
mount -v iso/isolinux/esp.img /mnt
mkdir -pv /mnt/EFI/BOOT
mv -fv iso/isolinux/grubx64.efi /mnt/EFI/BOOT/BOOTX64.EFI
umount -Rv /mnt

При необходимости, переместить созданный ранее репозиторий в подкаталог ISO-образа:

mv -fv repo iso

И, наконец, получить итоговый /tmp/media/setup.iso:

apt install xorriso
mv -fv iso/isolinux/isohdpfx.bin .
 
xorriso \
  -as mkisofs \
  -V "Setup CD/DVD/USB" \
  -o ./setup.iso \
  -isohybrid-mbr ./isohdpfx.bin \
  -c isolinux/boot.cat \
  -b isolinux/isolinux.bin \
  -no-emul-boot -boot-load-size 4 -boot-info-table \
  -eltorito-alt-boot \
  -e isolinux/esp.img \
  -no-emul-boot \
  -isohybrid-gpt-basdat \
  iso
# du -h /tmp/media/setup.iso
256M	/tmp/media/setup.iso

Использование ISO-образа

Запись на USB-накопитель:

lsblk
umount /dev/...
dd if=setup.iso of=/dev/...
sync

Настройка сети после загрузки:

# автоматически (DHCP)
dhclient -1 -v -w
 
# вручную
ls /sys/class/net
ip a add ...

Запуск SSH-сервера:

passwd
echo "PermitRootLogin yes" > /etc/ssh/sshd_config.d/99-PermitRootLogin.conf
mkdir -pv /run/sshd
sed -i '/parsec/d' /etc/pam.d/sshd
/sbin/sshd 

Доступ к репозиторию на носителе, а не в сети (для debootstrap):

mkdir -pv /setup
lsblk
mount /dev/... /setup
 
A=file:///setup/repo