Загружаем Fedora при помощи systemd-boot

В настоящее время для запуска большинства популярных дистрибутивов GNU/Linux применяется загрузчик Grub 2, однако это далеко не лучший вариант. В данной статье мы рассмотрим, как можно запускать ядра Linux напрямую при помощи EFIStub, а в качестве менеджера использовать systemd-boot.

Предупреждение

Внимание! Действия, описанные в статье, могут привести к полной неработоспособности системы, поэтому настоятельно рекомендуется сделать полную резервную копию всех данных на диске.

Описанные в статье действия вы выполняете исключительно свой страх и риск. Никто не может гарантировать отсутствия ошибок, а также нести какой-либо ответственности за любые потери, либо повреждение данных, оборудования и т.д.

Если вас полностью устраивает стандартный загрузчик Grub 2, то переходить на описанный в данной статье вариант не следует.

Введение

Все современные материнские платы поддерживают технологию загрузки UEFI Boot, а ядра Linux способны загружаться через EFIStub, поэтому необходимость в отдельном загрузчике теперь отсутствует.

К сожалению, напрямую работать с EFIStub ядрами достаточно сложно и неудобно, а также часто может приводить к возникновению различных проблем из-за отсутствия автоматизации, поэтому мы воспользуемся специально созданным для этой цели менеджером systemd-boot.

Данный компонент представляет собой небольшой предварительный загрузчик, лишь передающий управление ядру, а также менеджер EFIStub ядер, позволяющий легко управлять ими и загружать необходимое.

Шаг 1. Проверка конфигурации системы

Убедимся, что система установлена и загружена в UEFI режиме:

test -d /sys/firmware/efi && echo EFI || echo Legacy

Если ответ EFI, то проверим, чтобы диск, на котором установлена система, использовал GPT разметку (тип метки диска: gpt):

sudo fdisk -l /dev/sda

Если же ответы были Legacy или msdos, то на этом следует прекратить ибо система не поддерживает UEFI загрузку.

Т.к. systemd-boot не подписан цифровой подписью, зайдём в настройки UEFI Boot и полностью отключим технологию Secure Boot.

Шаг 2. Изменение конфигурации разделов

На данный момент systemd-boot умеет загружать лишь ядра, расположенные внутри служебного UEFI раздела (далее ESP), поэтому его размер должен быть не меньше 512 МБ (по умолчанию создаётся 200 МБ).

Воспользуемся утилитой GParted или любой другой для изменения размера раздела ESP до 512 МБ за счёт любого другого.

По стандарту данный раздел должен быть первым на диске с GPT разметкой, иметь файловую систему FAT32 (vfat), а также установленные флаги +boot +efi.

Шаг 3. Удаление Grub 2

Полностью удалим установленный в системе загрузчик Grub 2, предварительный загрузчик shim и не функционирующий в UEFI режиме memtest86+ (экранирование звёздочек символом обратного слэша обязательно):

sudo dnf remove grubby grub2\* shim\* memtest86\* --setopt protected_packages= --allowerasing

Очистим остатки Grub 2 (файлы конфигурации, темы, BLS):

sudo rm -rf /boot/grub2
sudo rm -rf /boot/loader

Начиная с этого момента и до завершения всего процесса, перезагружать систему не следует ни при каком условии!

Шаг 4. Настройка точки монтирования

Откроем файл /etc/fstab в текстовом редакторе:

sudoedit /etc/fstab

Убедимся, что точка монтирования ESP раздела задана корректно:

UUID=ABCD-0123 /boot/efi vfat umask=0077,shortname=winnt 0 2

Здесь ABCD-0123 — это UUID, который можно определить при помощи sudo blkid.

Добавим параметр монтирования umask=0077 (при отсутствии), т.к. файловая система FAT32 не поддерживает права доступа и любой пользователь может вносить любые изменения, что для нас не приемлемо.

Сохраним изменения в файле.

Шаг 5. Настройка параметров ядра

В данной конфигурации параметры ядра будут указаны в файле /etc/kernel/cmdline в формате обычной строки, разделённые пробелом:

cat /proc/cmdline | cut -d ' ' -f 2- | sudo tee /etc/kernel/cmdline
sudo chmod 644 /etc/kernel/cmdline

В данном примере будут автоматически использованы параметры текущего загруженного ядра из /proc/cmdline.

При необходимости внесём соответствующие правки:

sudoedit /etc/kernel/cmdline

Шаг 6. Установка systemd-boot

Установим systemd-boot в ESP:

sudo bootctl --path=/boot/efi install

Инициируем пересборку initrd ядра, а также сгенерируем новые файлы конфигурации:

sudo kernel-install add $(uname -r) /lib/modules/$(uname -r)/vmlinuz

Шаг 7. Перезагрузка системы

Проверим всё ли сделано верно и перезагрузим систему для применения изменений:

sudo systemctl reboot

Если всё было сделано верно, Fedora успешно загрузится при помощи EFIStub под управлением systemd-boot. В противном случае следует восстановить резервную копию, либо воспользоваться chroot с LiveUSB для решения возникших проблем.

Настройка параметров загрузки

Параметры загрузки допускается изменять в файле /boot/efi/loader/loader.conf:

sudoedit /boot/efi/loader/loader.conf

Литература

При написании статьи использовалась литература из следующих источников:

26 commentaries to post

  1. Т.к. systemd-boot не подписан цифровой подписью, зайдём в настройки UEFI Boot и полностью отключим технологию Secure Boot.

    Т.е. оно вообще не работает с включенным Secure Boot?

    1. Если подписать systemd-boot собственным удостоверяющим центром (CA), открытый ключ которого загрузить в список доверенных UEFI Secure Boot CA материнской платы, то всё будет работать и с включённым Secure Boot.

    2. Выглядит сложно. Пожалуй останусь на стоковом решении от федоры, а там может сами что-то придумают.

      1. Не думаю, что в ближайшее годы что-то изменится. По крайней мере пока systemd-boot не научится запускать ядра с отдельного /boot раздела.

        Описанный в статье способ работает на моём лэптопе уже более 2 месяцев.

  2. Сделал все до Шаг 6. Перезагрузка системы включительно. После перезагрузки: mount /new_root no filesystem type specified. You are now being dropped into an emergency shell. sh: can’t access tty; job control turned off [rootfs ]# Что не так?

    1. Загрузитесь с Live и проверьте содержимое файла /etc/fstab.

      Затем пересоберите образ initrd.

      1. Проверил. Пересобрал. Не помогло. Та же ошибка

        1. Нужно указать в файле /etc/kernel/cmdline правильные параметры ядра, например:

          root=UUID=XXXXX-XXX-XXX-XXXXX ro vconsole.font=latarcyrheb-sun16 rhgb quiet

          XXXXX-XXX-XXX-XXXXX — это UUID корневого раздела с Fedora.

          1. В общем разобрался, что нужно вручную создать entries и редактировать конфиг

      2. Уже пять раз все переделал,никаких ошибок, в итоге одно и тоже.

        1. У вас UEFI Secure Boot отключён? Он не будет работать без подписывания systemd-boot модуля собственным удостоверяющим центром.

        2. Нужно добавить параметры ядра в файл /etc/kernel/cmdline. Обновил статью.

  3. У меня в папке boot создается папка с различным набором символов в нутри которой папка с названием ядра. Так и должно быть?

    1. Да, это нормально. Случайный набор символов — это уникальный ID компьютера, присвоенный systemd.

  4. Доброго времени! Играюсь с ZFS на микрокоде UEFI. Вместо GRUB2 решил использовать systemd-boot. Некоторые моменты становятся проще:
    1) Перестали сыпать ошибки связанные с отсутствием поддержки метода компрессии
    2) Загрузчик изолирован одним диском (не обнаруживает ос на иных носителях, как по мне плюс в моих задачах)
    Но есть и не совсем приятные моменты
    1) Нужно пересобирать модули ZFS и микроядро для загрузчика при обновлении версии ядра
    DKMS спасает лишь от части. Все равно приходится пинать сборку модулей и повторно собирать initrd и linux под systemd-boot.
    Данные процессы вообще поддаются автоматизации???

    1. С dkms всё всегда было очень плохо, поэтому рекомендуется применять akmods, собирающий полноценные модули ядра в виде RPM пакетов с правильными скриптлетами, обновляющими initrd.

  5. Идея в целом интересная с systemd-boot, но во первых? он не доведен до ума, во вторых остается не удел огромный парк компьютеров без uefi. Так что пока лучшим все таки будет grub2.

    1. Железо без UEFI не выпускается с 2012 года. К тому же legacy boot сейчас поддерживается по остаточному принципу. Настоятельно рекомендуется переходить на нативный UEFI boot.

      systemd-boot — это не загрузчик, а менеджер EFIStub. Его задача — это прописывать в NVRAM параметры ядер и передавать управление на них. Весь остальной процесс загрузки уже выполняет само ядро.

      Я больше полугода использую systemd-boot, подписанный своим CA в режиме Secure Boot. Полёт нормальный.

      1. А как в такой конфигурации бороться с возможностью подмены/модификации initrd? Secure Boot от этого никак не защитит, systemd-boot тоже вряд ли поможет.

        1. Т.к. systemd-boot не является классическим загрузчиком, в нём нет поддержки сторонних ФС и верификации initrd по отсоединённой цифровой подписи, как например в GRUB 2.

          Однако, на мой взгляд, это не слишком большая проблема, т.к. если у злоумышленника есть физический доступ к ПК, он легко сможет загрузить любой код, т.к. существует как минимум два предзагрузчика, подписанные ЭЦП Microsoft, которой доверяет любое железо, например shim.

          При помощи подписанного предзагрузчика уже можно однократно одобрить любой сторонний CA и загрузить всё, что угодно.

          Этим же способом обходится и вариант с зашифрованным LUKS разделом /boot, т.к. существует возможность подмены обычного GRUB 2 на модифицированный, который например сохранит введённый пароль разблокировки.

          Решение — полное удаление всех предустановленных производителем ключей UEFI Secure Boot. Однако работает оно далеко не на каждом устройстве, т.к. в некоторых моделях ключи Microsoft удалить попросту невозможно.

          Это действие потребует ручной подписи своим собственным удостоверяющим центром прошивок всех устройств, работающих в UEFI на ранней стадии загрузки, например VBIOS видеокарт, а также сетевой карты (если нужна возможность загрузки по сети).

          1. Не понимаю, как указанное решение может помочь от подмены initrd даже в случае, если shim и GRUB отсутствуют в цепи загрузки.

            Если удалить ключи Microsoft и подписать systemd-boot (а так же все необходимые прошивки) собственным CA, то злоумышленник по-прежнему сможет подменить initrd и встроить свой код в цепь загрузки.

            Единственным решением вижу объединить kernel image и initrd в один efi (dracut —uefi), который уже подписывать. Именно такой способ указан в Boot Loader Specification для поддержки UEFI Secure Boot. Но в таком случае теряется вся необходимость и плюсы автоматизации от systemd-boot.

            Не могу найти решение, которое сочетало бы удобство systemd-boot с защитой initrd. Было бы неплохо увидить на сайте статью по настройке Secure Boot в Fedora.

          2. В случае использования systemd-boot от подмены initrd к сожалению ничего не защитит. Поэтому мы и рекомендуем монтировать ESP раздел с доступом только для суперпользователя, т.к. FAT32 не поддерживает установку прав доступа.

            По-настоящему защитить initrd можно лишь с использованием GRUB 2 с отсоединёнными цифровыми подписями после удаления всех предустановленных ключей производителя и Microsoft.

            Статья о тонкой настройке Secure Boot с собственными ключами есть в планах.

          3. И еще интересно, как Вы подписываете ядра при их обновлении.
            Есть идея добавить скрипт в /etc/kernel/install.d, но вдруг есть более элегантное решение?

          4. У меня ядро и внешние модули NVIDIA автоматически подписываются скриптом zz-sign.sh из каталога /etc/kernel/install.d.

          5. Спасибо за ответ, надеялся, что все-таки есть готовое и простое решение.
            Решил все-таки соединять initrd c ядром и подписывать своими ключами для Secure Boot. Dracut из коробки умеет генерировать такие образы, подписывать их и класть в /EFI/Linux, а systemd-boot их находит и видит. Это соответствует Boot Loader Specification, и, вроде как, разрабы systemd рекомендуют именно так защищать initrd.

          6. Было бы очень интересно почитать о тонкой настройке Secure Boot с собственными ключами.

Обсуждение закрыто.