Skip to content

Instantly share code, notes, and snippets.

@criscola
Last active February 28, 2026 15:59
Show Gist options
  • Select an option

  • Save criscola/d69475a5f517bc1d5b41ddb28dfc5473 to your computer and use it in GitHub Desktop.

Select an option

Save criscola/d69475a5f517bc1d5b41ddb28dfc5473 to your computer and use it in GitHub Desktop.
Manjaro Secure Boot with GRUB + Shim (ASUS Motherboard)

Manjaro Secure Boot with GRUB + Shim (ASUS Motherboard)

System: Manjaro/Windows dual-boot, NVMe drive, ASUS motherboard, GRUB bootloader Boot chain: UEFI firmware → shim (Microsoft-signed) → GRUB (MOK-signed) → kernel (MOK-signed) Last verified: February 2026, GRUB 2:2.14, shim-signed 15.8

Based on https://gist.github.com/Jai-JAP/5d5d9f67f19e5e5eaf6825b371a17d5d from Jai-JAP.


Why This Is Needed

Manjaro's GRUB has a built-in shim_lock_verifier that requires the shim protocol when Secure Boot is enabled. You cannot bypass shim — GRUB will refuse to load kernels with "shim protocols not found" if launched directly. The boot chain must be: firmware → shim → GRUB → kernel.

Additionally, modern kernels (especially 6.18+) have gaps between PE/COFF sections. Signing them in-place with sbsign --output $file $file corrupts the signature. You must sign to a temp file first, then move it.


Prerequisites

sudo pacman -S sbsigntools efibootmgr openssl
# shim-signed from AUR (provides shimx64.efi, mmx64.efi)
sudo pacman -S shim-signed

Step 1: Generate MOK Keys

sudo -i

mkdir -p /usr/share/secureboot/keys
cd /usr/share/secureboot/keys

# Generate 4096-bit RSA key pair, 10-year validity
openssl req -newkey rsa:4096 -nodes \
  -keyout MOK.key -new -x509 -sha256 -days 3650 \
  -subj "/CN=Manjaro MOK/" -out MOK.crt

# Create DER format for firmware enrollment
openssl x509 -outform DER -in MOK.crt -out MOK.cer

# Copy cert to ESP for firmware and shim enrollment
mkdir -p /boot/efi/keys
cp MOK.cer /boot/efi/keys/

Diagnostic: Verify keys

openssl x509 -in /usr/share/secureboot/keys/MOK.crt -noout -fingerprint -sha1 -dates
ls -la /usr/share/secureboot/keys/
# Should show: MOK.key (private), MOK.crt (PEM cert), MOK.cer (DER cert)

Step 2: Rebuild GRUB With All Modules Embedded

Under Secure Boot, GRUB enters lockdown mode and cannot insmod external modules from disk. Every module referenced by grub.cfg must be built into the EFI binary.

# Check which modules grub.cfg actually references
grep -oP "insmod \K\S+" /boot/grub/grub.cfg | sort -u

# Check which of those exist for EFI (some are BIOS-only)
for mod in $(grep -oP "insmod \K\S+" /boot/grub/grub.cfg | sort -u); do
    [ ! -f "/usr/lib/grub/x86_64-efi/${mod}.mod" ] && echo "MISSING (skip): $mod"
done

Build GRUB with all available modules. Omit any that don't exist (vbe, vga, ieee1275_fb are BIOS/OpenFirmware-only):

MODULES="all_video boot btrfs cat chain configfile cpuid cryptodisk echo \
efifwsetup efinet ext2 fat font gcry_arcfour gcry_blowfish gcry_camellia \
gcry_cast5 gcry_crc gcry_des gcry_dsa gcry_idea gcry_md4 gcry_md5 \
gcry_rfc2268 gcry_rijndael gcry_rmd160 gcry_rsa gcry_seed gcry_serpent \
gcry_sha1 gcry_sha256 gcry_sha512 gcry_tiger gcry_twofish gcry_whirlpool \
gettext gfxmenu gfxterm gfxterm_background gzio halt help hfsplus iso9660 \
jpeg keystatus linux loadenv loopback ls lsefi lsefimmap lsefisystab lssal \
luks luks2 lvm mdraid09 mdraid1x memdisk minicmd normal ntfs part_apple \
part_gpt part_msdos password_pbkdf2 play png probe raid5rec raid6rec reboot \
regexp search search_fs_file search_fs_uuid search_label serial sleep smbios \
squash4 test tpm true video xfs zfs zfscrypt zfsinfo efi_gop efi_uga \
video_bochs video_cirrus bli"

grub-install --target=x86_64-efi --efi-directory=/boot/efi \
  --modules="${MODULES}" --sbat /usr/share/grub/sbat.csv

grub-mkconfig -o /boot/grub/grub.cfg

