Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save mikaeldui/bf3cd9b6932ff3a2d49b924def778ebb to your computer and use it in GitHub Desktop.
Save mikaeldui/bf3cd9b6932ff3a2d49b924def778ebb to your computer and use it in GitHub Desktop.
CachyOS Kernel for Fedora with Secure Boot

image

CachyOS Kernel for Fedora with Secure Boot

Did you just install kernel-cachyos and got hit by bad shim signature when booting? Me too. This is how I fixed it.

First, make sure you have Secure Boot with mokutil --sb-state.

Note, there's a second way of doing this by using sbctl, but I didn't want to wipe my Secure Boot keys.

Installing the CachyOS Kernel

Full instructions at https://github.com/CachyOS/copr-linux-cachyos

  1. Check your CPU support /lib64/ld-linux-x86-64.so.2 --help | grep "(supported, searched)", my CPU supports v2, v3 and v4.
  2. Enable a suitable repo: sudo dnf copr enable bieszczaders/kernel-cachyos.
  3. Install suitable kernel: sudo dnf install kernel-cachyos kernel-cachyos-devel-matched.
  4. Let the kernel load modules: sudo setsebool -P domain_kernel_load_modules on.
  5. Done!

If you reboot now you'll get the "bad shim signature" error and have to pick an official Fedora kernel to boot. Don't worry, you didn't break anything.

Signing the CachyOS Kernel

We can self-sign the kernel by adding our key as a MOK (Machine Owner Key).

Based on general kernel signing procedures for Fedora and RHEL.

sudo dnf install pesign openssl kernel-devel mokutil keyutils
sudo echo "$USER" >> /etc/pesign/users
sudo /usr/libexec/pesign/pesign-authorize
openssl req -new -x509 -newkey rsa:2048 -keyout "key.pem" \
        -outform DER -out "cert.der" -nodes -days 36500 \
        -subj "/CN=CachyOS Secure Boot/"
openssl pkcs12 -export -out key.p12 -inkey key.pem -in cert.der
sudo certutil -A -i cert.der -n "CachyOS Secure Boot" -d /etc/pki/pesign/ -t "Pu,Pu,Pu"
sudo pk12util -i key.p12 -d /etc/pki/pesign
sudo mokutil --import "cert.der"
cd /boot
sudo pesign --certificate 'CachyOS Secure Boot' \
         --in vmlinuz-6.14.6-cachyos1.fc42.x86_64 \
         --sign \
         --out vmlinuz-6.14.6-cachyos1.fc42.x86_64.signed
sudo mv vmlinuz-6.14.6-cachyos1.fc42.x86_64.signed vmlinuz-6.14.6-cachyos1.fc42.x86_64

And reboot and choose enroll the key. The MOK password is only used once so I suggest using "12345678". Replace "CachyOS Secure Boot" and "vmlinuz-6.14.6-cachyos1.fc42.x86_64" with whatever applies in your case.

Automatically signing kernel updates

Whooray! You can now boot the CachyOS Kernel for Fedora with Secure Boot enabled! Let's make sure that it continues to work across updates!

  1. Create and open sudo nano /etc/kernel/postinst.d/00-signing
  2. Enter the following content:
#!/bin/sh

set -e

KERNEL_IMAGE="$2"
MOK_KEY_NICKNAME="CachyOS Secure Boot"

if [ "$#" -ne "2" ] ; then
	echo "Wrong count of command line arguments. This is not meant to be called directly." >&2
	exit 1
fi

if [ ! -x "$(command -v pesign)" ] ; then
	echo "pesign not executable. Bailing." >&2
	exit 1
fi

if [ ! -w "$KERNEL_IMAGE" ] ; then
	echo "Kernel image $KERNEL_IMAGE is not writable." >&2
	exit 1
fi

echo "Signing $KERNEL_IMAGE..."

pesign --certificate "$MOK_KEY_NICKNAME" --in "$KERNEL_IMAGE" --sign --out "$KERNEL_IMAGE.signed"
mv "$KERNEL_IMAGE.signed" "$KERNEL_IMAGE"
  1. Correct the permissions with: sudo chown root:root /etc/kernel/postinst.d/00-signing ; chmod u+rx /etc/kernel/postinst.d/00-signing

Fix default kernel after updates

Whenever you receive an update to the official Fedora kernel it will replace the CachyOS kernel as the default kernel. One solution is to uninstall the official kernel, and another is to reset the default kernel to CachyOS after each update:

  1. Create and open sudo nano /etc/kernel/postinst.d/99-default
  2. Enter the following content:
#!/bin/sh

set -e

grubby --set-default=/boot/$(ls /boot | grep vmlinuz.*cachy | sort -V | tail -1)
  1. Correct the permissions with: sudo chown root:root /etc/kernel/postinst.d/99-default ; sudo chmod u+rx /etc/kernel/postinst.d/99-default
@mikaeldui
Copy link
Author

mikaeldui commented May 20, 2025

@victor-borges added --refresh to sudo dnf update and now I got the 6.14.7 update too!

$ sudo pesign --show-signature --in /boot/vmlinuz-6.14.7-cachyos1.fc42.x86_64 
---------------------------------------------
certificate address is 0x7e064d5aa208
Content was not encrypted.
Content is detached; signature cannot be verified.
The signer's common name is Bolinder Secure Boot
No signer email address.
Signing time: Tue May 20, 2025
There were certs or crls included.
---------------------------------------------

It worked, uname -r = 6.14.7-cachyos1.fc42.x86_64!

I guess it could be good if the signing script checked if it is a "cachyos" kernel. Right now it'll re-sign the official Fedora kernels too I think, but that shouldn't be any problem.

Now to figure out a way to make LUKS/TPM work across kernel updates. Maybe I've too many PCRs...

@victor-borges
Copy link

@mikaeldui I'm using PCRs 7+14, 8 can't be used because the kernel version is in the command line

@mikaeldui
Copy link
Author

mikaeldui commented May 20, 2025

@victor-borges hm, I run sudo systemd-cryptenroll --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs=0+1+2+3+4+5+7 /dev/nvme0n1p3 after every kernel update. Seems my problem is #4. I'll try removing it and add #14.

PCR 4 changes on boot loader updates. The shim project will measure the PE binary it chain loads into this PCR. If the Linux kernel is invoked as UEFI PE binary, it is measured here, too. source

https://wiki.archlinux.org/title/Trusted_Platform_Module

@mikaeldui
Copy link
Author

@victor-borges I wouldn't have noticed the upgrade to 6.14.8 if I hadn't triggered it manually. :D

@Anifyuli
Copy link

Hi dude, I get file cert.der, key.p12, and key.pem in my $HOME. I want to move it to other directory on root. Where suitable place to move it? Thanks for your suggestions

@mikaeldui
Copy link
Author

mikaeldui commented May 25, 2025

Hi dude, I get file cert.der, key.p12, and key.pem in my $HOME. I want to move it to other directory on root. Where suitable place to move it? Thanks for your suggestions

You can delete them, pesign and mokutil/shim have their own copies 🙂

If you want to keep them then you could put them under /usr/share as they're for the machine and not the user.

I can recommend reading about the XDG directory variables, https://wiki.archlinux.org/title/XDG_Base_Directory

@Anifyuli
Copy link

Anifyuli commented May 25, 2025

You can delete them, pesign and mokutil/shim have their own copies 🙂

I see, thanks for new information, it's new things for me.

If you want to keep them then you could put them under /usr/share as they're for the machine and not the user.

I can recommend reading about the XDG directory variables, https://wiki.archlinux.org/title/XDG_Base_Directory

Thanks for your recommendation, but I decide to move it to /etc/secureboot/keys to imitate sbsigntools behavior on Arch Linux.
I have other questions, if I have out-off-tree kernel module and I successfully setup secure boot, what should I do?

