Fixing NVIDIA Drivers Under Secure Boot and Preventing Windows from Breaking EFI Boot Order
1. Identify the correct NVIDIA driver and install a DKMS build.
List suggestions from Ubuntu:
ubuntu-drivers listInstall the recommended one automatically:
sudo ubuntu-drivers autoinstallOr install a specific version, replace XXX with the version number:
sudo apt install nvidia-driver-XXXVerify the installed package:
dpkg -l | grep nvidia-driver
2. Pin the driver so apt does not change it later.
Replace XXX with your version.
sudo apt-mark hold nvidia-driver-XXXCheck that hold is active:
apt-mark showhold
3. Create and enroll a MOK key for Secure Boot module signing.
I keep keys in ~/mok and then copy to /etc/secureboot.
Generate the keypair in your home directory::
mkdir -p ~/mok cd ~/mok openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -nodes -days 36500 -subj "/CN=Local Secure Boot MOK/"Enroll the public key with shim. You will confirm on next reboot in the blue MOK manager screen:
sudo mokutil --import MOK.derAfter enrolling and rebooting, verify state:
mokutil --sb-state mokutil --list-enrolled | grep -A2 "Local Secure Boot MOK"
Copy the keypair to a secure system location so the signing script can always find it.
Preferred location:
sudo cp ~/mok/MOK.priv ~/mok/MOK.der /etc/secureboot/ sudo chmod 600 /etc/secureboot/MOK.*Alternative fallback location:
sudo cp ~/mok/MOK.* /root/ sudo chmod 600 /root/MOK.*4. Install the signing script that signs NVIDIA DKMS modules after builds.
Manually signing every module after a kernel update is time-consuming and easy to forget. A simple shell script can automate the task by scanning the NVIDIA modules and signing them with your MOK key. It also handles compressed files, so it works across Ubuntu versions. Once in place you can run it by hand whenever you need. Later it will be connected to DKMS so the process happens automatically.
Create /usr/local/bin/sign-nvidia-modules:
sudo tee /usr/local/bin/sign-nvidia-modules >/dev/null <<'EOF' #!/usr/bin/env bash set -euo pipefail MOK_PRIV="${MOK_PRIV:-/etc/secureboot/MOK.priv}" MOK_DER="${MOK_DER:-/etc/secureboot/MOK.der}" # Fallback if keys are still in root: if [[ ! -f "$MOK_PRIV" || ! -f "$MOK_DER" ]]; then if [[ -f "/root/MOK.priv" && -f "/root/MOK.der" ]]; then MOK_PRIV="/root/MOK.priv" MOK_DER="/root/MOK.der" fi fi # Find sign-file SIGN_FILE="" for CAND in "/usr/src/linux-headers-$(uname -r)/scripts/sign-file" "/lib/modules/$(uname -r)/build/scripts/sign-file"; do [[ -x "$CAND" ]] && SIGN_FILE="$CAND" && break done if [[ -z "$SIGN_FILE" ]]; then echo "sign-file helper not found. Install linux-headers-$(uname -r)." >&2 exit 1 fi if [[ ! -f "$MOK_PRIV" || ! -f "$MOK_DER" ]]; then echo "MOK keypair not found at $MOK_PRIV / $MOK_DER" >&2 exit 1 fi KVER="${1:-$(uname -r)}" MODDIR="/lib/modules/${KVER}/updates/dkms" [[ -d "$MODDIR" ]] || { echo "No DKMS dir at $MODDIR. Nothing to sign."; exit 0; } shopt -s nullglob mapfile -t MODS < <(find "$MODDIR" -type f \( -name "*.ko" -o -name "*.ko.zst" \) | sort) if (( ${#MODS[@]} == 0 )); then echo "No modules to sign under $MODDIR." exit 0 fi echo "[nvidia-sign] Using: $SIGN_FILE" for m in "${MODS[@]}"; do if [[ "$m" == *.ko.zst ]]; then echo "[nvidia-sign] Decompressing $m" /usr/bin/zstd -d --rm "$m" m="${m%.zst}" fi echo "[nvidia-sign] Signing $(basename "$m")" "$SIGN_FILE" sha256 "$MOK_PRIV" "$MOK_DER" "$m" if command -v zstd >/dev/null; then /usr/bin/zstd -T0 -q -f "$m" fi done depmod "$KVER" echo "[nvidia-sign] Done for $KVER" EOFSecure the keys and script permissions:
sudo mkdir -p /etc/secureboot
sudo cp ~/mok/MOK.* /etc/secureboot/
sudo chmod 600 /etc/secureboot/MOK.*
sudo chmod 755 /usr/local/bin/sign-nvidia-modules
5. Hook DKMS so every build is auto-signed.
Create a post-build hook:
sudo install -d -m 755 /etc/dkms/post-build.d
sudo tee /etc/dkms/post-build.d/zz-nvidia-sign >/dev/null <<'EOF' #!/usr/bin/env bash # DKMS sets kernelver or KERNELRELEASE KV="${kernelver:-${KERNELRELEASE:-}}" if [[ -n "$KV" ]]; then /usr/local/bin/sign-nvidia-modules "$KV" else /usr/local/bin/sign-nvidia-modules fi EOF
sudo chmod 755 /etc/dkms/post-build.d/zz-nvidia-signForce a DKMS rebuild to test the hook:
sudo dkms autoinstall
6. Verify signatures and module load.
After setting up automatic signing you should confirm that it is working. The command modinfo shows the digital signature on each module, including the name of the signer. In your case it should display the MOK you enrolled earlier. You should also check with lsmod that the NVIDIA modules are active in memory. This double check makes sure both the signing and the driver loading are functioning properly.
Check signature fields:
modinfo /lib/modules/$(uname -r)/updates/dkms/nvidia.ko 2>/dev/null | grep -E "signer|sig_key|sig_hash"Expected signer:
signer: Local Secure Boot MOKConfirm modules are present:
lsmod | grep -E "^nvidia|nvidia_drm|nvidia_modeset"
7. Prevent Windows from changing EFI BootOrder and MOK lists.
The biggest external problem is Windows, which writes to EFI variables every time it boots. This can reset your boot order and sometimes even clear your enrolled MOK keys. Disabling Fast Startup reduces this risk but does not always eliminate it. A stronger option is to lock the EFI variables from Linux so Windows cannot change them. By freezing BootOrder and MOK variables you make sure your Linux system always starts first and the keys remain intact.
In Windows, disable Fast Startup:
powercfg /h offBack in Linux, set the correct boot order and then freeze EFI variables. First, list and note IDs like Boot0002 for neon and Boot0000 for Windows:
sudo efibootmgr -vSet neon first, example only:
sudo efibootmgr -o 0002,0000Make variables immutable so Windows cannot rewrite them:
sudo chattr +i /sys/firmware/efi/efivars/BootOrder-*
sudo chattr +i /sys/firmware/efi/efivars/Boot0002-*
sudo chattr +i /sys/firmware/efi/efivars/Boot0000-*Protect MOK lists too:
sudo chattr +i /sys/firmware/efi/efivars/MokList*
sudo chattr +i /sys/firmware/efi/efivars/MokSB*If you need to edit later, remove immutability first:
sudo chattr -i /sys/firmware/efi/efivars/BootOrder-*
8. Common problems and fixes.
Secure Boot denies NVIDIA after a kernel update:
mokutil --list-enrolled | grep -A2 "Local Secure Boot MOK"
sudo apt install "linux-headers-$(uname -r)"
sudo /usr/local/bin/sign-nvidia-modulesDKMS hook did not run:
sudo chmod 755 /etc/dkms/post-build.d/zz-nvidia-sign
sudo dkms autoinstallFollowing these steps ensures that NVIDIA drivers load under Secure Boot and remain stable across updates. You keep control over which driver version is used, and you have a trusted key that allows the modules to load. Automatic signing through DKMS prevents future problems after kernel upgrades. Protecting EFI variables stops Windows from undoing your work. Together these measures create a reliable dual-boot setup where both Linux and Windows function without conflict.
Comments
Post a Comment