UKI setup won't start

HI everyone,

So I am trying to set my system up with UKI using the following script:

#!/bin/bash

set -e

EFI_PART="/dev/nvme0n1p1"
ROOT_PART="/dev/nvme0n1p2"
EFI_MOUNT="/boot/efi"
UKI_PATH="${EFI_MOUNT}/EFI/Linux/arch-linux.efi"


# 1. Ensure EFI partition is mounted
echo "[*] Mounting EFI partition..."
mkdir -p $EFI_MOUNT
mount $EFI_PART $EFI_MOUNT

mkdir -p "$(dirname "$UKI_PATH")"

# 2. Create a dracut config for UKI
echo "[*] Creating dracut UKI config..."
cat <<EOF > /etc/dracut.conf.d/uki.conf
uefi=yes
kernel_cmdline="root=${ROOT_PART} rw quiet splash"
compress=zstd
show_modules=yes
EOF

# 3. Build Unified Kernel Image
echo "[*] Building UKI..."
dracut --force --uefi --kernel-image /boot/vmlinuz-linux $UKI_PATH

# 4. Create a UEFI boot entry
echo "[*] Creating UEFI boot entry..."
efibootmgr --create \
  --disk /dev/nvme0n1 \
  --part 1 \
  --label "EndeavourOS (UKI)" \
  --loader '\EFI\Linux\arch-linux.efi'

# 5. Create pacman hook to rebuild UKI on kernel update
echo "[*] Setting up pacman hook for UKI rebuild..."
mkdir -p /etc/pacman.d/hooks

