#!/usr/bin/env nix-shell #!nix-shell -i bash -p bash coreutils gnugrep gum git pciutils # # Based on https://wiki.debian.org/NvidiaGraphicsDrivers?action=AttachFile&do=view&target=nvidia-versions.sh # # Copyright © 2026 Raphaël Numbus # # This package is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # Avoid cryptic failure when running dash on this script shopt -s compat31 nocasematch 2>/dev/null || { echo "Error: this script only works with bash." && exit 1; } # Colors GREEN='\033[0;32m' BLUE='\033[0;34m' YELLOW='\033[1;33m' RED='\033[0;31m' NC='\033[0m' # No Color USER_ID="$(id -u)" PCI_IDS_LOCATION="/run/user/${USER_ID}/gpu-detect" declare -A args=( ["brand"]="all" ["hw_accel"]="true" ) PCI_IDS=() show_help() { gum style --border-foreground="030" --bold --border=normal --padding="0 2" "GPU detection tool for NixOS" echo "Usage: gpu-detect [OPTIONS] [PCIID]..." echo "" echo "Options:" echo " -b, --brand BRAND Select GPU brand to detect: all, amd, intel, nvidia (default: all)" echo " -hw, --hw_accel BOOL Provide hardware acceleration configuration: true, false (default: true)" echo " -h, --help Show this help message and exit" echo "" echo "For each GPU installed in your system (or matching the specified brand/PCI ID)," echo "the program will provide you the needed NixOS configuration." exit 0 } while [[ $# -gt 0 ]]; do case "${1}" in --brand|-b) if [[ -n "${2}" && ! "${2}" =~ ^- ]]; then args["brand"]="${2,,}" shift 2 else echo -e "${RED}Error: --brand requires an argument.${NC}" exit 1 fi ;; --hw_accel|-hw) if [[ -n "${2}" && ! "${2}" =~ ^- ]]; then args["hw_accel"]="${2,,}" shift 2 else echo -e "${RED}Error: --hw_accel requires an argument.${NC}" exit 1 fi ;; --help|-h) show_help ;; -*) echo -e "${RED}Unknown option ${1}${NC}" show_help ;; *) PCI_IDS+=("${1}") shift ;; esac done gum style --border-foreground="030" --bold --border=normal --padding="0 2" "GPU detection tool for NixOS" # Get the PCI IDs from the repo if [[ ! -d "${PCI_IDS_LOCATION}" ]]; then echo -e "${BLUE}Fetching latest PCI IDs database...${NC}" mkdir -p "${PCI_IDS_LOCATION}" if ! git clone -q -b ids-database https://gittea.dev/numbus/gpu-detect.git "${PCI_IDS_LOCATION}"; then # Fallback to local checkout if remote is not available for testing purposes if [[ -d "../.git" ]]; then git clone -q -b ids-database "file://$(realpath ../)" "${PCI_IDS_LOCATION}" || true fi fi else echo -e "${BLUE}Updating PCI IDs database...${NC}" if ! git -C "${PCI_IDS_LOCATION}" pull -q; then echo -e "${RED}Error: Directory ${PCI_IDS_LOCATION} is not empty and does not contain the repository. Please check the folder and clean up manually.${NC}" exit 1 fi fi nvidia_detect() { local PCI_ID="${1}" local NVIDIA_VERSION="" local VERSIONS=("unsupported" "legacy_340" "legacy_390" "legacy_470" "legacy_580" "current") for version in "${VERSIONS[@]}"; do if grep -q -i "${PCI_ID}" "${PCI_IDS_LOCATION}/nvidia/${version}.ids" 2>/dev/null; then NVIDIA_VERSION="${version}" break fi done if [[ -z "${NVIDIA_VERSION}" ]]; then gum style --foreground="212" "Uh oh. It seems that your card couldn't be detected." "A newer driver may add support for your card later." return 1 fi if [[ "${NVIDIA_VERSION}" == "unsupported" ]]; then gum style --foreground="212" "Good news! You have nothing to do, your card runs with the 'nouveau' driver that is integrated in the kernel." "" "It seems you have a very old card! The proprietary NVIDIA drivers have been removed from Nixpkgs therefore it is not possible to install them." return 0 fi local EXTRA_PACKAGES="" local HW_ACCEL_CONFIG="" if [[ "${args["hw_accel"]}" == "true" ]]; then if [[ "${NVIDIA_VERSION}" == "legacy_340" || "${NVIDIA_VERSION}" == "legacy_390" || "${NVIDIA_VERSION}" == "legacy_470" ]]; then EXTRA_PACKAGES="libvdpau" elif [[ "${NVIDIA_VERSION}" == "legacy_580" || "${NVIDIA_VERSION}" == "current" ]]; then EXTRA_PACKAGES="nvidia-vaapi-driver libvdpau" fi HW_ACCEL_CONFIG=" hardware.graphics = { enable = true; extraPackages = with pkgs; [ ${EXTRA_PACKAGES} ]; };" fi local DRIVER_INFO="" local NVIDIA_CONFIG="" local NIX_PACKAGE_VER="${NVIDIA_VERSION}" if [[ "${NVIDIA_VERSION}" == "current" ]]; then NIX_PACKAGE_VER="stable" fi if [[ "${NVIDIA_VERSION}" == "current" ]]; then DRIVER_INFO="An official stable NVIDIA driver release is available for your card." NVIDIA_CONFIG="{ config, lib, pkgs, ... }: {${HW_ACCEL_CONFIG} services.xserver.videoDrivers = [ \"nvidia\" ]; hardware.nvidia = { modesetting.enable = true; nvidiaSettings = true; open = true; package = config.boot.kernelPackages.nvidiaPackages.${NIX_PACKAGE_VER}; # Advanced options, tweak if needed powerManagement.enable = false; # Experimental: Enable this if you have graphical corruption issues or application crashes after waking up from sleep. powerManagement.finegrained = false; # Experimental: Turns off GPU when not in use }; }" else DRIVER_INFO="An official legacy NVIDIA driver release is available for your card." NVIDIA_CONFIG="{ config, lib, pkgs, ... }: {${HW_ACCEL_CONFIG} services.xserver.videoDrivers = [ \"nvidia\" ]; hardware.nvidia = { modesetting.enable = true; nvidiaSettings = true; package = config.boot.kernelPackages.nvidiaPackages.${NIX_PACKAGE_VER}; # Unsupported options powerManagement.enable = false; powerManagement.finegrained = false; open = false; }; }" fi gum style --foreground="212" "${DRIVER_INFO}" if [[ "${args["hw_accel"]}" == "true" ]]; then gum style "You can add the following code snippet to your NixOS configuration in order to enable the proprietary NVIDIA driver with hardware acceleration support." else gum style "You can add the following code snippet to your NixOS configuration in order to enable the proprietary NVIDIA driver." fi gum format '```nix '"${NVIDIA_CONFIG}"' ```' } # Main logic if [[ ${#PCI_IDS[@]} -gt 0 ]]; then for id in "${PCI_IDS[@]}" ; do # Try to parse NVIDIA PCI ID (vendor 10de) PCIID=$(echo "$id" | sed -rn 's/^(10de)?:?([0-9a-fA-F]{4})$/10de\2/ip') if [ -n "$PCIID" ]; then gum style --foreground="030" "Checking driver support for NVIDIA PCI ID [$(echo $PCIID | sed -r 's/(....)(....)/\1:\2/')]" nvidia_detect "$PCIID" else echo -e "${YELLOW}Currently only NVIDIA PCI IDs (10de:XXXX) are supported when passing explicitly.${NC}" fi done else if [[ "${args["brand"]}" == "all" || "${args["brand"]}" == "nvidia" ]]; then NV_DEVICES=$(lspci -mn 2>/dev/null | awk '{ gsub("\"",""); if (($2 ~ "030[0-2]") && ($3 == "10de" || $3 == "12d2")) { print $1 } }') if [ -n "$NV_DEVICES" ]; then gum style --foreground="030" "Detected NVIDIA GPUs:" for d in $NV_DEVICES ; do lspci -nn -s $d done for d in $NV_DEVICES ; do gum style --foreground="030" "Checking card: $(lspci -s $d | awk -F: '{print $3}')" nvidia_detect "$(lspci -mn -s "$d" | awk '{ gsub("\"",""); print $3 $4 }')" done else if [[ "${args["brand"]}" == "nvidia" ]]; then gum style --foreground="212" "No NVIDIA GPU detected." fi fi fi if [[ "${args["brand"]}" == "all" || "${args["brand"]}" == "amd" ]]; then AMD_DEVICES=$(lspci -mn 2>/dev/null | awk '{ gsub("\"",""); if (($2 ~ "030[0-2]") && ($3 == "1002")) { print $1 } }') if [ -n "$AMD_DEVICES" ]; then gum style --foreground="030" "Detected AMD GPUs:" for d in $AMD_DEVICES ; do lspci -nn -s $d done gum style --foreground="212" "AMD configuration generation is not fully implemented yet." else if [[ "${args["brand"]}" == "amd" ]]; then gum style --foreground="212" "No AMD GPU detected." fi fi fi if [[ "${args["brand"]}" == "all" || "${args["brand"]}" == "intel" ]]; then INTEL_DEVICES=$(lspci -mn 2>/dev/null | awk '{ gsub("\"",""); if (($2 ~ "030[0-2]") && ($3 == "8086")) { print $1 } }') if [ -n "$INTEL_DEVICES" ]; then gum style --foreground="030" "Detected Intel GPUs:" for d in $INTEL_DEVICES ; do lspci -nn -s $d done gum style --foreground="212" "Intel configuration generation is not fully implemented yet." else if [[ "${args["brand"]}" == "intel" ]]; then gum style --foreground="212" "No Intel GPU detected." fi fi fi fi exit 0