Moving from GRUB to systemd boot

Since there is no easier way that I have found, I am trying to change GRUB boot to systemd boot in a virtual machine. I know that the hypervisor configuration has to utilize UEFI instead of default Legacy. Then Tianocore initiates the KVM boot. Don’t know what is omitted from the instructions or or needs to be updated for 38. I’m adding screenshots to see if anyone can figure out what is missing.


Screenshot from 2023-05-18 15-05-16

1 Like

Rather than creating the directory manually, it might be better to use bootctl’s --make-entry-directory=yes option when running bootctl install.

Also, sudo dnf reinstall kernel-core shouldn’t be necessary at the end.

Also, there is an os-prober package that is actually part of GRUB (even through it doesn’t have the grub2- prefix). You might want to remove that too.

Also, since you are removing grubby, you might want to also remove kexec-tools. The kexec-tools package adds /usr/lib/kernel/install.d/92-crashkernel.install which calls /usr/bin/kdumpctl which calls grubby and it will generate an error message whenever a new kernel is installed.

Don’t remove kexec-tools. See the below reply.

Step zero:

Disable secure boot.

kexec-tools are used for systemctl kexec. So removing them is not good advice in general. The packaging in kexec-tools needs to be fixed to silence that stupid warning.

EDIT: https://bugzilla.redhat.com/show_bug.cgi?id=2121912 was opened on 2022-08-27. No activity from the package maintainers.

1 Like

I’m not sure if it’s worth uninstalling grub2. This makes the whole process more risky. It should be fine if it stays installed but unused.

1 Like

I have done this conversion a few times, and always retained grub2 installed until I have verified that I can boot the system with sd-boot.

I had recommended removing grub2 in some older threads. But that was because, at the time, it really wouldn’t work with sd-boot. It would alter the drop-in configs under loader/entries such that there were variables in the kernel parameters that sd-boot wouldn’t be able to process.

Also, I like to “merge” the two bootloader partitions and have just one mounted at /boot. But grub2 didn’t get along with that configuration because it would create a symlink under /boot. I believe that has since been fixed. But I’ve long since stopped using grub2, so I don’t really know for sure.

I just tried in a VM.
Have a working grub configuration at hand, and a live usb.
The ESP should be mounted as /efi, not /boot/efi and should have enough space to accomodate kernels.

type: bootctl --make-entry-directoy=yes install
type: kernel-install add `uname -r` /boot/vmlinuz…
type: bootctl set-timeout 10

type bootctl and check especially that the kernel is in place, so under
/efi/machineid/version/linux and /efi/machineid/version/initrd.

Default Boot Loader Entry:
         type: Boot Loader Specification Type #1 (.conf)
        title: Fedora Linux 38 
           id: e6be5b4b3e824ea6a8244e6a741efe3e-6.3.3-200.fc38.x86_64.conf
       source: /efi//loader/entries/e6be5b4b3e824ea6a8244e6a741efe3e-6.3.3-200.fc38.x86_64.conf
     sort-key: fedora
      version: 6.3.3-200.fc38.x86_64
   machine-id: e6be5b4b3e824ea6a8244e6a741efe3e
        linux: /efi//e6be5b4b3e824ea6a8244e6a741efe3e/6.3.3-200.fc38.x86_64/linux
       initrd: /efi//e6be5b4b3e824ea6a8244e6a741efe3e/6.3.3-200.fc38.x86_64/initrd
      options: root=UUID=8259c2bc-d858-4576-bc3e-006eb56dc0f9 ro rhgb quiet systemd.machine_id=e6be5b4b3e824ea6a8244e6a741efe3e

There are still symlinks there

lrwxrwxrwx. 1 root root       46 May 15 06:26 symvers-6.2.15-300.fc38.x86_64.gz -> /lib/modules/6.2.15-300.fc38.x86_64/symvers.gz

I am not sure if anything needs them, though.

Yes, but that symlink is not part of the grub2 package. It is being added by the kernel package and it was just introduced in the 6.x kernel packages.

redhat: create /boot symvers link if it doesn’t exist (Jan Stancek)

It is extremely annoying that GRUB finally stopped trying to make symlinks under /boot and someone added a new one shortly thereafter. I even submitted a PR to fix that so it would copy that file to /boot instead of creating a symlink (the file is only 177KB). But, to date, no one has merged my pull request.

copy instead of symlink /boot/symvers-*

According to “0pointer.net: Linux Boot Partitions and How to Set Them Up”, a /boot partition formatted with FAT should be allowed.

Excerpt from “Linux Boot Partitions and How to Set Them Up”:

  • Whenever possible, only have one boot partition, not two. On EFI systems, make it the ESP. On non-EFI systems use an XBOOTLDR partition instead (see below). Only have both in the case where a Linux OS is installed on a system that already contains an OS with an ESP that is too small to carry sufficient kernels/initrds. When a system contains a XBOOTLDR partition put kernels/initrd on that, otherwise the ESP.

  • Use vFAT for both partitions, it’s the only thing universally understood among relevant firmwares and Linux. It’s simple enough to be useful for untrusted storage. Or to say this differently: writing a file system driver that is not easily vulnerable to rogue disk images is much easier for vFAT than for let’s say btrfs. – But the choice of vFAT implies some care needs to be taken to address the data safety issues it brings, see below.

Before GRUB, when syslinux was a popular bootloader, it was common to format /boot with a FAT filesystem. (People could then put small DOS binaries such as firmware updates on their /boot and chainload them with syslinux.)

It was never required that /boot be a POSIX filesystem. Please do not introduce any such new requirement!

The symbolic link is created by the shell file /usr/lib/kernel/install.d/20-grub.install. If you convert the kernel-core rpm file to cpio and unpack it you can see that the symlink does not come from the rpm file.

So blame goes back to grub2.

Hmm, I don’t have that file.

$ ls /usr/lib/kernel/install.d/20-grub.install
"/usr/lib/kernel/install.d/20-grub.install": No such file or directory (os error 2)

I don’t even have grub2 installed.

$ rpm -q grub2
package grub2 is not installed

I still see attempts to create that symlink though.

...
ln: failed to create symbolic link '/boot/symvers-6.2.15-200.fc37.x86_64.gz': Operation not permitted
restorecon: lstat(/boot/symvers-6.2.15-200.fc37.x86_64.gz) failed: No such file or directory
warning: %posttrans(kernel-core-6.2.15-200.fc37.x86_64) scriptlet failed, exit status 255

Error in POSTTRANS scriptlet in rpm package kernel-core
...

So, are you sure?

I think the reason you aren’t seeing it when extracting the RPM archive with cpio is because it is being created in a post transaction script.

But maybe there are multiple packages trying to create that symlink?

There is. When runing rpm -q --scripts kernel-core-6.2.15-300.fc38.x86_64 you get this (and more).

posttrans scriptlet (using /bin/sh):
rm -f /var/lib/rpm-state/kernel/installing_core_6.2.15-300.fc38.x86_64
/bin/kernel-install add 6.2.15-300.fc38.x86_64 /lib/modules/6.2.15-300.fc38.x86_64/vmlinuz || exit $?
if [[ ! -e "/boot/symvers-6.2.15-300.fc38.x86_64.gz" ]]; then
    ln -s "/lib/modules/6.2.15-300.fc38.x86_64/symvers.gz" "/boot/symvers-6.2.15-300.fc38.x86_64.gz"
    command -v restorecon &>/dev/null && restorecon "/boot/symvers-6.2.15-300.fc38.x86_64.gz" 
fi

Why that was added, is not stated and does not make sense in Fedora as grub2 would take care of creating this symbolic link. At least refer to a readable Bugzilla report.

sudo mkdir /usr/lib/systemd/boot/efi
is required before
bootctl install --make-entry-directory=yes
and I am not sure why none of the directions mention that since it is needed.