cat <<EOF > /etc/pacman.d/hooks/90-uki.hook
[Trigger]
Type = Path
Target = usr/lib/modules/*/vmlinuz
Target = usr/lib/firmware/amd-ucode/microcode_amd*.bin
Operation = Install
Operation = Upgrade

[Action]
Description = Rebuilding Unified Kernel Image (UKI)...
When = PostTransaction
Exec = /usr/bin/dracut --force --uefi --no-early-microcode --kernel-image /boot/vmlinuz-linux $UKI_PATH
EOF

echo "[✓] EFISTUB UKI setup complete. Reboot to test!"

But everytime I try to boot it i find the same issue in my journal.

systemd-logind[730]: Parsed PE file ‘/boot/efi/EFI/Linux/vmlinuz.efi’ is not a UKI.

Can anyone help me solve this. when I get to the emergency shell it goes into a loop so I can’t pull the initrmfs error log that it creates.

Not related to your issue, but the “K” stands for “kernel”.

Paste the output of the script into the thread so we can see what is happening.

[*] Mounting EFI partition...
[*] Creating dracut UKI config...
[*] Building UKI...
dracut[I]: Executing: /usr/bin/dracut --force --uefi --no-early-microcode --kernel-image /boot/vmlinuz-linux /boot/efi/EFI/Linux/arch-linux.efi
bash
systemd
systemd-ask-password
systemd-battery-check
systemd-cryptsetup
systemd-initrd
systemd-journald
systemd-modules-load
systemd-pcrphase
systemd-sysctl
systemd-tmpfiles
systemd-udevd
modsign
i18n
systemd-sysusers
Creating group 'nobody' with GID 65534.
Creating group 'audio' with GID 996.
Creating group 'disk' with GID 995.
Creating group 'input' with GID 994.
Creating group 'kmem' with GID 993.
Creating group 'kvm' with GID 992.
Creating group 'lp' with GID 991.
Creating group 'optical' with GID 990.
Creating group 'render' with GID 989.
Creating group 'sgx' with GID 988.
Creating group 'storage' with GID 987.
Creating group 'tty' with GID 5.
Creating group 'uucp' with GID 986.
Creating group 'video' with GID 985.
Creating group 'users' with GID 984.
Creating group 'systemd-journal' with GID 983.
Creating user 'root' (Super User) with UID 0 and GID 0.
Creating user 'nobody' (Kernel Overflow User) with UID 65534 and GID 65534.
btrfs
crypt
dm
dmraid
kernel-modules
kernel-modules-extra
lvm
mdraid
multipath
nvdimm
qemu
qemu-net
btrfs-snapshot-overlay
fido2
pkcs11
hwdb
lunmask
resume
rootfs-block
terminfo
udev-rules
virtiofs
dracut-systemd
usrmount
base
fs-lib
shell-interpreter
shutdown
dracut[I]: *** Including modules done ***
dracut[I]: *** Installing kernel module dependencies ***
dracut[I]: *** Installing kernel module dependencies done ***
dracut[I]: *** Resolving executable dependencies ***
dracut[I]: *** Resolving executable dependencies done ***
dracut[I]: *** Hardlinking files ***
dracut[I]: *** Hardlinking files done ***
dracut[I]: *** Store current command line parameters ***
dracut[I]: *** Stripping files ***
dracut[I]: *** Stripping files done ***
dracut[I]: *** Creating image file '/boot/efi/EFI/Linux/arch-linux.efi' ***
dracut[I]: Using UEFI kernel cmdline:
dracut[I]: root=/dev/nvme0n1p2 rw quiet splash
dracut[I]: *** Creating UEFI image file '/boot/efi/EFI/Linux/arch-linux.efi' done ***
[*] Creating UEFI boot entry...
BootCurrent: 0000
Timeout: 0 seconds
BootOrder: 0001,0000,0016,0012,0013,0014,0015,0018,0019
Boot0000* endeavouros   HD(1,GPT,6fbb15e4-f892-4030-b148-1fb0a62d1f03,0x1000,0x200000)/\EFI\endeavouros\grubx64.efi
Boot0010  Setup FvFile(721c8b66-426c-4e86-8e99-3457c46ab0b9)
Boot0011  Boot Menu     FvFile(86488440-41bb-42c7-93ac-450fbf7766bf)
Boot0012* NVMe: WD_BLACK SN770 2TB                      PciRoot(0x0)/Pci(0x2,0x4)/Pci(0x0,0x0)/NVMe(0x1,00-1B-44-8B-47-AD-F2-78){99191c00-d932-4e4c-ae9a-a0b6e98eb8a4}
Boot0013* ATA HDD:      VenMsg(bc7838d2-0f82-4d60-8316-c068ee79d25b,91af625956449f41a7b91f4f892ab0f600)
Boot0014* ATA HDD1:     VenMsg(bc7838d2-0f82-4d60-8316-c068ee79d25b,91af625956449f41a7b91f4f892ab0f601)
Boot0015* ATAPI CD:     VenMsg(bc7838d2-0f82-4d60-8316-c068ee79d25b,aea2090adfde214e8b3a5e471856a354)
Boot0016* USB HDD:      VenMsg(bc7838d2-0f82-4d60-8316-c068ee79d25b,33e821aaaf33bc4789bd419f88c50803)
Boot0017  PCI LAN:      VenMsg(bc7838d2-0f82-4d60-8316-c068ee79d25b,78a84aaf2b2afc4ea79cf5cc8f3d3803)
Boot0018* USB FDD:      VenMsg(bc7838d2-0f82-4d60-8316-c068ee79d25b,6ff015a28830b543a8b8641009461e49)
Boot0019* USB CD:       VenMsg(bc7838d2-0f82-4d60-8316-c068ee79d25b,86701296aa5a7848b66cd49dd3ba6a55)
Boot001A  UEFI Diagnostics      FvFile(1de8487e-0df5-6c66-56ca-83705aaf1f59)
Boot0001* EndeavourOS (UKI)     HD(1,GPT,6fbb15e4-f892-4030-b148-1fb0a62d1f03,0x1000,0x200000)/\EFI\Linux\arch-linux.efi
[*] Setting up pacman hook for UKI rebuild...
[✓] EFISTUB UKI setup complete. Reboot to test!

Are you sure you don’t want early loading for your microcode?

You may need to add the --no-hostonly-cmdline dracut flag. Without it, dracut grabs the current system’s kernel command line from /proc/cmdline (instead of using what you have defined in your dracut config). If you are building the UKI from a live ISO or chroot, it will have a different root device.

I don’t think this message is actually the smoking gun for your system not booting. Is there any way to capture the output on the screen before you drop to the emergency shell? Even just a photo may offer a clue.

Persistent kernel descriptors (like UUID or PARTUUID) are more reliable than using the block device paths during the initramfs stage. It’s hard to say if this is the cause of the issue or not without seeing the messages you get before the emergency shell, but for a UKI I would not risk it.

I don’t think quiet or splash will work with the kernel_cmdline option in a dracut config, since it only sets initrd parameters.

man dracut.conf
        kernel_cmdline="parameters"
           Specify default kernel command line parameters. Despite its name, this command only sets initrd parameters.

Also, it’s probably not related to your issue but you are adding the uefi option twice–once in the dracut config, and then again with the flag when running dracut.

No, I missed one of the lines when I was making necessary changes to add my microcode.
I will also add the --no-host-only-cmdline flag, Thanks for that one.

I will look deeper into understanding the uuid or partuuid aspect. I’m having a hard time wrapping my head around that. I will also drop the quiet splash part of the kernel_cmdline.

I do know the error that it starts with says something about switch root. I will rerun it and get a photo to add.

Here is what it shows when it stops loading. When I hit continue it goes into a loop saying it can’t connect to some service, i presume it has something to do with the drives not mounting.

just a quick update, after I made your changes, I arch-chroot in run my script and then i get the lovely BSOD Kernel panic. There is absolutely nothing helpful from that screen.
The only errors in journalctl -b is the same as I stated in my original post.

I am wondering if this is enough information for dracut to build the UKI, since the kernel version is not explicitly specified (it has to know what modules to include in the image, etc).

Let’s try using --kver instead. You will need to add some kind of option to your script for determining the kernel version.

For testing purposes, manually setting a hard-coded value in the script should be fine (just to confirm the UKI boots).

KERNEL_VERSION=6.14.2-arch1-1

Use the actual kernel version available in the installed system (check in /usr/lib/modules if you are not sure).

Then change your dracut line to use the --kver flag.

dracut --force --uefi --kver "$KERNEL_VERSION" "$UKI_PATH"

Sorry for the long period of my reply. I will look into it this afternoon or tomorrow and reply