Systemd-boot и UKI (unified kernel image) — практичный способ сделать загрузку Linux более предсказуемой: ядро, initrd, командная строка и метаданные хранятся в одном EFI-файле. Для админа на VDS это означает меньше «магии» вокруг initramfs, меньше рассинхрона конфигов и понятный путь к Secure Boot: подписываем один артефакт на каждое ядро.
Ниже — пошаговая схема для Debian/Ubuntu, ориентированная на сервер без физической консоли. Разберём, что такое sd-stub, как UKI живёт в ESP, как обновлять kernel/initrd без сюрпризов и где чаще всего ломают систему.
Что такое UKI и почему это удобно на VDS
UKI — единый исполняемый EFI-образ (PE/COFF), внутри которого упакованы:
- ядро Linux (
vmlinuz); initrd/initramfs;- командная строка ядра (kernel cmdline);
- опционально микрокод CPU;
- опционально OS-метаданные (ID, версия, build-id);
- возможность подписать всё как один файл для Secure Boot.
Для загрузчика это модель «всё-в-одном»: systemd-boot (через bootctl) видит EFI-файлы в ESP и предлагает их в меню. Не нужно поддерживать отдельные записи «ядро тут, initrd там», которые легко рассинхронизировать при обновлении.
На сервере без удобной консоли ценится предсказуемость: UKI снижает шанс получить ситуацию «ядро обновилось, а initrd/параметры — нет».
Как это связано с Secure Boot
Secure Boot в идеале требует, чтобы загрузчик и то, что он запускает, было подписано доверенным ключом. В классической схеме с отдельными vmlinuz и initrd цепочка сложнее: больше объектов, больше мест, где можно ошибиться путём или версией.
UKI упрощает задачу: мы подписываем один EFI-файл на каждую версию ядра. Сам systemd-boot подписывается отдельно. В итоге «цепочка доверия» короче и проще в эксплуатации.
Важно: на многих VDS Secure Boot может быть недоступен на уровне виртуальной прошивки UEFI, или провайдер не даёт им управлять. Но конфигурация «Secure Boot-ready» всё равно полезна: вы выстраиваете процесс сборки/подписи артефактов, и при появлении Secure Boot не придётся переделывать весь boot-процесс.

Проверяем UEFI, ESP и готовим безопасный план отката
Перед изменениями убедитесь, что система действительно загружена через UEFI (иначе systemd-boot не заработает):
test -d /sys/firmware/efi && echo UEFI || echo BIOS
Проверьте, где смонтирован ESP (EFI System Partition). Обычно это /boot/efi, иногда /efi или /boot:
findmnt -no SOURCE,TARGET,FSTYPE,OPTIONS /boot/efi
ls -la /boot/efi/EFI
Если ESP не смонтирован — смонтируйте и добавьте в /etc/fstab. UUID берите через blkid.
На сервере «без рук» держите страховки:
- не удаляйте старый загрузчик/старые записи, пока не подтвердили успешную перезагрузку;
- по возможности обеспечьте out-of-band доступ (serial/VNC в панели);
- всегда держите минимум два загрузочных варианта: «текущий рабочий» и «новый тестовый».
Устанавливаем systemd-boot и понимаем структуру ESP
Systemd-boot — UEFI-загрузчик, управляется утилитой bootctl. Он читает конфиги в ESP (обычно /boot/efi/loader) и подхватывает UKI из стандартного каталога EFI/Linux.
Базовые команды:
bootctl status
bootctl install
bootctl status
Полезно понимать, что именно появится в ESP:
EFI/systemd/systemd-bootx64.efi(или другой arch) — сам загрузчик;loader/loader.conf— глобальные настройки;EFI/Linux/— стандартное место для UKI.
Минимальный loader.conf (без интерактивного редактирования cmdline в меню):
cat > /boot/efi/loader/loader.conf <<'EOF'
default @saved
timeout 3
console-mode max
editor no
EOF
Опция editor no — небольшой, но полезный hardening: в меню нельзя интерактивно править параметры ядра (актуально, если у кого-то появится доступ к консоли).
Из чего состоит UKI: sd-stub, initrd и cmdline
В экосистеме systemd ключевой компонент — sd-stub. Это EFI-«обёртка», которая запускает Linux-ядро и передаёт ему встроенный initrd и командную строку. UKI — это по сути EFI-файл с «приклеенными» секциями.
Сборку UKI обычно делает ukify (часть systemd в современных релизах). Проверка наличия:
ukify --help
Если команды нет, проверьте версию systemd:
systemd --version
На старых Debian/Ubuntu может понадобиться выбрать другой маршрут (например, генерация UKI средствами вашей initramfs-системы). Но базовая эксплуатационная логика всё равно одна: фиксируем cmdline, собираем UKI в ESP, держим минимум 2 версии для отката.
Готовим cmdline для UKI (самое важное на VDS)
В GRUB параметры часто лежат в /etc/default/grub. Для UKI удобнее вынести cmdline в отдельный файл, чтобы сборка была воспроизводимой. Главная задача — корректно указать root и (при необходимости) параметры консоли.
Сначала выясните, на чём живёт корень:
findmnt -no SOURCE,FSTYPE,OPTIONS /
blkid
Надёжнее всего использовать root=UUID=.... Создайте файл:
mkdir -p /etc/kernel
cat > /etc/kernel/cmdline <<'EOF'
root=UUID=PUT-YOUR-ROOT-UUID-HERE ro
EOF
Если у вас используется serial-консоль, добавьте явные console= (значения зависят от платформы/провайдера):
cat > /etc/kernel/cmdline <<'EOF'
root=UUID=PUT-YOUR-ROOT-UUID-HERE ro console=tty0 console=ttyS0,115200n8
EOF
Не копируйте параметры вслепую: лишняя или неверная console= может «спрятать» вывод на ожидаемой консоли и усложнить диагностику.
Собираем первый UKI вручную через ukify
Базовый рецепт: берём текущее ядро и текущий initramfs, собираем EFI-файл в /boot/efi/EFI/Linux/. На Debian/Ubuntu пути обычно такие:
- ядро:
/boot/vmlinuz-<version>; - initrd:
/boot/initrd.img-<version>.
Узнайте текущую версию ядра:
uname -r
Соберите UKI:
mkdir -p /boot/efi/EFI/Linux
ukify build --linux=/boot/vmlinuz-$(uname -r) --initrd=/boot/initrd.img-$(uname -r) --cmdline=@/etc/kernel/cmdline --output=/boot/efi/EFI/Linux/uki-$(uname -r).efi
Systemd-boot обычно автоматически подхватывает UKI из EFI/Linux. Проверьте список:
bootctl list
Если записи нет, проверьте типовые причины:
- ESP действительно смонтирован (и вы пишете именно в него);
- архитектура совпадает (x64/aa64);
- файл реально лежит в
/boot/efi/EFI/Linux/; - systemd-boot установлен в ту же ESP, откуда грузится система.
Обновления ядра без сюрпризов: 2–3 UKI, место в ESP и уборка
После установки нового kernel появляется новая пара vmlinuz и initrd. Если UKI собираете вручную (или полуавтоматически), заведите дисциплину:
- после установки нового ядра — собрать новый UKI;
- старый UKI не удалять до успешной перезагрузки;
- держать лимит на количество UKI (ESP часто небольшая).
Практичный минимум для сервера: хранить 2–3 последних UKI, именовать по версии ядра, а после подтверждения работоспособности нового ядра — удалять самое старое ядро штатными средствами ОС, а уже затем чистить соответствующий UKI.
Контролируйте свободное место в ESP:
df -h /boot/efi
Если ESP переполнена, UKI может не записаться целиком или сборка упадёт, а вы заметите это только после перезагрузки. Это один из самых неприятных классов ошибок на VDS.
Если вы настраиваете сервер «в долгую», заранее продумайте разметку: иногда имеет смысл выделить ESP побольше. Отдельно про практику работы с дисками и ФС на VPS/VDS у нас есть материал: выбор и настройка ext4/XFS под VDS.