In my latest attempt, I did not reinstall kernel core. I don’t know how to remove os-prober. I did not remove kexec-tools or grub.

When I tried
kernel-install add 'uname r`/boot/vmlinuz…
then there was an error message like this
grub2mkrelpath: error: failed to get canonical path (…6.2.9-300fc38…) dirname missing operand

So I ignored that because the advice above appears equivocal to me. Doesn’t seem mission critical. Then I did a reboot and boot was successful but I don’t know how to verify that the boot was a systemd boot and not a grub boot. What information should I be looking for in sudo bootctl?

Refering to h.janssen, bootctl does not return the same information you have listed to check kernel (6.2.9-300). It has a list of several red x and other info. How do I check “default boot loader entry” like you did?

Also, I will mention that the outcome, the end result I am looking for is to cryptenroll systemd boot with Yubikey. To test that in a VM first, I need to know how to passthrough USB by editing XML in KVM. I also need to know how to do that to test the dracut Yubikey method which I think eliminates the need for systemd boot. You might reply to other threads I have posted about this or here if you have answers. Ultimately, I am grub/systemd boot agnostic since from what I have read about the varying methods, there aren’t obvious reasons to favor one boot method over the other. Admittedly, that’s what part of this discussion is about.

Thanks for the information.

I use systemd boot. But I’ve never made that directory. I’ve always mounted /boot at the root of my filesystem hierarchy.

Do you have a way of opting for systemd boot at installation?

After I followed the steps I could piece together from the replies, and entered
bootctl install --make-entry-directory=yes
the output is
“Failed to open boot loader directory usr/lib/systemd/boot/efi”
so I had to make it and then it installs.

The third screenshot of gparted I posted above is the sort of hierarchy you would expect, isn’t it? That’s how the directions from kowalski7 seemed to think best.

If I remember correctly, when I ran bootctl, I also specified the path to the ESP by adding --esp-path=/boot. Maybe that parameter is required? I set my Fedora Linux installs up in a highly-customized way. So I may not be much help with answering how things should be. FWIW, this is what those parts of the PC I’m currently working from look like.

[/root]# sgdisk -p /dev/sda
Disk /dev/sda: 1875385008 sectors, 894.3 GiB
Model: SanDisk Ultra II
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): 91174D70-39C1-47F7-B809-CB406AAA5490
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 1875384974
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         2099199   1024.0 MiB  EF00  boot@a
   2         2099200      1875384974   893.3 GiB   8304  pool.a
[/root]# sgdisk -p /dev/sdb
Disk /dev/sdb: 1875385008 sectors, 894.3 GiB
Model: SanDisk Ultra II
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): FD015AD5-3CA0-45D8-A155-5394795F2097
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 1875384974
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         2099199   1024.0 MiB  EF00  boot@b
   2         2099200      1875384974   893.3 GiB   8304  pool.b
