Last active
February 2, 2026 17:09
-
-
Save Cerothen/4a35e82ba18e653562016d506d983ac5 to your computer and use it in GitHub Desktop.
Script to manage Nvidia driver versions on proxmox hosts and in lxc containers. Execute in containers to install drivers in the container, or on the host to install anywhere (Selectable) | bash -c "$(wget -O - https://gist.githubusercontent.com/Cerothen/4a35e82ba18e653562016d506d983ac5/raw/e5a8dd24f718a7b39273c544020c178c14b5d949/nvidia_pve_pass…
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 | |
| SHOW_VERSION_COUNT=20 | |
| USE_VERSION="" | |
| RECOMMENDED_VERSION="580.105.08" | |
| # Ingest Args (FUTURE NOT WORKING) | |
| process_args() { | |
| echo "Processing arguments for function: $@" | |
| # Iterate while arguments exist | |
| while [ "$#" -gt 0 ]; do | |
| case "$1" in | |
| -a|--all) | |
| echo "Showing all versions." | |
| SHOW_VERSION_COUNT=9999 | |
| shift # Move to the next argument | |
| ;; | |
| -v|--version) | |
| echo "Using version '$2' if it exists." | |
| USE_VERSION=$2 | |
| shift 2 # Move past the option and its value | |
| ;; | |
| *) | |
| echo "Unknown option or argument: $1" | |
| shift | |
| ;; | |
| esac | |
| done | |
| } | |
| # Function to check if running inside an LXC container | |
| is_lxc() { | |
| if command -v systemd-detect-virt &> /dev/null; then | |
| if [ $(systemd-detect-virt) = "lxc" ]; then | |
| return 0 # True, it's LXC | |
| fi | |
| fi | |
| if grep -q "lxc" /proc/1/cgroup; then | |
| return 0 # True, it's LXC | |
| fi | |
| return 1 # False, not LXC | |
| } | |
| # Check for and install missing dependency | |
| confirm_depend () { | |
| if ! command -v "$1" &> /dev/null; then | |
| echo "[DEPEND] Missing dependency '$1' installing now." | |
| apt-get update | |
| apt install -y "$1" | |
| fi | |
| } | |
| # Handle arguments | |
| #process_args | |
| # Get run scope | |
| IS_LXC=$(is_lxc && echo "true" || echo "false") | |
| # Detect current version | |
| CURRENT_VERSION="NOT INSTALLED" | |
| if command -v nvidia-smi &> /dev/null; then | |
| CURRENT_VERSION_RAW=$(nvidia-smi --version | grep 'DRIVER version') | |
| CURRENT_VERSION="${CURRENT_VERSION_RAW#*:}" | |
| CURRENT_VERSION=$(echo "$CURRENT_VERSION" | xargs) | |
| fi | |
| PVE_LXC_DIR="/etc/pve/lxc/" | |
| INSTALL_MODE="HOST" | |
| INSTALL_TARGET="SELF" | |
| if [[ "$IS_LXC" == "true" ]]; then | |
| echo "[CONTAINER] Detected script is running in an LXC container." | |
| INSTALL_MODE="LXC" | |
| else | |
| echo "[HOST] Detected script is running on bare metal." | |
| INSTALL_MODE="HOST" | |
| # Check if proxmox host and if lxc directory exists | |
| if [ -d "$PVE_LXC_DIR" ]; then | |
| # Check if host drivers are installed | |
| if [[ "$CURRENT_VERSION" == "NOT INSTALLED" ]]; then | |
| echo "Detected Proxmox host, install drivers on host to setup passthrough in containers." | |
| echo "Defaulting to HOST installation." | |
| else | |
| # Get LXC Configs | |
| PVE_LXC_CONFIGS_RAW=( $PVE_LXC_DIR/*.conf ) | |
| PVE_LXC_CONFIGS=() | |
| for i in "${!PVE_LXC_CONFIGS_RAW[@]}"; do | |
| PVE_LXC_CONFIGS[i]="$(basename ${PVE_LXC_CONFIGS_RAW[i]%*/} .conf)" | |
| done | |
| echo "Select [HOST] or Container ID to install NVIDIA Drivers: | |
| ['h' for HOST] ['q' to exit]" | |
| select item in "${PVE_LXC_CONFIGS[@]}"; do | |
| if [ "$REPLY" == "q" ]; then | |
| echo "Exiting." | |
| exit 98 | |
| elif [ "$REPLY" == "h" ]; then | |
| INSTALL_MODE="HOST" | |
| break | |
| elif [ -n "$item" ]; then | |
| INSTALL_MODE="CONTAINER" | |
| INSTALL_TARGET=$item | |
| break | |
| else | |
| echo "Invalid choice, please try again." | |
| fi | |
| done | |
| fi | |
| fi | |
| fi | |
| echo "Install details: | |
| INSTALL MODE: $INSTALL_MODE | |
| INSTALL TARGET: $INSTALL_TARGET" | |
| # Prepare installation proceedure | |
| if [[ "$INSTALL_MODE" != "CONTAINER" ]]; then | |
| # Depends | |
| confirm_depend "curl" | |
| confirm_depend "pup" | |
| # Get latest version information | |
| VERSION_LATEST_RAW=$(curl -s https://download.nvidia.com/XFree86/Linux-x86_64/latest.txt) | |
| VERSION_LATEST="${VERSION_LATEST_RAW%% *}" | |
| # Get all versions | |
| VERSION_LIST=$(curl -s https://download.nvidia.com/XFree86/Linux-x86_64/ | pup 'ul li span.dir a[href] attr{href}') | |
| # Create array and count items | |
| mapfile -t VERSION_LIST_ASC <<<"$VERSION_LIST" | |
| VERSION_COUNT=${#VERSION_LIST_ASC[@]} | |
| # Remove trailing slash | |
| for i in "${!VERSION_LIST_ASC[@]}"; do | |
| VERSION_LIST_ASC[i]="${VERSION_LIST_ASC[i]%*/}" | |
| done | |
| # Sort NEW -> OLD | |
| VERSION_LIST_DESC=() | |
| for ((i = VERSION_COUNT - 1; i >= 0; i--)); do | |
| VERSION_LIST_DESC+=("${VERSION_LIST_ASC[i]}") | |
| done | |
| # Show information | |
| echo "NVIDIA DRIVER INSTALL TOOL | |
| DRIVER COUNT: $VERSION_COUNT | |
| LATEST VERSION: $VERSION_LATEST | |
| RECOMMENDED VERSION: $RECOMMENDED_VERSION | |
| CURRENT VERSION: $CURRENT_VERSION | |
| ['l' for latest] ['r' for recommended] ['q' to quit] | |
| Enter the number for the driver to install: | |
| " | |
| # Show selections | |
| select item in "${VERSION_LIST_DESC[@]:0:$SHOW_VERSION_COUNT}"; do | |
| if [ "$REPLY" == "q" ]; then | |
| echo "Exiting." | |
| exit 99 | |
| elif [ "$REPLY" == "l" ]; then | |
| USE_VERSION=$VERSION_LATEST | |
| break | |
| elif [ "$REPLY" == "r" ]; then | |
| USE_VERSION=$RECOMMENDED_VERSION | |
| break | |
| elif [ -n "$item" ]; then | |
| USE_VERSION=$item | |
| break | |
| else | |
| echo "Invalid choice, please try again." | |
| fi | |
| done | |
| echo "Selected version: $USE_VERSION" | |
| # Remove old version if required | |
| if command -v nvidia-uninstall &> /dev/null; then | |
| echo "[OLD VERSION] Found old version of nvidia drivers, removing them first..." | |
| nvidia-uninstall --silent | |
| fi | |
| # Download Drivers and make Executable | |
| wget https://download.nvidia.com/XFree86/Linux-x86_64/$USE_VERSION/NVIDIA-Linux-x86_64-$USE_VERSION.run -P /tmp | |
| chmod +x /tmp/NVIDIA-Linux-x86_64-$USE_VERSION.run | |
| # Install Drivers | |
| if [[ "$INSTALL_MODE" == "HOST" ]]; then | |
| if [ -d "$PVE_LXC_DIR" ]; then | |
| confirm_depend "pve-headers" | |
| confirm_depend "pve-nvidia-vgpu-helper" | |
| pve-nvidia-vgpu-helper setup | |
| fi | |
| /tmp/NVIDIA-Linux-x86_64-$USE_VERSION.run -a -q --silent --kernel-module-type=proprietary | |
| else | |
| /tmp/NVIDIA-Linux-x86_64-$USE_VERSION.run -a -q --silent --no-kernel-module --kernel-module-type=proprietary | |
| fi | |
| # Cleanup | |
| rm -f /tmp/NVIDIA-Linux-x86_64-$USE_VERSION.run | |
| # Reboot if not host | |
| if [[ "$INSTALL_MODE" == "HOST" ]]; then | |
| echo "!!! === Please reboot when as soon as is reasonable. === !!!" | |
| else | |
| reboot | |
| fi | |
| else | |
| # Container version should be the same as the host version | |
| echo "Using host version for LXC container: $CURRENT_VERSION" | |
| USE_VERSION=$CURRENT_VERSION | |
| # Configure the container to allow the setup of the GPU | |
| if ! grep -qF "/dev/nvidia0" "$PVE_LXC_DIR/${INSTALL_TARGET}.conf"; then | |
| echo "Updating LXC Config: $INSTALL_TARGET" | |
| # Stop the container | |
| pct shutdown $INSTALL_TARGET | |
| # Set Passthrough Configs | |
| pct set $INSTALL_TARGET --dev0 "/dev/nvidia0" | |
| pct set $INSTALL_TARGET --dev1 "/dev/nvidiactl" | |
| pct set $INSTALL_TARGET --dev2 "/dev/nvidia-modeset" | |
| pct set $INSTALL_TARGET --dev3 "/dev/nvidia-uvm" | |
| pct set $INSTALL_TARGET --dev4 "/dev/nvidia-uvm-tools" | |
| pct set $INSTALL_TARGET --dev5 "/dev/nvram" | |
| # Update Tags | |
| TAGS=$(pct config $INSTALL_TARGET | grep tags | cut -d' ' -f2- | sed 's/;/A/g' | sed 's/A/,/g') | |
| TAGS+=",GPU" | |
| pct set $INSTALL_TARGET --tags "$TAGS" | |
| # Start the container | |
| pct start $INSTALL_TARGET | |
| fi | |
| TMPFILE=$(mktemp) | |
| # Install in container | |
| echo "Generating LXC install script." | |
| echo "#!/usr/bin/env bash | |
| # TEMPORARY GENERATED SCRIPT TO INSTALL NVIDIA drivers | |
| # VERSION: $USE_VERSION | |
| $ CONTAINER ID: $INSTALL_TARGET | |
| if command -v nvidia-uninstall &> /dev/null; then | |
| nvidia-uninstall --silent | |
| fi | |
| wget https://download.nvidia.com/XFree86/Linux-x86_64/$USE_VERSION/NVIDIA-Linux-x86_64-$USE_VERSION.run -P /tmp | |
| chmod +x /tmp/NVIDIA-Linux-x86_64-$USE_VERSION.run | |
| /tmp/NVIDIA-Linux-x86_64-$USE_VERSION.run -a -q --silent --no-kernel-module --kernel-module-type=proprietary | |
| rm -f /tmp/NVIDIA-Linux-x86_64-$USE_VERSION.run | |
| reboot | |
| " > $TMPFILE | |
| echo "Pushing script to LXC container: $INSTALL_TARGET" | |
| pct push $INSTALL_TARGET $TMPFILE $TMPFILE | |
| echo "Executing script inside LXC container: $INSTALL_TARGET" | |
| pct exec $INSTALL_TARGET -- chmod +x $TMPFILE | |
| pct exec $INSTALL_TARGET -- $TMPFILE | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment