#!/bin/bash # bos-nvidia-setup — optional proprietary NVIDIA driver + Hyprland env. # # Installs nvidia + nvidia-utils only (never cuda). Writes # ~/.config/hypr/nvidia.lua, which skel hyprland.lua dofiles only when # the file exists — Mesa machines stay unchanged. Existing installs get # the same include patched in if it is missing. # # Click-to-install from Settings, or run by hand. Not invoked from # bos-first-boot. Idempotent. Prints "reboot required". # # Must run on an installed system. Elevates via pkexec, then sudo. set -uo pipefail usage() { cat <<'EOF' Usage: bos-nvidia-setup [--home DIR] Install nvidia + nvidia-utils (not cuda) and write the Hyprland NVIDIA env drop-in for this user. Reboot after. --home DIR user home that owns ~/.config/hypr (required under pkexec if PKEXEC_UID / SUDO_USER cannot be resolved) EOF } TARGET_HOME="" while [[ $# -gt 0 ]]; do case "$1" in --home) TARGET_HOME="${2:-}" shift 2 ;; -h|--help) usage exit 0 ;; *) echo "bos-nvidia-setup: unknown argument: $1" >&2 usage >&2 exit 2 ;; esac done if [[ "$(id -un)" == "liveuser" || -d /run/archiso ]]; then echo "bos-nvidia-setup is for an installed system, not the live ISO." >&2 exit 1 fi if [[ "$(id -u)" -ne 0 ]]; then home="${TARGET_HOME:-${HOME:-}}" if [[ -z "$home" ]]; then echo "bos-nvidia-setup: cannot determine home; pass --home" >&2 exit 1 fi self="$(command -v bos-nvidia-setup 2>/dev/null || true)" [[ -n "$self" ]] || self="$(readlink -f "$0" 2>/dev/null || printf '%s' "$0")" if command -v pkexec >/dev/null 2>&1; then exec pkexec "$self" --home "$home" fi if command -v sudo >/dev/null 2>&1; then exec sudo "$self" --home "$home" fi echo "bos-nvidia-setup: need root (pkexec or sudo)" >&2 exit 1 fi if [[ -z "$TARGET_HOME" ]]; then if [[ -n "${PKEXEC_UID:-}" ]]; then TARGET_HOME="$(getent passwd "$PKEXEC_UID" | cut -d: -f6 || true)" elif [[ -n "${SUDO_USER:-}" && "${SUDO_USER}" != root ]]; then TARGET_HOME="$(getent passwd "$SUDO_USER" | cut -d: -f6 || true)" fi fi if [[ -z "$TARGET_HOME" || "$TARGET_HOME" == /root || ! -d "$TARGET_HOME" ]]; then echo "bos-nvidia-setup: cannot determine user home (pass --home)" >&2 exit 1 fi HYPR_DIR="$TARGET_HOME/.config/hypr" NVIDIA_LUA="$HYPR_DIR/nvidia.lua" HYPR_LUA="$HYPR_DIR/hyprland.lua" # Hyprland 0.56 (Aquamarine). Wiki (https://wiki.hypr.land/Nvidia/): # LIBVA_DRIVER_NAME + __GLX_VENDOR_LIBRARY_NAME. NVD_BACKEND is the # current VA-API hint. No WLR_* (not wlroots). No GBM_BACKEND (not # required; older docs cargo-culted it and it can break Firefox). NVIDIA_LUA_BODY='-- Written by bos-nvidia-setup. hyprland.lua dofiles this only when it exists. -- Hyprland 0.56 (Aquamarine) — no WLR_* variables. -- https://wiki.hypr.land/Nvidia/ hl.env("LIBVA_DRIVER_NAME", "nvidia") hl.env("__GLX_VENDOR_LIBRARY_NAME", "nvidia") hl.env("NVD_BACKEND", "direct") ' # Self-contained so it is safe to append to a hand-edited hyprland.lua. HYPR_INCLUDE='-- bos-nvidia-setup: optional proprietary env; no-op when the file is absent do local nvidia = (os.getenv("HOME") or "") .. "/.config/hypr/nvidia.lua" local f = io.open(nvidia, "r") if f then f:close() pcall(dofile, nvidia) end end ' own_as_user() { local path="$1" [[ -e "$path" ]] || return 0 local owner owner="$(stat -c '%u:%g' "$TARGET_HOME" 2>/dev/null || true)" [[ -n "$owner" ]] || return 0 chown "$owner" "$path" 2>/dev/null || true } echo "==> Installing nvidia + nvidia-utils (not cuda)" if ! command -v pacman >/dev/null 2>&1; then echo "bos-nvidia-setup: pacman not found" >&2 exit 1 fi if ! pacman -S --needed --noconfirm -- nvidia nvidia-utils; then echo "bos-nvidia-setup: pacman install failed" >&2 exit 1 fi echo "==> Writing $NVIDIA_LUA" mkdir -p "$HYPR_DIR" || { echo "bos-nvidia-setup: cannot create $HYPR_DIR" >&2 exit 1 } printf '%s' "$NVIDIA_LUA_BODY" >"$NVIDIA_LUA" || { echo "bos-nvidia-setup: cannot write $NVIDIA_LUA" >&2 exit 1 } own_as_user "$NVIDIA_LUA" if [[ -f "$HYPR_LUA" ]] && ! grep -q 'nvidia\.lua' "$HYPR_LUA"; then echo "==> Including nvidia.lua from $HYPR_LUA" if [[ -n "$(tail -c1 "$HYPR_LUA" 2>/dev/null || true)" ]]; then printf '\n' >>"$HYPR_LUA" fi printf '%s\n' "$HYPR_INCLUDE" >>"$HYPR_LUA" own_as_user "$HYPR_LUA" fi echo "reboot required" exit 0