@mikaeldui
Copy link
Author

You can delete them, pesign and mokutil/shim have their own copies 🙂

I see, thanks for new information, it's new things for me.

If you want to keep them then you could put them under /usr/share as they're for the machine and not the user.
I can recommend reading about the XDG directory variables, https://wiki.archlinux.org/title/XDG_Base_Directory

Thanks for your recommendation, but I decide to move it to /etc/secureboot/keys to imitate sbsigntools behavior on Arch Linux. I have other questions, if I have out-off-tree kernel module and I successfully setup secure boot, what should I do?

I guess /etc (global variant of ~/.config) is fine. I'm new to Linux myself and don't know what the difference between "config" and "data" is. "Cache" is easy, stuff that can be generated/downloaded again, but apparently there's also "state".

As for signing kernel modules, it's not something I've done but it's mentioned in the Fedora and REHL guides linked. Keys made for signing kernels can be used for modules, but not the other way around, is the only thing I know. 😁

@Anifyuli
Copy link

As for signing kernel modules, it's not something I've done but it's mentioned in the Fedora and REHL guides linked. Keys made for signing kernels can be used for modules, but not the other way around, is the only thing I know. 😁

I see. Thanks for your help dude :)

@msmafra
Copy link

msmafra commented May 26, 2025

Basing on 99-default, things inside /etc/kernel/* are run as root by the update/upgrade processes, right?
If so the sudo inside the 00-signing woudn't be needed.
Are those files run by bash?

@mikaeldui
Copy link
Author

mikaeldui commented May 26, 2025

Basing on 99-default, things inside /etc/kernel/* are run as root by the update/upgrade processes, right? If so the sudo inside the 00-signing woudn't be needed. Are those files run by bash?

@msmafra Run by root. Thanks for noticing! I've updated the gist.

@msmafra
Copy link

msmafra commented May 26, 2025

@msmafra Run by root. Thanks for noticing! I've updated the gist.

Not at all. Thank you for the tutorial.
Just the automatic part is that I have to wait for the next CachyOS kernel update.
Looking (Messing with) the files/scripts in the 00-signing you check the count for 2 parameters but I see only one being used ($2). Will the update/upgrade process send two args but only the second one is needed?

00-signing

#!/bin/bash

set -o errexit

sigining_cachyos_kernel() {

    local KERNEL_IMAGE
    local MOK_KEY_NICKNAME
    local PESIGN_EXEC

    shift
    KERNEL_IMAGE="$1"
    MOK_KEY_NICKNAME="CachyOS Secure Boot"
    PESIGN_EXEC="$(command -v pesign)"

    if [ "${#}" -ne "2" ]; then
        printf "%s\n" "Wrong count of command line arguments. This is not meant to be called directly." >&2
        exit 1
    fi

    if [ ! -x "${PESIGN_EXEC}" ]; then
        printf "%s\n" "pesign not executable. Bailing." >&2
        exit 1
    fi

    if [ ! -w "${KERNEL_IMAGE}" ]; then
        printf "Kernel image %s is not writable.\n" "${KERNEL_IMAGE}" >&2
        exit 1
    fi

    printf "Signing %s...\n" "${KERNEL_IMAGE}"

    pesign --certificate "${MOK_KEY_NICKNAME}" --in "${KERNEL_IMAGE}" --sign --out "${KERNEL_IMAGE}.signed"
    mv --verbose "${KERNEL_IMAGE}.signed" "${KERNEL_IMAGE}"

}
sigining_cachyos_kernel "${@}"

99-default

#!/bin/bash

set -o errexit

set_cachyos_as_default() {

    local MOST_RECENT
    MOST_RECENT="$(find /boot -name "vmlinuz*cachyos*.*" | sort --version-sort | tail --lines=1 | tr --delete "\n")"

    grubby --set-default=/boot/"${MOST_RECENT}"

}

set_cachyos_as_default

@mikaeldui
Copy link
Author

mikaeldui commented May 26, 2025

@msmafra It's a copy paste of some "kernel install hook" script that I found, that I modified for pesign. I'm far from a bash expert. There are more checks to be added, e.g. it shouldn't re-sign the official Fedora kernels. 😂 I'll check and test your code tomorrow. Perhaps this should be turned into a general MOK kernel signing tool in a normal Git repo.

If you can't wait for the next update then you can trigger a reinstall with sudo dnf reinstall kernel-cachyos-core apparently. I don't know what happens if you reinstall the running kernel though.

@infirms
Copy link

infirms commented Jun 15, 2025

Thanks, looks very promising, will definitely use it.

@msmafra
Copy link

msmafra commented Jun 15, 2025

I'm flabbergasted (:smile: ) how it's been working on my machine, but the 99-default has a mistake of my part there.

#!/bin/bash

set -o errexit

set_cachyos_as_default() {

    local MOST_RECENT
    MOST_RECENT="$(find /boot -name "vmlinuz*cachyos*.*" | sort --version-sort | tail --lines=1 | tr --delete "\n")"

    grubby --set-default=/boot/"${MOST_RECENT}"

}

set_cachyos_as_default

The find line does this
Screenshot-2025-06-15-09-58-28
the ls line does
Screenshot-2025-06-15-10-00-39

The variable will receive the value e.g /boot/vmlinuz-6.15.2-cachyos1.fc42.x86_64 instead of vmlinuz-6.15.2-cachyos1.fc42.x86_64 as @mikaeldui 's original, making the grubby line /boot//boot/vmlinuz-6.15.2-cachyos1.fc42.x86_64 (which I still shocked is working on my machine. So the grubby line should actuall have only the "MOST_RECENT" variable to avoid problems. Very sorry.

So this, removing the /boot/ part should be the one used.

#!/bin/bash

set -o errexit

set_cachyos_as_default() {

    local MOST_RECENT
    MOST_RECENT="$(find /boot -name "vmlinuz*cachy*.*" | sort --version-sort | tail --lines=1 | tr --delete "\n")"

    grubby --set-default="${MOST_RECENT}"

}

set_cachyos_as_default

@mikaeldui
Copy link
Author

I'm flabbergasted (:smile: ) how it's been working on my machine

It's ridiculously smooth for how simple it is. I can't even tell when I'm getting the kernel updates.
image

"vmlinuz*cachyos*.*"

@msmafra I've updated the Gist to now look for just "cachy" so that it's compatible with all the different CachyOS kernels, that all start with "cachy" in Fedora/COPR, .e.g. "cachyos", "cachylts", "cachyrt" and "cachyserver".

If you want you could create scripts for Fedora Silverblue and derivatives: https://discussion.fedoraproject.org/t/bieszczaders-kernel-cachyos/46112/126

Gnome Boxes/libvirt can properly simulate Secure Boot when UEFI is enabled, so you get "bad shim signature" if the kernel signing fails.

@msmafra
Copy link

msmafra commented Jun 15, 2025

I'm flabbergasted (:smile: ) how it's been working on my machine

It's ridiculously smooth for how simple it is. I can't even tell when I'm getting the kernel updates. image

"vmlinuz*cachyos*.*"

@msmafra I've updated the Gist to now look for just "cachy" so that it's compatible with all the different CachyOS kernels, that all start with "cachy" in Fedora/COPR, .e.g. "cachyos", "cachylts", "cachyrt" and "cachyserver".

If you want you could create scripts for Fedora Silverblue and derivatives: https://discussion.fedoraproject.org/t/bieszczaders-kernel-cachyos/46112/126

Gnome Boxes/libvirt can properly simulate Secure Boot when UEFI is enabled, so you get "bad shim signature" if the kernel signing fails.

Oh, thanks. I updated my files to match it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment