Skip to content

Instantly share code, notes, and snippets.

@timsonner
Created April 30, 2026 06:40
Show Gist options
  • Select an option

  • Save timsonner/465ed1dc64cf073c0b0401b12e41a0d5 to your computer and use it in GitHub Desktop.

Select an option

Save timsonner/465ed1dc64cf073c0b0401b12e41a0d5 to your computer and use it in GitHub Desktop.
Sets up a Machine Owner Key (MOK) to sign DKMS modules (nvidia, evdi)
#!/bin/bash
# fix-secureboot-mok.sh
#
# Sets up a Machine Owner Key (MOK) to sign DKMS modules (nvidia, evdi)
# so they load under Secure Boot on Proxmox VE / Debian trixie.
#
# Root cause: Secure Boot requires all kernel modules to be signed by a key
# trusted by the UEFI firmware. DKMS-built modules (nvidia, evdi/DisplayLink)
# are unsigned by default. A MOK enrolled in shim's MOK database fills this gap.
#
# Process:
# 1. Generate RSA-2048 MOK key pair
# 2. Configure DKMS to auto-sign future module builds with the key
# 3. Sign all currently installed DKMS modules (nvidia + evdi)
# 4. Enroll the certificate into the MOK database (requires reboot + UEFI prompt)
#
# Usage:
# sudo ./fix-secureboot-mok.sh
#
# After running:
# - Reboot
# - At the blue "Perform MOK management" screen: choose "Enroll MOK"
# then enter the password you set when prompted
# - System will reboot into Secure Boot with signed modules
#
# Requirements:
# - mokutil, openssl installed
# - DKMS modules already built (dkms status shows "installed")
# - Secure Boot NOT yet enabled (enable it after the MOK is enrolled)
set -e
KERNEL=$(uname -r)
MOK_DIR="/root/mok"
MOK_KEY="$MOK_DIR/mok.key"
MOK_CERT="$MOK_DIR/mok.crt" # PEM — used by sign-file
MOK_DER="$MOK_DIR/mok.der" # DER — required by mokutil
SIGN_HELPER="/etc/dkms/sign_helper.sh"
SIGN_FILE=$(find /usr/src/linux-headers-*/scripts/sign-file 2>/dev/null | sort -V | tail -1)
if [ "$(id -u)" -ne 0 ]; then
echo "Error: run as root (sudo $0)" >&2
exit 1
fi
echo "=== Step 1: Install dependencies ==="
apt-get install -y --no-install-recommends mokutil openssl
echo "OK"
echo ""
echo "=== Step 2: Generate MOK key pair ==="
if [ -f "$MOK_KEY" ] && [ -f "$MOK_CERT" ]; then
echo "MOK key already exists at $MOK_DIR — skipping generation."
echo "Delete $MOK_DIR and re-run to regenerate."
else
mkdir -p "$MOK_DIR"
chmod 700 "$MOK_DIR"
openssl req -new -x509 -newkey rsa:2048 \
-keyout "$MOK_KEY" \
-out "$MOK_CERT" \
-days 3650 \
-subj "/CN=DKMS MOK $(hostname)/" \
-nodes
chmod 600 "$MOK_KEY"
chmod 644 "$MOK_CERT"
# Convert to DER format — mokutil requires DER, not PEM
openssl x509 -in "$MOK_CERT" -outform DER -out "$MOK_DER"
chmod 644 "$MOK_DER"
echo "Generated: $MOK_KEY"
echo "Generated: $MOK_CERT (PEM)"
echo "Generated: $MOK_DER (DER)"
fi
# If DER is missing but PEM exists (re-run scenario), regenerate DER
if [ -f "$MOK_CERT" ] && [ ! -f "$MOK_DER" ]; then
openssl x509 -in "$MOK_CERT" -outform DER -out "$MOK_DER"
chmod 644 "$MOK_DER"
echo "Regenerated: $MOK_DER (DER)"
fi
echo ""
echo "=== Step 3: Locate sign-file tool ==="
if [ -z "$SIGN_FILE" ]; then
echo "Error: sign-file not found. Install linux-headers-$KERNEL" >&2
exit 1
fi
echo "Using: $SIGN_FILE"
echo ""
echo "=== Step 4: Configure DKMS auto-signing ==="
# Write the sign helper script DKMS calls for each module
cat > "$SIGN_HELPER" <<EOF
#!/bin/sh
# DKMS sign helper — calls kernel sign-file with the MOK key
exec "$SIGN_FILE" sha256 "$MOK_KEY" "$MOK_CERT" "\$@"
EOF
chmod +x "$SIGN_HELPER"
echo "Wrote $SIGN_HELPER"
# Configure DKMS framework to use the sign helper and MOK
FRAMEWORK_CONF="/etc/dkms/framework.conf.d/mok-signing.conf"
mkdir -p /etc/dkms/framework.conf.d
cat > "$FRAMEWORK_CONF" <<EOF
# MOK signing for Secure Boot — generated by fix-secureboot-mok.sh
mok_signing_key="$MOK_KEY"
mok_certificate="$MOK_CERT"
sign_tool="$SIGN_HELPER"
EOF
echo "Wrote $FRAMEWORK_CONF"
echo ""
echo "=== Step 5: Sign currently installed DKMS modules ==="
MODULES_TO_SIGN=$(dkms status | grep "$(uname -r)" | grep 'installed' | \
awk -F'[/,]' '{print $1}' | sort -u)
echo "Modules to sign for kernel $KERNEL: $MODULES_TO_SIGN"
echo ""
sign_module() {
local path="$1"
if [ ! -f "$path" ]; then
echo " Skipping (not found): $path"
return
fi
"$SIGN_FILE" sha256 "$MOK_KEY" "$MOK_CERT" "$path" && \
echo " Signed: $(basename $path)" || \
echo " Warning: failed to sign $path"
}
for mod_name in $MODULES_TO_SIGN; do
echo "-- $mod_name --"
find /lib/modules/"$KERNEL" -name "${mod_name}.ko" -o -name "${mod_name}.ko.xz" \
-o -name "${mod_name}.ko.zst" 2>/dev/null | while read -r ko; do
# Decompress if needed, sign, recompress
case "$ko" in
*.ko.zst)
zstd -d "$ko" -o "${ko%.zst}" --force -q
sign_module "${ko%.zst}"
zstd "${ko%.zst}" -o "$ko" --force -q
rm -f "${ko%.zst}"
;;
*.ko.xz)
xz -d "$ko"
sign_module "${ko%.xz}"
xz "${ko%.xz}"
;;
*.ko)
sign_module "$ko"
;;
esac
done
done
echo ""
echo "=== Step 6: Enroll MOK certificate ==="
echo ""
echo "You will be prompted to set a one-time enrollment password."
echo "You'll need to enter this password at the UEFI screen after reboot."
echo ""
# mokutil requires DER format (not PEM)
mokutil --import "$MOK_DER"
echo ""
echo "=== Done ==="
echo ""
echo "NEXT STEPS:"
echo ""
echo " 1. Reboot now:"
echo " sudo reboot"
echo ""
echo " 2. At the blue 'Perform MOK management' UEFI screen:"
echo " - Select 'Enroll MOK'"
echo " - Select 'Continue'"
echo " - Enter the password you just set"
echo " - Select 'Yes' to enroll"
echo " - Select 'Reboot'"
echo ""
echo " 3. After reboot, enable Secure Boot in your BIOS/UEFI settings."
echo ""
echo " 4. Verify modules loaded:"
echo " mokutil --sb-state # should say SecureBoot enabled"
echo " lsmod | grep nvidia # should show nvidia modules"
echo " lsmod | grep evdi # should show evdi"
echo ""
echo " Future DKMS builds will be signed automatically."
echo " MOK key stored at: $MOK_DIR (keep this secure)"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment