在 Ubuntu Linux 和 Alma/Rocky Linux 上安装 GPU NVIDIA 驱动和 CUDA¶
在这篇文章中
我们建议仅在 Ubuntu 22.04/24.04/26.04 的 LTS 版本上使用 Nvidia 显卡。若要在其他发行版上安装驱动,请使用我们为基于 CentOS 的 RPM 发行版编写的脚本,或遵循官方开发人员指南:
信息
警告
为了确保 Tesla 系列 GPU(例如 NVIDIA Tesla T4)正常运行,请确保在服务器 BIOS 中启用了“above 4G decoding”、“large/64bit BARs”或“Above 4G MMIO BIOS assignment”参数。
打开服务器控制台(通过原生控制台或 SSH),以 root 身份登录,复制下面的脚本,将其粘贴到命令行中,然后按 Enter 即可自动安装驱动和 CUDA。如果您的软件需要 docker 或 docker compose 才能工作,请在安装驱动**之前**安装它们,以便脚本可以将 GPU 支持“透传”给容器。
备注
如果您使用的命令行 Shell 不是 bash(例如 zsh 或其他),请通过执行 exec bash 切换到 bash 以运行脚本。
警告
在安装过程中,您可能需要按 Enter 以确认安装新的内核模块或重启服务。
Ubuntu Linux 安装脚本¶
#!/bin/bash
#===============================================================================
# Universal NVIDIA Driver + CUDA Installer for Ubuntu 22.04/24.04/26.04 LTS
# - Legacy GPUs (CC < 7.5): pinned driver + CUDA 12.9 (last branch supporting Pascal/Volta)
# - Blackwell GPUs: open kernel modules + latest CUDA
# - All other GPUs (incl. RTX A5000, CC 8.6): proprietary driver 580 + latest CUDA
# - cuda-drivers meta-package is NEVER installed (avoids pulling open modules)
#===============================================================================
set -euo pipefail
#-------------------------------------------------------------------------------
# CONFIGURATION FLAGS
#-------------------------------------------------------------------------------
DO_OS_POLICY_CHECK=1
ALLOWED_UBUNTU_VERSIONS=("22.04" "24.04" "26.04")
DO_APT_UPGRADE=1
DO_INSTALL_HWE=1
DO_INSTALL_KERNEL_HEADERS=1
DO_INSTALL_BUILD_TOOLS=1
DO_PURGE_OLD_PACKAGES=1
DO_SETUP_CUDA_REPO=1
DO_INSTALL_CUDA_STACK=1
# Legacy GPUs: pinned driver per card (CC < 7.5, CUDA 12.x only)
LEGACY_GPUS=(
"10de:1b06|GeForce GTX 1080 Ti|nvidia-driver-535"
"10de:1db1|Tesla V100|nvidia-driver-535"
"10de:1b80|GeForce GTX 1070|nvidia-driver-535"
"10de:1c03|GeForce GTX 1060|nvidia-driver-535"
)
# Blackwell GPUs: require open kernel modules
BLACKWELL_GPUS=(
"10de:2b85|GeForce RTX 5090"
"10de:2b87|GeForce RTX 5090 D"
"10de:2b84|GeForce RTX 5080"
"10de:2b83|GeForce RTX 5070 Ti"
"10de:2b82|GeForce RTX 5070"
"10de:2f80|GeForce RTX 5070 Laptop GPU"
"10de:2bb5|RTX PRO 6000 Blackwell Server Edition"
"10de:2bb4|RTX PRO 6000 Blackwell Workstation Edition"
"10de:2bb1|RTX PRO 6000 Blackwell Max-Q"
"10de:2bb3|RTX PRO 5000 Blackwell"
"10de:2c31|RTX PRO 4500 Blackwell"
"10de:2c37|RTX PRO 4000 Blackwell"
"10de:2c36|RTX PRO 3000 Blackwell"
"10de:2d30|RTX PRO 2000 Blackwell"
"10de:2c35|RTX PRO 2000 Blackwell (Alternative)"
"10de:2c3a|RTX PRO 4500 Blackwell Server Edition"
"10de:2c77|RTX PRO 5000 Blackwell Embedded GPU"
"10de:2c38|RTX PRO 5000 Blackwell Generation Laptop GPU"
"10de:2f38|RTX PRO 3000 Blackwell Generation Laptop GPU"
"10de:2db8|RTX PRO 1000 Blackwell Generation Laptop GPU"
)
DO_BLACKLIST_NOUVEAU=1
DO_TRY_RMMOD_NOUVEAU=1
DO_USER_GROUPS=0
DO_BASHRC_CUDA_PATHS=1
DO_VERIFY_NVIDIA_SMI=1
DO_VERIFY_NVCC=1
DO_INSTALL_NVIDIA_CONTAINER_TOOLKIT=1
DO_CONFIGURE_DOCKER_RUNTIME=1
DO_RESTART_DOCKER=1
# ---- Start ----
echo "Starting NVIDIA driver + CUDA installation (Non-Interactive)..."
#-------------------------------------------------------------------------------
# DEPENDENCY CHECK
#-------------------------------------------------------------------------------
for cmd in lspci wget gpg curl sed awk uname; do
command -v "$cmd" >/dev/null 2>&1 || { echo "Missing dependency: $cmd"; exit 1; }
done
#-------------------------------------------------------------------------------
# OS DETECTION
#-------------------------------------------------------------------------------
osr="/etc/os-release"
[[ -r "$osr" ]] || osr="/usr/lib/os-release"
[[ -r "$osr" ]] || { echo "Cannot read os-release file. Exiting."; exit 1; }
set -a
. "$osr"
set +a
[[ "${ID:-}" != "ubuntu" ]] && { echo "This script is intended for Ubuntu only. Exiting."; exit 1; }
UBUNTU_VERSION="${VERSION_ID:-}"
UBUNTU_CODENAME="${VERSION_CODENAME:-}"
if [[ -z "${UBUNTU_CODENAME}" ]]; then
case "${UBUNTU_VERSION}" in
"22.04") UBUNTU_CODENAME="jammy" ;;
"24.04") UBUNTU_CODENAME="noble" ;;
"26.04") UBUNTU_CODENAME="resolute" ;;
*) UBUNTU_CODENAME="unknown" ;;
esac
fi
[[ -z "${UBUNTU_VERSION}" ]] && { echo "Cannot detect Ubuntu VERSION_ID. Exiting."; exit 1; }
if [[ "${DO_OS_POLICY_CHECK:-0}" -eq 1 ]]; then
ok=0
for v in "${ALLOWED_UBUNTU_VERSIONS[@]}"; do
[[ "${UBUNTU_VERSION}" == "${v}" ]] && { ok=1; break; }
done
[[ "${ok}" -ne 1 ]] && { echo "Unsupported Ubuntu version: ${UBUNTU_VERSION}"; exit 1; }
fi
RELEASE_VERSION="$(echo "${UBUNTU_VERSION}" | sed 's/\([0-9]\+\)\.\([0-9]\+\)/\1\2/')"
echo "OS: Ubuntu ${UBUNTU_VERSION} (${UBUNTU_CODENAME})"
#-------------------------------------------------------------------------------
# GPU DETECTION
#-------------------------------------------------------------------------------
NVIDIA_GPU_LINES="$(lspci -nn | grep -iE 'vga|3d' | grep -i '10de:' || true)"
[[ -z "${NVIDIA_GPU_LINES}" ]] && { echo "No NVIDIA GPU detected (vendor 10de). Exiting."; exit 1; }
echo "NVIDIA GPUs detected:"
echo "${NVIDIA_GPU_LINES}"
DETECTED_GPUS="$(lspci -nn)"
REBOOT_REQUIRED=0
#-------------------------------------------------------------------------------
# SYSTEM PREPARATION
#-------------------------------------------------------------------------------
export DEBIAN_FRONTEND=noninteractive
export NEEDRESTART_MODE=a
if [[ "${DO_APT_UPGRADE}" -eq 1 ]]; then
echo "Updating system packages..."
sudo -E apt-get update
sudo -E apt-get upgrade -y \
-o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold"
fi
if [[ "${DO_INSTALL_HWE}" -eq 1 ]]; then
case "${UBUNTU_VERSION}" in
"22.04") HWE_PKG="linux-generic-hwe-22.04" ;;
"24.04") HWE_PKG="linux-generic-hwe-24.04" ;;
"26.04") HWE_PKG="" ;;
*) HWE_PKG="" ;;
esac
if [[ -n "${HWE_PKG}" ]]; then
echo "Installing HWE kernel: ${HWE_PKG}"
sudo -E apt-get install -y \
-o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" \
"${HWE_PKG}"
REBOOT_REQUIRED=1
fi
fi
if [[ "${DO_INSTALL_KERNEL_HEADERS}" -eq 1 ]]; then
CURRENT_KERNEL="$(uname -r)"
echo "Installing kernel headers for: ${CURRENT_KERNEL}"
sudo -E apt-get install -y \
-o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" \
"linux-headers-${CURRENT_KERNEL}" || {
echo "Failed to install linux-headers. DKMS may fail."; exit 1; }
fi
if [[ "${DO_INSTALL_BUILD_TOOLS}" -eq 1 ]]; then
case "${UBUNTU_VERSION}" in
"22.04") GCC_PACKAGES=("gcc-12" "g++-12") ;;
"24.04") GCC_PACKAGES=("gcc-13" "g++-13") ;;
"26.04") GCC_PACKAGES=("gcc-15" "g++-15") ;;
*) GCC_PACKAGES=("gcc" "g++") ;;
esac
echo "Installing build tools: ${GCC_PACKAGES[*]}"
sudo -E apt-get install -y -o Dpkg::Options::="--force-confdef" "${GCC_PACKAGES[@]}"
fi
#-------------------------------------------------------------------------------
# PURGE OLD PACKAGES
#-------------------------------------------------------------------------------
if [[ "${DO_PURGE_OLD_PACKAGES}" -eq 1 ]]; then
echo "Purging previous NVIDIA/CUDA installations..."
sudo dpkg --configure -a || true
sudo -E apt-get purge -y "nvidia-*" "libnvidia-*" "cuda-*" "nvidia-driver-*" "*cudnn*" "*nsight*" 2>/dev/null || true
sudo -E apt-get remove --purge -y nvidia-cuda-toolkit nvidia-prime nvidia-settings 2>/dev/null || true
sudo -E apt-get autoremove -y || true
sudo -E apt-get --fix-broken install -y || true
sudo -E apt-get clean -y || true
fi
#-------------------------------------------------------------------------------
# SETUP CUDA REPOSITORY
#-------------------------------------------------------------------------------
if [[ "${DO_SETUP_CUDA_REPO}" -eq 1 ]]; then
echo "Setting up CUDA repo for ubuntu${RELEASE_VERSION}..."
wget -q "https://developer.download.nvidia.com/compute/cuda/repos/ubuntu${RELEASE_VERSION}/x86_64/cuda-keyring_1.1-1_all.deb"
sudo dpkg -i cuda-keyring_1.1-1_all.deb 2>/dev/null || true
rm -f cuda-keyring_1.1-1_all.deb
sudo -E apt-get update
fi
#-------------------------------------------------------------------------------
# BLACKLIST NOUVEAU
#-------------------------------------------------------------------------------
if [[ "${DO_BLACKLIST_NOUVEAU}" -eq 1 ]]; then
BL_FILE="/etc/modprobe.d/blacklist-nouveau.conf"
if [[ ! -f "${BL_FILE}" ]] || ! grep -q "^blacklist nouveau" "${BL_FILE}" 2>/dev/null; then
echo "Blacklisting nouveau (requires reboot)..."
sudo tee "${BL_FILE}" >/dev/null <<'EOF'
blacklist nouveau
options nouveau modeset=0
EOF
sudo update-initramfs -u
REBOOT_REQUIRED=1
fi
fi
#-------------------------------------------------------------------------------
# INSTALL DRIVER
#-------------------------------------------------------------------------------
IS_BLACKWELL=0
IS_LEGACY=0
IS_PROPRIETARY=0
# 1) Blackwell: open modules
for gpu_spec in "${BLACKWELL_GPUS[@]}"; do
IFS='|' read -r pci_id gpu_name <<< "$gpu_spec"
if echo "$DETECTED_GPUS" | grep -q "$pci_id"; then
echo "Detected Blackwell GPU: $gpu_name ($pci_id)"
echo "Installing open kernel modules..."
sudo -E apt-get install -y -o Dpkg::Options::="--force-confdef" \
nvidia-open nvidia-driver-open nvidia-dkms-open
IS_BLACKWELL=1
break
fi
done
# 2) Legacy GPUs: pinned driver
if [[ "$IS_BLACKWELL" -eq 0 ]]; then
for gpu_spec in "${LEGACY_GPUS[@]}"; do
IFS='|' read -r pci_id gpu_name driver_pkg <<< "$gpu_spec"
if echo "$DETECTED_GPUS" | grep -q "$pci_id"; then
echo "Detected legacy GPU: $gpu_name ($pci_id) -> $driver_pkg"
sudo -E apt-get install -y -o Dpkg::Options::="--force-confdef" \
"$driver_pkg" "nvidia-dkms-${driver_pkg#nvidia-driver-}"
IS_LEGACY=1
break
fi
done
fi
# 3) Everything else: PROPRIETARY driver 580 (RTX A5000 falls here)
if [[ "$IS_BLACKWELL" -eq 0 && "$IS_LEGACY" -eq 0 ]]; then
echo "Detected non-Blackwell, non-legacy GPU (e.g., RTX A5000)."
echo "Installing proprietary driver 580..."
sudo -E apt-get install -y -o Dpkg::Options::="--force-confdef" \
nvidia-driver-580 nvidia-dkms-580
IS_PROPRIETARY=1
fi
#-------------------------------------------------------------------------------
# INSTALL CUDA TOOLKIT
# - Legacy (CC < 7.5): CUDA 12.9 (last branch supporting Pascal/Volta)
# - Blackwell / Proprietary (CC >= 7.5): latest cuda-toolkit meta-package
# - cuda-drivers is NEVER installed
#-------------------------------------------------------------------------------
if [[ "${DO_INSTALL_CUDA_STACK}" -eq 1 ]]; then
if [[ "$IS_LEGACY" -eq 1 ]]; then
echo "Installing CUDA Toolkit 12.9 (legacy path, last branch supporting Pascal/Volta)..."
sudo -E apt-get install -y -o Dpkg::Options::="--force-confdef" cuda-toolkit-12-9
else
echo "Installing latest available CUDA Toolkit (Blackwell/proprietary path)..."
sudo -E apt-get install -y -o Dpkg::Options::="--force-confdef" cuda-toolkit
fi
fi
#-------------------------------------------------------------------------------
# POST-INSTALL STEPS
#-------------------------------------------------------------------------------
if [[ "${DO_TRY_RMMOD_NOUVEAU}" -eq 1 ]]; then
sudo rmmod -f nouveau 2>/dev/null || true
fi
if [[ "${DO_USER_GROUPS}" -eq 1 ]]; then
TARGET_USER="${SUDO_USER:-$USER}"
sudo usermod -aG video,render "${TARGET_USER}" || true
echo "User ${TARGET_USER} added to video/render groups."
REBOOT_REQUIRED=1
fi
if [[ "${DO_BASHRC_CUDA_PATHS}" -eq 1 ]]; then
TARGET_USER="${SUDO_USER:-$USER}"
TARGET_HOME="$(getent passwd "${TARGET_USER}" | cut -d: -f6)"
TARGET_BASHRC="${TARGET_HOME}/.bashrc"
MARKER="NVIDIA CUDA Paths"
[[ -f "${TARGET_BASHRC}" ]] || sudo -u "${TARGET_USER}" touch "${TARGET_BASHRC}" || true
if ! grep -q "${MARKER}" "${TARGET_BASHRC}" 2>/dev/null; then
cat >> "${TARGET_BASHRC}" <<'EOF'
# NVIDIA CUDA Paths
export PATH="/usr/local/cuda/bin:$PATH"
export LD_LIBRARY_PATH="/usr/local/cuda/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
EOF
echo "Added CUDA PATH to ${TARGET_BASHRC}"
fi
fi
#-------------------------------------------------------------------------------
# VERIFICATION
#-------------------------------------------------------------------------------
if [[ "${DO_VERIFY_NVIDIA_SMI}" -eq 1 ]]; then
echo "Verifying nvidia-smi..."
nvidia-smi || true
fi
if [[ "${DO_VERIFY_NVCC}" -eq 1 ]]; then
if command -v nvcc >/dev/null 2>&1; then
echo "Verifying nvcc..."
nvcc -V || true
else
echo "nvcc not found in PATH yet (re-login/reboot may be needed)"
fi
fi
#-------------------------------------------------------------------------------
# NVIDIA CONTAINER TOOLKIT
#-------------------------------------------------------------------------------
if [[ "${DO_INSTALL_NVIDIA_CONTAINER_TOOLKIT}" -eq 1 ]]; then
if command -v docker >/dev/null 2>&1; then
echo "Docker detected: installing NVIDIA Container Toolkit..."
sudo -E apt-get update
sudo -E apt-get install -y -o Dpkg::Options::="--force-confdef" curl gnupg2
sudo install -d -m 0755 /usr/share/keyrings
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
| sudo gpg --dearmor --yes -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
| sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
| sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list >/dev/null
sudo -E apt-get update
sudo -E apt-get install -y -o Dpkg::Options::="--force-confdef" nvidia-container-toolkit
if [[ "${DO_CONFIGURE_DOCKER_RUNTIME}" -eq 1 ]]; then
command -v nvidia-ctk >/dev/null 2>&1 && sudo nvidia-ctk runtime configure --runtime=docker || true
fi
if [[ "${DO_RESTART_DOCKER}" -eq 1 ]]; then
sudo systemctl restart docker || true
fi
else
echo "Docker not found. Skipping container toolkit."
fi
fi
#-------------------------------------------------------------------------------
# FINAL
#-------------------------------------------------------------------------------
echo ""
echo "========================================"
echo "Installation finished"
echo "========================================"
if [[ "${REBOOT_REQUIRED}" -eq 1 ]]; then
echo ">> REBOOT REQUIRED: sudo reboot"
fi
echo "After reboot, verify with:"
echo " nvidia-smi"
echo " nvcc -V"
警告
运行脚本后,必须使用 sudo reboot 命令重启服务器。这是激活新内核模块所必需的。
重启后,请使用 nvidia-smi 和 nvcc -V 命令验证驱动和 CUDA 的安装情况。您应该会看到类似于以下内容的输出:
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 595.71.05 Driver Version: 595.71.05 CUDA Version: 13.2 |
+-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA GeForce RTX 4090 On | 00000000:07:00.0 Off | Off |
| 31% 27C P8 7W / 450W | 33MiB / 24564MiB | 0% Default |
| | | N/A |
+-----------------------------------------+------------------------+----------------------+
+-----------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
| No running processes found |
+-----------------------------------------------------------------------------------------+
以及
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2026 NVIDIA Corporation
Built on Thu_Mar_19_11:12:51_PM_PDT_2026
Cuda compilation tools, release 13.2, V13.2.78
Build cuda_13.2.r13.2/compiler.37668154_0
Alma/Rocky Linux 安装脚本¶
#!/bin/bash
#===============================================================================
# Universal NVIDIA Driver + CUDA Installer for AlmaLinux/Rocky Linux 9 & 10
# - Legacy GPUs (CC < 7.5): pinned proprietary driver (535-dkms) + CUDA 12.x
# - Blackwell GPUs: open kernel modules + latest CUDA
# - All other GPUs (incl. RTX A4000/A5000, CC 8.6): proprietary latest-dkms
# - Unknown GPUs: fall back to latest-dkms with an explicit DKMS build check
# - cuda-drivers meta-package is NEVER installed
#===============================================================================
set -euo pipefail
#-------------------------------------------------------------------------------
# CONFIGURATION FLAGS
#-------------------------------------------------------------------------------
DO_OS_POLICY_CHECK=1
ALLOWED_OS_MAJOR_VERSIONS=("9" "10")
DO_DNF_UPGRADE=1
DO_INSTALL_KERNEL_HEADERS=1
DO_INSTALL_BUILD_TOOLS=1
DO_PURGE_OLD_PACKAGES=1
DO_SETUP_CUDA_REPO=1
DO_INSTALL_CUDA_STACK=1
# Legacy GPUs: pinned driver per card (CC < 7.5, CUDA 12.x only).
# For RHEL 9, driver 535 is available via module stream. For RHEL 10,
# legacy support relies on whatever is available or RPM Fusion (not covered).
LEGACY_GPUS=(
"10de:1b06|GeForce GTX 1080 Ti|535"
"10de:1db1|Tesla V100|535"
"10de:1b80|GeForce GTX 1070|535"
"10de:1c03|GeForce GTX 1060|535"
)
# Blackwell GPUs: require open kernel modules
BLACKWELL_GPUS=(
"10de:2b85|GeForce RTX 5090"
"10de:2b87|GeForce RTX 5090 D"
"10de:2b84|GeForce RTX 5080"
"10de:2b83|GeForce RTX 5070 Ti"
"10de:2b82|GeForce RTX 5070"
"10de:2f80|GeForce RTX 5070 Laptop GPU"
"10de:2bb5|RTX PRO 6000 Blackwell Server Edition"
"10de:2bb4|RTX PRO 6000 Blackwell Workstation Edition"
"10de:2bb1|RTX PRO 6000 Blackwell Max-Q"
"10de:2bb3|RTX PRO 5000 Blackwell"
"10de:2c31|RTX PRO 4500 Blackwell"
"10de:2c37|RTX PRO 4000 Blackwell"
"10de:2c36|RTX PRO 3000 Blackwell"
"10de:2d30|RTX PRO 2000 Blackwell"
"10de:2c35|RTX PRO 2000 Blackwell (Alternative)"
"10de:2c3a|RTX PRO 4500 Blackwell Server Edition"
"10de:2c77|RTX PRO 5000 Blackwell Embedded GPU"
"10de:2c38|RTX PRO 5000 Blackwell Generation Laptop GPU"
"10de:2f38|RTX PRO 3000 Blackwell Generation Laptop GPU"
"10de:2db8|RTX PRO 1000 Blackwell Generation Laptop GPU"
)
DO_BLACKLIST_NOUVEAU=1
DO_TRY_RMMOD_NOUVEAU=1
DO_USER_GROUPS=0
DO_BASHRC_CUDA_PATHS=1
DO_VERIFY_NVIDIA_SMI=1
DO_VERIFY_NVCC=1
DO_INSTALL_NVIDIA_CONTAINER_TOOLKIT=1
DO_CONFIGURE_DOCKER_RUNTIME=1
DO_RESTART_DOCKER=1
# ---- Start ----
echo "Starting NVIDIA driver + CUDA installation for RHEL-family (Non-Interactive)..."
#-------------------------------------------------------------------------------
# DEPENDENCY CHECK + AUTO-INSTALL (AlmaLinux 9/10)
#-------------------------------------------------------------------------------
# Mapping: command -> package in AlmaLinux 9/10
declare -A PKG_MAP=(
[lspci]="pciutils"
[wget]="wget"
[curl]="curl"
[sed]="sed"
[awk]="gawk"
[uname]="coreutils"
[dnf]="dnf"
)
MISSING_CMDS=()
MISSING_PKGS=()
# 1. Check
for cmd in "${!PKG_MAP[@]}"; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "Missing dependency: $cmd"
MISSING_CMDS+=("$cmd")
MISSING_PKGS+=("${PKG_MAP[$cmd]}")
fi
done
# 2. Install missing packages
if [ ${#MISSING_PKGS[@]} -gt 0 ]; then
UNIQUE_PKGS=$(printf "%s\n" "${MISSING_PKGS[@]}" | sort -u | tr '\n' ' ')
echo "Installing packages: $UNIQUE_PKGS"
if ! command -v dnf >/dev/null 2>&1; then
echo "ERROR: dnf is not available. Cannot install dependencies automatically." >&2
exit 1
fi
if ! sudo dnf install -y $UNIQUE_PKGS; then
echo "ERROR: Failed to install packages: $UNIQUE_PKGS" >&2
exit 1
fi
echo "Re-checking dependencies..."
for cmd in "${MISSING_CMDS[@]}"; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "ERROR: '$cmd' still missing after installation." >&2
exit 1
fi
done
echo "All dependencies installed successfully."
else
echo "All dependencies are present."
fi
#-------------------------------------------------------------------------------
# OS DETECTION
#-------------------------------------------------------------------------------
osr="/etc/os-release"
[[ -r "$osr" ]] || { echo "Cannot read os-release file. Exiting."; exit 1; }
set -a
. "$osr"
set +a
if [[ "${ID:-}" != "almalinux" && "${ID:-}" != "rocky" ]]; then
echo "This script is intended for AlmaLinux or Rocky Linux only. Exiting."
exit 1
fi
OS_MAJOR_VERSION="${VERSION_ID%%.*}"
OS_NAME="${ID}"
if [[ "${DO_OS_POLICY_CHECK:-0}" -eq 1 ]]; then
ok=0
for v in "${ALLOWED_OS_MAJOR_VERSIONS[@]}"; do
[[ "${OS_MAJOR_VERSION}" == "${v}" ]] && { ok=1; break; }
done
[[ "${ok}" -ne 1 ]] && { echo "Unsupported OS major version: ${OS_MAJOR_VERSION}"; exit 1; }
fi
echo "OS: ${OS_NAME} ${VERSION_ID} (major ${OS_MAJOR_VERSION})"
#-------------------------------------------------------------------------------
# GPU DETECTION
#-------------------------------------------------------------------------------
NVIDIA_GPU_LINES="$(lspci -nn | grep -iE 'vga|3d' | grep -i '10de:' || true)"
[[ -z "${NVIDIA_GPU_LINES}" ]] && { echo "No NVIDIA GPU detected (vendor 10de). Exiting."; exit 1; }
echo "NVIDIA GPUs detected:"
echo "${NVIDIA_GPU_LINES}"
DETECTED_GPUS="$(lspci -nn)"
REBOOT_REQUIRED=0
#-------------------------------------------------------------------------------
# SYSTEM PREPARATION
#-------------------------------------------------------------------------------
if [[ "${DO_DNF_UPGRADE}" -eq 1 ]]; then
echo "Updating system packages..."
sudo dnf upgrade -y
fi
# install kernel-devel/headers for the RUNNING kernel explicitly.
# kernel-devel-matched alone can miss the running kernel if it is newer than
# the installed kernel package, which makes DKMS fail with missing headers.
if [[ "${DO_INSTALL_KERNEL_HEADERS}" -eq 1 ]]; then
CURRENT_KERNEL="$(uname -r)"
echo "Installing kernel headers/devel for running kernel: ${CURRENT_KERNEL}"
if ! sudo dnf install -y "kernel-devel-${CURRENT_KERNEL}" "kernel-headers-${CURRENT_KERNEL}"; then
echo "Exact kernel-devel/headers not available; falling back to kernel-devel-matched."
sudo dnf install -y kernel-devel-matched kernel-headers || {
echo "ERROR: Failed to install kernel-devel/headers. DKMS will fail." >&2
exit 1
}
fi
fi
if [[ "${DO_INSTALL_BUILD_TOOLS}" -eq 1 ]]; then
# RHEL 9/10 provide gcc via the base repo; specific versions are not strictly necessary for DKMS
echo "Installing build tools: gcc, gcc-c++, make, dkms"
sudo dnf install -y gcc gcc-c++ make dkms
fi
#-------------------------------------------------------------------------------
# PURGE OLD PACKAGES
#-------------------------------------------------------------------------------
if [[ "${DO_PURGE_OLD_PACKAGES}" -eq 1 ]]; then
echo "Purging previous NVIDIA/CUDA installations..."
# Disable module streams if they were previously enabled
sudo dnf module reset -y nvidia-driver 2>/dev/null || true
# Remove NVIDIA and CUDA packages
sudo dnf remove -y '*nvidia*' '*cuda*' 2>/dev/null || true
# remove stale DKMS build trees. Without this, "dkms autoinstall"
# keeps rebuilding the previously installed version even after packages
# were swapped, which is exactly how a 610 build survived a 535 switch.
sudo rm -rf /var/lib/dkms/nvidia/* 2>/dev/null || true
sudo dnf autoremove -y || true
sudo dnf clean all || true
fi
#-------------------------------------------------------------------------------
# TEMPORARY SHA1 ENABLE (for old NVIDIA GPG keys)
#-------------------------------------------------------------------------------
echo "Temporarily enabling SHA1 crypto policy for NVIDIA repo compatibility..."
sudo update-crypto-policies --set DEFAULT:SHA1
#-------------------------------------------------------------------------------
# SETUP CUDA REPOSITORY
#-------------------------------------------------------------------------------
if [[ "${DO_SETUP_CUDA_REPO}" -eq 1 ]]; then
# NVIDIA uses rhel9/rhel10 repo paths for all RHEL-compatible distros
CUDA_REPO_DISTRO="rhel${OS_MAJOR_VERSION}"
REPO_URL="https://developer.download.nvidia.com/compute/cuda/repos/${CUDA_REPO_DISTRO}/x86_64/cuda-${CUDA_REPO_DISTRO}.repo"
echo "Setting up CUDA repo for ${CUDA_REPO_DISTRO}..."
sudo dnf config-manager --add-repo "${REPO_URL}" 2>/dev/null || {
# Fallback for dnf5 (RHEL 10) where config-manager syntax differs
sudo dnf config-manager addrepo --from-repofile="${REPO_URL}" 2>/dev/null || true
}
# Disable the nvidia-driver module from the CUDA repo for RHEL 9 only.
# RHEL 10 does not use module streams for NVIDIA drivers.
if [[ "${OS_MAJOR_VERSION}" == "9" ]]; then
sudo dnf module disable -y nvidia-driver 2>/dev/null || true
fi
sudo dnf clean all
sudo dnf makecache
fi
#-------------------------------------------------------------------------------
# BLACKLIST NOUVEAU
#-------------------------------------------------------------------------------
if [[ "${DO_BLACKLIST_NOUVEAU}" -eq 1 ]]; then
BL_FILE="/etc/modprobe.d/blacklist-nouveau.conf"
if [[ ! -f "${BL_FILE}" ]] || ! grep -q "^blacklist nouveau" "${BL_FILE}" 2>/dev/null; then
echo "Blacklisting nouveau (requires reboot)..."
sudo tee "${BL_FILE}" >/dev/null <<'EOF'
blacklist nouveau
options nouveau modeset=0
EOF
sudo dracut --force
REBOOT_REQUIRED=1
fi
fi
#-------------------------------------------------------------------------------
# DRIVER INSTALL HELPERS
#-------------------------------------------------------------------------------
install_open_driver() {
echo "Installing open kernel modules..."
if [[ "${OS_MAJOR_VERSION}" == "9" ]]; then
sudo dnf module install -y nvidia-driver:latest-open
else
sudo dnf install -y nvidia-open
fi
}
# Helper to install proprietary driver (legacy or generic)
# $1: optional module stream (e.g. "535") for RHEL 9
install_proprietary_driver() {
local stream="${1:-}"
if [[ "${OS_MAJOR_VERSION}" == "9" ]]; then
if [[ -n "${stream}" ]]; then
echo "Installing proprietary driver stream ${stream}-dkms (RHEL 9)..."
sudo dnf module install -y "nvidia-driver:${stream}-dkms"
else
echo "Installing proprietary driver stream latest-dkms (RHEL 9)..."
sudo dnf module install -y "nvidia-driver:latest-dkms"
fi
else
# RHEL 10: no module streams; install the driver package directly.
# Note: cuda-drivers pulls proprietary modules; we avoid it per original logic.
echo "Installing proprietary driver package (RHEL 10)..."
sudo dnf install -y nvidia-driver
fi
}
IS_BLACKWELL=0
IS_LEGACY=0
IS_PROPRIETARY=0
# 1) Blackwell: open modules
for gpu_spec in "${BLACKWELL_GPUS[@]}"; do
IFS='|' read -r pci_id gpu_name <<< "$gpu_spec"
if echo "$DETECTED_GPUS" | grep -q "$pci_id"; then
echo "Detected Blackwell GPU: $gpu_name ($pci_id)"
install_open_driver
IS_BLACKWELL=1
break
fi
done
# 2) Legacy GPUs: pinned driver
if [[ "$IS_BLACKWELL" -eq 0 ]]; then
for gpu_spec in "${LEGACY_GPUS[@]}"; do
IFS='|' read -r pci_id gpu_name driver_stream <<< "$gpu_spec"
if echo "$DETECTED_GPUS" | grep -q "$pci_id"; then
echo "Detected legacy GPU: $gpu_name ($pci_id) -> stream $driver_stream"
if [[ "${OS_MAJOR_VERSION}" == "9" ]]; then
install_proprietary_driver "$driver_stream"
else
echo "Warning: Legacy driver streams (${driver_stream}) may not be available on RHEL 10. Attempting latest proprietary."
install_proprietary_driver
fi
IS_LEGACY=1
break
fi
done
fi
# 3) Everything else: proprietary latest-dkms (RTX A4000/A5000 fall here).
# FIX #4: unknown GPUs are handled by this same branch instead of aborting.
if [[ "$IS_BLACKWELL" -eq 0 && "$IS_LEGACY" -eq 0 ]]; then
echo "Detected non-Blackwell, non-legacy GPU (e.g. RTX A4000/A5000)."
echo "Installing proprietary latest-dkms driver..."
install_proprietary_driver
IS_PROPRIETARY=1
fi
#-------------------------------------------------------------------------------
# EXPLICIT DKMS BUILD + VERIFICATION
# do not rely on the package hook alone. Build the module for the
# running kernel and fail loudly if it did not land. This turns a silent
# "nvidia-smi cannot communicate" into an actionable script error.
#-------------------------------------------------------------------------------
CURRENT_KERNEL="$(uname -r)"
echo "Building DKMS module for kernel ${CURRENT_KERNEL}..."
if ! sudo dkms autoinstall -k "${CURRENT_KERNEL}"; then
echo "ERROR: DKMS build failed for kernel ${CURRENT_KERNEL}." >&2
echo "Check the build log under /var/lib/dkms/nvidia/*/build/make.log" >&2
exit 1
fi
if ! dkms status | grep -q "nvidia/.*installed"; then
echo "ERROR: DKMS reports no installed nvidia module after build." >&2
echo "Current dkms status:" >&2
dkms status >&2 || true
exit 1
fi
echo "DKMS module installed successfully:"
dkms status | grep nvidia || true
#-------------------------------------------------------------------------------
# INSTALL CUDA TOOLKIT
# - Legacy (CC < 7.5): CUDA 12.x (last branch supporting Pascal/Volta)
# - Blackwell / Proprietary (CC >= 7.5): latest cuda-toolkit
# - cuda-drivers is NEVER installed
#-------------------------------------------------------------------------------
if [[ "${DO_INSTALL_CUDA_STACK}" -eq 1 ]]; then
if [[ "$IS_LEGACY" -eq 1 ]]; then
# For RHEL 9, CUDA 12.9 is available. On RHEL 10, only newer CUDA is available.
if [[ "${OS_MAJOR_VERSION}" == "9" ]]; then
echo "Installing CUDA Toolkit 12.9 (legacy path)..."
sudo dnf install -y cuda-toolkit-12-9
else
echo "Warning: CUDA 12.9 may not be available on RHEL 10. Installing latest cuda-toolkit."
sudo dnf install -y cuda-toolkit
fi
else
echo "Installing latest available CUDA Toolkit..."
sudo dnf install -y cuda-toolkit
fi
fi
#-------------------------------------------------------------------------------
# POST-INSTALL STEPS
#-------------------------------------------------------------------------------
if [[ "${DO_TRY_RMMOD_NOUVEAU}" -eq 1 ]]; then
sudo rmmod -f nouveau 2>/dev/null || true
fi
if [[ "${DO_USER_GROUPS}" -eq 1 ]]; then
TARGET_USER="${SUDO_USER:-$USER}"
sudo usermod -aG video,render "${TARGET_USER}" || true
echo "User ${TARGET_USER} added to video/render groups."
REBOOT_REQUIRED=1
fi
if [[ "${DO_BASHRC_CUDA_PATHS}" -eq 1 ]]; then
TARGET_USER="${SUDO_USER:-$USER}"
TARGET_HOME="$(getent passwd "${TARGET_USER}" | cut -d: -f6)"
TARGET_BASHRC="${TARGET_HOME}/.bashrc"
MARKER="NVIDIA CUDA Paths"
[[ -f "${TARGET_BASHRC}" ]] || sudo -u "${TARGET_USER}" touch "${TARGET_BASHRC}" || true
if ! grep -q "${MARKER}" "${TARGET_BASHRC}" 2>/dev/null; then
cat >> "${TARGET_BASHRC}" <<'EOF'
# NVIDIA CUDA Paths
export PATH="/usr/local/cuda/bin:$PATH"
export LD_LIBRARY_PATH="/usr/local/cuda/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
EOF
echo "Added CUDA PATH to ${TARGET_BASHRC}"
fi
fi
#-------------------------------------------------------------------------------
# VERIFICATION
#-------------------------------------------------------------------------------
if [[ "${DO_VERIFY_NVIDIA_SMI}" -eq 1 ]]; then
echo "Verifying nvidia-smi..."
nvidia-smi || true
fi
if [[ "${DO_VERIFY_NVCC}" -eq 1 ]]; then
if command -v nvcc >/dev/null 2>&1; then
echo "Verifying nvcc..."
nvcc -V || true
else
echo "nvcc not found in PATH yet (re-login/reboot may be needed)"
fi
fi
#-------------------------------------------------------------------------------
# NVIDIA CONTAINER TOOLKIT
#-------------------------------------------------------------------------------
if [[ "${DO_INSTALL_NVIDIA_CONTAINER_TOOLKIT}" -eq 1 ]]; then
if command -v docker >/dev/null 2>&1 || command -v podman >/dev/null 2>&1; then
echo "Container engine detected: installing NVIDIA Container Toolkit..."
# Add repo (works for RHEL family)
curl -s -L https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo \
| sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo >/dev/null
sudo dnf install -y nvidia-container-toolkit
if [[ "${DO_CONFIGURE_DOCKER_RUNTIME}" -eq 1 ]] && command -v docker >/dev/null 2>&1; then
command -v nvidia-ctk >/dev/null 2>&1 && sudo nvidia-ctk runtime configure --runtime=docker || true
fi
if [[ "${DO_RESTART_DOCKER}" -eq 1 ]] && command -v docker >/dev/null 2>&1; then
sudo systemctl restart docker || true
fi
else
echo "Docker/Podman not found. Skipping container toolkit."
fi
fi
#-------------------------------------------------------------------------------
# RESTORE DEFAULT CRYPTO POLICY
#-------------------------------------------------------------------------------
echo "Restoring default crypto policy (SHA1 disabled)..."
sudo update-crypto-policies --set DEFAULT
#-------------------------------------------------------------------------------
# FINAL
#-------------------------------------------------------------------------------
echo ""
echo "========================================"
echo "Installation finished"
echo "========================================"
if [[ "${REBOOT_REQUIRED}" -eq 1 ]]; then
echo ">> REBOOT REQUIRED: sudo reboot"
fi
echo "After reboot, verify with:"
echo " nvidia-smi"
echo " nvcc -V"