Created
December 15, 2025 15:16
-
-
Save alexjoedt/b785cf8dc236d24d79c7aaed3ff0ef10 to your computer and use it in GitHub Desktop.
arch-nvidia-installer
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
| #!/bin/bash | |
| # This script is auto-generated with AI from https://github.com/JaKooLit/Arch-Hyprland | |
| # Standalone NVIDIA Driver Installation Script for Arch Linux with Hyprland # | |
| # This script installs and configures NVIDIA drivers for systems with Hyprland already installed # | |
| set -e | |
| #============================================================================== | |
| # Color Definitions | |
| #============================================================================== | |
| OK="$(tput setaf 2)[OK]$(tput sgr0)" | |
| ERROR="$(tput setaf 1)[ERROR]$(tput sgr0)" | |
| NOTE="$(tput setaf 3)[NOTE]$(tput sgr0)" | |
| INFO="$(tput setaf 4)[INFO]$(tput sgr0)" | |
| WARN="$(tput setaf 1)[WARN]$(tput sgr0)" | |
| CAT="$(tput setaf 6)[ACTION]$(tput sgr0)" | |
| MAGENTA="$(tput setaf 5)" | |
| YELLOW="$(tput setaf 3)" | |
| GREEN="$(tput setaf 2)" | |
| BLUE="$(tput setaf 4)" | |
| SKY_BLUE="$(tput setaf 6)" | |
| RESET="$(tput sgr0)" | |
| #============================================================================== | |
| # NVIDIA Packages to Install | |
| #============================================================================== | |
| nvidia_pkg=( | |
| nvidia-dkms | |
| nvidia-settings | |
| nvidia-utils | |
| libva | |
| libva-nvidia-driver | |
| ) | |
| #============================================================================== | |
| # Script Setup | |
| #============================================================================== | |
| SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" | |
| cd "$SCRIPT_DIR" || { echo "${ERROR} Failed to change directory to $SCRIPT_DIR"; exit 1; } | |
| # Create Directory for Install Logs | |
| if [ ! -d Install-Logs ]; then | |
| mkdir -p Install-Logs | |
| fi | |
| # Set the name of the log file | |
| LOG="Install-Logs/nvidia-install-$(date +%Y%m%d-%H%M%S).log" | |
| #============================================================================== | |
| # Helper Functions | |
| #============================================================================== | |
| # Show progress spinner during installation | |
| show_progress() { | |
| local pid=$1 | |
| local package_name=$2 | |
| local spin_chars=("●○○○○○○○○○" "○●○○○○○○○○" "○○●○○○○○○○" "○○○●○○○○○○" "○○○○●○○○○" \ | |
| "○○○○○●○○○○" "○○○○○○●○○○" "○○○○○○○●○○" "○○○○○○○○●○" "○○○○○○○○○●") | |
| local i=0 | |
| tput civis | |
| printf "\r${NOTE} Installing ${YELLOW}%s${RESET} ..." "$package_name" | |
| while ps -p $pid &> /dev/null; do | |
| printf "\r${NOTE} Installing ${YELLOW}%s${RESET} %s" "$package_name" "${spin_chars[i]}" | |
| i=$(( (i + 1) % 10 )) | |
| sleep 0.3 | |
| done | |
| printf "\r${NOTE} Installing ${YELLOW}%s${RESET} ... Done!%-20s \n" "$package_name" "" | |
| tput cnorm | |
| } | |
| # Detect AUR helper (yay or paru) | |
| detect_aur_helper() { | |
| if command -v yay &> /dev/null; then | |
| ISAUR="yay" | |
| elif command -v paru &> /dev/null; then | |
| ISAUR="paru" | |
| else | |
| echo -e "${ERROR} No AUR helper found. Please install yay or paru first." | |
| echo -e "${INFO} You can install yay with: git clone https://aur.archlinux.org/yay.git && cd yay && makepkg -si" | |
| exit 1 | |
| fi | |
| echo -e "${OK} Using ${YELLOW}$ISAUR${RESET} as AUR helper" | |
| } | |
| # Function to install packages | |
| install_package() { | |
| local pkg="$1" | |
| local log_file="$2" | |
| if $ISAUR -Q "$pkg" &>> /dev/null; then | |
| echo -e "${INFO} ${MAGENTA}$pkg${RESET} is already installed. Skipping..." | |
| else | |
| ( | |
| stdbuf -oL $ISAUR -S --noconfirm "$pkg" 2>&1 | |
| ) >> "$log_file" 2>&1 & | |
| PID=$! | |
| show_progress $PID "$pkg" | |
| # Verify installation | |
| if $ISAUR -Q "$pkg" &>> /dev/null; then | |
| echo -e "${OK} Package ${YELLOW}$pkg${RESET} has been successfully installed!" | |
| else | |
| echo -e "\n${ERROR} ${YELLOW}$pkg${RESET} failed to install. Please check $log_file" | |
| echo -e "${INFO} You may need to install this package manually." | |
| fi | |
| fi | |
| } | |
| # Print a section header | |
| print_header() { | |
| printf "\n" | |
| echo -e "${SKY_BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}" | |
| echo -e "${SKY_BLUE} $1${RESET}" | |
| echo -e "${SKY_BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}" | |
| printf "\n" | |
| } | |
| #============================================================================== | |
| # Pre-flight Checks | |
| #============================================================================== | |
| clear | |
| echo -e "${MAGENTA}" | |
| cat << "EOF" | |
| _ ___ _____ ____ ___ _ | |
| | \ | \ \ / /_ _| _ \_ _| / \ | |
| | \| |\ \ / / | || | | | | / _ \ | |
| | |\ | \ V / | || |_| | | / ___ \ | |
| |_| \_| \_/ |___|____/___/_/ \_\ | |
| ___ _ _ _ | |
| |_ _|_ __ ___| |_ __ _| | | ___ _ __ | |
| | || '_ \/ __| __/ _` | | |/ _ \ '__| | |
| | || | | \__ \ || (_| | | | __/ | | |
| |___|_| |_|___/\__\__,_|_|_|\___|_| | |
| EOF | |
| echo -e "${RESET}" | |
| echo -e "${INFO} Standalone NVIDIA Driver Installation for Arch Linux with Hyprland" | |
| echo -e "${INFO} Log file: ${YELLOW}$LOG${RESET}" | |
| printf "\n" | |
| # Check if running as root | |
| if [[ $EUID -eq 0 ]]; then | |
| echo -e "${ERROR} This script should ${WARN}NOT${RESET} be executed as root!" | |
| echo -e "${INFO} Please run as a regular user with sudo privileges." | |
| exit 1 | |
| fi | |
| # Check if this is Arch Linux | |
| if [ ! -f /etc/arch-release ]; then | |
| echo -e "${ERROR} This script is designed for Arch Linux only!" | |
| exit 1 | |
| fi | |
| # Check for NVIDIA GPU | |
| print_header "Checking for NVIDIA GPU" | |
| if ! lspci | grep -i nvidia &> /dev/null; then | |
| echo -e "${ERROR} No NVIDIA GPU detected in your system!" | |
| echo -e "${INFO} This script is only for systems with NVIDIA graphics cards." | |
| exit 1 | |
| fi | |
| echo -e "${OK} NVIDIA GPU detected:" | |
| lspci | grep -i nvidia | tee -a "$LOG" | |
| printf "\n" | |
| # Check if Hyprland is installed | |
| print_header "Checking Hyprland Installation" | |
| if ! pacman -Qs hyprland > /dev/null; then | |
| echo -e "${WARN} Hyprland is not installed on this system." | |
| echo -e "${INFO} This script is designed for systems with Hyprland already installed." | |
| read -p "Do you want to continue anyway? (y/N): " continue_choice | |
| if [[ ! "$continue_choice" =~ ^[Yy]$ ]]; then | |
| echo -e "${INFO} Exiting..." | |
| exit 0 | |
| fi | |
| else | |
| echo -e "${OK} Hyprland is installed." | |
| fi | |
| # Detect AUR helper | |
| print_header "Detecting AUR Helper" | |
| detect_aur_helper | |
| # Confirmation prompt | |
| printf "\n" | |
| echo -e "${CAT} This script will:" | |
| echo -e " ${YELLOW}1.${RESET} Install NVIDIA drivers (nvidia-dkms) and utilities" | |
| echo -e " ${YELLOW}2.${RESET} Install Linux kernel headers for your kernel(s)" | |
| echo -e " ${YELLOW}3.${RESET} Configure mkinitcpio with NVIDIA modules" | |
| echo -e " ${YELLOW}4.${RESET} Add modprobe options for NVIDIA" | |
| echo -e " ${YELLOW}5.${RESET} Configure bootloader (GRUB or systemd-boot) if detected" | |
| echo -e " ${YELLOW}6.${RESET} Rebuild initramfs" | |
| printf "\n" | |
| read -p "$(echo -e ${CAT}) Do you want to proceed? (y/N): " proceed | |
| if [[ ! "$proceed" =~ ^[Yy]$ ]]; then | |
| echo -e "${INFO} Installation cancelled." | |
| exit 0 | |
| fi | |
| #============================================================================== | |
| # Remove Conflicting Hyprland Packages | |
| #============================================================================== | |
| print_header "Checking for Conflicting Packages" | |
| echo -e "${YELLOW}Checking for conflicting hyprland-nvidia packages...${RESET}" | |
| for hyprnvi in hyprland-git hyprland-nvidia hyprland-nvidia-git hyprland-nvidia-hidpi-git; do | |
| if pacman -Qs "$hyprnvi" > /dev/null 2>&1; then | |
| echo -e "${NOTE} Removing conflicting package: ${YELLOW}$hyprnvi${RESET}" | |
| sudo pacman -R --noconfirm "$hyprnvi" 2>&1 | tee -a "$LOG" || true | |
| fi | |
| done | |
| echo -e "${OK} Conflicting packages check complete." | |
| #============================================================================== | |
| # Install NVIDIA Packages and Kernel Headers | |
| #============================================================================== | |
| print_header "Installing NVIDIA Packages and Kernel Headers" | |
| echo -e "${INFO} Detecting installed kernels..." | |
| installed_kernels=$(cat /usr/lib/modules/*/pkgbase 2>/dev/null | sort -u) | |
| if [ -z "$installed_kernels" ]; then | |
| echo -e "${ERROR} Could not detect installed kernels!" | |
| exit 1 | |
| fi | |
| echo -e "${OK} Detected kernels: ${YELLOW}$installed_kernels${RESET}" | |
| printf "\n" | |
| # Install kernel headers and NVIDIA packages for each kernel | |
| for krnl in $installed_kernels; do | |
| echo -e "${INFO} Installing headers for kernel: ${YELLOW}$krnl${RESET}" | |
| install_package "${krnl}-headers" "$LOG" | |
| done | |
| printf "\n" | |
| echo -e "${INFO} Installing NVIDIA packages..." | |
| for pkg in "${nvidia_pkg[@]}"; do | |
| install_package "$pkg" "$LOG" | |
| done | |
| #============================================================================== | |
| # Configure mkinitcpio | |
| #============================================================================== | |
| print_header "Configuring mkinitcpio" | |
| MKINITCPIO_CONF="/etc/mkinitcpio.conf" | |
| if grep -qE '^MODULES=.*nvidia. *nvidia_modeset.*nvidia_uvm.*nvidia_drm' "$MKINITCPIO_CONF"; then | |
| echo -e "${INFO} NVIDIA modules already included in $MKINITCPIO_CONF" | tee -a "$LOG" | |
| else | |
| echo -e "${NOTE} Adding NVIDIA modules to $MKINITCPIO_CONF..." | |
| sudo sed -Ei 's/^(MODULES=\([^\)]*)\)/\1 nvidia nvidia_modeset nvidia_uvm nvidia_drm)/' "$MKINITCPIO_CONF" 2>&1 | tee -a "$LOG" | |
| echo -e "${OK} NVIDIA modules added to mkinitcpio.conf" | |
| fi | |
| #============================================================================== | |
| # Rebuild Initramfs | |
| #============================================================================== | |
| print_header "Rebuilding Initramfs" | |
| echo -e "${INFO} Rebuilding initramfs with mkinitcpio -P..." | |
| sudo mkinitcpio -P 2>&1 | tee -a "$LOG" | |
| echo -e "${OK} Initramfs rebuilt successfully." | |
| #============================================================================== | |
| # Configure modprobe | |
| #============================================================================== | |
| print_header "Configuring modprobe" | |
| NVEA="/etc/modprobe.d/nvidia.conf" | |
| if [ -f "$NVEA" ]; then | |
| if grep -q "nvidia_drm modeset=1" "$NVEA" && grep -q "fbdev=1" "$NVEA"; then | |
| echo -e "${INFO} ${YELLOW}nvidia_drm modeset=1 fbdev=1${RESET} already configured in $NVEA" | |
| else | |
| echo -e "${NOTE} Updating $NVEA with required options..." | |
| echo "options nvidia_drm modeset=1 fbdev=1" | sudo tee "$NVEA" > /dev/null 2>&1 | tee -a "$LOG" | |
| echo -e "${OK} modprobe options updated." | |
| fi | |
| else | |
| echo -e "${NOTE} Creating $NVEA with NVIDIA options..." | |
| echo "options nvidia_drm modeset=1 fbdev=1" | sudo tee "$NVEA" > /dev/null 2>&1 | tee -a "$LOG" | |
| echo -e "${OK} Created $NVEA with modprobe options." | |
| fi | |
| #============================================================================== | |
| # Configure GRUB (if present) | |
| #============================================================================== | |
| if [ -f /etc/default/grub ]; then | |
| print_header "Configuring GRUB Bootloader" | |
| echo -e "${INFO} ${YELLOW}GRUB${RESET} bootloader detected" | tee -a "$LOG" | |
| GRUB_UPDATED=false | |
| # Check and add nvidia-drm.modeset=1 | |
| if ! sudo grep -q "nvidia-drm.modeset=1" /etc/default/grub; then | |
| sudo sed -i -e 's/\(GRUB_CMDLINE_LINUX_DEFAULT=".*\)"/\1 nvidia-drm.modeset=1"/' /etc/default/grub | |
| echo -e "${OK} Added nvidia-drm.modeset=1 to GRUB config" | tee -a "$LOG" | |
| GRUB_UPDATED=true | |
| else | |
| echo -e "${INFO} nvidia-drm.modeset=1 already present in GRUB config" | |
| fi | |
| # Check and add nvidia_drm.fbdev=1 | |
| if ! sudo grep -q "nvidia_drm.fbdev=1" /etc/default/grub; then | |
| sudo sed -i -e 's/\(GRUB_CMDLINE_LINUX_DEFAULT=".*\)"/\1 nvidia_drm.fbdev=1"/' /etc/default/grub | |
| echo -e "${OK} Added nvidia_drm.fbdev=1 to GRUB config" | tee -a "$LOG" | |
| GRUB_UPDATED=true | |
| else | |
| echo -e "${INFO} nvidia_drm.fbdev=1 already present in GRUB config" | |
| fi | |
| # Regenerate GRUB config if changes were made | |
| if [ "$GRUB_UPDATED" = true ]; then | |
| echo -e "${NOTE} Regenerating GRUB configuration..." | |
| sudo grub-mkconfig -o /boot/grub/grub.cfg 2>&1 | tee -a "$LOG" | |
| echo -e "${OK} GRUB configuration regenerated" | |
| fi | |
| echo -e "${OK} GRUB bootloader configuration complete" | tee -a "$LOG" | |
| fi | |
| #============================================================================== | |
| # Configure systemd-boot (if present) | |
| #============================================================================== | |
| if [ -f /boot/loader/loader.conf ]; then | |
| print_header "Configuring systemd-boot Bootloader" | |
| echo -e "${INFO} ${YELLOW}systemd-boot${RESET} bootloader detected" | tee -a "$LOG" | |
| backup_count=$(find /boot/loader/entries/ -type f -name "*.conf.bak" 2>/dev/null | wc -l) | |
| conf_count=$(find /boot/loader/entries/ -type f -name "*.conf" ! -name "*.bak" 2>/dev/null | wc -l) | |
| if [ "$backup_count" -ne "$conf_count" ]; then | |
| find /boot/loader/entries/ -type f -name "*.conf" ! -name "*.bak" | while read imgconf; do | |
| # Create backup | |
| sudo cp "$imgconf" "$imgconf.bak" | |
| echo -e "${INFO} Backup created: ${YELLOW}$imgconf.bak${RESET}" | tee -a "$LOG" | |
| # Clean up existing nvidia options and add new ones | |
| sdopt=$(grep -w "^options" "$imgconf" | sed 's/\b nvidia-drm.modeset=[^ ]*\b//g' | sed 's/\b nvidia_drm.fbdev=[^ ]*\b//g') | |
| sudo sed -i "/^options/c${sdopt} nvidia-drm.modeset=1 nvidia_drm.fbdev=1" "$imgconf" 2>&1 | tee -a "$LOG" | |
| echo -e "${OK} Updated: ${YELLOW}$imgconf${RESET}" | |
| done | |
| echo -e "${OK} systemd-boot configuration complete" | tee -a "$LOG" | |
| else | |
| echo -e "${INFO} systemd-boot appears to be already configured (backups exist)" | tee -a "$LOG" | |
| fi | |
| fi | |
| #============================================================================== | |
| # Create NVIDIA Pacman Hook (Optional - Rebuilds initramfs on NVIDIA updates) | |
| #============================================================================== | |
| print_header "Creating NVIDIA Pacman Hook" | |
| HOOK_DIR="/etc/pacman.d/hooks" | |
| HOOK_FILE="$HOOK_DIR/nvidia.hook" | |
| if [ ! -f "$HOOK_FILE" ]; then | |
| echo -e "${NOTE} Creating pacman hook to rebuild initramfs on NVIDIA updates..." | |
| sudo mkdir -p "$HOOK_DIR" | |
| sudo tee "$HOOK_FILE" > /dev/null << 'HOOKEOF' | |
| [Trigger] | |
| Operation=Install | |
| Operation=Upgrade | |
| Operation=Remove | |
| Type=Package | |
| Target=nvidia | |
| Target=nvidia-dkms | |
| Target=nvidia-lts | |
| Target=linux | |
| Target=linux-lts | |
| Target=linux-zen | |
| Target=linux-hardened | |
| [Action] | |
| Description=Rebuilding initramfs after NVIDIA driver update... | |
| Depends=mkinitcpio | |
| When=PostTransaction | |
| NeedsTargets | |
| Exec=/bin/sh -c 'while read -r trg; do case $trg in linux*) exit 0; esac; done; /usr/bin/mkinitcpio -P' | |
| HOOKEOF | |
| echo -e "${OK} NVIDIA pacman hook created at $HOOK_FILE" | |
| else | |
| echo -e "${INFO} NVIDIA pacman hook already exists at $HOOK_FILE" | |
| fi | |
| #============================================================================== | |
| # Summary and Final Steps | |
| #============================================================================== | |
| print_header "Installation Complete!" | |
| echo -e "${OK} NVIDIA driver installation and configuration complete!" | |
| printf "\n" | |
| echo -e "${INFO} ${YELLOW}Summary of changes:${RESET}" | |
| echo -e " ✓ Installed NVIDIA drivers and utilities" | |
| echo -e " ✓ Configured mkinitcpio with NVIDIA modules" | |
| echo -e " ✓ Created/updated modprobe configuration" | |
| if [ -f /etc/default/grub ]; then | |
| echo -e " ✓ Configured GRUB bootloader" | |
| fi | |
| if [ -f /boot/loader/loader.conf ]; then | |
| echo -e " ✓ Configured systemd-boot bootloader" | |
| fi | |
| echo -e " ✓ Created pacman hook for automatic initramfs rebuild" | |
| printf "\n" | |
| echo -e "${WARN} ${YELLOW}IMPORTANT:${RESET} A system reboot is required to load the NVIDIA drivers!" | |
| printf "\n" | |
| read -p "$(echo -e ${CAT}) Would you like to reboot now? (y/N): " reboot_choice | |
| if [[ "$reboot_choice" =~ ^[Yy]$ ]]; then | |
| echo -e "${INFO} Rebooting system..." | |
| sudo reboot | |
| else | |
| echo -e "${INFO} Please remember to reboot your system to apply the changes." | |
| echo -e "${INFO} You can reboot manually with: ${YELLOW}sudo reboot${RESET}" | |
| fi | |
| printf "\n" | |
| echo -e "${OK} Log file saved to: ${YELLOW}$LOG${RESET}" | |
| echo -e "${INFO} Thank you for using the NVIDIA installer! 💫" | |
| printf "\n" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment