Created
April 30, 2026 06:40
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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