Diagnostic: Verify GRUB build

ls -lh /boot/efi/EFI/Manjaro/grubx64.efi
# Should be ~2MB (indicates modules are embedded)
# A tiny ~160KB binary means modules were NOT embedded

objdump -h /boot/efi/EFI/Manjaro/grubx64.efi | grep sbat
# Should show an .sbat section

Step 3: Sign GRUB

sbsign --key /usr/share/secureboot/keys/MOK.key \
       --cert /usr/share/secureboot/keys/MOK.crt \
       --output /boot/efi/EFI/Manjaro/grubx64.efi \
       /boot/efi/EFI/Manjaro/grubx64.efi

Diagnostic: Verify GRUB signature

sbverify --list /boot/efi/EFI/Manjaro/grubx64.efi
# Should show: subject: /CN=Manjaro MOK

sbverify --cert /usr/share/secureboot/keys/MOK.crt /boot/efi/EFI/Manjaro/grubx64.efi
# Should show: Signature verification OK

Step 4: Sign Kernels (Correctly!)

Critical: Modern kernels have PE/COFF gaps. In-place signing corrupts the signature. Always sign to a temp file, then replace.

for kernel in /boot/vmlinuz-*; do
    echo "=== Signing $kernel ==="
    # Remove any existing (potentially bad) signature
    sbattach --remove "$kernel" 2>/dev/null

    # Sign to temp file, then move (avoids in-place corruption)
    sbsign --key /usr/share/secureboot/keys/MOK.key \
           --cert /usr/share/secureboot/keys/MOK.crt \
           --output "${kernel}.signed" \
           "$kernel"
    mv "${kernel}.signed" "$kernel"
done

Diagnostic: Verify kernel signatures

for k in /boot/vmlinuz-*; do
    echo "=== $k ==="
    sbverify --cert /usr/share/secureboot/keys/MOK.crt "$k" 2>&1
done
# ALL must show: Signature verification OK
# The "data remaining / gaps between PE/COFF sections" warning on newer kernels is normal

Step 5: Place Shim Files

Shim and GRUB must be in the same directory. Shim automatically loads grubx64.efi from its own directory.

# Copy shim and MokManager next to GRUB
cp /usr/share/shim-signed/shimx64.efi /boot/efi/EFI/Manjaro/shimx64.efi
cp /usr/share/shim-signed/mmx64.efi /boot/efi/EFI/Manjaro/mmx64.efi

# Also set up the UEFI fallback boot path
cp /usr/share/shim-signed/shimx64.efi /boot/efi/EFI/boot/bootx64.efi
cp /boot/efi/EFI/Manjaro/grubx64.efi /boot/efi/EFI/boot/grubx64.efi
cp /usr/share/shim-signed/mmx64.efi /boot/efi/EFI/boot/mmx64.efi

Diagnostic: Verify EFI layout

find /boot/efi/EFI/Manjaro/ /boot/efi/EFI/boot/ -type f -name "*.efi" | sort
# Expected:
#   /boot/efi/EFI/Manjaro/grubx64.efi    (~2MB, your signed GRUB)
#   /boot/efi/EFI/Manjaro/mmx64.efi      (MokManager)
#   /boot/efi/EFI/Manjaro/shimx64.efi    (shim)
#   /boot/efi/EFI/boot/bootx64.efi       (copy of shim, UEFI fallback)
#   /boot/efi/EFI/boot/grubx64.efi       (copy of signed GRUB)
#   /boot/efi/EFI/boot/mmx64.efi         (copy of MokManager)

sbverify --list /boot/efi/EFI/Manjaro/shimx64.efi 2>&1 | head -5
# Should show: Microsoft Corporation UEFI CA

sbverify --list /boot/efi/EFI/Manjaro/grubx64.efi 2>&1 | head -5
# Should show: /CN=Manjaro MOK

Step 6: Update UEFI Boot Entry

The existing Manjaro entry must point to shim, not directly to GRUB. Do NOT create a separate "Shim" entry — just update the Manjaro one.

# Check current entry
efibootmgr -v | grep -i manjaro
# Note the boot number (e.g., Boot0000)

# Delete and recreate pointing to shim
efibootmgr --delete-bootnum --bootnum 0000
efibootmgr --unicode --disk /dev/nvme0n1 --part 1 \
  --create --label "Manjaro" --loader /EFI/Manjaro/shimx64.efi

Diagnostic: Verify boot entries

efibootmgr -v
# Manjaro entry should point to \EFI\Manjaro\shimx64.efi
# Windows entry should still point to \EFI\Microsoft\Boot\bootmgfw.efi

Step 7: Enroll MOK Key in Shim's Trust Store

Shim has its own key database separate from the UEFI firmware. Even if the key is in the firmware's db, shim needs it enrolled in its MOK list too.

