Created
July 19, 2026 11:55
-
-
Save timsonner/661d15b1a2be66f5469889ccfa516d2b to your computer and use it in GitHub Desktop.
fix broken nvidia install ubuntu 26.04
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
| #!/usr/bin/env bash | |
| # Fix NVIDIA RTX 3050 Mobile on Ubuntu 26.04 (XPS 15 9520) | |
| # Root causes found: | |
| # 1) GRUB has nomodeset -> disables KMS (i915 + nvidia-drm) | |
| # 2) DKMS nvidia modules signed with a private key obscure Canonical-signed modules | |
| # 3) Secure Boot is ON and MOK only has Canonical CA -> DKMS modules cannot load | |
| # 4) Partial server/headless stack installed instead of full desktop driver | |
| set -euo pipefail | |
| if [[ ${EUID:-$(id -u)} -ne 0 ]]; then | |
| echo "Re-running with sudo..." | |
| exec sudo -E bash "$0" "$@" | |
| fi | |
| export DEBIAN_FRONTEND=noninteractive | |
| KVER="$(uname -r)" | |
| LOG="/home/tim/fix-nvidia-driver.log" | |
| exec > >(tee -a "$LOG") 2>&1 | |
| echo "===== NVIDIA driver fix starting $(date) =====" | |
| echo "Kernel: $KVER" | |
| echo "Secure Boot: $(mokutil --sb-state 2>/dev/null || true)" | |
| echo | |
| echo "[1/7] Remove nomodeset from GRUB" | |
| if grep -q 'nomodeset' /etc/default/grub; then | |
| cp -a /etc/default/grub "/etc/default/grub.bak.$(date +%Y%m%d%H%M%S)" | |
| sed -i 's/\bnomodeset\b//g' /etc/default/grub | |
| # collapse leftover double spaces inside the quotes | |
| sed -i -E 's/(GRUB_CMDLINE_LINUX_DEFAULT=")[ ]+/\1/; s/[ ]+(")/\1/; s/ +/ /g' /etc/default/grub | |
| grep '^GRUB_CMDLINE' /etc/default/grub || true | |
| else | |
| echo "nomodeset already absent" | |
| fi | |
| # also scrub any leftover copies | |
| if [[ -f /etc/default/grub.ucf-dist ]]; then | |
| sed -i 's/\bnomodeset\b//g' /etc/default/grub.ucf-dist || true | |
| fi | |
| update-grub | |
| echo | |
| echo "[2/7] Remove broken DKMS NVIDIA tree that overrides signed modules" | |
| if dkms status 2>/dev/null | grep -qi nvidia; then | |
| dkms status || true | |
| # remove all installed nvidia dkms versions for this and any kernel | |
| while read -r line; do | |
| # formats like: nvidia/595.71.05, 7.0.0-28-generic, x86_64: installed | |
| ver="$(echo "$line" | awk -F'[/ ,]' '{print $2}')" | |
| k="$(echo "$line" | awk -F'[, ]+' '{print $2}')" | |
| if [[ -n "${ver:-}" ]]; then | |
| echo "dkms remove nvidia/$ver -k ${k:-$KVER} || dkms remove nvidia/$ver --all" | |
| dkms remove "nvidia/$ver" -k "${k:-$KVER}" 2>/dev/null \ | |
| || dkms remove "nvidia/$ver" --all 2>/dev/null \ | |
| || true | |
| fi | |
| done < <(dkms status 2>/dev/null | grep -i '^nvidia' || true) | |
| fi | |
| rm -rf /var/lib/dkms/nvidia || true | |
| rm -rf /usr/src/nvidia-595.71.05 || true | |
| # wipe updates/dkms overrides so depmod prefers Canonical-signed modules | |
| if [[ -d /lib/modules/$KVER/updates/dkms ]]; then | |
| rm -f /lib/modules/$KVER/updates/dkms/nvidia*.ko* || true | |
| rmdir /lib/modules/$KVER/updates/dkms 2>/dev/null || true | |
| fi | |
| depmod -a "$KVER" | |
| echo | |
| echo "[3/7] Purge partial server/headless NVIDIA packages" | |
| apt-get update -y | |
| # Keep firmware if possible; remove the broken stack metapackages | |
| apt-get purge -y \ | |
| 'nvidia-headless*' \ | |
| 'nvidia-kernel-source-*-server*' \ | |
| 'linux-modules-nvidia-*-server*' \ | |
| 'nvidia-compute-utils-*-server' \ | |
| 'libnvidia-compute-*-server' \ | |
| 'libnvidia-cfg1-*-server' \ | |
| 'nvidia-kernel-common-*-server' \ | |
| 'nvidia-firmware-*-server*' \ | |
| 2>/dev/null || true | |
| # Also catch any leftover nvidia packages that would conflict | |
| apt-get autoremove -y --purge || true | |
| echo | |
| echo "[4/7] Install Ubuntu-recommended signed desktop driver (595-open + prebuilt signed modules)" | |
| # Prefer prebuilt signed modules for this HWE kernel flavour so Secure Boot works | |
| # without enrolling a MOK key. | |
| apt-get install -y \ | |
| linux-modules-nvidia-595-open-generic-hwe-26.04 \ | |
| nvidia-driver-595-open \ | |
| nvidia-prime \ | |
| nvidia-settings | |
| echo | |
| echo "[5/7] Rebuild module deps and ensure blacklists are sane" | |
| depmod -a "$KVER" | |
| # nouveau should stay blacklisted (package conf handles it) | |
| if [[ ! -f /etc/modprobe.d/nvidia-blacklist.conf ]]; then | |
| cat >/etc/modprobe.d/nvidia-blacklist.conf <<'EOF' | |
| blacklist nouveau | |
| options nouveau modeset=0 | |
| EOF | |
| fi | |
| update-initramfs -u -k "$KVER" | |
| echo | |
| echo "[6/7] Configure prime for on-demand (laptop hybrid Intel+NVIDIA)" | |
| if command -v prime-select >/dev/null; then | |
| # on-demand is the right default for XPS 15 hybrid graphics | |
| prime-select on-demand || prime-select nvidia || true | |
| prime-select query || true | |
| fi | |
| echo | |
| echo "[7/7] Try loading modules now (may still need reboot after nomodeset removal)" | |
| # With nomodeset currently active in THIS boot, full modeset may still fail | |
| # until reboot — but Secure Boot + signed module path should work post-reboot. | |
| modprobe -r nouveau 2>/dev/null || true | |
| if modprobe nvidia; then | |
| echo "nvidia module loaded" | |
| modprobe nvidia-modeset || true | |
| modprobe nvidia-drm modeset=1 || modprobe nvidia-drm || true | |
| modprobe nvidia-uvm || true | |
| sleep 1 | |
| ls -la /dev/nvidia* 2>/dev/null || true | |
| nvidia-smi || true | |
| else | |
| echo "nvidia module failed to load on this live boot (expected if nomodeset still active)." | |
| echo "dmesg tail:" | |
| dmesg | tail -40 || true | |
| fi | |
| echo | |
| echo "===== Post-check =====" | |
| echo "Signed package modules:" | |
| modinfo -F signer "/lib/modules/$KVER/kernel/nvidia-"*"/nvidia.ko" 2>/dev/null || \ | |
| find "/lib/modules/$KVER" -path '*nvidia*/nvidia.ko' -exec modinfo -F filename {} \; -exec modinfo -F signer {} \; 2>/dev/null | head -20 | |
| echo "DKMS overrides left:" | |
| ls -la "/lib/modules/$KVER/updates/dkms/" 2>/dev/null || echo "(none)" | |
| echo "Current cmdline: $(cat /proc/cmdline)" | |
| echo "GRUB default cmdline:" | |
| grep '^GRUB_CMDLINE' /etc/default/grub || true | |
| echo | |
| echo "DONE. A reboot is required for nomodeset removal and clean driver bring-up." | |
| echo "After reboot run: nvidia-smi" | |
| echo "Log saved to: $LOG" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment