[Tutorial] Convert to systemd-boot

Updated 12/22/2022 to match the method used for installing systemd-boot in Cassini and later ISOs

Several people have asked me for a tutorial on how to convert an existing EndeavourOS install to systemd-boot, an alternative to grub.

The first question is who should install systemd-boot. From my perspective, here are the reasons to install systemd-boot

  • systemd-boot is less complicated than grub. It uses simple text based config files which only contain a few lines
  • It is less prone to breakage, easy to troubleshoot and doesn’t require any process to rebuild config files

On the other hand, simplicity comes with limitations

  • It only supports UEFI
  • It doesn’t have all the advanced features of grub
  • Your kernels must be kept inside your efi partition so it needs to be large enough to hold them all
  • Because of the above, booting directly from btrfs snapshots is not easily achieved

To be clear, systemd-boot isn’t for everyone. However, it offers a simple solution that is basically maintenance free.

Systemd-boot is quite simple to install. However, because I am going to be presenting two options for managing it, this tutorial will be quite a bit longer than the actual process. It generally should only take 5-10 minutes to convert your setup.


  • It is of critical importance that you not stop halfway or reboot during the process. Once you start converting your system you need to finish it. If you don’t, your system won’t boot.
  • If you get an error, don’t ignore it and keep going. Stop and fix the error or ask for help.
  • I strongly recommend updating your system and rebooting before you start this process.
  • Whenever you mess with your bootloader, it is a good idea to have a copy of the ISO ready to boot off of in the event something goes wrong.
  • If you use LUKS on any partitions please see the section at the bottom on special handling for LUKS

With that, lets get started.

Install systemd-boot

The first thing is to ensure that your efi partition is large enough. Run the command du -sh /boot and compare that to the size of your EFI partition. Your EFI partition needs to be larger than the output of the command. If it is, you can continue. If not, you need to enlarge the partition before going any further.

Next we need to remove grub:

sudo pacman -Rc grub

Next, we can cleanup /boot to prepare for the changes

sudo rm -r /boot/efi /boot/grub /boot/initramfs* /boot/vmlinuz*

Now we remount the EFI partition to /efi.

sudo mkdir /efi
efidevice=$(findmnt /boot/efi -no SOURCE) # save the efi partition location
sudo umount /boot/efi
sudo mount ${efidevice} /efi
# To make the mount change permanent, edit `/etc/fstab` and change where it reads `/boot/efi` to `/efi`

Next we can install systemd-boot

sudo bootctl install
# Edit the file `/efi/loader/loader.conf` and uncomment the "timeout" line.

Technically speaking, you have now successfully installed systemd-boot. Congrats!

Of course, since we haven’t added any boot entries or other config, if you reboot now you will be sitting at a screen where the only option is to enter your firmware interface. :scream:

From here, we need to configure the system to manage our boot entries and get everything setup.

First install the package that configures kernel-install for EndeavourOS. Either install kernel-install-mkinitcpio(AUR) or kernel-install-for-dracut(repo) depending on if you are using mkinitcpio or dracut. Both packages provide the same functionality and differ only in their support of mknitcpio or dracut.

sudo pacman -S kernel-install-for-dracut

If you have eos-dracut installed, you should remove it:

sudo pacman -R eos-dracut

Now we need to get your machine ready for kernel-install and run kernel-install on all your installed kernels. You can either save the below as a script and run it or run the commands one at a time. If you run it manually, the mkdir and kernel-install will need to be run as with sudo. Otherwise, just run the whole script with sudo.

#!/usr/bin/env bash

# Find the configured esp
esp=$(bootctl -p)

# Prepare the efi partition for kernel-install
machineid=$(cat /etc/machine-id)
if [[ ${machineid} ]]; then
    mkdir ${esp}/${machineid}
    echo "Failed to get the machine ID"

# Run kernel install for all the installed kernels

Now you can reboot into your new system. As you install/remove kernels, the whole process should be automated.

Special handling for LUKS

By default there is a keyfile in the initramfs. With systemd-boot, the initramfs is now in the ESP. This means that your keyfile is now in an unencrypted location. That is bad.

The good news is that shouldn’t need a keyfile in your initramfs with systemd-boot so we can simply remove it. Here is how:

Carefully follow the following steps:

  • Either:
    • For mknitcpio: Edit /etc/mkinitcpio.conf and remove /crypto_keyfile.bin from the files section.
    • For dracut: Edit /etc/dracut.conf.d/calamares-luks.conf and remove /crypto_keyfile.bin from the install_items+= line.
  • Run sudo reinstall-kernels
  • Reboot and make sure everything is still working. You should get asked for your password.

If you no longer need the keyfile at all, you can remove it completely. Be aware, if you have more than one luks partition, removing this keyfile may cause you to be asked for your password more than once.

  • Use cryptsetup to delete the key from the luks partition
    sudo cryptsetup luksRemoveKey /dev/sdxy /crypto_keyfile.bin 
    Replace /dev/sdxy with the partition you have luks installed on.
  • Delete the keyfile from the disk - sudo rm /crypto_keyfile.bin

While I have done this a couple of times without issue, keep in mind that whenever you mess around with your luks partition you run the risk of locking yourself out so it is wise to have a backup.

How to modify kernel options

A couple of people have asked my how to modify kernel options as you would in grub by editing GRUB_CMDLINE_LINUX and then running grub-mkconfig.