mokutil --import /usr/share/secureboot/keys/MOK.cer
# Enter a one-time password (you'll need it at next boot)

On reboot, shim will present the MokManager screen:

  1. Select "Enroll MOK"
  2. Select "Continue"
  3. Select "Yes"
  4. Enter the password you just set
  5. Select "Reboot"

Diagnostic: Verify MOK enrollment (after reboot)

mokutil --list-enrolled | grep "CN=Manjaro MOK"
# Should show your key

mokutil --test-key /usr/share/secureboot/keys/MOK.cer
# Should show: /usr/share/secureboot/keys/MOK.cer is already in db

Step 8: Enroll MOK Key in ASUS Firmware DB

This is required in addition to shim's MOK enrollment. The firmware needs to trust shim, and shim needs to trust your GRUB and kernels.

ASUS BIOS Steps:

  1. Reboot into BIOS (press Del or F2 at POST)
  2. Go to Advanced tab → Secure Boot (or Boot tab, varies by model)
  3. Set Secure Boot Mode to Custom
  4. Enter Key Management
  5. Select Authorized Signatures (db)
  6. Select Append (⚠️ NOT "Replace" — that would delete Microsoft's keys and break Windows!)
  7. Navigate to your EFI partition and select keys/MOK.cer
  8. When asked "Input File Format", select "Public Key Certificate"
  9. Confirm the enrollment
  10. Set Secure Boot to Enabled
  11. Save & Exit (F10)

Step 9: Verify Everything Works

Boot into Manjaro with Secure Boot enabled, then verify:

# Secure Boot should be enabled
mokutil --sb-state
# Expected: SecureBoot enabled

# Key should be in firmware db
mokutil --test-key /usr/share/secureboot/keys/MOK.cer
# Expected: already in db

# Boot chain verification
dmesg | grep -i "secure boot"
# Should indicate Secure Boot is active

Boot into Windows to verify it still works (it should — we appended to db, didn't replace).


Pacman Hooks (Auto-Signing on Updates)

Kernel Signing Hook

Create /etc/pacman.d/hooks/999-signKernel.hook:

[Trigger]
Type = Package
Operation = Install
Operation = Upgrade
Operation = Remove
Target = linux*

[Action]
Description = Signing kernel with MOK for Secure Boot
When = PostTransaction
Exec = /bin/bash -c 'for k in /boot/vmlinuz-*; do sbattach --remove "$k" 2>/dev/null; sbsign --key /usr/share/secureboot/keys/MOK.key --cert /usr/share/secureboot/keys/MOK.crt --output "${k}.signed" "$k" && mv "${k}.signed" "$k"; done'
Depends = sbsigntools

Note: This hook uses the temp-file signing method to avoid in-place corruption on kernels with PE/COFF gaps.

GRUB Signing Hook

Create /etc/pacman.d/hooks/1000-signGrub.hook:

[Trigger]
Operation = Install
Operation = Upgrade
Operation = Remove
Type = Path
Target = /boot/efi/EFI/Manjaro/grubx64.efi

[Action]
Description = Signing GRUB with MOK for Secure Boot
When = PostTransaction
Exec = /usr/share/secureboot/signGrub.sh
Depends = sbsigntools
Depends = findutils
Depends = grep
Depends = grub

Create /usr/share/secureboot/signGrub.sh:

#!/bin/bash

MODULES="all_video boot btrfs cat chain configfile cpuid cryptodisk echo \
efifwsetup efinet ext2 fat font gcry_arcfour gcry_blowfish gcry_camellia \
gcry_cast5 gcry_crc gcry_des gcry_dsa gcry_idea gcry_md4 gcry_md5 \
gcry_rfc2268 gcry_rijndael gcry_rmd160 gcry_rsa gcry_seed gcry_serpent \
gcry_sha1 gcry_sha256 gcry_sha512 gcry_tiger gcry_twofish gcry_whirlpool \
gettext gfxmenu gfxterm gfxterm_background gzio halt help hfsplus iso9660 \
jpeg keystatus linux loadenv loopback ls lsefi lsefimmap lsefisystab lssal \
luks luks2 lvm mdraid09 mdraid1x memdisk minicmd normal ntfs part_apple \
part_gpt part_msdos password_pbkdf2 play png probe raid5rec raid6rec reboot \
regexp search search_fs_file search_fs_uuid search_label serial sleep smbios \
squash4 test tpm true video xfs zfs zfscrypt zfsinfo efi_gop efi_uga \
video_bochs video_cirrus bli"

if ! /usr/bin/sbverify --list /boot/efi/EFI/Manjaro/grubx64.efi 2>/dev/null | /usr/bin/grep -q "signature certificates"; then
    /usr/bin/grub-install --target=x86_64-efi --efi-directory=/boot/efi/ \
      --modules="${MODULES}" --sbat /usr/share/grub/sbat.csv
    /usr/bin/sbsign --key /usr/share/secureboot/keys/MOK.key \
      --cert /usr/share/secureboot/keys/MOK.crt \
      --output /boot/efi/EFI/Manjaro/grubx64.efi \
      /boot/efi/EFI/Manjaro/grubx64.efi
    /usr/bin/cp /boot/efi/EFI/Manjaro/grubx64.efi /boot/efi/EFI/boot/grubx64.efi
fi
chmod +x /usr/share/secureboot/signGrub.sh

Full Diagnostic Script

Run this anytime to check the health of your Secure Boot setup:

sudo bash -c '
echo "========================================="
echo "  Secure Boot Diagnostic"
echo "========================================="

echo ""
echo "=== Secure Boot State ==="
mokutil --sb-state 2>/dev/null

echo ""
echo "=== Boot Entries ==="
efibootmgr -v | grep "^Boot"

echo ""
echo "=== EFI Layout ==="
find /boot/efi/EFI/Manjaro/ /boot/efi/EFI/boot/ -type f -name "*.efi" 2>/dev/null | sort

echo ""
echo "=== GRUB Size & Signature ==="
ls -lh /boot/efi/EFI/Manjaro/grubx64.efi
sbverify --list /boot/efi/EFI/Manjaro/grubx64.efi 2>&1 | grep -A2 "subject"

echo ""
echo "=== Shim Signature ==="
sbverify --list /boot/efi/EFI/Manjaro/shimx64.efi 2>&1 | grep -A2 "issuer" | head -3

echo ""
echo "=== Kernel Signatures ==="
for k in /boot/vmlinuz-*; do
    echo "--- $(basename $k) ---"
    sbverify --cert /usr/share/secureboot/keys/MOK.crt "$k" 2>&1
done

echo ""
echo "=== MOK Key Fingerprint ==="
openssl x509 -in /usr/share/secureboot/keys/MOK.crt -noout -fingerprint -sha1

echo ""
echo "=== MOK Enrolled in Shim? ==="
mokutil --list-enrolled 2>/dev/null | grep "SHA1 Fingerprint"

echo ""
echo "=== MOK in Firmware DB? ==="
mokutil --test-key /usr/share/secureboot/keys/MOK.cer 2>/dev/null

echo ""
echo "=== GRUB Modules Check ==="
echo "Modules in grub.cfg that are BIOS-only (expected to be missing):"
for mod in $(grep -oP "insmod \K\S+" /boot/grub/grub.cfg | sort -u); do
    [ ! -f "/usr/lib/grub/x86_64-efi/${mod}.mod" ] && echo "  $mod (BIOS-only, harmless)"
done

echo ""
echo "========================================="
echo "  Done"
echo "========================================="
'

Troubleshooting

Error Cause Fix
"shim protocols not found" GRUB launched directly, not through shim Boot entry must point to shimx64.efi, not grubx64.efi
"bad shim lock signature" Kernel signature is invalid or signed with wrong key Re-sign kernels using temp-file method (Step 4)
Silent loop back to GRUB menu GRUB can't load external modules in lockdown mode Rebuild GRUB with all modules embedded (Step 2)
"alloc magic is broken" GRUB binary too large / memory corruption Reduce module count; remove modules not in /usr/lib/grub/x86_64-efi/
Signature verification failed (sbverify) In-place signing corrupted the signature Strip signature with sbattach --remove, re-sign to temp file
Windows won't boot Microsoft keys removed from firmware db Re-enter BIOS → Secure Boot → Restore Factory Keys, then re-append your MOK.cer

Key Files Reference

File Location Purpose
MOK private key /usr/share/secureboot/keys/MOK.key Signs GRUB and kernels
MOK cert (PEM) /usr/share/secureboot/keys/MOK.crt Used by sbsign
MOK cert (DER) /usr/share/secureboot/keys/MOK.cer Enrolled in firmware db and shim
MOK cert on ESP /boot/efi/keys/MOK.cer Accessible from BIOS for enrollment
Shim /boot/efi/EFI/Manjaro/shimx64.efi Microsoft-signed first-stage loader
MokManager /boot/efi/EFI/Manjaro/mmx64.efi Key enrollment tool
GRUB /boot/efi/EFI/Manjaro/grubx64.efi MOK-signed bootloader
GRUB config /boot/grub/grub.cfg Generated by grub-mkconfig
GRUB defaults /etc/default/grub Input for grub-mkconfig
Kernel signing hook /etc/pacman.d/hooks/999-signKernel.hook Auto-signs on kernel update
GRUB signing hook /etc/pacman.d/hooks/1000-signGrub.hook Auto-signs on GRUB update
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment