Getting rid of Grub

This is similar to a “normal” Fedora installation and pretty straight forward.

Before you try this make sure you have a backup of any data before you
start. Playing with the boot loader can bring you very easily in the situation
that your PC refuses to start. Of course you also should have a rescue USB
stick ready so you can do fixes when it really comes to this.

I just want to keep a note here in case anyone comes up with the same
question: how can I get rid of grub?

To be one the safe side first thing I did was to replace all symbolic
links in /boot with copy of the corresponding files.

Then make a tarball of the content of /boot and safe this somewhere
(e.g. in /root).

Next step is to format the partitions which where /boot and /boot/efi
with vfat (mkfs.vfat). The original efi partition which has been /boot/efi
will no longer be used.

You should not forget to check in /dev/disk/by-uuid for your new uuid
of /boot. You can copy your /boot/efi entry in /etc/fstab and change
/boot/efi to /boot and put your new UUID for /boot there. Comment out
your original /boot/efi entry and also you original /boot entry.

So you will have a new boot entry with vfat and the new UUID and no
/boot/efi entry any longer.

Now you should use parted or fdisk to unset the boot flag on the original
efi partiion and set in on the boot partition. You can also change the names
if you like. As already said the original efi partition will no longer be used.

Back in you /boot partition untar your saved boot tar file so you have
all your files back in /boot.

It is very important that you now move your efi directory. In the original
layout in was placed in /boot/efi/EFI because /boot/efi was a mount point.

cd /boot
mv efi efi.x
mv efi.x/EFI .
rm -rf efi.x

All EFI stuff is now in /boot/EFI.

Now we have a vfat formatted boot partition without any extra efi partition.
This also means that the kernel and the initial ramdisk are on a vfat
partition which is readable by your UEFI.

For a test you can boot your PC now and grub will come up. After the
described steps I got an error message and the hint I should press a key.
Press any key and the installation will start up will continue.

Next step is to install systemd-boot. This is done simply by

bootctl install

All relevant EFI stuff is now in /boot/EFI/systemd.

If you boot your PC at this point you will have to disable Secure boot
because systemd-boot cannot handle signed binaries as it is able with grub.
This is due to the fact that the kernel is started by the UEFI directly.

In order to fix that we need to apply the secure boot system of the
Linux Foundation which was presented in Februrary 2013 by James Bottomley.

https://blog.hansenpartnership.com/linux-foundation-secure-boot-system-released/

Download PreLoader.efi and HashTool.efi and put them into
/boot/EFI/systemd.

cd /boot/EFI/systemd
mv systemd-bootx64.efi loader.efi
cp PreLoader.efi systemd-bootx64.efi

As you can see from this PreLoader.efi will act as systemd-bootx64.efi.
Then loader.efi (the original systemd-bootx64.efi) is loaded.

PreLoader.efi is signed by Microsoft and will start with Secure Boot.

Now you can start your PC. You will see a “blue screen” telling you
that you need to do hash enrollment. First you have to sign loader.efi.
After this you have to sign your kernel (/boot/ostree/fedora-…/vmlinuz-…).

For each new kernel you will get you have to repeat this and do the
enrollment with HashTool.

BTW: if you for some reason want to remove your MokList you can enter
and EFI shell and do

dmpstore -d MokList

This solution still does not deal with signed binaries like grub but
since you manually have to add a hash into the MokList with the HashTool
you prevent your systems to startup binaries you have not agreed to.
Nobody who has not physical access to your system can use your HashTool.

Of course it is a matter of taste but I prefer to see the boot menu
and also have a timeout so you can activate the correspondent lines
in /boot/loader/loader.conf.

Booting now will even work with activated Secure Boot.

This seems to me much simpler than all these complicated grub configurations
with several stages.

Well as awesome as this is, IIRC OSTree doesn’t support placing kernels on a fat partition, so you’ll now be unable to run an upgrade…

It refuses to update because of the file system? What concept is that?