Автоматизация: безопасный хук на kernel update
На Debian/Ubuntu обновление ядра запускает хуки. Ваша автоматизация должна:
- собирать UKI для конкретной версии ядра, которую только что установили;
- не ломать загрузку, если сборка не удалась (старый UKI должен остаться);
- давать понятный лог результата.
Ниже — пример скрипта, который собирает UKI для заданной версии ядра. Его удобно вызывать из вашего hook-механизма (конкретный путь хука зависит от дистрибутива и того, как у вас устроены обновления ядра).
cat > /usr/local/sbin/uki-build-one <<'EOF'
#!/bin/sh
set -eu
kver="$1"
esp="/boot/efi"
cmdline="/etc/kernel/cmdline"
linux="/boot/vmlinuz-$kver"
initrd="/boot/initrd.img-$kver"
out="$esp/EFI/Linux/uki-$kver.efi"
mkdir -p "$esp/EFI/Linux"
ukify build --linux="$linux" --initrd="$initrd" --cmdline=@"$cmdline" --output="$out"
EOF
chmod +x /usr/local/sbin/uki-build-one
Перед подключением к хукам прогоните вручную (например, для текущего ядра), чтобы убедиться, что CLI ukify в вашей версии systemd понимает --cmdline=@/path:
/usr/local/sbin/uki-build-one $(uname -r)
Дальше подключайте к хукам так, чтобы сбой сборки UKI не прерывал установку пакета ядра и не удалял старые артефакты. На проде лучше иметь отдельный мониторинг на свободное место ESP и на факт появления нового UKI после kernel update.
Secure Boot-ready на практике: ключи, подпись и рутина
Чтобы UKI был «готов к Secure Boot», нужен процесс подписи:
- ключи (генерация, хранение, ротация);
- подпись
systemd-boot*.efiи каждогоuki-*.efi; - автоподпись нового UKI при обновлении ядра;
- контроль того, что именно вы подписываете (исходники/артефакты/хэши).
Главный практический вопрос на VDS: где хранить приватный ключ подписи. Держать его на самом сервере удобно, но рискованно: компрометация ОС означает компрометацию ключа. Более безопасная схема — подписывать артефакты в CI/на отдельной машине и доставлять на сервер уже подписанные EFI-файлы.
Secure Boot — это не «галочка», а процесс управления ключами и артефактами. UKI просто делает этот процесс проще и прозрачнее.
Даже если Secure Boot недоступен у провайдера, вы можете выстроить «готовность»: единый каталог EFI/Linux, единый файл cmdline, воспроизводимая сборка UKI и привычка хранить 2–3 версии для отката. А когда потребуется защищать внешний периметр, уместно добавить SSL-сертификаты для сервисов и интерфейсов управления (это уже другой слой безопасности, но в продакшене обычно нужен).
Типовые проблемы и диагностика
systemd-boot не появляется после install
Проверьте, что вы ставите в ту ESP, с которой реально загружается UEFI. На некоторых VDS бывают несколько дисков/разделов, и «правильная» ESP не та, что примонтирована в /boot/efi. Начните с:
bootctl status
Если доступ к переменным UEFI разрешён, посмотрите записи загрузки:
efibootmgr -v
Если efibootmgr не работает (ограничения прошивки/гипервизора), ориентируйтесь на фактическое содержимое ESP и на то, как был установлен исходный образ ОС.
UKI лежит в ESP, но не виден в меню
Проверьте путь EFI/Linux, расширение .efi и то, что вы используете именно systemd-boot. Быстрая проверка:
bootctl list
Если UKI не подхватился, временно можно создать явный entry-файл, но в большинстве случаев проще привести расположение UKI к стандартному каталогу EFI/Linux и пересобрать образ.
После обновления kernel система не грузится
Чаще всего виноваты:
- неверный
root=UUID=...в cmdline; - UKI собран с «чужим»
initrd(перепутали версию); - ESP переполнена и UKI не записался корректно;
- параметры консоли настроены так, что вывод «уходит не туда».
Именно поэтому правило «не удалять старый UKI до успешной перезагрузки» — не бюрократия, а обязательная страховка.
Рабочий регламент для продакшена
Перед миграцией убедиться в UEFI и корректном ESP.
Установить systemd-boot через
bootctl installи настроитьloader.conf.Зафиксировать cmdline в
/etc/kernel/cmdline(root по UUID, при необходимости — serial console).Собрать UKI для текущего ядра, проверить
bootctl list.Сделать тестовую перезагрузку в окно работ и убедиться, что есть путь отката.
Добавить автоматизацию сборки UKI при kernel update с «мягким» fail.
По мере взросления процесса — добавить подпись UKI и процессы управления ключами.
Итоги
Systemd-boot + UKI превращают загрузку Linux в понятный набор артефактов: один EFI-файл на ядро, единый cmdline и прозрачная схема обновлений. На VDS это особенно полезно: цена ошибки при kernel update выше, а доступ к консоли может быть ограничен.
Если аккуратно организовать хранение UKI в ESP, дисциплину обновлений и (по возможности) подпись, вы получаете «Secure Boot-ready» подход, который проще поддерживать, автоматизировать и проверять.