In systemd-boot, it is actually quite simple. You edit the appropriate entry file which can be found on your EFI partition in the loader/entries directory. Each entry is a boot option on the menu and each has a line called options. Simply edit that line to suit your liking. If you are using the manual method described above, there is nothing else to do.

It is slightly more complicated if you are using the kernel-install method. The reason is that the kernel-install is generating the entries for you. So you can edit them, and that will work but the next time you install/update a kernel they will be reset. Although it isn’t fully needed to understand the details of how that works, I think it is worth explaining for those interested. If you just want instructions, then skip the next part. :see_no_evil:

How kernel-install determines what kernel options to set

Generally speaking, kernel-install takes the running kernel options from /proc/cmdline unless you have specific settings in /etc/kernel/cmdline. The latter will always take precedence. So that means, by default, if you make a change to the running options or change the entry file and reboot, those changes will automatically get picked up.

This sounds great and it works great too. Well…it works great until you need to rescue your system in a chroot. Now the running kernel has the completely wrong options. If you understand(and remember) all this then when you are in the chroot you can simply copy the options line from one of your entries into /etc/kernel/cmdline and all will be good. However, if you don’t know, don’t remember or don’t have access to the existing entries, your entries will get populated with bad kernel options and your rescue attempts will have become more complicated.

When I built the automation around kernel-install, I wanted it to be as simple and automated as possible. I also didn’t want the end-user to have to understand how it worked to be able to use it. So what the hooks/scripts do is whenever a kernel is installed/updated, if /etc/kernel/cmdline doesn’t exist then the running kernel options are saved into it. That means that if you are ever in chroot you should have a good copy of the proper kernel options you need and everything should “just work” without you having to worry about it.

Enough about the details, how do I change the options?

There are actually a few different ways you can do this. Here are a couple of good ways. Keep in mind, you only need to use one of these methods, not both of them.

  • You can modify the entry file you are using manually and reboot. Once you have it working to your satisfaction, delete /etc/kernel/cmdline. The next time you install/update a kernel it will get created again with your new options.
  • You can modify /etc/kernel/cmdline and then either reinstall your kernel or call kernel-install directly to regenerate your entry. Reinstalling a kernel is probably easier to remember but if you would prefer to call it manually, an example of how you would do that is below.
    kernel-install add 5.10.43-1-lts /usr/lib/modules/5.10.43-1-lts/vmlinuz
  • If you with to have separate options for the fallback kernel you can optionally create /etc/kernel/cmdline_fb using the same format as /etc/kernel/cmdline.

Can i try this in a v-box install?


Of course, it will work fine in a VM.

In fact, I would recommend that anyone who isn’t familiar with the process try it on a VM first. I would take a snapshot before you start so if you make a mistake you can revert it.


It say’s it can’t find /efi?

Well the first step there is creating it. Did you miss that step?

Nope the dir is there with nothing in it.
Edit: It’s mounted.
Edit2 :Nothing in this file.

Edit the file `/efi/loader/loader.conf` and uncomment the "timeout" line.

If that file doesn’t exist, you probably missed running sudo bootctl install

No i did but I’ll run it again.

[ricklinux@eos-xfce ~]$ sudo bootctl install
[sudo] password for ricklinux: 
Couldn't find EFI system partition. It is recommended to mount it to /boot or /efi.
Alternatively, use --esp-path= to specify path to mount point.
[ricklinux@eos-xfce ~]$ 

What is the output of findmnt --real

[ricklinux@eos-xfce ~]$ findmnt --real
/      /dev/sda2 ext4   rw,noatime
└─/efi /dev/sda1 vfat   rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro
[ricklinux@eos-xfce ~]$ 


sudo bootctl --esp-path=/efi install
[ricklinux@eos-xfce ~]$ sudo bootctl --esp-path=/efi install
File system "/dev/block/8:1" has wrong type for an EFI System Partition (ESP).
[ricklinux@eos-xfce ~]$ 

Are you sure you aren’t trying to convert a bios/mbr/legacy install?

Although i despise systemd-boot itself, it’s still a great tutorial @dalto :+1:


It’s in v-box and i set it up as UEFI? :thinking:

1 Like

What does sudo parted -l show?

Edit: Repasted

[ricklinux@eos-xfce ~]$ sudo parted -l
[sudo] password for ricklinux: 
Disk /dev/sda: 19.3GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: 

Number  Start   End     Size    File system  Name  Flags
 1      1049kB  538MB   537MB   fat32              msftdata
 2      538MB   19.3GB  18.8GB  ext4

Warning: Unable to open /dev/sr0 read-write (Read-only file system).  /dev/sr0
has been opened read-only.
Model: VBOX CD-ROM (scsi)                                                 
Disk /dev/sr0: 2045MB
Sector size (logical/physical): 2048B/2048B
Partition Table: msdos
Disk Flags: 

Number  Start  End    Size   Type     File system  Flags
 2      369kB  269MB  268MB  primary               esp

[ricklinux@eos-xfce ~]$ 

/dev/sda1 isn’t an efi partition.

Well i created it as efi. I flagged it as efi. I set v-box as UEFI? :thinking:

I’ll start again and see if i forgot something. I created the partitions manually in vbox. I’ll go back and make sure i use gparted after the fact and flag the efi partition with gparted.

Edit: Okay you are right i just used gparted and changed it. Don’t know why it didn’t work the first time.

Before you start, make sure you have a valid working efi installation.

1 Like