It’s not quite that simple, basically OSTree will try to do stuff like set the permissions on the kernel for security reasons, but chmod isn’t supported on fat32, therefore your next kernel update will likely fail.

I kind of want to make a PR to fix it since it’s not super tricky and I don’t like GRUB, but I haven’t found the time yet.

1 Like

I have reconfigured my system back to grub. I don’t understand why it is used instead of systemd-boot but perhaps it is because of secure boot.

rpm-ostree is not working anymore.

[root@bat ~]# rpm-ostree status
error: Timeout was reached

Could you try journalctl -u rpm-ostreed -b -e?

I think ostree came out before gummiboot became systemd-boot, so it could partly just be that at the time it made more sense.

I have already done another reinstallation.

My last command was “ostree admin cleanup” before I rebooted my PC and it refused to start because ostree did not start.

This ostree stuff is completely new to me and I have no idea how to debug or fix it.

The whole thing was about getting rid of grub and obviously this did not work.

I have now some kind of parallel installation of grub and systemd-boot but the latter is not really usable because I don’t see a good way to maintain it.

I created some loader file like this:

title Fedora 30 (5.0.17)
machine-id 0c7ef96f9e934c259738840ef39fdbef
linux /0c7ef96f9e934c259738840ef39fdbef/vmlinuz-5.0.17-300.fc30.x86_64
initrd /0c7ef96f9e934c259738840ef39fdbef/initramfs-5.0.17-300.fc30.x86_64.img
options resume=/dev/mapper/fedora-swap rd.lvm.lv=fedora/root rd.lvm.lv=fedora/swap rd.luks.uuid=luks-6cf16b77-a720-48ef-b734-47f4ffe4c288 root=/dev/mapper/fedora-root ostree=/ostree/boot.0/fedora/8150f1d4dfd6f83fbb5b9ea391455543c40c72242cecd4d7774ef96a04a81fd2/0

As you can see this contains this long ostree number. I put kernel and initrd on this small efi partition (which is ok for just one pair of them) but I consider it only as some test that this would work.

From my point of view it looks like that systemd-boot is not really supported by Fedora (maybe because secure boot does not work with signed binaries).

This means I have to correct myself: we can not get rid of the volume and directory layout given by Fedora.

We have to work with /boot/efi/EFI/systemd. The /boot partition has to be xfs (or ext4 if you prefer this) and /boot/efi is vfat.

For maintenance something like this should do for the beginning.

Configure your own LUKS_UUID or adapt the script to your scenario. In my case I use LVM on LUKS.

#!/bin/bash
# write-ostree-boot-config.sh

# --- configure this -------------------------------------------------------
MAX_DEPLOY=1 # works only with 1 at the moment
LUKS_UUID='6cf16b77-a720-48ef-b734-47f4ffe4c288'
# -------------------------------------------------------------------------

ARCH=$(uname -m)
ID=$(cat /etc/machine-id)

if [[ ! ${ID:0:1} =~ [0-9,a-z] ]]
then
  echo 'machine-id not correct'
  exit 1
fi

if [[ ! -d /boot/efi/${ID} ]]
then
  mkdir /boot/efi/${ID}
fi

# find current boot number
BOOT=$(find /ostree/ -maxdepth 1 -type l | grep boot)
BOOT_NUM_ORG=${BOOT##*.}

# find latest deployment and corresponding ostree boot
# currently we take only the latest deployment
DEPLOY_LIST=''
DEPLOY_BASE_DIR='/ostree/deploy/fedora/deploy'
DEPLOY_LIST_FILES=$(ls -t ${DEPLOY_BASE_DIR}/*.origin)

for d_elt_tmp in ${DEPLOY_LIST_FILES}
do
  d_elt_tmp2=${d_elt_tmp%.origin}
  d_elt=${d_elt_tmp2##*/}
  DEPLOY_LIST="${DEPLOY_LIST} $d_elt"
done

deploy_counter=0;

for dp in ${DEPLOY_LIST}
do
  deploy_counter=$((deploy_counter+1))
  if [[ $deploy_counter -gt ${MAX_DEPLOY} ]]
  then
    break
  fi

  KERNEL_DP=$(ls ${DEPLOY_BASE_DIR}/${dp}/usr/lib/ostree-boot/vmlinuz*)
  INITRD_DP=$(ls ${DEPLOY_BASE_DIR}/${dp}/usr/lib/ostree-boot/initramfs*)
done

KERNEL_DP_BASE=$(basename ${KERNEL_DP})
OSTREE_CURRENT=${KERNEL_DP_BASE##*-}
FEDORA_KERNEL_DIR=/boot/ostree/fedora-${OSTREE_CURRENT}
k_tmp=${KERNEL_DP_BASE##*vmlinuz-}
VER_LIST=${k_tmp%-${OSTREE_CURRENT}}
VER=${VER_LIST}

# swap boot number after new deployment
if [[ -d $FEDORA_KERNEL_DIR ]]
then
  BOOT_NUM=${BOOT_NUM_ORG}
else
  if [[ ${BOOT_NUM_ORG} -eq 0 ]]
  then
    BOOT_NUM=1
  elif [[ ${BOOT_NUM_ORG} -eq 1 ]]
  then
    BOOT_NUM=0
  else
    BOOT_NUM=${BOOT_NUM_ORG}
    echo "WARNING: ${BOOT_NUM} is neither 0 or 1. \
This is unexpected and will probably go wrong."
  fi
fi

OSTREE_BOOT_DIR=/ostree/boot.${BOOT_NUM}/fedora/${OSTREE_CURRENT}/0

cd /boot/efi/${ID}

if [[ $? -ne 0 ]]
then
   echo "cannot enter /boot/efi/${ID}";
   exit 1
fi

# check which version we have in the EFI partition
# remove those we don't have in /boot/ostree
EXISTING_VERSIONS=$(ls)

for EXISTING_VERSION in ${EXISTING_VERSIONS}
do
  version_found=0
  for VER in ${VER_LIST}
  do
    if [[ "${EXISTING_VERSION}" == "${VER}" ]]
    then
      version_found=1
    fi
   done

  if [[ $version_found == 0 ]]
  then
    echo "removing ${EXISTING_VERSION}"
    rm -rf ${EXISTING_VERSION}
  fi
done

KERNEL_DIRS=fedora-${OSTREE_CURRENT}

for KERNEL_DIR in ${KERNEL_DIRS}
do
   OPTIONS="resume=/dev/mapper/fedora-swap \
rd.lvm.lv=fedora/root \
rd.lvm.lv=fedora/swap \
rd.luks.uuid=luks-${LUKS_UUID} \
root=/dev/mapper/fedora-root \
ostree=${OSTREE_BOOT_DIR} \
rhgb quiet"

  cd /boot/efi

  if [[ $? -ne 0 ]]
  then
    echo "cannot enter /boot/efi"
    exit 1
  fi

  rm -f loader/entries/${ID}-[1-9]*.conf

  ENTRY=loader/entries/${ID}-${VER}.conf

  mkdir -p ${ID}/${VER}

  KERNEL_TARGET=${ID}/${VER}/linux
  INITRD_TARGET=${ID}/${VER}/initrd

  if [[ -f ${KERNEL_TARGET} ]]
  then
    echo "${KERNEL_TARGET} already exists"
  else
    cp ${KERNEL_DP} ${KERNEL_TARGET}
  fi

  if [[ -f ${INITRD_TARGET} ]]
  then
    echo "${INITRD_TARGET} already exists"
  else
    cp ${INITRD_DP} ${INITRD_TARGET}
  fi

  cat <<EOF > ${ENTRY}
title      ${VER}
version    ${VER}
machine-id ${ID}
options    ${OPTIONS}
linux      /${KERNEL_TARGET}
initrd     /${INITRD_TARGET}
EOF
done