[/root]# tree /boot
/boot
├── 8c76d196c474411a85814e376f2c30c4
│   ├── 6.1.18-200.fc37.x86_64
│   │   ├── initrd
│   │   └── linux
│   ├── 6.1.8-200.fc37.x86_64
│   │   ├── initrd
│   │   └── linux
│   ├── 6.2.10-200.fc37.x86_64
│   │   ├── initrd
│   │   └── linux
│   ├── 6.2.12-200.fc37.x86_64
│   │   ├── initrd
│   │   └── linux
│   ├── 6.2.14-200.fc37.x86_64
│   │   ├── initrd
│   │   └── linux
│   └── 6.2.15-200.fc37.x86_64
│       ├── initrd
│       └── linux
├── efi
│   ├── boot
│   │   └── bootx64.efi
│   ├── efi
│   │   ├── boot
│   │   └── fedora
│   ├── syslinux
│   │   ├── ldlinux.e64
│   │   ├── libcom32.c32
│   │   ├── libutil.c32
│   │   ├── syslinux.efi
│   │   └── vesamenu.c32
│   └── systemd
│       └── systemd-bootx64.efi
├── extlinux
│   ├── cat.c32
│   ├── chain.c32
│   ├── cmd.c32
│   ├── cmenu.c32
│   ├── config.c32
│   ├── cptime.c32
│   ├── cpu.c32
│   ├── cpuid.c32
│   ├── cpuidtest.c32
│   ├── debug.c32
│   ├── dhcp.c32
│   ├── dir.c32
│   ├── disk.c32
│   ├── dmi.c32
│   ├── dmitest.c32
│   ├── elf.c32
│   ├── ethersel.c32
│   ├── gfxboot.c32
│   ├── gpxecmd.c32
│   ├── hdt.c32
│   ├── hexdump.c32
│   ├── host.c32
│   ├── ifcpu64.c32
│   ├── ifcpu.c32
│   ├── ifmemdsk.c32
│   ├── ifplop.c32
│   ├── kbdmap.c32
│   ├── kontron_wdt.c32
│   ├── ldlinux.c32
│   ├── lfs.c32
│   ├── libcom32.c32
│   ├── libgpl.c32
│   ├── liblua.c32
│   ├── libmenu.c32
│   ├── libutil.c32
│   ├── linux.c32
│   ├── ls.c32
│   ├── lua.c32
│   ├── mboot.c32
│   ├── memdisk
│   ├── meminfo.c32
│   ├── menu.c32
│   ├── pci.c32
│   ├── pcitest.c32
│   ├── pmload.c32
│   ├── poweroff.c32
│   ├── prdhcp.c32
│   ├── pwd.c32
│   ├── pxechn.c32
│   ├── reboot.c32
│   ├── rosh.c32
│   ├── sanboot.c32
│   ├── sdi.c32
│   ├── sysdump.c32
│   ├── syslinux.c32
│   ├── vesa.c32
│   ├── vesainfo.c32
│   ├── vesamenu.c32
│   ├── vpdtest.c32
│   ├── whichsys.c32
│   └── zzjson.c32
├── IMAGEO2H.rom
├── loader
│   ├── entries
│   │   ├── 8c76d196c474411a85814e376f2c30c4-6.1.18-200.fc37.x86_64.conf
│   │   ├── 8c76d196c474411a85814e376f2c30c4-6.1.8-200.fc37.x86_64.conf
│   │   ├── 8c76d196c474411a85814e376f2c30c4-6.2.10-200.fc37.x86_64.conf
│   │   ├── 8c76d196c474411a85814e376f2c30c4-6.2.12-200.fc37.x86_64.conf
│   │   ├── 8c76d196c474411a85814e376f2c30c4-6.2.14-200.fc37.x86_64.conf
│   │   └── 8c76d196c474411a85814e376f2c30c4-6.2.15-200.fc37.x86_64.conf
│   ├── loader.conf
│   └── random-seed
├── O2H3X.rom
└── syslinux.cfg

18 directories, 91 files
[/root]# 

(Yes, I have this system configured to use the syslinux bootloader.)

/usr/lib/systemd/boot/efi and its contents are provided by the package systemd-boot-unsigned. If that package is not installed, you will need to install it.

Not too long ago systemd-boot-unsigned was split out from the systemd package and may not be installed by default.

Only if you chose to mount the ESP partition on /boot. It is easier to mount the ESP on /efi, and then that would be automatically detected. Also when you haven’t remove grub2 yet.

It will auto-detect /boot as long as /efi doesn’t exist. Below are the lines from the kernel-install script that show what order it searches for the ESP.

if [ -n "$BOOT_ROOT" ]; then
    # If this was already configured, don't try to guess
    BOOT_ROOT_SEARCH="$BOOT_ROOT"
else
    BOOT_ROOT_SEARCH="/efi /boot /boot/efi"
fi

Oh, yeah, I think I get what you are saying. @system76g6: You need to have a properly-formatted ESP mounted at /efi or /boot before you run bootctl install.