Compare commits

...

20 Commits

Author SHA1 Message Date
stornic56 53088aad4b Docs Update
- ZRAM Scaling (docs/QUICKSTART.md): Updated Step 9 with the current fixed-4096MB formula: `≤8 GB → 50%`, `>8 GB → 4096 MB fixed`. Replaced obsolete `ram_gb > 16 ? 25% : 50%` and `/4` vs `/2` logic with the new behavior (`ram_gb <= 8 ? 50% : 4096 MB`). Examples: 4GB → 2048 MB, 8GB → 4096 MB, 16GB → 4096 MB, 32GB → 4096 MB.

- GPU Configuration (docs/gpu.md): Added AMD GCN Migration subsection with duplicate guard (`content_differs-style` check) and sed fix logic. Added Secure Boot warning for NVIDIA DKMS (`mokutil --sb-state` detection). Documented `|| return 1` protection for `/etc/modprobe.d/nvidia-wayland.conf` writing. Renumbered duplicate sections 7 → 8 → 9 to avoid duplicate headings.

- Firmware Installation (docs/firmware.md): Updated Broadcom section with `_run_cmd` wrappers (`|| true`) for `apt install broadcom-sta-dkms` and `modprobe wl`. Added SSH network warning (`WARNING: SSH is not recommended on a router`) before `modprobe -r`. Updated Initramfs step with `_run_cmd` wrapper (`|| true`).

- Repo Configuration (docs/repos_config.md): Removed `REPOS_CONFIGURED=true` from the POST-EXECUTION PHASE diagram and Safety Mechanisms. Added `_write_branch_sources` with its `_restore_backup` rollback and "Branch Migration Rollback" safety note to the diagram.

- System Info & Pre-flight (docs/system_info.md): Added pre-flight init (auto-install whiptail + lsb-release). Added LSPCI_OUTPUT cache with `command -v lspci` guard. Added `_ensure_apt_updated` deduplication helper. Added `STATE_REFRESHED=true` flag mechanism across all menu branches.

- User Home Ownership (docs/user_priv_feed.md): Updated Option 3 (Repair Home Ownership) to use `getent passwd "${SUDO_USER:-$USER}"` instead of the insecure `eval echo "~$USER"` pattern. Added documentation note explaining the security rationale.

- QuickStart ZRAM (docs/QUICKSTART.md): Updated Step 9 ZRAM scaling to "50% of RAM (≤8 GB) or 4096 MB fixed (>8 GB)".
2026-09-12 16:53:10 -05:00
stornic56 1fc395c188 dual-gpu hardening & wireless robustness
- Protected apt repository writes across modules/repos.sh by adding `|| return 1` to `_write_deb822()` and `_write_classic()`, ensuring script continuation on failure instead of aborting under set -e.
- Added idempotent backup restoration in restore_previous_repos() with `sudo cp ... || true` and `sudo rm ... || true` to prevent fatal errors during repository recovery operations.
- Implemented rollback mechanism in migrate_to_branch() by wrapping _write_branch_sources() in a conditional check, restoring backup on failure and returning error code 1.
- Hardened firmware installation flow in modules/firmware.sh with `|| true` guards on all apt commands (broadcom-sta-dkms, network firmware packages, backports/stable paths), preventing set -e aborts during package management.
- Secured modprobe operations by adding `|| true` to wl module loading and blacklist file writes, ensuring wireless driver installation proceeds even if kernel module operations fail.
- Added GPU tools installation protection in _helpers.sh with `|| true` guard on vainfo command execution after nvtop installation completes successfully.
- Fixed NVIDIA Wayland configuration in modules/gpu/nvidia.sh by adding `|| return 1` to nvidia-wayland.conf tee operation, preventing silent failures when writing modprobe configuration files.
- Implemented network warning notification before Broadcom wireless module removal to alert users of potential SSH disconnection during WiFi driver transitions.
- Added broadcom blacklist file protection with `|| true` guard on modprobe.d/blacklist-broadcom.conf writes to prevent script termination on filesystem errors.
- Standardized error handling patterns across all firmware and GPU modules, replacing direct command execution with conditional wrappers that maintain script continuity under failure conditions.
2026-09-12 15:15:01 -05:00
stornic56 8c922ee424 dual-gpu fix & lspci cache
- Replaced the restrictive Broadcom firmware installation flow with a persistent, step-by-step process in modules/firmware.sh. Now installs dkms, wireless-tools, and linux-headers-amd64 separately, then applies blacklist configuration, updates initramfs, and loads conflicting modules properly.
- Fixed conky package name across system.sh and bullseye/extras.sh. Changed from "conky" to "conky-all" with corresponding state variable updates for correct installation via apt.
- Corrected broken GRUB sed command in modules/gpu.sh for AMD GCN support. Added grep guard to prevent duplicate parameter insertion and fixed regex pattern for proper cmdline modification.
- Added whiptail pre-flight check in debianito.sh. Auto-installs required TUI dependencies if missing before the main menu, preventing runtime failures.
- Fixed home directory path resolution bug in modules/sudo_config.sh. Replaced eval echo "~$USER" with getent passwd approach for reliable user home detection across SUDO_USER contexts.
- Implemented global lspci output caching across 18+ locations. Single cache population via _init_lspci_cache() before detect_gpu, all subsequent reads use LSPCI_OUTPUT variable to eliminate redundant hardware polling calls.
- Added apt update deduplication helper in modules/utils.sh. _ensure_apt_updated() with APT_UPDATED flag bypasses redundant package list refreshes across extras/, gaming/, firmware/, and desktop_display/ modules while preserving transactional rollback paths in repos.sh.
- Fixed STATE_REFRESHED logic in debianito.sh main_menu case statement. Added STATE_REFRESHED=true to branches 3, 5, 7, 9, 11, 12, and 13 that mutate system state, ensuring refresh_system_state() triggers correctly after configuration changes.
- Removed dead REPOS_CONFIGURED variable from debianito.sh and modules/repos.sh. Variable was written but never read, eliminated to clean up global namespace without affecting repository functionality.
2026-08-27 01:41:33 -05:00
stornic56 0eacdc095f Broadcom wl Single-Path Rewrite
- Removed 4 Broadcom classification helper functions (`_is_broadcom_brcm`, `_is_broadcom_b43`, `_is_broadcom_b43legacy`, `_detect_broadcom_plan_lines`) and their call in `install_firmware()`.
- Rewrote `_handle_wireless()` to a single-path Broadcom → broadcom-sta-dkms → clean conflicting modules → load wl → verify approach, replacing the old 3-tier classification logic.
- Added `linux-headers-amd64` availability verification via `apt-cache policy` before driver installation.
- Added user confirmation step before installing Broadcom driver.
- Preserved BT combo handling (softdep wl post: btusb) and Post-DKMS verification (Fix 5) with the same behavior as the original code.
- Preserved USB Broadcom device detection (0a5c grep) and final message logic.
- Removed `wl_conflict_offered` variable from `_handle_wireless()`.
- All other helpers, arrays, and logic paths remain unchanged.
2026-08-22 21:47:44 -05:00
stornic56 8932da160d Broadcom WiFi & zram enhancements
- modules/firmware.sh — 4 fixes:
  - Added _detect_broadcom_plan_lines() helper to display firmware-brcm80211 in the firmware plan. The plan now shows the correct package for all Tier 1 Broadcom chips.
  - Added post-install verification for Tier 1 (brcmfmac): checks that /lib/firmware/brcm/brcmfmac43* files exist after apt install. If missing, displays a warning with dpkg-reconfigure guidance.
  - Added conflict detection between broadcom-sta-dkms and brcmfmac (wl). If broadcom-sta-dkms is installed, the script prompts the user to purge it before installing firmware-brcm80211, preserving the correct driver.
  - Added a reboot warning after successful brcmfmac firmware installation: [+] Broadcom brcmfmac firmware installed. A system reboot is required to load the new firmware.
  - Added || true to the Tier 3 (wl) _run_cmd call and introduced a wl_build_failed flag to suppress the "No special WiFi firmware needed" message when the DKMS build fails.
  - Removed BCM4313 (ID 4727), BCM43225 (ID 4357), and BCM43227 (ID 4358) from _is_broadcom_brcm. These chips belong to the wl tier and should use broadcom-sta-dkms, not firmware-brcm80211.

- modules/zram.sh — 1 fix:
  - Changed zram sizing logic from 3 branches to 2: the >16 GB branch (which allocated 25% or 50% of RAM) is replaced by a single threshold check. RAM > 8 GB → fixed 4096 MB; RAM ≤ 8 GB → 50% of RAM (using the same ((RAM_KB / 1024 / 1024 + 1) / 2) * 1024 rounding pattern).
2026-08-21 01:27:53 -05:00
stornic56 9230cda5dd Firefox bug fix & LXDE desktop option
- Resolved Firefox installation conflict: the "both" selection no longer triggers duplicate dialogs or cancellation; the installer now passes the resolved choice to both Mozilla and ESR installers, preserving co-installation without redundant prompts.
- Fixed bugs across Debian 11/12/13 scripts:
- Migrated `migrate.sh` to write classic `.sources` format for Debian 11 and skip the security stanza for SID.
- Corrected non-free token matching in `firmware.sh` to avoid false positives on non-free-firmware-only systems.
- Added `sudo` to `broadcom-combo.conf` creation and fixed `/etc/modprobe.d` directory handling.
- Fixed write propagation in `repos.sh` to prevent silent failures on user rejection.
- Corrected PipeWire state detection for Debian 11 and added SID security stanza exclusion.
- Added LXDE desktop environment option to `debianito.sh`:
- New "LXDE (Full)" and "LXDE Core" options in the Desktop Environment menu.
- Both options install `lightdm` in a single `apt-get install` call and enable the service via `systemctl enable`.
- Includes debconf preseed for LightDM default display manager selection.
- No extra packages, no Openbox/LXDE configuration changes.
- Added `_radiolist()` helper to `utils.sh` for safe radio-list cancellation under `set -e`.
- Added `lxde_menu()` to `desktop_display.sh` with exact 2-option radio list, single-shot dispatch, and clean `return 0` on cancel.
- Added `_install_lxde_full()` and `_install_lxde_core()` with `debconf-set-selections`, single `apt` call, and `systemctl enable lightdm` post-install.
2026-08-19 00:18:41 -05:00
stornic56 0e24e8f9ae System-Wide Refactor & Critical Fixes
- Resolved NVIDIA driver management issues by expanding package detection patterns (including nvidia-open and nvidia-kernel-open-dkms), enhancing purge process to ensure clean uninstallation of v590/595 drivers, and adding conditional skip for manage menu when no driver is installed.  
- Enhanced Firefox variant selection in internet.sh using exact token matching (grep -qx) instead of substring search to prevent incorrect removal or unintended ESR/Firefox conflicts. 
- New XFCE install option with 4 options
- Restructured Desktop Environment into two-level menu system with dispatcher and Xfce sub-menu for scalability, enabling future additions like GNOME/KDE without disrupting existing flows.  
- Added Polkit rules in desktop_display.sh to grant suspend permissions without password prompts on laptops, including idempotent group (backlight) creation and user membership management with || true fallbacks.  
- Enforced LC_ALL=C LANGUAGE=C environment variables for all dpkg-reconfigure commands across System Preferences and utils.sh to ensure native dialogues run consistently in English.  
- Fixed kernel backports menu option availability to only appear on Debian 13, preventing errors on Debian 12 where backports repositories are EOL.  
- Improved ZRAM module initialization sequence by ensuring swapoff and zram module removal occur before writing new configuration files to prevent race conditions during system setup.
2026-08-17 23:50:39 -05:00
stornic56 dbd2dfca37 nvidia ux & bookworm bpo cleanup
- Removed redundant confirmation dialogs from `_install_nvidia_stack`. Users can now access driver management (including removal) without first confirming installation intent; initial plan display is followed by pause for review instead of blocking prompt.
- Automated CUDA repository enabling on Debian 13/Bookworm paths (590/595). Manual confirmation prompts eliminated; script auto-enables repo via `_enable_cuda_repo` with error handling while maintaining safety checks.
- Split CUDA driver installation into two distinct APT transactions in `nvidia.sh`. Step 1 installs mandatory version pinning (`nvidia-driver-pinning-${ver}`); failure aborts process. Step 2 installs `nvidia-open`, relying on transitive dependencies for firmware rather than explicit package listing.
- Eliminated all Bookworm backports support due to EOL (2026-08-09). Removed `_install_nvidia_bookworm_bpo()`, dead code `install_nvidia_driver()`, and dispatcher logic for Debian 12. Turing now installs standard packages only; Trixie backports remain intact.
- Updated documentation (`docs/gpu.md`) to reflect actual installation flow and removed references to deprecated functions.
2026-08-10 17:58:03 -05:00
stornic56 2bcdb511b2 Fix NVIDIA CUDA Repo Debian 13
- Fixed critical abort in `_install_nvidia_cuda_repo` for Debian 13 (Trixie) when installing v590/v595 due to `nvidia-open` availability checks.
- Removed pre-install `apt-cache policy` verification that caused premature script termination on version mismatches.
- Eliminated manual creation of `/etc/apt/preferences.d/block-nvidia`, relying exclusively on official NVIDIA pinning packages (`nvidia-driver-pinning-${ver}`).
- Updated error handling to display real `apt` output on failure instead of generic abort messages, improving troubleshooting visibility.
- Synchronized documentation in `docs/gpu.md` to reflect the simplified CUDA repo flow and removed references to manual pinning or candidate checks.
2026-08-10 00:55:47 -05:00
stornic56 f0be860f98 nvidia menu & management updates
- Refined `_show_nvidia_version_menu` in `modules/gpu/nvidia.sh` for Debian 12/13 with precise labels ("Newest Stable", "Kepler Support") and explicit official repo recommendations.
- Introduced new standalone module `modules/gpu/nvidia_manage.sh` integrated into the dispatcher to handle driver lifecycle management (Install/Change vs Remove) before version selection.
- Implemented safe removal logic (`_nvidia_remove`) with explicit package purging, explicitly excluding `firmware-misc-nonfree`, and cleaning specific configs/repos without wildcards.
- Ensured idempotency across all steps using `|| true` and preserved user CUDA toolkits while restoring Nouveau via initramfs regeneration.
2026-08-07 23:43:29 -05:00
stornic56 59c93ba459 nvidia & zram fixes
- Fixed critical NVIDIA driver bug on Debian 13 (Trixie) where repo configuration installed v550 instead of selected v595. Implemented version-specific enabling: cuda-keyring for Trixie, extrepo for Bookworm. Added explicit apt update after repo enable and candidate verification before pinning checks to abort cleanly if expected driver unavailable.
- Rewrote `_install_nvidia_standard()` with auto-detected architecture via `_get_nvidia_arch_family()`. Turing/Ampere/Ada/Blackwell → nvidia-open-kernel-dkms (open module); Maxwell/Pascal/Volta/unknown/empty → nvidia-kernel-dkms (closed, safe fallback). Removed all `nvidia-detect` references across modules and docs.
- Fixed `_install_nvidia_cuda_repo()` to use correct CUDA repository package names: v590/v595 → nvidia-open metapackage (includes nvidia-kernel-open-dkms); v550 and below → nvidia-driver. Added dynamic warning message based on installed module type.
- Fixed uninitialized variable bug in `modules/gaming/tools.sh` causing script abortion under `set -u`. Initialized all local variables (`deb_url`, `sha256`, `json`, `deb_suffix`) with default values and added defensive initialization for `$USER` environment variable.
- Fixed ZRAM configuration persistence bug where old config persisted after changes. Added device reset sequence (swapoff + modprobe -r) before writing new config, post-config verification check, and changed default recommendation from 50% to 25% for systems with >16GB RAM.
- Added `_warn_nvidia_gnome_wayland()` function in `gpu.sh` to warn about Debian bug #1109409 (GDM3 + NVIDIA + Wayland black screen issue). Warning displays only when gdm3 present, GNOME Shell 4.x detected, and NVIDIA driver installed.
- Standardized menu headers across all modules using centralized SCROLL_HINT variable, replacing hardcoded strings with uniform Whiptail instructions. Updated documentation for cuda-keyring (Trixie) and ZRAM configuration flow diagrams.
2026-08-05 21:13:32 -05:00
stornic56 0ec9639030 nvidia driver stability & version menu
- Refactored NVIDIA installation with robust DKMS verification (`_verify_nvidia_dkms_build`). Automatically detects build failures for the current kernel and repairs them via `dpkg-reconfigure`, ensuring modules compile against active kernels without manual intervention.
- Added Secure Boot detection (`_nvidia_secure_boot_enabled`) to warn users if the NVIDIA module is compiled but unsigned, preventing boot issues on systems with UEFI security enabled.
- Implemented `_configure_nvidia_wayland()` for Wayland support. Detects hybrid laptops (Optimus) vs desktops using DMI chassis types and battery presence. Configures `NVreg_PreserveVideoMemoryAllocations` only for desktops to avoid Optimus conflicts, and adds architecture-specific guards (e.g., Kepler warnings).
- Introduced version selection menu (`_show_nvidia_version_menu`). Users can select driver versions (470/535/550/590/595) based on Debian release. Parametrized CUDA repo installation for 590/595 with post-install DKMS branch verification.
- Fixed state inconsistency bugs in `NVIDIA_DRIVER_MODE`. Added guards to ensure configuration files are only written upon successful installation, preventing partial setups after failures (e.g., backports, CUDA repo).
- Improved hardware detection helpers (`_is_hybrid_laptop`, `_get_nvidia_arch_family`). Prevents false positives on multi-GPU desktops by verifying iGPU presence alongside dGPU.
- Updated Java/Minecraft support in `modules/extras/java.sh`. Added Temurin 25 ("Minecraft 26+") to the runtime selection menu and updated documentation.
- Enhanced utility robustness (`_run_cmd`, `_configure_lightdm`). Properly propagates exit codes from commands and handles failures gracefully (yellow warnings + skip) instead of crashing under `set -e`.
2026-08-05 01:25:26 -05:00
stornic56 09ef6bcda5 Repos: Empty Sources, Deb822 & Security Fixes
- Enhanced repository detection logic in `modules/repos/repo_detect.sh`. Implemented `has_active_deb_sources()` for content-aware scanning across `sources.list`, `*.list`, and `*.sources` files. Empty or comment-only files are now correctly identified as "none" to trigger bootstrapping.
- Enforced Debian 13 (Trixie) specific logic in `detect_repo_format()`. Deb822 format is only applied when `debian.sources` is active; Bookworm and Bullseye systems default strictly to classic sources.list regardless of file presence.
- Added state guard against mixed configuration formats (deb822 + classic active simultaneously) with a warning prompt before writing, preventing duplicate entries in `/etc/apt/sources.list`.
- Rewrote `_repos_enable_components()` in `modules/repos.sh` to remove early returns when components are already enabled. The script now verifies and ensures security and updates sections exist/were written correctly if missing or different.
- Created new `bootstrap_repositories()` function for systems with no active sources. Includes user dialogue for format selection (Trixie) or auto-classic (older versions), backup/restore safety, and cleanup of empty sources.list files post-bootstrap.
- Fixed false success reporting in `modules/firmware.sh` and `gaming.sh`. Added pre-checks to ensure APT sources exist before attempting `sed -i` modifications; if sources are missing, the script now triggers a full repository bootstrap instead of silently failing.
- Implemented post-write verification in firmware/gaming modules to confirm components were actually added before reporting success to the user.
- Generalized backports detection in `modules/utils.sh` (`is_backports_enabled()`) to scan all `*.list` and `*.sources` files rather than relying on fixed canonical filenames.
- Corrected test harness variable expansion order and trimmed whitespace from component parsing logic during development verification.
2026-08-02 00:10:12 -05:00
stornic56 28bb52c87d Fix NVIDIA Kepler Logic & Kernel Headers
- Normalized PCI ID case sensitivity in `_helpers.sh`. The `detect_nvidia_arch()` function now converts input to uppercase (`${1^^}`) to match legacy architecture map keys, resolving "unknown" detection for all NVIDIA GPUs.
- Removed silent fallback to standard drivers in `gpu.sh` Bookworm logic. Kepler and other architectures now invoke specific installation functions directly without defaulting to unsupported driver versions (e.g., 535).
- Corrected NVIDIA legacy package name in `nvidia.sh`. Updated `_install_nvidia_bookworm_kepler()` to use `nvidia-tesla-470-driver` instead of deprecated Bullseye naming conventions for Debian 12.
- Replaced specific kernel header references (`linux-headers-$(uname -r)`) with meta-package `linux-headers-amd64` in `firmware.sh`. Fixes DKMS installation failures for Broadcom/WiFi drivers across multiple Debian versions.
2026-07-31 00:38:30 -05:00
stornic56 b423ccfc0b audio stack & GPU driver unification
- Unified PipeWire installation into a single checklist option ("PipeWire Audio Stack"). Removed confusing dual options (Standard/Backports) to streamline Debian 13 workflows. Added Bluetooth Hi-Res codec support (LDAC, aptX, AAC) with automatic detection of `libfdk-aac` variants across all Debian versions.
- Refactored `_install_nvidia_standard()` in `modules/gpu/nvidia.sh` to respect the `NVIDIA_DRIVER_MODE` signal from the dispatcher, eliminating external dependency on `nvidia-detect`. Added logic to select between Open Kernel Modules (Turing/Ada/Ampere) and Classic DKMS (Maxwell/Pascal/Volta). Enhanced confirmation dialogs to display both driver and kernel module versions.
- Updated `_install_mesa_32bit()` in `modules/gaming/_helpers.sh` with the same version resolution and upgrade logic as Audio, ensuring consistent UX for Backports selection on Debian 13.
- Expanded `NVIDIA_FAMILY_MAP` in `modules/gpu/_helpers.sh` to include missing silicon prefixes (Hopper, Blackwell variants) while maintaining "legacy" abstraction for driver policy separation.
2026-07-30 20:33:21 -05:00
stornic56 8a45d75e95 Fix Mesa 32-bit dependencies on Debian 13
- Resolved critical dependency conflicts for `libgl1-mesa-dri:i386` and related Mesa libraries on Debian 13 when backports are enabled.
- Modified `_install_mesa_32bit()` in `modules/gaming/_helpers.sh` to force `-t trixie-backports` target repository for i386 packages if detected.
- Prevents version mismatch errors (Stable 25.0.7 vs Backports 26.1.2) and missing `libgbm1:i386` issues by ensuring consistent architecture resolution from the backports branch.
2026-07-29 00:32:59 -05:00
stornic56 ddc2642718 dual-gpu & audio fixes + flatpak migration
- Fixed `set -euo pipefail` crashes across hardware detection: Added `|| true` guards to all `nvidia-smi`, `dpkg -l`, `apt-cache policy`, and `nvidia-detect` pipelines in `sysinfo.sh` (3 lines) and `gpu/nvidia.sh` (7+ lines).
- Created new Audio & Sound module (`modules/extras/audio/audio.sh`) with Debian version-specific logic: Bullseye basic mode vs Bookworm/Trixie standard PipeWire stack, plus ALSA utilities, pavucontrol, pulsemixer, playerctl. Added menu entry "14 Audio & Sound".
- Migrated Flatpak from System Tools to Software Center category. Renamed menu to "Software Center & Flatpak", converted single-select to multi-select checklist in `software_centers.sh`, removed logic from `system.sh`.
- Implemented robust time synchronization: New `_ensure_time_synced()` function in `utils.sh` forces NTP active, validates timezone with interactive `dpkg-reconfigure tzdata` if needed, restarts `systemd-timesyncd`, and verifies sync status. Replaced `check_system_time` call in main script.
- Fixed System Info network detection: Removed hardcoded 2-line height limit (now dynamic via terminal size), fixed hard-coded array indices to use progressive counters for multiple interfaces including USB WiFi adapters.
2026-07-28 19:55:22 -05:00
stornic56 f0cea296d7 fix harden hardware detection D3cold freezes
Fixes a critical startup crash on hybrid graphics laptops (e.g., Intel + Nvidia) running fresh Debian installs without proprietary drivers. 

When the secondary GPU enters D3cold power state, kernel-level I/O operations (like `lspci` or reading `/sys/block/`) hang in Uninterruptible Sleep (State D), ignoring standard kill signals and freezing the terminal. Combined with `set -euo pipefail`, these hangs made the script silently fail or enter infinite loops.

Changes:
- Timeout Wrappers: Wrapped all hardware probing commands (`lspci`, `lsblk`, `cat /sys/...`, `ip`, `iwgetid`, `pw-cli`) with `timeout 2` to force-continue if the kernel blocks.
- Pipeline Safety: Added `|| true` to `nvidia-smi` and `dpkg` fallback queries to prevent `pipefail` from killing the script when drivers are missing.
- Loop Hardening: Fixed an infinite loop in `detect_gpu()` where empty `lspci` outputs caused by timeouts would loop forever by adding `[[ -z "$line" ]] && continue`.
- TUI Fallbacks: Added default values for `${LINES:-24}` and `${COLUMNS:-80}` to prevent `set -u` from crashing the `whiptail` menu in restricted shell environments.
2026-07-26 01:15:57 -05:00
stornic56 762285f993 fix script
-fix script and nvidia-smi
2026-07-25 22:53:18 -05:00
stornic56 cd965a6678 bash gpu detection fix & nvidia-smi hardening
- Fixed critical script termination on hybrid GPU systems (Intel+Nvidia). The `set -euo pipefail` header was causing immediate exit when `read` reached EOF with exit code 1, preventing further execution despite valid hardware detection.
- Added `|| true` to the lspci processing loop in `modules/utils.sh`. This forces the while read condition to always return success (0), allowing clean loop termination and proper variable assignment for `HAS_NVIDIA=true` and `HAS_INTEL=true`.
- Hardened nvidia-smi driver version query with timeout protection. Wrapped the command call with `|| true` to capture exit code 124 from `timeout`, preventing script abortion when GPU enters D3cold state or command fails.
- Changes applied at line 204 (while read loop) and line 243 (nvidia-smi query). Both modifications ensure the main script continues execution after hardware detection completes, enabling full menu loading on dual-GPU laptops.
2026-07-25 22:03:13 -05:00
46 changed files with 4434 additions and 2382 deletions
+39 -158
View File
@@ -40,189 +40,62 @@ chmod +x debianito.sh && ./debianito.sh
After running the script: After running the script:
1. **Select Option:** Use arrow keys or type 1-10. 1. **Select Option:** Use arrow keys or type 1-14.
2. **Navigation:** Use Arrow Keys (Up↑/Down↓) to move between list options and ENTER key to confirm selection. 2. **Navigation:** Use Arrow Keys (Up↑/Down↓) to move between list options and ENTER key to confirm selection.
3. **Confirm Actions:** Installation prompts use whiptail for TUI confirmations. 3. **Confirm Actions:** Installation prompts use whiptail for TUI confirmations.
4. **Review System Info:** Header displays detected Debian version and hardware summary before each action. 4. **Review System Info:** Header displays detected Debian version and hardware summary before each action.
5. **Repeat as Needed:** Return to main menu at any time or exit when done. 5. **Repeat as Needed:** Return to main menu at any time or exit when done.
| Option | Description | What it does | | Option | Description | What it does |
|--------|-------------|--------------| | -------- | ------------- | -------------- |
| **1** | [System Info](/docs/system_info.md) | Show detected OS, CPU, RAM, GPU and hardware details | | **1** | [System Info](/docs/system_info.md) | Show detected OS, CPU, RAM, GPU and hardware details |
| **2** | [User Privileges & Feedback](/docs/user_priv_feed.md) | Configure sudo group membership, enable passwordless sudo for frequent tasks, repair home directory ownership issues, and toggle visual password feedback (asterisks) in terminal | | **2** | [User Privileges & Feedback](/docs/user_priv_feed.md) | Configure sudo group membership, enable passwordless sudo for frequent tasks, repair home directory ownership issues, and toggle visual password feedback (asterisks) in terminal |
| **3** | [Configure Repositories](/docs/repos_config.md) | Setup official repos with non-free/contrib options, optional Backports support and Deb822/classic format injection.| | **3** | [System Preferences](/docs/system_prefs.md) | Configure date/time & timezone, language/locales & keyboard layout, and audio stack (PipeWire, ALSA, PulseAudio) |
| **4** | [Firmware, Wireless & Bluetooth](/docs/firmware.md) | Install essential firmware for GPUs and wireless| | **4** | [Configure Repositories](/docs/repos_config.md) | Setup official repos with non-free/contrib options, optional Backports support and Deb822/classic format injection |
| **5** | [Graphics Drivers & Mesa Stack](/docs/gpu.md) | Configure AMD/Intel/NVIDIA drivers and Mesa graphics stack + monitoring tools | | **5** | [Firmware, Wireless & Bluetooth](/docs/firmware.md) | Install essential firmware for GPUs and wireless; configure Bluetooth stack (bluez, bluedevil/blueman) |
| **6** | [Backports Kernel](/docs/kernel.md) | Install latest kernel from Debian backports| | **6** | [Graphics Drivers & Mesa Stack](/docs/gpu.md) | Configure AMD/Intel/NVIDIA drivers and Mesa graphics stack + monitoring tools |
| **7** | [Gaming Setup ](/docs/gaming.md)| Steam, Heroic Games Launcher, [RetroArch](/docs/retroarch.md) GameMode, MangoHud, OpenRGB, Java JRE (Temurin 8/17/21) | | **7** | [Kernel](/docs/kernel.md) | Install kernel variants: Stable, RT, Cloud, or Backports (Debian 13) |
| **8** | [ZRAM](/docs/zram.md)| Configure compressed RAM for memory optimization| | **8** | [Gaming Setup](/docs/gaming.md) | Steam, Heroic Games Launcher, [RetroArch](/docs/retroarch.md), GameMode, MangoHud, OpenRGB, Java JRE (Temurin 8/17/21/25) |
| **9** | [Swap Management](/docs/swap.md)| Manage swap file or partition size and enable/disable swap space for system stability| | **9** | [ZRAM](/docs/zram.md) | Configure compressed RAM for memory optimization |
| **10** | Install Programs and Software | Browse and install packages by category (Development, Themes, System Tools, etc.) using APT | | **10** | [Swap Management](/docs/swap.md) | Manage swap file or partition size and enable/disable swap space for system stability |
| **11** | [Boot Rescue + GRUB](/docs/boot.md)| Config and fix GRUB bootloader issues, chroot repair, or restore system boot configuration| | **11** | Install Programs and Software | Browse and install packages by category (Development, Themes, System Tools, etc.) using APT |
| **12** | [Desktop & Display](/docs/desktops_display.md)| Install and configure desktops and display managers| | **12** | [Boot Rescue + GRUB](/docs/boot.md) | Config and fix GRUB bootloader issues, chroot repair, or restore system boot configuration |
| **13** | Exit | Return to terminal | | **13** | [Desktop & Display](/docs/desktops_display.md) | Install and configure desktops (XFCE, LXDE) and display managers (LightDM, GDM3, SDDM, greetd) |
| **14** | Exit | Return to terminal |
### Install Programs and Software (Option 10) ### Install Programs and Software (Option 11)
The submenu offers the next categories: The submenu offers the next categories:
| Option | Category Title | Description | | Option | Category Title | Description |
|--------|-------------------------------|-------------| | -------- | ------------------------------- | ------------- |
| **0** | Essential Pack | Quick install of common tools (compression, system info, VLC, MS fonts)| | **0** | Essential Pack | Quick install of common tools (compression, system info, VLC, MS fonts) |
| **1** | Customization System | Desktop themes, icon themes, cursor themes, and fonts | | **1** | Customization System | Desktop themes, icon themes, cursor themes, and fonts |
| **2** | Download & Network | Downloaders (aria2, ytdlp, FileZilla) + Torrent clients (qBittorrent, Deluge, Transmission) | | **2** | Download & Network | Downloaders (aria2, ytdlp, FileZilla) + Torrent clients (qBittorrent, Deluge, Transmission) |
| **3** | Internet (Browsers, Email Clients, VPN) | Web browsers (Firefox, LibreWolf, Floorp, Chromium, Tor), email client (Thunderbird), and VPN tools (RiseUp, Proton, Mullvad)| | **3** | Internet (Browsers, Email Clients, VPN) | Web browsers (Firefox, LibreWolf, Floorp, Chromium, Tor), email client (Thunderbird), and VPN tools (RiseUp, Proton, Mullvad) |
| **4** | Media Players | Multimedia playback with VLC media player and MPV for advanced video/audio support | | **4** | Communication | Signal, Telegram, HexChat — chat and messaging clients (GUI only) |
| **5** | Multimedia & Design | image editing (GIMP), video editing (Kdenlive, HandBrake), 3D modeling (Blender), audio recording (Audacity), and graphics design (Inkscape) | | **5** | Media Players | Multimedia playback with VLC media player and MPV for advanced video/audio support |
| **6** | Code Editors & IDEs | vim, vim-gtk3, Neovim, Helix, nano, Emacs, Kate, Mousepad, Gedit, Geany, GNOME Text Editor, and VSCodium (VS Code open-source) | | **6** | Multimedia & Design | Image editing (GIMP), video editing (Kdenlive, HandBrake), 3D modeling (Blender), audio recording (Audacity), and graphics design (Inkscape) |
| **7** | Servers & Dev Tools | Web servers (Nginx/Apache), databases (PostgreSQL/MariaDB), Java Development Kit (Temurin 17/21/25 JDK), Docker, Python, SSH tools, Jellyfin Server and essential utilities | | **7** | Code Editors & IDEs | vim, vim-gtk3, Neovim, Helix, nano, Emacs, Kate, Mousepad, Gedit, Geany, GNOME Text Editor, and VSCodium (VS Code open-source) |
| **8** | Security & Networking | Wireshark, tcpdump, Zenmap, ClamAV, UFW, fail2ban | | **8** | Servers & Dev Tools | Web servers (Nginx/Apache), databases (PostgreSQL/MariaDB), Java Development Kit (Temurin 17/21/25 JDK), Docker, Python, SSH tools, Jellyfin Server and essential utilities |
| **9** | Software Centers | Choose a software store to install. | | **9** | Security & Networking | Wireshark, tcpdump, Zenmap, ClamAV, UFW, fail2ban |
| **10** | Office & Productivity | Choose a software store to install. | | **10** | Software Center & Flatpak | GNOME Software / KDE Discover and Flatpak support |
| **12** | System Tools | htop/btop, ncdu, Timeshift, tmux/screen, nvme-cli, Flatpak support, extension repository manager and qemu/virtmanager | | **11** | Office & Productivity | Office suites (LibreOffice), document tools, productivity apps |
| **12** | Fetch / System Info | fastfetch/neofetch, hyfetch, Linux logo and screenfetch | | **12** | System Tools | htop/btop, ncdu, Timeshift, tmux/screen, nvme-cli, extension repository manager and qemu/virtmanager |
| **13** | Back to Main Menu | Return directly to the main Debianito menu (exit submenu) | | **13** | Fetch / System Info | fastfetch/neofetch, hyfetch, Linux logo and screenfetch |
| **14** | Back to Main Menu | Return directly to the main Debianito menu (exit submenu) |
--- ---
## Quick Start — Recommended Setup Order
This section shows the recommended order to configure a fresh Debian installation for maximum performance and usability. Follow these steps in order — each step builds on the previous one.
---
### Step 1 — Know Your System
**Menu:** `1 System Information`
Check your hardware before installing anything. The script detects your CPU, RAM, GPU vendor and generation, network adapters, and display server. Write down what you see — especially the GPU line (Intel/AMD/NVIDIA) and any WiFi chipset. You'll need this info for steps 4 and 5.
> 💡 If no GPU is detected, you're likely on a VM or headless server — skip step 5.
---
### Step 2 — Enable Password Feedback
**Menu:** `2 User Privileges & Feedback` → select option for Sudo Password Feedback
Enable asterisks (`****`) when typing your sudo password. This prevents typos during the many installation steps that follow. Toggle it on now, disable it later if you prefer hidden input.
---
### Step 3 — Configure Repositories
**Menu:** `3 Configure Repositories`
This is the foundation — all subsequent installations depend on correct repos.
1. **Enable Contrib & Non-Free Components** (required for firmware, drivers, Steam)
2. **Setup/Update Backports repositories** (recommended — gives you newer kernels, Mesa drivers, and firmware for modern hardware)
> ⚠️ Without non-free enabled, steps 4 and 5 will fail. Do not skip this.
---
### Step 4 — Install Firmware & Wireless Drivers
**Menu:** `4 Firmware, Wireless & Bluetooth`
The script scans ALL network hardware (PCI + USB) and installs exactly the firmware your system needs. Accept the plan it shows — it's based on your actual hardware.
This step also sets up Bluetooth if your system has Bluetooth hardware (KDE gets bluedevil, XFCE gets blueman, GNOME uses built-in).
> ⚠️ You need internet for this step. If WiFi isn't working after firmware install, reboot first — the driver needs a fresh load.
---
### Step 5 — Install Graphics Drivers
**Menu:** `5 Graphics Drivers & Mesa Stack`
The script auto-detects your GPU and installs the correct driver:
- **NVIDIA:** The script chooses the best path automatically (CUDA repo, backports, or stable) based on your GPU generation and kernel. Just confirm the plan.
- **AMD/Intel:** Installs firmware + Mesa stack + Vulkan drivers. Also installs 32-bit libraries if gaming is planned.
- **Hybrid (laptop):** Installs Intel/AMD firmware first, then NVIDIA driver.
> 💡 After installation, reboot before testing. NVIDIA drivers need a fresh kernel load to activate.
---
### Step 6 — Kernel Configuration
**Menu:** `6 Kernel`
If you enabled backports in step 3, you can install a newer kernel (e.g., 7.x) for better hardware support. The script offers stable vs backports:
| Choice | Best for |
|--------|----------|
| Stable (default) | Maximum stability, older hardware |
| Backports | Modern CPUs (Intel Arrow Lake, AMD Zen 5), new GPUs, better power management |
> ⚠️ If you installed NVIDIA drivers in step 5, the backports kernel may require DKMS recompilation. The script warns about this — it's usually fine.
---
### Step 7 — Gaming Setup (Optional)
**Menu:** `7 Gaming Setup`
If you plan to game on Debian:
1. **Enable i386 architecture** when prompted — this is REQUIRED for Steam/Proton and 32-bit game libraries
2. Select your launchers: Steam, Heroic Games Launcher, Lutris
3. Select performance tools: GameMode, MangoHud, GOverlay
4. Select RetroArch if you want retro emulation (pre-installed with GBA, SNES, NES, GB cores)
> ⚠️ Steam requires the contrib repository (step 3) and i386 architecture. The script warns if either is missing.
---
### Step 8 — ZRAM Compressed Swap (Optional)
**Menu:** `8 ZRAM`
ZRAM compresses memory pages in RAM instead of writing to disk. This is especially useful on systems with limited RAM (8GB or less). The script automatically sets ZRAM to ~50% of your physical RAM with priority 100 (used before disk swap).
Choose **LZ4** for gaming (fastest compression) or **ZSTD** for general use (better compression ratio).
> 💡 If you also use disk-based swap (Option 9), ZRAM is used first. Disk swap only kicks in after ZRAM fills up.
---
### Step 9 — Essential Software
**Menu:** `10 Install Programs and Software` → option `0 Essential Pack`
One-click install of the most common tools:
| Package | What you get |
|---------|--------------|
| htop, inxi | System monitoring |
| neofetch / fastfetch | System info display |
| vlc | Media player |
| ufw | Firewall|
| zip, unrar, p7zip | Compression tools |
After this, browse the other categories (browsers, editors, dev tools) as needed.
---
### Complete Flow Summary
1. System Information ← Know your hardware
2. User Privileges & Feedback ← Enable password asterisks
3. Configure Repositories ← Enable contrib + non-free + backports
4. Firmware, Wireless & Bluetooth ← Install WiFi/BT firmware
5. Graphics Drivers & Mesa Stack ← Install GPU drivers
6. Kernel ← Optional: newer kernel (Backports)
7. Gaming Setup ← Optional: Steam + tools
8. ZRAM ← Optional: compressed swap
9. Install Programs → 0 Essential ← Common tools
**Estimated time:** 15-20 minutes for a full setup (steps 1-5 + 9). Steps 6-8 are optional and depend on your use case.
---
## File Structure ## File Structure
| Directory/File | Description | | Directory/File | Description |
|----------------|-------------| | ---------------- | ------------- |
| `debianito.sh` | Main entry point; handles menu navigation and system detection. | | `debianito.sh` | Main entry point; handles menu navigation and system detection. |
| `docs/` | Documentation directory containing Markdown files for each module. | | `docs/` | Documentation directory containing Markdown files for each module. |
| `modules/` | Core modular scripts organized by category: repos, gpu, gaming, kernel, firmware, zram, etc. | | `modules/` | Core modular scripts organized by category: repos, gpu, gaming, kernel, firmware, zram, etc. |
| `modules/bullseye/` | Legacy Debian 11 (Bullseye) specific modules: `extras.sh`, `legacy.sh`, `repos.sh`. | | `modules/bullseye/` | Legacy Debian 11 (Bullseye) specific modules: `extras.sh`, `legacy.sh`, `repos.sh`. |
| `modules/system/` | System preferences: `system_prefs.sh` (timezone, locale, keyboard) and `audio.sh` (PipeWire, ALSA). |
| `modules/extras/` | Software installer sub-modules split by category (themes, downloaders, internet, dev tools, etc.). | | `modules/extras/` | Software installer sub-modules split by category (themes, downloaders, internet, dev tools, etc.). |
| `modules/gaming/` | Gaming launcher and optimization scripts: Steam, Heroic, Lutris, performance tools. | | `modules/gaming/` | Gaming launcher and optimization scripts: Steam, Heroic, Lutris, performance tools. |
| `modules/gpu/` | GPU driver installation scripts for AMD and NVIDIA with architecture detection. | | `modules/gpu/` | GPU driver installation scripts for AMD and NVIDIA with architecture detection. |
@@ -237,10 +110,12 @@ After this, browse the other categories (browsers, editors, dev tools) as needed
│   ├── gaming.md │   ├── gaming.md
│   ├── gpu.md │   ├── gpu.md
│   ├── kernel.md │   ├── kernel.md
│   ├── QUICKSTART.md
│   ├── repos_config.md │   ├── repos_config.md
│   ├── retroarch.md │   ├── retroarch.md
│   ├── swap.md │   ├── swap.md
│   ├── system_info.md │   ├── system_info.md
│   ├── system_prefs.md
│   ├── user_priv_feed.md │   ├── user_priv_feed.md
│   └── zram.md │   └── zram.md
├── media ├── media
@@ -254,6 +129,7 @@ After this, browse the other categories (browsers, editors, dev tools) as needed
│   │   └── repos.sh │   │   └── repos.sh
│   ├── desktop_display.sh │   ├── desktop_display.sh
│   ├── extras │   ├── extras
│   │   ├── audio
│   │   ├── communication │   │   ├── communication
│   │   │   └── communication.sh │   │   │   └── communication.sh
│   │   ├── design │   │   ├── design
@@ -305,6 +181,7 @@ After this, browse the other categories (browsers, editors, dev tools) as needed
│   ├── gpu │   ├── gpu
│   │   ├── amd_intel.sh │   │   ├── amd_intel.sh
│   │   ├── _helpers.sh │   │   ├── _helpers.sh
│   │   ├── nvidia_manage.sh
│   │   └── nvidia.sh │   │   └── nvidia.sh
│   ├── gpu.sh │   ├── gpu.sh
│   ├── kernel.sh │   ├── kernel.sh
@@ -316,10 +193,14 @@ After this, browse the other categories (browsers, editors, dev tools) as needed
│   ├── sudo_config.sh │   ├── sudo_config.sh
│   ├── swap.sh │   ├── swap.sh
│   ├── sysinfo.sh │   ├── sysinfo.sh
│   ├── system
│   │   ├── audio.sh
│   │   └── system_prefs.sh
│   ├── utils.sh │   ├── utils.sh
│   └── zram.sh │   └── zram.sh
└── README.md └── README.md
``` ```
--- ---
> 🤖 **AI-Assisted Development Note** > 🤖 **AI-Assisted Development Note**
+108 -76
View File
@@ -5,6 +5,7 @@ set -euo pipefail
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' NC='\033[0m'
# TUI dimensions — fixed centered size for whiptail dialogs # TUI dimensions — fixed centered size for whiptail dialogs
@@ -16,38 +17,39 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODULES_DIR="${SCRIPT_DIR}/modules" MODULES_DIR="${SCRIPT_DIR}/modules"
source "${MODULES_DIR}/utils.sh" source "${MODULES_DIR}/utils.sh"
[ -f "${MODULES_DIR}/sysinfo.sh" ] && source "${MODULES_DIR}/sysinfo.sh" [ -f "${MODULES_DIR}/sysinfo.sh" ] && source "${MODULES_DIR}/sysinfo.sh"
source "${MODULES_DIR}/sudo_config.sh" source "${MODULES_DIR}/sudo_config.sh"
source "${MODULES_DIR}/repos/repo_detect.sh" source "${MODULES_DIR}/repos/repo_detect.sh"
source "${MODULES_DIR}/repos.sh" source "${MODULES_DIR}/repos.sh"
[ -f "${MODULES_DIR}/firmware.sh" ] && source "${MODULES_DIR}/firmware.sh" [ -f "${MODULES_DIR}/firmware.sh" ] && source "${MODULES_DIR}/firmware.sh"
[ -f "${MODULES_DIR}/bluetooth.sh" ] && source "${MODULES_DIR}/bluetooth.sh" [ -f "${MODULES_DIR}/bluetooth.sh" ] && source "${MODULES_DIR}/bluetooth.sh"
[ -f "${MODULES_DIR}/gpu.sh" ] && source "${MODULES_DIR}/gpu.sh" [ -f "${MODULES_DIR}/gpu.sh" ] && source "${MODULES_DIR}/gpu.sh"
[ -f "${MODULES_DIR}/kernel.sh" ] && source "${MODULES_DIR}/kernel.sh" [ -f "${MODULES_DIR}/kernel.sh" ] && source "${MODULES_DIR}/kernel.sh"
[ -f "${MODULES_DIR}/gaming.sh" ] && source "${MODULES_DIR}/gaming.sh" [ -f "${MODULES_DIR}/gaming.sh" ] && source "${MODULES_DIR}/gaming.sh"
[ -f "${MODULES_DIR}/extras.sh" ] && source "${MODULES_DIR}/extras.sh" [ -f "${MODULES_DIR}/extras.sh" ] && source "${MODULES_DIR}/extras.sh"
[ -f "${MODULES_DIR}/zram.sh" ] && source "${MODULES_DIR}/zram.sh" [ -f "${MODULES_DIR}/zram.sh" ] && source "${MODULES_DIR}/zram.sh"
[ -f "${MODULES_DIR}/extras/java.sh" ] && source "${MODULES_DIR}/extras/java.sh" [ -f "${MODULES_DIR}/extras/java.sh" ] && source "${MODULES_DIR}/extras/java.sh"
[ -f "${MODULES_DIR}/rescue.sh" ] && source "${MODULES_DIR}/rescue.sh" [ -f "${MODULES_DIR}/rescue.sh" ] && source "${MODULES_DIR}/rescue.sh"
[ -f "${MODULES_DIR}/swap.sh" ] && source "${MODULES_DIR}/swap.sh" [ -f "${MODULES_DIR}/swap.sh" ] && source "${MODULES_DIR}/swap.sh"
[ -f "${MODULES_DIR}/desktop_display.sh" ] && source "${MODULES_DIR}/desktop_display.sh" [ -f "${MODULES_DIR}/desktop_display.sh" ] && source "${MODULES_DIR}/desktop_display.sh"
[ -f "${MODULES_DIR}/system/system_prefs.sh" ] && source "${MODULES_DIR}/system/system_prefs.sh"
[ -f "${MODULES_DIR}/system/audio.sh" ] && source "${MODULES_DIR}/system/audio.sh"
# ── Bullseye-specific modules (loaded only on Debian 11) ── # ── Bullseye-specific modules (loaded only on Debian 11) ──
if [ -d "${MODULES_DIR}/bullseye" ]; then if [ -d "${MODULES_DIR}/bullseye" ]; then
[ -f "${MODULES_DIR}/bullseye/legacy.sh" ] && source "${MODULES_DIR}/bullseye/legacy.sh" [ -f "${MODULES_DIR}/bullseye/legacy.sh" ] && source "${MODULES_DIR}/bullseye/legacy.sh"
[ -f "${MODULES_DIR}/bullseye/repos.sh" ] && source "${MODULES_DIR}/bullseye/repos.sh" [ -f "${MODULES_DIR}/bullseye/repos.sh" ] && source "${MODULES_DIR}/bullseye/repos.sh"
[ -f "${MODULES_DIR}/bullseye/extras.sh" ] && source "${MODULES_DIR}/bullseye/extras.sh" [ -f "${MODULES_DIR}/bullseye/extras.sh" ] && source "${MODULES_DIR}/bullseye/extras.sh"
fi fi
REPOS_CONFIGURED=false
DEBIAN_VERSION="" DEBIAN_VERSION=""
DEBIAN_CODENAME="" DEBIAN_CODENAME=""
main_menu() { main_menu() {
# Auto-adjust TUI dimensions for small terminals # Auto-adjust TUI dimensions for small terminals
if [ "${LINES:-24}" -lt $((TUI_ALTO + 6)) ] || [ "${COLUMNS:-80}" -lt $((TUI_ANCHO + 6)) ]; then if [ "${LINES:-24}" -lt $((TUI_ALTO + 6)) ] || [ "${COLUMNS:-80}" -lt $((TUI_ANCHO + 6)) ]; then
TUI_ALTO=$((LINES - 4 > 8 ? LINES - 4 : 8)) TUI_ALTO=$((${LINES:-24} - 4 > 8 ? ${LINES:-24} - 4 : 8))
TUI_ANCHO=$((COLUMNS - 4 > 50 ? COLUMNS - 4 : 50)) TUI_ANCHO=$((${COLUMNS:-80} - 4 > 50 ? ${COLUMNS:-80} - 4 : 50))
TUI_ALTO_LISTA=$((TUI_ALTO - 10 > 4 ? TUI_ALTO - 10 : 4)) TUI_ALTO_LISTA=$((TUI_ALTO - 10 > 4 ? TUI_ALTO - 10 : 4))
fi fi
@@ -59,72 +61,97 @@ main_menu() {
$TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"1" "System Information" \ "1" "System Information" \
"2" "User Privileges & Feedback" \ "2" "User Privileges & Feedback" \
"3" "Configure Repositories" \ "3" "System Preferences" \
"4" "Firmware, Wireless & Bluetooth" \ "4" "Configure Repositories" \
"5" "Graphics Drivers & Mesa Stack" \ "5" "Firmware, Wireless & Bluetooth" \
"6" "Kernel" \ "6" "Graphics Drivers & Mesa Stack" \
"7" "Gaming Setup" \ "7" "Kernel" \
"8" "ZRAM" \ "8" "Gaming Setup" \
"9" "Swap Management" \ "9" "ZRAM" \
"10" "Install Programs and Software" \ "10" "Swap Management" \
"11" "Boot Rescue + GRUB" \ "11" "Install Programs and Software" \
"12" "Desktop & Display" \ "12" "Boot Rescue + GRUB" \
"13" "Exit") "13" "Desktop & Display" \
"14" "Exit")
clear clear
case "$choice" in case "$choice" in
1) _show_sysinfo ;; 1) _show_sysinfo ;;
2) config_sudo || true ;; 2) config_sudo || true ;;
3) 3)
if [ "$DEBIAN_VERSION" = "11" ] && type configure_repos_bullseye &>/dev/null; then _system_preferences_menu
configure_repos_bullseye || true STATE_REFRESHED=true
else ;;
configure_repos || true 4)
fi if [ "$DEBIAN_VERSION" = "11" ] && type configure_repos_bullseye &>/dev/null; then
STATE_REFRESHED=true configure_repos_bullseye || true
;; else
4) configure_repos || true
if [ "$DEBIAN_VERSION" = "11" ] && type install_firmware_bullseye &>/dev/null; then fi
install_firmware_bullseye || true STATE_REFRESHED=true
else ;;
install_firmware || true 5)
fi if [ "$DEBIAN_VERSION" = "11" ] && type install_firmware_bullseye &>/dev/null; then
;; install_firmware_bullseye || true
5) else
local gpu_sub install_firmware || true
gpu_sub=$(_menu "Graphics Drivers" "" 12 50 2 \ fi
"1" "Radeon/Intel Mesa" \ STATE_REFRESHED=true
"2" "NVIDIA Drivers") ;;
[ -z "$gpu_sub" ] && continue 6)
clear local gpu_sub
case $gpu_sub in gpu_sub=$(_menu "Graphics Drivers" "" 12 50 2 \
1) _install_amd_intel_stack || true ;; "1" "Radeon/Intel Mesa" \
2) _install_nvidia_stack || true ;; "2" "NVIDIA Drivers")
esac [ -z "$gpu_sub" ] && continue
STATE_REFRESHED=true clear
;; case $gpu_sub in
6) show_kernel_menu || true ;; 1) _install_amd_intel_stack || true ;;
7) 2) _install_nvidia_stack || true ;;
if [ "$DEBIAN_VERSION" = "11" ] && type install_gaming_bullseye &>/dev/null; then esac
install_gaming_bullseye || true STATE_REFRESHED=true
else ;;
install_gaming || true 7)
fi show_kernel_menu || true
STATE_REFRESHED=true STATE_REFRESHED=true
;; ;;
8) zram_menu || true ;; 8)
9) manage_swap || true; STATE_REFRESHED=true ;; if [ "$DEBIAN_VERSION" = "11" ] && type install_gaming_bullseye &>/dev/null; then
10) install_gaming_bullseye || true
if [ "$DEBIAN_VERSION" = "11" ] && type install_extras_bullseye &>/dev/null; then else
install_extras_bullseye || true install_gaming || true
else fi
install_extras || true STATE_REFRESHED=true
fi ;;
;; 9)
11) rescue_boot || true ;; zram_menu || true
12) manage_desktop_display || true ;; STATE_REFRESHED=true
13) echo "Exiting."; exit 0 ;; ;;
10)
manage_swap || true
STATE_REFRESHED=true
;;
11)
if [ "$DEBIAN_VERSION" = "11" ] && type install_extras_bullseye &>/dev/null; then
install_extras_bullseye || true
else
install_extras || true
fi
STATE_REFRESHED=true
;;
12)
rescue_boot || true
STATE_REFRESHED=true
;;
13)
manage_desktop_display || true
STATE_REFRESHED=true
;;
14)
echo "Exiting."
exit 0
;;
esac esac
if $STATE_REFRESHED; then if $STATE_REFRESHED; then
refresh_system_state refresh_system_state
@@ -134,6 +161,10 @@ main_menu() {
check_root check_root
check_sudo check_sudo
if ! command -v whiptail >/dev/null 2>&1; then
echo -e "${YELLOW}[+] whiptail not found. Installing required TUI dependencies...${NC}"
_ensure_apt_updated && sudo apt-get install -y whiptail
fi
if ! _check_network; then if ! _check_network; then
echo -e "${YELLOW}──────────────────────────────────────────${NC}" echo -e "${YELLOW}──────────────────────────────────────────${NC}"
echo -e "${YELLOW} No internet connectivity detected.${NC}" echo -e "${YELLOW} No internet connectivity detected.${NC}"
@@ -142,11 +173,12 @@ if ! _check_network; then
echo -e "${YELLOW} other offline features.${NC}" echo -e "${YELLOW} other offline features.${NC}"
echo -e "${YELLOW}──────────────────────────────────────────${NC}" echo -e "${YELLOW}──────────────────────────────────────────${NC}"
fi fi
check_system_time _ensure_time_synced
detect_debian_version detect_debian_version
detect_cpu_ram detect_cpu_ram
detect_kernel detect_kernel
_init_lspci_cache
detect_gpu detect_gpu
detect_network detect_network
detect_displayserver detect_displayserver
+331
View File
@@ -0,0 +1,331 @@
# Debianito — Quick Start Visual Guide
> **Scope:** Fresh Debian 11 / 12 / 13 installation → fully configured desktop in ~15-20 minutes.
> **Prerequisites:** Normal user with `sudo` access. Do **not** run the script as root.
> **Related:** [README Overview](../README.md) · [System Info](system_info.md) · [Repositories](repos_config.md) · [Firmware](firmware.md) · [GPU](gpu.md) · [Kernel](kernel.md) · [Gaming](gaming.md)
---
## Before You Start
```bash
git clone https://github.com/stornic56/debianito-post-install
cd debianito-post-install
chmod +x debianito.sh && ./debianito.sh
```
The script automatically checks for `whiptail` and `lsb-release`, installs them if missing, verifies `sudo` access, checks network connectivity, and synchronizes the system clock (`systemd-timesyncd` + `tzdata`).
> **Screenshot placeholder:** `media/screenshots/00-main-menu.png` — Main menu (14 options, whiptail centered at 78×20).
---
## Recommended Order
Each step builds on the previous one. Steps 1-5 + 10 are the essential path; 6-9 are optional.
### Step 1 — Know Your System
**Menu:** `1 System Information`
Opens a whiptail message box populated by `utils.sh` detection functions (`detect_cpu_ram`, `detect_gpu`, `detect_network`, `detect_storage`, `detect_displayserver`, `detect_desktop_environment`).
You will see:
- Debian version and codename
- CPU model and RAM size
- GPU vendor(s) and device IDs (e.g., `10de:2684` for NVIDIA)
- Network adapters (Ethernet + WiFi chipset) and their state/IP
- Storage topology (NVMe / SSD / HDD / USB-SD)
- Display server (Wayland / X11 / tty) and desktop environment
Write down the **GPU line** (Intel / AMD / NVIDIA) and any **WiFi chipset** — you will need them in Steps 4-5.
> **Screenshot placeholder:** `media/screenshots/01-system-info.png` — System Information dialog with hardware summary.
> **Tip:** If `GPU: No GPU detected` appears, you are on a VM or headless server — skip Step 5 (Graphics Drivers).
### Step 2 — Fix Permissions Early (Optional but Recommended)
**Menu:** `2 User Privileges & Feedback`
A sub-menu with four toggles:
| Option | What It Does | When to Enable |
| -------- | -------------- | ---------------- |
| Sudo group membership | `usermod -aG sudo $USER` | Fresh install where the first user is not in `sudo` |
| Passwordless sudo | Creates `/etc/sudoers.d/$USER-nopasswd` with `NOPASSWD` for `apt`, `systemctl`, etc. | Lab / personal machine; skip on shared systems |
| Repair home ownership | `chown -R $USER:$USER $HOME` | Home files owned by root after a mishandled `sudo` |
| Sudo password feedback | Writes `Defaults pwfeedback` to `/etc/sudoers.d/pwfeedback` — shows `****` while typing | **Enable now** to avoid typos during the many installs that follow |
> **Screenshot placeholder:** `media/screenshots/02-user-privileges.png` — User Privileges & Feedback menu.
> **Screenshot placeholder:** `media/screenshots/02b-pwfeedback.png` — Confirmation dialog for "Sudo Password Feedback" with asterisk preview.
### Step 3 — System Preferences (Optional)
**Menu:** `3 System Preferences`
```
1 Date, Time & Timezone
2 Language, Locales & Keyboard
3 Audio & Sound Stack
4 Back to main menu
```
- **Date, Time & Timezone** — Runs `dpkg-reconfigure tzdata` and then `_ensure_time_synced` (NTP + `systemd-timesyncd`). Fix timezone before `apt update` — a wrong clock breaks GPG verification.
- **Language, Locales & Keyboard** — Runs `dpkg-reconfigure locales` and `keyboard-configuration`. Requires re-login to apply `LANG`.
- **Audio & Sound Stack** — Checklist with `pipewire-audio` (or `pipewire` on Bullseye), `alsa-utils`, `pavucontrol` (hidden on TTY), `pulsemixer`, `playerctl`. PipeWire on Trixie offers a Backports vs Stable choice and installs Bluetooth Hi-Res codecs (`LDAC`, `aptX`, `AAC`). See [system_prefs.md](system_prefs.md).
> **Screenshot placeholder:** `media/screenshots/03-system-prefs.png` — System Preferences menu.
> **Screenshot placeholder:** `media/screenshots/03b-audio.png` — Audio & Sound checklist with PipeWire selected.
### Step 4 — Configure Repositories (Required)
**Menu:** `4 Configure Repositories`
```
1 Enable Contrib & Non-Free Components
2 Migrate traditional sources.list to DEB822 format
3 Setup/Update Backports repositories
4 [ADVANCED] Upgrade system branch (Testing / SID)
5 Back to main menu
```
1. Choose **1. Enable Contrib & Non-Free** — adds `contrib`, `non-free`, `non-free-firmware` (Bookworm/Trixie). Required for firmware, NVIDIA drivers, and Steam (`contrib`). The script handles both `/etc/apt/sources.list` (classic) and `/etc/apt/sources.list.d/debian.sources` (DEB822) and validates via `apt update` with automatic rollback.
2. Choose **3. Setup/Update Backports** — answers `Yes` to enable `trixie-backports` / `bookworm-backports` in a separate file (`debian-backports.sources` or `.list`). Backports gives newer kernels, Mesa, and firmware. See [repos_config.md](repos_config.md).
> ⚠️ Without `non-free` and `contrib`, Steps 5 and 8 will fail. Do not skip.
> **Screenshot placeholder:** `media/screenshots/04-repos.png` — Repositories menu.
> **Screenshot placeholder:** `media/screenshots/04b-backports.png` — Backports confirmation dialog.
### Step 5 — Install Firmware & Wireless Drivers
**Menu:** `5 Firmware, Wireless & Bluetooth`
The script:
- Scans **all** network hardware (PCI `lspci -nn` + USB `lsusb`, filtered for Realtek/Intel/Mediatek/Atheros/Qualcomm) and Bluetooth controllers
- Maps vendors to packages: `firmware-iwlwifi`, `firmware-realtek`, `firmware-mediatek`, `firmware-atheros`, `firmware-intel-misc` — plus `firmware-linux-nonfree` as the base meta-package
- Builds a plan showing detected controllers and planned packages, including Bluetooth handling (KDE → `bluedevil`, XFCE → `blueman`, GNOME → built-in, plus `pipewire-pulse`/`wireplumber` if PipeWire is active)
- Asks for confirmation before installing; offers Stable vs Backports for the base firmware
Accept the plan it shows — it is based on your actual hardware. Broadcom wireless (if present) is handled via `broadcom-sta-dkms` with DKMS build checks and `update-initramfs` + `modprobe wl`.
> ⚠️ You need internet for this step. If WiFi does not work after firmware install, **reboot** first — the driver needs a fresh load.
> **Screenshot placeholder:** `media/screenshots/05-firmware-plan.png` — Firmware plan dialog with hardware + package list.
> **Screenshot placeholder:** `media/screenshots/05b-bluetooth.png` — Bluetooth section of the plan (if applicable).
### Step 6 — Install Graphics Drivers
**Menu:** `6 Graphics Drivers & Mesa Stack`
Whiptail radiolist with two options:
```
1 Radeon/Intel Mesa
2 NVIDIA Drivers
```
#### Path A — Radeon/Intel Mesa
Shows a plan with detected GPUs (`Intel firmware + intel-media-va-driver-non-free` or `i965-va-driver-shaders` for Gen7-, `firmware-amd-graphics` for AMD, plus `Mesa Vulkan/OpenGL/VA-API`). Offers legacy AMD GCN 1.0/1.1 migration to `amdgpu` via GRUB params (`radeon.si_support=0 ... amdgpu.si_support=1`). Installs Mesa from Backports or Stable (`_install_mesa_backports`), verifies `mesa-vulkan-drivers`, and offers vendor-specific telemetry (`radeontop`, `intel-gpu-tools`, `vainfo`).
#### Path B — NVIDIA Drivers
Shows detected NVIDIA GPUs and a two-stage menu:
1. **Manage menu** (if a driver is already installed): *Install / Change Driver Version* vs *Remove Driver and Restore Nouveau*.
2. **Version menu** (depends on Debian version):
- Bookworm: `v535` (Recommended) or `v470` (Kepler legacy via `nvidia-tesla-470-driver`)
- Trixie: `v550` (Debian stable, Recommended), `v590` or `v595` (NVIDIA CUDA Repo with `cuda-keyring` + `nvidia-open` + `firmware-nvidia-gsp`)
The script auto-detects the GPU architecture (`kepler` / `fermi` / `maxwell` / `pascal` / `turing` / `ampere` / `ada` / `blackwell`) and enforces compatibility — e.g., Blackwell requires `v590+` on Trixie, Maxwell/Pascal on Trixie + backports kernel is forced to `v550` stable, Fermi is vetoed on Bookworm/Trixie with an explanatory message.
> **Screenshot placeholder:** `media/screenshots/06-gpu-choice.png` — GPU type selector (Radeon/Intel vs NVIDIA).
> **Screenshot placeholder:** `media/screenshots/06b-nvidia-version.png` — NVIDIA version menu (535 / 470 or 550 / 590 / 595).
> **Tip:** After installation, **reboot** before testing. NVIDIA drivers need a fresh kernel load.
### Step 7 — Kernel Configuration (Optional)
**Menu:** `7 Kernel`
```
stable Install linux-image-amd64 (Stable)
backports Install from backports (Trixie only)
rt Install linux-image-rt-amd64 (Preempt-RT)
cloud Install linux-image-cloud-amd64
back Return to main menu
```
- **Stable** — default Debian kernel (6.12 LTS on Trixie).
- **Backports** — only on Trixie; requires `trixie-backports` enabled in Step 4. Newer kernel (e.g., 7.x) for Intel Arrow Lake / AMD Zen 5, Battlemage D3cold, etc.
- **RT** — Preempt-RT low-latency kernel. Warns if `GPU_TYPE == nvidia` (proprietary drivers may not support RT).
- **Cloud** — minimal kernel for VMs/containers (`linux-image-cloud-amd64`).
Each variant installs the matching `linux-headers-*` package atomically (`sudo apt install -y [-t trixie-backports] linux-image-* linux-headers-*`). The script warns about DKMS recompilation if NVIDIA is present.
> **Screenshot placeholder:** `media/screenshots/07-kernel.png` — Kernel menu with four variants.
> See [kernel.md](kernel.md) for backports rationale and bootloader details.
### Step 8 — Gaming Setup (Optional)
**Menu:** `8 Gaming Setup`
A single checklist with all options:
```
[*] i386 Enable 32-bit (i386) architecture
[*] steam Steam (requires 32-bit support)
[*] mangohud Performance overlay (Vulkan/OpenGL)
[ ] gamemode Game performance optimization
[*] goverlay MangoHud config GUI
[ ] heroic Heroic Launcher (Epic/GOG)
[ ] java Minecraft Java Runtime
[ ] openrgb OpenRGB (RGB lighting control)
[ ] lutris Lutris + Wine (requires 32-bit support)
[ ] retroarch RetroArch Emulator Frontend
```
- If `steam`, `lutris`, or `i386` is checked, the script runs `dpkg --add-architecture i386` + `apt update`, then installs 32-bit graphics libraries (`_install_nvidia_32bit` or `_install_mesa_32bit`).
- `steam` checks `contrib` (`ensure_contrib_repo`) and installs `steam-installer`.
- `heroic` fetches the latest `.deb` from GitHub releases (`api.github.com`).
- `openrgb` is Bookworm/Trixie only; handles `i2c-dev`, udev, `i2c` group, and `setcap`.
- `java` offers Temurin 8 / 17 / 21 / 25 via `extrepo adoptium`.
- Requires GUI for some installers (skipped on headless).
> **Screenshot placeholder:** `media/screenshots/08-gaming.png` — Gaming checklist with i386 + Steam + MangoHud checked.
> See [gaming.md](gaming.md) and [retroarch.md](retroarch.md).
### Step 9 — ZRAM Compressed Swap (Optional)
**Menu:** `9 ZRAM`
```
1 View ZRAM status
2 Create / Reconfigure ZRAM
3 Remove ZRAM
4 Back to main menu
```
- **View** — Shows `/etc/default/zramswap` (`ALGO`, `SIZE`, `PRIORITY`) and `zramctl` output.
- **Create / Reconfigure** — Choice of `lz4` (fastest, gaming) vs `zstd` (better ratio). Recommended size is 50% of RAM (≤8 GB) or 4096 MB fixed (>8 GB), configurable. Writes to `/etc/default/zramswap` (`ALGO`, `SIZE`, `PRIORITY=100`) and `systemctl restart zramswap || true`. Priority 100 ensures ZRAM is used before any disk swap (priority 10).
- **Remove** — `systemctl stop zramswap`, `swapoff /dev/zram0`, `modprobe -r zram`, `apt purge zram-tools`, removes `/etc/default/zramswap`.
> **Screenshot placeholder:** `media/screenshots/09-zram-algo.png` — Algorithm choice (lz4 vs zstd).
> **Screenshot placeholder:** `media/screenshots/09b-zram-status.png` — `zramctl` status output in whiptail.
> See [zram.md](zram.md).
### Step 10 — Swap Management (Optional)
**Menu:** `10 Swap Management`
```
1 Show current swap & swappiness
2 Create / resize swapfile
3 Remove swapfile
4 Change swappiness
5 Back to main menu
```
- Uses `/swapfile` with `pri=10` (below ZRAM's 100) and tag `# debianito-managed-swap` in `/etc/fstab`.
- Btrfs: warns about `nodatacow` (`chattr +C`) and hibernation limitations; uses `dd` instead of `fallocate`.
- Fstab is written via a temp file and validated with `findmnt --verify` before replacing `/etc/fstab`.
- Concurrency is guarded by `flock /run/lock/debianito-swap.lock`.
> **Screenshot placeholder:** `media/screenshots/10-swap.png` — Swap Management menu.
> See [swap.md](swap.md).
### Step 11 — Essential Software
**Menu:** `11 Install Programs and Software``0 Essential Pack`
One-click install of `htop`, `inxi`, `neofetch`/`fastfetch`, `vlc`, `ufw`, `zip`, `unrar`, `p7zip`, plus `lsb-release` fixes.
After this, browse the other categories as needed:
| Category | Example Packages |
| ---------- | ------------------ |
| Customization System | Desktop themes, icons, cursors, fonts |
| Download & Network | aria2, ytdlp, qBittorrent, Deluge |
| Internet | Firefox, LibreWolf, Chromium, Tor, Thunderbird, RiseUp/Mullvad VPN |
| Communication | Signal, Telegram, HexChat |
| Media Players | VLC, MPV |
| Multimedia & Design | GIMP, Kdenlive, Blender, Audacity, Inkscape |
| Code Editors & IDEs | Neovim, Helix, Emacs, VSCodium, Geany |
| Servers & Dev Tools | Nginx, PostgreSQL, Docker, Temurin JDK, Jellyfin |
| Security & Networking | Wireshark, ClamAV, UFW, fail2ban |
| Software Center & Flatpak | GNOME Software, KDE Discover, Flatpak |
| Office & Productivity | LibreOffice, document tools |
| System Tools | htop/btop, Timeshift, extension-manager, virt-manager |
| Fetch / System Info | fastfetch, neofetch, hyfetch, screenfetch |
> **Screenshot placeholder:** `media/screenshots/11-essentials.png` — Category menu with 0-14 options.
> **Screenshot placeholder:** `media/screenshots/11b-essential-pack.png` — Essential Pack confirmation.
### Step 12 — Boot Rescue
**Menu:** `12 Boot Rescue + GRUB`
- **GRUB boot menu settings** — 4 presets (hidden 0s / 3s / 5s / custom) writing `GRUB_TIMEOUT`, `GRUB_TIMEOUT_STYLE`, `GRUB_RECORDFAIL_TIMEOUT`, `GRUB_DISABLE_OS_PROBER` to `/etc/default/grub.d/99_script_override.cfg` with `update-grub` + backup/rollback.
- **UEFI Secure Boot repair** — reinstalls `shim-signed`, `grub-efi-amd64-signed`, `linux-image-amd64`, runs `grub-install` + `update-grub` (UEFI only, checked via `/sys/firmware/efi` + `mokutil`).
- **Initramfs regeneration** — `update-initramfs -u -k all || true`.
> See [boot.md](boot.md).
### Step 13 — Desktop & Display
**Menu:** `13 Desktop & Display`
```
1 Desktop Environment
2 Display Manager
3 Back to main menu
```
- **Desktop Environment** — XFCE (full / minimal / Wayland `labwc` on Trixie / custom checklist) or LXDE (full / core). Installs polkit rules (`85-suspend.rules`, `89-backlight.rules`) + `backlight` group.
- **Display Manager** — LightDM (GTK greeter, user list, autologin), GDM3 (user list, autologin, NVIDIA Wayland override via `61-gdm.rules → /dev/null`), SDDM (autologin with session auto-detection `plasmawayland → lxqt-wayland → plasma → lxqt`), greetd (base / tuigreet / gtkgreet / nwg-hello / wlgreet — manual `/etc/greetd/config.toml` required).
> See [desktops_display.md](desktops_display.md).
---
## After the Script
1. **Reboot** if you installed firmware, GPU drivers, or a new kernel.
2. Verify:
```bash
sudo zramctl # ZRAM active?
sudo swapon --show # Swap with correct priorities?
vainfo # VA-API acceleration?
nvidia-smi # NVIDIA driver loaded?
systemctl status bluetooth # Bluetooth active?
```
3. For gaming, enable `i386` was handled — verify with `dpkg --print-foreign-architectures | grep i386`.
---
## Troubleshooting Quick Answers
| Symptom | Fix |
| --------- | ----- |
| **WiFi not working after firmware** | Reboot. Check `lspci -nn \| grep Network` and verify the package (`firmware-iwlwifi` etc.) is `ii` via `dpkg -l`. Ensure `non-free` + `non-free-firmware` were enabled in Step 4. |
| **Black screen after NVIDIA + Wayland (GNOME/GDM3)** | At login, select *GNOME on Xorg* (gear icon) or disable Wayland: `sudo nano /etc/gdm3/daemon.conf` → `WaylandEnable=false`. The script only warns about Debian bug #1109409, it does not force X11. |
| **GRUB menu hidden and cannot enter** | Hold `ESC` immediately after power-on. Or boot a live USB, `chroot`, and run `12 Boot Rescue → GRUB boot menu settings → Show 5 seconds`. |
| **Steam fails to start** | Verify `i386` is enabled: `dpkg --print-foreign-architectures`. Check `contrib` is in `/etc/apt/sources.list`. Re-run `8 Gaming Setup` and ensure the checklist had `i386` + `steam` checked. |
| **greetd installed but cannot log in** | This is expected — you must create `/etc/greetd/config.toml` manually. See `man greetd` and `man 5 greetd-sessions`. |
| **Bluetooth tray icon missing** | Reboot or `systemctl restart bluetooth`. Ensure `bluez`, `bluedevil` (KDE) or `blueman` (XFCE) is installed. For PipeWire, check `systemctl --user status pipewire pipewire-pulse wireplumber`. |
| **PipeWire crackling / no Bluetooth Hi-Res codec** | Re-run `3 System Preferences → Audio & Sound → PipeWire Audio Stack`. Verify `libldacbt-*`, `libopenaptx0`, `libfdk-aac2t64` are installed (`dpkg -l \| grep -E 'ldac\|aptx\|fdk'`). |
---
## Taking Screenshots for This Guide
Screenshots are taken from `whiptail` dialogs. To capture them:
1. Run the script inside a terminal that supports image export (e.g., `gnome-terminal` + `gnome-screenshot`, or `asciinema`).
2. For whiptail, press `PrintScreen` or use `import -window root screenshot.png` (ImageMagick).
3. Save under `media/screenshots/` with the filenames referenced above (`01-system-info.png`, `04-repos.png`, etc.).
4. Keep width ≈ 800px; the script uses fixed `TUI_ANCHO=78` and `TUI_ALTO=20` centered dialogs.
> **Note:** Until real screenshots are added, the placeholders above describe the expected content of each image.
+12 -5
View File
@@ -1,11 +1,13 @@
## Option 11: Boot Rescue & Repair # Option 12: Boot Rescue + GRUB
### 1. What does this component do? ### 1. What does this component do?
This component serves as a comprehensive rescue toolkit designed to diagnose and fix boot-related issues on Debian systems, specifically targeting GRUB configuration, UEFI Secure Boot integrity, and initrd image validity. It provides three primary operations: configuring the GRUB boot menu behavior (including timeout adjustments and visibility settings), repairing UEFI Secure Boot by reinstalling signed bootloader packages after kernel or driver changes, and regenerating initramfs images to resolve missing driver errors. All modifications are protected by automatic backup creation before system files are altered, with built-in rollback mechanisms that restore the original state if any operation fails during execution. This component serves as a comprehensive rescue toolkit designed to diagnose and fix boot-related issues on Debian systems, specifically targeting GRUB configuration, UEFI Secure Boot integrity, and initrd image validity. It provides three primary operations: configuring the GRUB boot menu behavior (including timeout adjustments and visibility settings), repairing UEFI Secure Boot by reinstalling signed bootloader packages after kernel or driver changes, and regenerating initramfs images to resolve missing driver errors. All modifications are protected by automatic backup creation before system files are altered, with built-in rollback mechanisms that restore the original state if any operation fails during execution.
### 2. Logical Execution Flow ### 2. Logical Execution Flow
**Block 1 — GRUB Boot Menu Settings** **Block 1 — GRUB Boot Menu Settings**
- **Menu Options:** Users select from four presets or a custom option to control boot behavior: - **Menu Options:** Users select from four presets or a custom option to control boot behavior:
1. Hide GRUB menu entirely (Fastest boot, requires holding ESC during power-on). 1. Hide GRUB menu entirely (Fastest boot, requires holding ESC during power-on).
2. Show 3-second countdown (Faster boot). 2. Show 3-second countdown (Faster boot).
@@ -16,6 +18,7 @@ This component serves as a comprehensive rescue toolkit designed to diagnose and
- **Execution & Rollback:** The system runs `update-grub` to apply changes. If this command fails, the script automatically restores the timestamped backup and removes the override file to prevent boot issues. - **Execution & Rollback:** The system runs `update-grub` to apply changes. If this command fails, the script automatically restores the timestamped backup and removes the override file to prevent boot issues.
**Block 2 — UEFI Secure Boot Repair** **Block 2 — UEFI Secure Boot Repair**
- **Pre-checks:** Before proceeding, the script verifies two conditions: - **Pre-checks:** Before proceeding, the script verifies two conditions:
1. The system is running in UEFI mode (checks for existence of `/sys/firmware/efi`). 1. The system is running in UEFI mode (checks for existence of `/sys/firmware/efi`).
2. Secure Boot is currently enabled (uses `mokutil --sb-state` to confirm status). 2. Secure Boot is currently enabled (uses `mokutil --sb-state` to confirm status).
@@ -26,8 +29,9 @@ This component serves as a comprehensive rescue toolkit designed to diagnose and
3. Regenerates the GRUB configuration via `update-grub`. 3. Regenerates the GRUB configuration via `update-grub`.
**Block 3 — Initramfs Regeneration** **Block 3 — Initramfs Regeneration**
- **Confirmation:** The script prompts for user confirmation before proceeding to avoid unintended rebuilds. - **Confirmation:** The script prompts for user confirmation before proceeding to avoid unintended rebuilds.
- **Execution:** Upon approval, it runs `update-initramfs -u -k all` to regenerate initrd images for all installed kernels. - **Execution:** Upon approval, it runs `update-initramfs -u -k all || true` to regenerate initrd images for all installed kernels.
- **Purpose:** This fixes boot issues caused by missing drivers or corrupted initrd images that prevent the system from loading properly. - **Purpose:** This fixes boot issues caused by missing drivers or corrupted initrd images that prevent the system from loading properly.
### 3. Intelligent Automation ### 3. Intelligent Automation
@@ -43,23 +47,26 @@ This component serves as a comprehensive rescue toolkit designed to diagnose and
### 4. Paquetes y Recursos Gestionados ### 4. Paquetes y Recursos Gestionados
**Boot Packages Reinstalled (Secure Boot Repair):** **Boot Packages Reinstalled (Secure Boot Repair):**
| Package | Purpose | | Package | Purpose |
|---|---| | --- | --- |
| shim-signed | UEFI Secure Boot shim (first-stage bootloader) | | shim-signed | UEFI Secure Boot shim (first-stage bootloader) |
| grub-efi-amd64-signed | Signed GRUB for UEFI | | grub-efi-amd64-signed | Signed GRUB for UEFI |
| linux-image-amd64 | Kernel image (re-signed) | | linux-image-amd64 | Kernel image (re-signed) |
**GRUB Settings Modified:** **GRUB Settings Modified:**
| Variable | Option 1 | Option 2 | Option 3 | Custom | | Variable | Option 1 | Option 2 | Option 3 | Custom |
|---|---|---|---|---| | --- | --- | --- | --- | --- |
| GRUB_TIMEOUT | 0 | 3 | 5 | User value | | GRUB_TIMEOUT | 0 | 3 | 5 | User value |
| GRUB_TIMEOUT_STYLE | hidden | menu | menu | menu | | GRUB_TIMEOUT_STYLE | hidden | menu | menu | menu |
| GRUB_RECORDFAIL_TIMEOUT | 0 | 3 | 5 | User value | | GRUB_RECORDFAIL_TIMEOUT | 0 | 3 | 5 | User value |
| GRUB_DISABLE_OS_PROBER | true | — | — | — | | GRUB_DISABLE_OS_PROBER | true | — | — | — |
**System Files Modified:** **System Files Modified:**
| Package | Purpose | | Package | Purpose |
|---|---| | --- | --- |
| /etc/default/grub | Main GRUB configuration | | /etc/default/grub | Main GRUB configuration |
| /etc/default/grub.d/99_script_override.cfg | Persistent override (survives grub updates) | | /etc/default/grub.d/99_script_override.cfg | Persistent override (survives grub updates) |
| /etc/default/grub.backup.* | Timestamped backup (auto-created) | | /etc/default/grub.backup.* | Timestamped backup (auto-created) |
+21 -8
View File
@@ -1,14 +1,18 @@
## Option 12: Desktop & Display # Option 13: Desktop & Display
### 1. What does this component do? ### 1. What does this component do?
This component manages display managers (the login screen you see before entering your desktop). It allows users to install and configure LightDM, GDM3, SDDM, or greetd. It handles autologin setup, user list visibility toggles, and a specific Wayland override for NVIDIA GPUs. Currently, Desktop Environment management is marked as "Coming Soon".
This component manages both desktop environments and display managers. Desktop Environment installs XFCE/LXDE with polkit integration; Display Manager handles LightDM, GDM3, SDDM, and greetd (login screens). It handles autologin setup, user list visibility toggles, and a specific Wayland override for NVIDIA GPUs. Desktop Environment management supports **XFCE** (full / minimal / Wayland `labwc` on Trixie / custom) and **LXDE** (full / core), with polkit rules for suspend/backlight.
### 2. Logical Flow of Execution ### 2. Logical Flow of Execution
The execution logic is divided into five functional blocks: The execution logic is divided into five functional blocks:
**Block 1 — Display Manager Selection** **Block 1 — Desktop & Display Menu**
- The main menu offers two primary options within Option 12: "Desktop Environment" (currently unavailable) and "Display Manager".
- Selecting "Display Manager" opens a submenu listing available display managers based on the Debian version. - The main menu (`manage_desktop_display` in `desktop_display.sh`) offers two primary options: `1 Desktop Environment` and `2 Display Manager` (plus `3 Back to main menu`).
- **Desktop Environment** opens `desktop_environment_menu` — XFCE or LXDE.
- **Display Manager** opens `display_manager_menu` — LightDM, GDM3, SDDM, and greetd (12/13 only).
- **Available Managers:** - **Available Managers:**
- LightDM (available on all Debian versions). - LightDM (available on all Debian versions).
- GDM3 (available on all Debian versions). - GDM3 (available on all Debian versions).
@@ -17,6 +21,7 @@ The execution logic is divided into five functional blocks:
- Each selected manager opens its own dedicated configuration submenu. - Each selected manager opens its own dedicated configuration submenu.
**Block 2 — LightDM Configuration** **Block 2 — LightDM Configuration**
- A checklist menu presents three options: - A checklist menu presents three options:
1. Install LightDM + GTK Greeter (auto-selects the display manager via debconf-set-selections). 1. Install LightDM + GTK Greeter (auto-selects the display manager via debconf-set-selections).
2. Enable user list at login screen (writes `greeter-hide-users=false` to a configuration file in `.conf.d`). 2. Enable user list at login screen (writes `greeter-hide-users=false` to a configuration file in `.conf.d`).
@@ -24,6 +29,7 @@ The execution logic is divided into five functional blocks:
- **Idempotency:** The script checks if `lightdm` and `lightdm-gtk-greeter-settings` are already installed before attempting installation, skipping redundant steps. - **Idempotency:** The script checks if `lightdm` and `lightdm-gtk-greeter-settings` are already installed before attempting installation, skipping redundant steps.
**Block 3 — GDM3 Configuration** **Block 3 — GDM3 Configuration**
- A checklist menu presents up to four options: - A checklist menu presents up to four options:
1. Install/Reinstall gdm3 (auto-selects via debconf). 1. Install/Reinstall gdm3 (auto-selects via debconf).
2. Toggle user list visibility (toggles `disable-user-list` in greeter.dconf-defaults). 2. Toggle user list visibility (toggles `disable-user-list` in greeter.dconf-defaults).
@@ -35,6 +41,7 @@ The execution logic is divided into five functional blocks:
- **Toggle Behavior:** If the symlink exists, removing it reverts to default behavior; if not present, creating it enables the override. - **Toggle Behavior:** If the symlink exists, removing it reverts to default behavior; if not present, creating it enables the override.
**Block 4 — SDDM Configuration** **Block 4 — SDDM Configuration**
- A submenu offers two options: - A submenu offers two options:
1. Install SDDM (auto-selects via debconf). 1. Install SDDM (auto-selects via debconf).
2. Enable Autologin: 2. Enable Autologin:
@@ -43,6 +50,7 @@ The execution logic is divided into five functional blocks:
- **Fallback:** If no session is found, it enables autologin but warns that SDDM will use the default session. - **Fallback:** If no session is found, it enables autologin but warns that SDDM will use the default session.
**Block 5 — greetd Configuration** **Block 5 — greetd Configuration**
- greetd is a minimal, modern display manager designed for Wayland environments. - greetd is a minimal, modern display manager designed for Wayland environments.
- Submenu options vary by Debian version: - Submenu options vary by Debian version:
- **All Versions:** Install base `greetd`, Install `greetd` + `tuigreet` (recommended TUI greeter). - **All Versions:** Install base `greetd`, Install `greetd` + `tuigreet` (recommended TUI greeter).
@@ -51,7 +59,9 @@ The execution logic is divided into five functional blocks:
- **Important Warning:** greetd is installed but NOT configured by the script. The user must manually create `/etc/greetd/config.toml` to be able to log in. The script displays a warning with references to man pages for configuration details. - **Important Warning:** greetd is installed but NOT configured by the script. The user must manually create `/etc/greetd/config.toml` to be able to log in. The script displays a warning with references to man pages for configuration details.
### 3. Smart Automations ### 3. Smart Automations
The component utilizes several intelligent automation features: The component utilizes several intelligent automation features:
- **debconf-set-selections:** Pre-selects the display manager as default before `apt install`, preventing the interactive "Configuring shared/default-x-display-manager" dialog that would otherwise pause the script execution. - **debconf-set-selections:** Pre-selects the display manager as default before `apt install`, preventing the interactive "Configuring shared/default-x-display-manager" dialog that would otherwise pause the script execution.
- **Session Auto-Detection (SDDM):** Checks `.desktop` files in priority order (Wayland first, then X11) to set the correct session type for autologin configuration. - **Session Auto-Detection (SDDM):** Checks `.desktop` files in priority order (Wayland first, then X11) to set the correct session type for autologin configuration.
- **Wayland Toggle:** Creates or removes a udev rule symlink to `/dev/null`. This is a known workaround that disables the GDM rule blocking NVIDIA Wayland support. - **Wayland Toggle:** Creates or removes a udev rule symlink to `/dev/null`. This is a known workaround that disables the GDM rule blocking NVIDIA Wayland support.
@@ -62,8 +72,9 @@ The component utilizes several intelligent automation features:
### 4. Packages and Resources Managed ### 4. Packages and Resources Managed
**Display Manager Packages:** **Display Manager Packages:**
| DM | Packages | Debian Versions | | DM | Packages | Debian Versions |
|---|---|---| | --- | --- | --- |
| LightDM | lightdm, lightdm-gtk-greeter, lightdm-gtk-greeter-settings | All | | LightDM | lightdm, lightdm-gtk-greeter, lightdm-gtk-greeter-settings | All |
| GDM3 | gdm3 | All | | GDM3 | gdm3 | All |
| SDDM | sddm | All | | SDDM | sddm | All |
@@ -74,8 +85,9 @@ The component utilizes several intelligent automation features:
| greetd + wlgreet | greetd, wlgreet | 13 only | | greetd + wlgreet | greetd, wlgreet | 13 only |
**Configuration Files Modified:** **Configuration Files Modified:**
| DM | File Path | Configuration Purpose | | DM | File Path | Configuration Purpose |
|---|---|---| | --- | --- | --- |
| LightDM | /etc/lightdm/lightdm.conf.d/50-debianito-userlist.conf | User list visibility toggle | | LightDM | /etc/lightdm/lightdm.conf.d/50-debianito-userlist.conf | User list visibility toggle |
| LightDM | /etc/lightdm/lightdm.conf | Autologin user + timeout settings | | LightDM | /etc/lightdm/lightdm.conf | Autologin user + timeout settings |
| GDM3 | /etc/gdm3/greeter.dconf-defaults | User list toggle (disable-user-list) | | GDM3 | /etc/gdm3/greeter.dconf-defaults | User list toggle (disable-user-list) |
@@ -84,8 +96,9 @@ The component utilizes several intelligent automation features:
| SDDM | /etc/sddm.conf.d/autologin.conf | Autologin user + session type | | SDDM | /etc/sddm.conf.d/autologin.conf | Autologin user + session type |
**Session Detection Priority (SDDM Autologin):** **Session Detection Priority (SDDM Autologin):**
| Priority | Session File | Session Type | | Priority | Session File | Session Type |
|---|---|---| | --- | --- | --- |
| 1 | /usr/share/wayland-sessions/plasmawayland.desktop | KDE Wayland | | 1 | /usr/share/wayland-sessions/plasmawayland.desktop | KDE Wayland |
| 2 | /usr/share/wayland-sessions/lxqt-wayland.desktop | LXQt Wayland | | 2 | /usr/share/wayland-sessions/lxqt-wayland.desktop | LXQt Wayland |
| 3 | /usr/share/xsessions/plasma.desktop | KDE X11 | | 3 | /usr/share/xsessions/plasma.desktop | KDE X11 |
+75 -30
View File
@@ -1,58 +1,103 @@
# Option 4: Advanced Firmware & Wireless Architecture # Option 5: Firmware, Wireless & Bluetooth
## 1. The Hidden Debian "Problem" ## 1. The Hidden Debian "Problem"
In standard Debian packaging, the meta-package `firmware-linux-nonfree` serves as a generic aggregator for hardware blobs. However, due to internal dependency resolution rules and conservative versioning strategies within the repository, this package often fails to automatically include vendor-specific firmware drivers for newer or niche network controllers (specifically Realtek Wi-Fi/Bluetooth and Intel Ethernet/Wi-Fi variants). In standard Debian packaging, the meta-package `firmware-linux-nonfree` serves as a generic aggregator for hardware blobs. However, due to internal dependency resolution rules and conservative versioning strategies within the repository, this package often fails to automatically include vendor-specific firmware drivers for newer or niche network controllers (specifically Realtek Wi-Fi/Bluetooth and Intel Ethernet/Wi-Fi variants).
This script acts as an intelligent injector to bridge that gap. It does not rely solely on the meta-package's `Recommends` field; instead, it actively scans the hardware topology to identify missing dependencies. By decoupling the detection from the installation logic, the architecture ensures that even if the base package is installed, specific vendor blobs (e.g., `firmware-iwlwifi`, `firmware-realtek`) are explicitly pulled in only when their corresponding hardware IDs are confirmed present on the system. This prevents "half-baked" network connectivity where the interface exists but lacks the necessary firmware to initialize. This script acts as an intelligent injector to bridge that gap. It does not rely solely on the meta-package's `Recommends` field; instead, it actively scans the hardware topology to identify missing dependencies. By decoupling the detection from the installation logic, the architecture ensures that even if the base package is installed, specific vendor blobs (e.g., `firmware-iwlwifi`, `firmware-realtek`) are explicitly pulled in only when their corresponding hardware IDs are confirmed present on the system. This prevents "half-baked" network connectivity where the interface exists but lacks the necessary firmware to initialize.
## 2. Dual Scan Engine (PCI & USB) ## 2. Dual Scan Engine (PCI & USB)
To ensure comprehensive hardware detection while minimizing false positives, the script utilizes a dual-scan engine that interrogates both PCI and USB buses with strict filtering logic: To ensure comprehensive hardware detection while minimizing false positives, the script utilizes a dual-scan engine that interrogates both PCI and USB buses with strict filtering logic:
* **PCI Bus Scanning (`lspci`):** The engine parses `lspci -nn` output specifically targeting lines containing "network controller" or "ethernet controller". This captures both wireless adapters (e.g., Intel AX200) and wired NICs (e.g., Realtek RTL8125 2.5GbE), ensuring that Ethernet firmware requirements are also met during the process. * **PCI Bus Scanning (`lspci`):** The engine parses `lspci -nn` output specifically targeting lines containing "network controller" or "ethernet controller". This captures both wireless adapters (e.g., Intel AX200) and wired NICs (e.g., Realtek RTL8125 2.5GbE), ensuring that Ethernet firmware requirements are also met during the process.
* **USB Bus Scanning (`lsusb`):** The USB scan applies keyword filtering to ignore peripherals unrelated to networking, such as audio devices or card readers. It specifically looks for terms like "wireless", "wifi", "802.11", and "wlan". Bluetooth devices are also detected separately through `PCI_BT_DEVS` and `USB_BT_DEVS`. * **USB Bus Scanning (`lsusb`):** The USB scan applies keyword filtering to ignore peripherals unrelated to networking, such as audio devices or card readers. It specifically looks for terms like "wireless", "wifi", "802.11", and "wlan". Bluetooth devices are also detected separately through `PCI_BT_DEVS` and `USB_BT_DEVS`.
* **Deduplication:** The collected device lists are merged into a single array (`dev_list`) to prevent duplicate processing of the same hardware instance across different bus categories, ensuring a clean plan generation. * **Deduplication:** The collected device lists are merged into a single array (`dev_list`) to prevent duplicate processing of the same hardware instance across different bus categories, ensuring a clean plan generation.
## 3. Dynamic Hardware Mapping Matrix ## 3. Dynamic Hardware Mapping Matrix
The script employs an associative mapping strategy in `_detect_firmware_needs` to translate raw vendor strings from `lspci`/`lsusb` into specific Debian package names. This matrix is critical for handling the "Intel Split" and other vendor-specific requirements: The script employs an associative mapping strategy in `_detect_firmware_needs` to translate raw vendor strings from `lspci`/`lsusb` into specific Debian package names. This matrix is critical for handling the "Intel Split" and other vendor-specific requirements:
* **Vendor Filtering:** The engine first filters out generic or unsupported vendors (e.g., non-Realtek, non-Intel, non-Atheros) to avoid unnecessary package pulls. * **Vendor Filtering:** The engine first filters out generic or unsupported vendors (e.g., non-Realtek, non-Intel, non-Atheros) to avoid unnecessary package pulls.
* **Package Assignment Logic:** * **Package Assignment Logic:**
* **Intel Wi-Fi Hardware**`firmware-iwlwifi` (Specific driver for wireless chips). * **Intel Wi-Fi Hardware** ➔ `firmware-iwlwifi` (Specific driver for wireless chips).
* **Intel Ethernet Hardware**`firmware-intel-misc` (Often pulled via `Recommends` of the base package, but explicitly tracked here). * **Intel Ethernet Hardware** ➔ `firmware-intel-misc` (Often pulled via `Recommends` of the base package, but explicitly tracked here).
* **Realtek Hardware**`firmware-realtek`. * **Realtek Hardware** ➔ `firmware-realtek`.
* **MediaTek / Ralink Hardware**`firmware-mediatek`. * **MediaTek / Ralink Hardware** ➔ `firmware-mediatek`.
* **Atheros / Qualcomm Hardware**`firmware-atheros`. * **Atheros / Qualcomm Hardware** ➔ `firmware-atheros`.
This mapping ensures that if a system contains an Intel Wi-Fi 6 card, the script explicitly queues `firmware-iwlwifi` regardless of whether the base meta-package claims to cover it. The output is rendered as a deduplicated plan with visual indicators (e.g., `[+] package ← hardware`) for user clarity. This mapping ensures that if a system contains an Intel Wi-Fi 6 card, the script explicitly queues `firmware-iwlwifi` regardless of whether the base meta-package claims to cover it. The output is rendered as a deduplicated plan with visual indicators (e.g., `[+] package ← hardware`) for user clarity.
## 4. Installation Execution Flow (Atomic Pipeline) ## 4. Installation Execution Flow (Atomic Pipeline)
The installation process follows a strict atomic pipeline defined in `install_firmware`, ensuring system stability and version consistency: The installation process follows a strict atomic pipeline defined in `install_firmware`, ensuring system stability and version consistency:
1. **Repository Validation:** The script first verifies that `/etc/apt/sources.list` or `.d/` contains the `non-free` component. If absent, it halts to prevent installation failures. 1. **Repository Validation:** The script first verifies that `/etc/apt/sources.list` or `.d/` contains the `non-free` component. If absent, it halts to prevent installation failures.
2. **Plan Rendering & Confirmation:** A diagnostic tree is generated showing detected controllers and planned packages. The user must explicitly confirm ("Apply the network & firmware plan?") before proceeding. 2. **Plan Rendering & Confirmation:** A diagnostic tree is generated showing detected controllers and planned packages. The user must explicitly confirm ("Apply the network & firmware plan?") before proceeding.
3. **Base Meta-Package Selection (Backports vs. Stable):** 3. **Base Meta-Package Selection (Backports vs. Stable):**
* If `firmware-linux-nonfree` is already installed, the script checks for a newer version in backports (`${DEBIAN_CODENAME}-backports`). It prompts to upgrade if available, as backports often contain firmware for very recent hardware not yet in stable. * If `firmware-linux-nonfree` is already installed, the script checks for a newer version in backports (`${DEBIAN_CODENAME}-backports`). It prompts to upgrade if available, as backports often contain firmware for very recent hardware not yet in stable.
* If not installed, it presents a choice between Stable (Ultra-tested) and Backports (Recommended for modern hardware). * If not installed, it presents a choice between Stable (Ultra-tested) and Backports (Recommended for modern hardware).
4. **Sequential Injection:** After the base package is secured, the script iterates through `_DETECTED_FW_PKGS`. It uses `apt-cache policy` to validate availability before installing specific vendor packages (`firmware-realtek`, etc.), skipping those already present or unavailable in repositories. 4. **Sequential Injection:** After the base package is secured, the script iterates through `_DETECTED_FW_PKGS`. It uses `apt-cache policy` to validate availability before installing specific vendor packages (`firmware-realtek`, etc.), skipping those already present or unavailable in repositories.
## 5. Broadcom Redundancy System (3-Tier Support) ## 5. Broadcom Wireless Support (DKMS Single-Path)
Broadcom chipsets require complex handling due to their mix of open-source and proprietary driver support. The `_handle_wireless` function implements a three-tier logic to maximize compatibility without breaking the kernel:
* **Tier 1 (Open/Non-Free Direct):** For supported chips, it attempts to install `firmware-brcm80211`. This is preferred as it uses standard DKMS modules provided by Debian. Broadcom chipsets require proprietary handling because no open-source driver covers most `14e4:*` devices on modern kernels. The current implementation in `firmware.sh:_handle_wireless` uses a **single-path DKMS flow** (`broadcom-sta-dkms` + `wl` module) — not a 3-tier fallback:
* **Tier 2 (Firmware Emulation):** If Tier 1 fails or the chipset requires firmware emulation (e.g., older B43 chips), the script installs `firmware-b43-installer` or `firmware-b43legacy-installer`. This is a fallback for hardware that cannot be driven by standard kernel modules.
* **Tier 3 (Proprietary DKMS):** For unsupported chipsets where open-source drivers are insufficient, the system falls back to compiling proprietary drivers (`broadcom-sta-dkms`). The script explicitly checks for `linux-headers` availability before attempting this compilation, as it requires kernel headers matching the running version. It warns the user that a reboot may be required after installation.
This tiered approach ensures that even if one method fails (e.g., proprietary driver compilation errors), the system attempts other supported methods to restore network functionality. 1. **Device detection** — Iterates `PCI_NET_DEVS` (parsed from `lspci -nn` at startup) and extracts the Broadcom ID `14e4:XXXX`. Non-Broadcom devices are skipped.
2. **Dependency guard** — Verifies `linux-headers-amd64` and `dkms` are available via `apt-cache show`. If missing, shows: `"linux-headers-amd64 or dkms are not available in your repositories."`
3. **User confirmation**`whiptail --yesno "Install broadcom-sta-dkms, dkms, and wireless-tools?"`
4. **Step-by-step install** (allows partial failure without aborting the whole module):
```bash
_run_cmd "Broadcom Dependencies" "sudo DEBIAN_FRONTEND=noninteractive apt install -y dkms wireless-tools linux-headers-amd64" || true
_run_cmd "Broadcom Driver" "sudo DEBIAN_FRONTEND=noninteractive apt install -y broadcom-sta-dkms" || true
```
5. **Blacklist persistence** — Writes `/etc/modprobe.d/blacklist-broadcom.conf`:
```
blacklist b43
blacklist b43legacy
blacklist brcmsmac
blacklist bcma
blacklist ssb
```
6. **SSH Warning + Module Switch** — Before unloading current WiFi modules, the script warns about SSH disconnection. Then removes conflicting modules and loads the Broadcom driver:
```bash
_msg "Network Warning" "The script is about to unload current WiFi kernel modules to load the Broadcom driver.
If you are connected via SSH over WiFi, YOUR CONNECTION WILL DROP. Please reconnect after a few seconds."
_run_cmd "Modprobe" "sudo modprobe -r b43 b43legacy b44 bcma brcmsmac brcmfmac ssb wl 2>/dev/null || true" || true
_run_cmd "Modprobe" "sudo modprobe wl" || true
```
7. **Initramfs** — Rebuilds the initramfs to include the new `wl` module:
```bash
_run_cmd "Initramfs" "sudo update-initramfs -u" || true
```
1. **Combo BT handling** — If a Broadcom Bluetooth device is also present (`PCI_BT_DEVS` grep `broadcom`), writes `softdep wl post: btusb` to `/etc/modprobe.d/broadcom-combo.conf`
2. **Post-DKMS verification** — Checks for `/lib/modules/$(uname -r)/updates/dkms/wl.ko*`. If missing, shows the last 20 lines of `dmesg` and offers `dpkg-reconfigure broadcom-sta-dkms`. On success, verifies `lsmod | grep ^wl` and reports `Broadcom WiFi activated (wl module loaded)` or `driver installed but wl module did not load — reboot required`.
USB Broadcom (`0a5c` vendor, `lsusb`) is detected but **not auto-installed** — the script shows a message that Linux lacks native drivers for most USB Broadcom WiFi chips and that `ndiswrapper` may be needed.
> **Historical note:** Earlier drafts of this document described a 3-tier system (`firmware-brcm80211` → `firmware-b43-installer` → `broadcom-sta-dkms`). The current script has consolidated to the DKMS path only. The other firmware packages are still available via the base `firmware-linux-nonfree` metapackage and vendor-specific packages (`firmware-realtek`, etc.).
## 6. Bluetooth Stack Integration ## 6. Bluetooth Stack Integration
Bluetooth support is handled through a dedicated module (`bluetooth.sh`) that integrates seamlessly with the firmware detection process: Bluetooth support is handled through a dedicated module (`bluetooth.sh`) that integrates seamlessly with the firmware detection process:
* **Hardware Detection:** The script identifies both PCI and USB Bluetooth controllers using `PCI_BT_DEVS` and `USB_BT_DEVS` arrays, ensuring comprehensive coverage of all Bluetooth hardware types. * **Hardware Detection:** The script identifies both PCI and USB Bluetooth controllers using `PCI_BT_DEVS` and `USB_BT_DEVS` arrays, ensuring comprehensive coverage of all Bluetooth hardware types.
* **Base Stack Installation:** When Bluetooth hardware is detected, the system installs the core stack (`bluez`, `bluez-utils`, `bluez-obexd`) if not already present. * **Base Stack Installation:** When Bluetooth hardware is detected, the system installs the core stack (`bluez`, `bluez-utils`, `bluez-obexd`) if not already present.
* **Desktop Environment Optimization:** Based on the detected desktop environment: * **Desktop Environment Optimization:** Based on the detected desktop environment:
* **KDE:** Installs `bluedevil` and optionally `pipewire-pulse` + `wireplumber` for Pipewire audio server integration. * **KDE:** Installs `bluedevil` and optionally `pipewire-pulse` + `wireplumber` for Pipewire audio server integration.
* **GNOME:** Uses built-in GNOME Bluetooth support in `gnome-control-center`. * **GNOME:** Uses built-in GNOME Bluetooth support in `gnome-control-center`.
* **XFCE/Other:** Installs `blueman` as the GTK Bluetooth manager. * **XFCE/Other:** Installs `blueman` as the GTK Bluetooth manager.
* **Service Management:** The script ensures the Bluetooth service is enabled and started automatically on boot, with session restart or reboot recommendation for desktop applets to load properly. * **Service Management:** The script ensures the Bluetooth service is enabled and started automatically on boot, with session restart or reboot recommendation for desktop applets to load properly.
This modular approach keeps Bluetooth handling separate from network firmware while maintaining tight integration through shared device detection arrays and coordinated installation flow. This modular approach keeps Bluetooth handling separate from network firmware while maintaining tight integration through shared device detection arrays and coordinated installation flow.
+18 -18
View File
@@ -1,4 +1,4 @@
## Option 7: Gaming Ecosystem, Performance Tweaks & Runtimes # Option 8: Gaming Ecosystem, Performance Tweaks & Runtimes
### 1. Philosophy of the Gaming Environment in Debian ### 1. Philosophy of the Gaming Environment in Debian
@@ -19,6 +19,7 @@ The module architecture separates concerns into distinct scripts (`steam.sh`, `h
**Steam Installation Logic:** The `install_steam()` function in `steam.sh` leverages Debian's native package management through the `apt install -y steam-installer` command. This approach differs from Valve's official repository for several reasons: **Steam Installation Logic:** The `install_steam()` function in `steam.sh` leverages Debian's native package management through the `apt install -y steam-installer` command. This approach differs from Valve's official repository for several reasons:
1. **32-bit Architecture Requirement:** Steam requires 32-bit libraries to run modern Windows games via Proton. The script explicitly prompts users to enable Multi-Arch support (`dpkg --add-architecture i386`) and install the complete Mesa stack for both amd64 and i386 architectures: 1. **32-bit Architecture Requirement:** Steam requires 32-bit libraries to run modern Windows games via Proton. The script explicitly prompts users to enable Multi-Arch support (`dpkg --add-architecture i386`) and install the complete Mesa stack for both amd64 and i386 architectures:
```bash ```bash
apt install mesa-vulkan-drivers libglx-mesa0:i386 mesa-vulkan-drivers:i386 \ apt install mesa-vulkan-drivers libglx-mesa0:i386 mesa-vulkan-drivers:i386 \
libgl1-mesa-dri:i386 libegl-mesa0:i386 mesa-va-drivers:i386 libgl1-mesa-dri:i386 libegl-mesa0:i386 mesa-va-drivers:i386
@@ -59,6 +60,7 @@ This approach ensures users always get the latest stable release while maintaini
4. **Screensaver Inhibition:** Prevents screensavers from activating during gaming sessions 4. **Screensaver Inhibition:** Prevents screensavers from activating during gaming sessions
The `install_gamemode()` function in `tools.sh` ensures the daemon is available system-wide: The `install_gamemode()` function in `tools.sh` ensures the daemon is available system-wide:
```bash ```bash
_run_install gamemode _run_install gamemode
``` ```
@@ -73,6 +75,7 @@ This allows users to wrap game launch commands with `gamemoderun %command%` for
4. **Native Rendering:** Uses Vulkan/OpenGL hooks for efficient overlay rendering without impacting game performance 4. **Native Rendering:** Uses Vulkan/OpenGL hooks for efficient overlay rendering without impacting game performance
The `install_mangohud()` function handles both 64-bit and 32-bit installations: The `install_mangohud()` function handles both 64-bit and 32-bit installations:
```bash ```bash
if dpkg --print-foreign-architectures | grep -q i386; then if dpkg --print-foreign-architectures | grep -q i386; then
echo "Installing 32-bit MangoHud..." echo "Installing 32-bit MangoHud..."
@@ -94,6 +97,7 @@ The `goverlay` component extends this functionality by integrating with Wayland
4. **Capability Assignment:** Sets raw I/O capabilities on the binary using `setcap cap_sys_rawio=ep /usr/bin/openrgb`, allowing direct hardware communication while maintaining user-space execution 4. **Capability Assignment:** Sets raw I/O capabilities on the binary using `setcap cap_sys_rawio=ep /usr/bin/openrgb`, allowing direct hardware communication while maintaining user-space execution
The script includes version-specific download URLs for Debian Bookworm (12) and Trixie (13), ensuring compatibility with different kernel versions: The script includes version-specific download URLs for Debian Bookworm (12) and Trixie (13), ensuring compatibility with different kernel versions:
```bash ```bash
if [ "$DEBIAN_VERSION" = "12" ]; then if [ "$DEBIAN_VERSION" = "12" ]; then
url="https://codeberg.org/OpenRGB/OpenRGB/releases/download/release_candidate_1.0rc2/openrgb_1.0rc2_amd64_bookworm_0fca93e.deb" url="https://codeberg.org/OpenRGB/OpenRGB/releases/download/release_candidate_1.0rc2/openrgb_1.0rc2_amd64_bookworm_0fca93e.deb"
@@ -106,32 +110,32 @@ This approach eliminates the security risk of running OpenRGB as root while main
--- ---
### 5. Java Runtimes (Eclipse Temurin 8 / 17 / 21) ### 5. Java Runtimes (Eclipse Temurin 8 / 17 / 21 / 25)
**Multi-Version Support:** The gaming module provides three specific Eclipse Temurin versions to accommodate different game requirements: **Multi-Version Support:** The gaming module provides four specific Eclipse Temurin versions to accommodate different game requirements:
| Version | Use Case | Justification | | Version | Use Case | Justification |
|---------|----------|---------------| | --------- | ---------- | --------------- |
| **Temurin 8** | Legacy Minecraft mods, older Java games | Maintains compatibility with mods written for Java 8 (2014-2019 era) | | **Temurin 8** | Legacy Minecraft mods, older Java games | Maintains compatibility with mods written for Java 8 (2014-2019 era) |
| **Temurin 17** | Modern Minecraft servers, newer game clients | Balances performance and compatibility for post-1.16+ game versions | | **Temurin 17** | Modern Minecraft servers, newer game clients | Balances performance and compatibility for post-1.16+ game versions |
| **Temurin 21** | Latest game engines, cutting-edge mods | Provides best performance for modern Java applications | | **Temurin 21** | Latest game engines, cutting-edge mods | Provides best performance for modern Java applications |
| **Temurin 25** | Minecraft 26+ and latest game engines | Best performance for the newest Java applications |
**Repository Management via extrepo:** The script leverages the `extrepo` utility to manage external repositories cleanly rather than manually injecting repository URLs into system files. This approach offers several advantages: **Repository Management via extrepo:** The script leverages the `extrepo` utility to manage external repositories cleanly rather than manually injecting repository URLs into system files. This approach offers several advantages:
1. **Automated Keyring Handling:** `extrepo` manages GPG keys and source file configurations automatically, eliminating manual intervention with `/etc/apt/sources.list.d/`. 1. **Automated Keyring Handling:** `extrepo` manages GPG keys and source file configurations automatically, eliminating manual intervention with `/etc/apt/sources.list.d/`.
2. **Dependency Resolution:** The utility checks for its own installation and handles the enabling of the Adoptium Temurin repository before proceeding with package installation. 2. **Dependency Resolution:** The utility checks for its own installation and handles the enabling of the Adoptium Temurin repository before proceeding with package installation.
3. **Maintenance Safety:** Updates to the upstream repository are reflected through `extrepo` without requiring direct edits to system configuration files, reducing the risk of breakage during OS updates. 3. **Maintenance Safety:** Updates to the upstream repository are reflected through `extrepo` without requiring direct edits to system configuration files, reducing the risk of breakage during OS updates.
**Version Selection Logic:** Users can choose which Temurin version to install based on their specific game requirements via a TUI menu (`install_minecraft_java()`). The module justifies offering all three versions because: **Version Selection Logic:** Users can choose which Temurin version to install based on their specific game requirements via a TUI menu (`install_minecraft_java()`). The module justifies offering all four versions because:
1. **Backward Compatibility:** Java 8 remains in use by many Minecraft mods and older game clients that haven't been updated for newer JVMs 1. **Backward Compatibility:** Java 8 remains in use by many Minecraft mods and older game clients that haven't been updated for newer JVMs
2. **Performance Optimization:** Java 21 provides the best performance characteristics for modern games with heavy multithreading requirements 2. **Performance Optimization:** Java 21 provides the best performance characteristics for modern games with heavy multithreading requirements
3. **Security Updates:** All Temurin versions receive regular security patches from the Eclipse Foundation community 3. **Security Updates:** All Temurin versions receive regular security patches from the Eclipse Foundation community
The installation process ensures clean repository management without polluting the system with multiple conflicting JRE installations, maintaining Debian's package integrity while providing flexibility for different gaming scenarios. It automatically installs `extrepo` if not present and enables the Adoptium source before proceeding with version-specific packages (e.g., `temurin-8-jre`, `temurin-17-jre`). The installation process ensures clean repository management without polluting the system with multiple conflicting JRE installations, maintaining Debian's package integrity while providing flexibility for different gaming scenarios. It automatically installs `extrepo` if not present and enables the Adoptium source before proceeding with version-specific packages (e.g., `temurin-8-jre`, `temurin-17-jre`, `temurin-25-jre`).
### References
### References:
- [https://wiki.debian.org/Steam](https://wiki.debian.org/Steam) - [https://wiki.debian.org/Steam](https://wiki.debian.org/Steam)
- [wiki.archlinux.org/title/Steam](wiki.archlinux.org/title/Steam) - [wiki.archlinux.org/title/Steam](wiki.archlinux.org/title/Steam)
@@ -144,7 +148,3 @@ The installation process ensures clean repository management without polluting t
- [https://github.com/feralinteractive/gamemode](https://github.com/feralinteractive/gamemode) - [https://github.com/feralinteractive/gamemode](https://github.com/feralinteractive/gamemode)
- [https://gitlab.com/CalcProgrammer1/OpenRGB](https://gitlab.com/CalcProgrammer1/OpenRGB) - [https://gitlab.com/CalcProgrammer1/OpenRGB](https://gitlab.com/CalcProgrammer1/OpenRGB)
- [https://adoptium.net/es/installation/linux](https://adoptium.net/es/installation/linux) - [https://adoptium.net/es/installation/linux](https://adoptium.net/es/installation/linux)
+118 -79
View File
@@ -1,12 +1,12 @@
## Option 5: Graphics Drivers, Mesa Stack & Display Architecture # Option 6: Graphics Drivers, Mesa Stack & Display Architecture
### 1. Philosophy of the Graphics Stack (Open-Source vs. Proprietary) ### 1. Philosophy of the Graphics Stack (Open-Source vs. Proprietary)
The `debianito` script adopts a **hybrid-first architecture philosophy**. It prioritizes the stability and security of the Linux kernel's native open-source drivers while maintaining the capability to inject proprietary solutions where necessary for performance or legacy support. This approach is implemented through three distinct layers: The `debianito` script adopts a **hybrid-first architecture philosophy**. It prioritizes the stability and security of the Linux kernel's native open-source drivers while maintaining the capability to inject proprietary solutions where necessary for performance or legacy support. This approach is implemented through three distinct layers:
1. **DRM/KMS & Mesa (Open-Source Core)**: For Intel and AMD hardware, the script relies on the `i915`/`amdgpu` kernel drivers (KMS) paired with the `Mesa` user-space stack. This ensures that graphics acceleration is handled by the mainline Linux kernel without requiring third-party blobs or external repositories for basic functionality. The script explicitly installs the necessary Gallium3D drivers (`radeonsi`, `iris`) and Vulkan implementations (`RADV`). 1. **DRM/KMS & Mesa (Open-Source Core)**: For Intel and AMD hardware, the script relies on the `i915`/`amdgpu` kernel drivers (KMS) paired with the `Mesa` user-space stack. This ensures that graphics acceleration is handled by the mainline Linux kernel without requiring third-party blobs or external repositories for basic functionality. The script explicitly installs the necessary Gallium3D drivers (`radeonsi`, `iris`) and Vulkan implementations (`RADV`).
2. **Proprietary Injection (NVIDIA)**: For NVIDIA hardware, the open-source Nouveau driver is often insufficient for gaming or compute workloads. The script manages the installation of proprietary `.run` or DKMS modules via official NVIDIA repositories. This requires careful handling to ensure compatibility with the running kernel version, especially when using backports kernels. 2. **Proprietary Injection (NVIDIA)**: For NVIDIA hardware, the open-source Nouveau driver is often insufficient for gaming or compute workloads. The script manages the installation of proprietary `.run` or DKMS modules via official NVIDIA repositories. This requires careful handling to ensure compatibility with the running kernel version, especially when using backports kernels.
3. **Firmware & Microcode**: A critical prerequisite layer handled by `firmware.sh`. Before any driver can load, the correct firmware blobs (e.g., `iwlwifi`, `amdgpu`, `nvidia`) must be present in `/lib/firmware`. The script scans hardware via `lspci` and `lsusb` to populate a dynamic installation plan for these non-free components. 3. **Firmware & Microcode**: A critical prerequisite layer handled by `firmware.sh`. Before any driver can load, the correct firmware blobs (e.g., `iwlwifi`, `amdgpu`, `nvidia`) must be present in `/lib/firmware`. The script scans hardware via `lspci` and `lsusb` to populate a dynamic installation plan for these non-free components.
This philosophy ensures that users on standard Debian Stable releases get maximum compatibility, while advanced users can opt into backports kernels or enterprise NVIDIA repositories without breaking the base system integrity. This philosophy ensures that users on standard Debian Stable releases get maximum compatibility, while advanced users can opt into backports kernels or enterprise NVIDIA repositories without breaking the base system integrity.
@@ -17,11 +17,13 @@ This philosophy ensures that users on standard Debian Stable releases get maximu
The script utilizes a robust pre-flight detection sequence defined in `utils.sh` and executed within `gpu.sh`. This pipeline minimizes user interaction by automatically categorizing hardware before presenting installation options. The script utilizes a robust pre-flight detection sequence defined in `utils.sh` and executed within `gpu.sh`. This pipeline minimizes user interaction by automatically categorizing hardware before presenting installation options.
**Detection Flow:** **Detection Flow:**
1. **Hardware Scanning**: The function `detect_gpu()` executes `lspci -nn | grep -E "VGA|3D"`. It parses the output using `sed` and `grep` to identify vendor IDs (e.g., `8086` for Intel, `10de` for NVIDIA).
2. **Variable State**: Global variables are populated immediately: 1. **Hardware Scanning**: The function `detect_gpu()` executes `lspci -nn | grep -E "VGA|3D"`. It parses the output using `sed` and `grep` to identify vendor IDs (e.g., `8086` for Intel, `10de` for NVIDIA).
* `GPU_TYPE`: Set to `"intel"`, `"amd"`, or `"nvidia"`. If no GPU is found, it defaults to `"unknown"` (common in VMs or headless servers). 2. **Variable State**: Global variables are populated immediately:
* `INTEL_GPU_DEVICE_ID` / `NVIDIA_GPU_DEVICE_ID`: Hexadecimal device IDs extracted for precise generation matching. * `GPU_TYPE`: Set to `"intel"`, `"amd"`, or `"nvidia"`. If no GPU is found, it defaults to `"unknown"` (common in VMs or headless servers).
3. **Logic Branching**: Inside `install_gpu_drivers()`, the script checks these variables: * `INTEL_GPU_DEVICE_ID` / `NVIDIA_GPU_DEVICE_ID`: Hexadecimal device IDs extracted for precise generation matching.
3. **Logic Branching**: Inside `install_gpu_drivers()`, the script checks these variables:
```bash ```bash
if [ "$GPU_TYPE" = "unknown" ]; then if [ "$GPU_TYPE" = "unknown" ]; then
# Install generic Mesa stack (Safe fallback) # Install generic Mesa stack (Safe fallback)
@@ -33,9 +35,10 @@ The script utilizes a robust pre-flight detection sequence defined in `utils.sh`
# Route to AMD-specific logic (amdgpu/radeonsi) # Route to AMD-specific logic (amdgpu/radeonsi)
install_amd_firmware && offer_amd_tools install_amd_firmware && offer_amd_tools
``` ```
4. **Hybrid Support**: For laptops with hybrid graphics (e.g., Intel iGPU + NVIDIA dGPU), the script detects both `HAS_INTEL=true` and `HAS_NVIDIA=true`. It executes a sequential plan:
* Install Intel firmware/drivers first to ensure the base display server works. 4. **Hybrid Support**: For laptops with hybrid graphics (e.g., Intel iGPU + NVIDIA dGPU), the script detects both `HAS_INTEL=true` and `HAS_NVIDIA=true`. It executes a sequential plan:
* Install NVIDIA drivers second, configuring them for PRIME offloading if detected. * Install Intel firmware/drivers first to ensure the base display server works.
* Install NVIDIA drivers second, configuring them for PRIME offloading if detected.
This "detect-then-deploy" model prevents users from installing unnecessary drivers (e.g., `i965` on an RTX 4090) and ensures that critical firmware is present before the driver installation phase begins. This "detect-then-deploy" model prevents users from installing unnecessary drivers (e.g., `i965` on an RTX 4090) and ensures that critical firmware is present before the driver installation phase begins.
@@ -48,9 +51,9 @@ This "detect-then-deploy" model prevents users from installing unnecessary drive
| **Gen4** (Broadwater) | 65nm | GMA X4500, GMA X4500HD | `i915` | `i915` | Not supported | Predecessor to HD Graphics. Very limited support. The i915 DRI driver is the original, now obsolete. | | **Gen4** (Broadwater) | 65nm | GMA X4500, GMA X4500HD | `i915` | `i915` | Not supported | Predecessor to HD Graphics. Very limited support. The i915 DRI driver is the original, now obsolete. |
| **Gen5** (Ironlake) | 32nm | HD Graphics (Westmere/Arrandale) | `i915` | `crocus` | Not supported | First generation "HD Graphics". OpenGL up to 3.3 only. Legacy driver `i965` was **removed** in Mesa 24.1, so `crocus` is now the only option. | | **Gen5** (Ironlake) | 32nm | HD Graphics (Westmere/Arrandale) | `i915` | `crocus` | Not supported | First generation "HD Graphics". OpenGL up to 3.3 only. Legacy driver `i965` was **removed** in Mesa 24.1, so `crocus` is now the only option. |
| **Gen6** (Sandy Bridge) | 32nm | HD Graphics 2000/3000 | `i915` | `crocus` | Not supported | Significant performance improvement. Maximum OpenGL 3.3. | | **Gen6** (Sandy Bridge) | 32nm | HD Graphics 2000/3000 | `i915` | `crocus` | Not supported | Significant performance improvement. Maximum OpenGL 3.3. |
| **Gen7** (Ivy Bridge) | 22nm | HD Graphics 2500/4000 | `i915` | `crocus` | `ANV/HASVK` [(incomplete/broken)](https://www.reddit.com/r/vulkan/s/Hnf5zU8WZY) | First Gen at 22nm. `crocus` is the recommended OpenGL driver. Vulkan is exposed but completely non-conformant (0.0.0.0 ), lacks basic features (e.g., texture swizzle), and is [unusable for real-world tasks](https://www.phoronix.com/news/Intel-HasVK-Drop-Dead-Code).| | **Gen7** (Ivy Bridge) | 22nm | HD Graphics 2500/4000 | `i915` | `crocus` | `ANV/HASVK` [(incomplete/broken)](https://www.reddit.com/r/vulkan/s/Hnf5zU8WZY) | First Gen at 22nm. `crocus` is the recommended OpenGL driver. Vulkan is exposed but completely non-conformant (0.0.0.0 ), lacks basic features (e.g., texture swizzle), and is [unusable for real-world tasks](https://www.phoronix.com/news/Intel-HasVK-Drop-Dead-Code). |
| **Gen7** (Bay Trail) | 22nm | HD Graphics (Bay Trail) | `i915` | `crocus` | `ANV`[(incomplete)](https://lists.debian.org/debian-user/2023/07/msg00550.html) | `conformanceVersion = 0.0.0.0` Support is experimental up to Vulkan 1.2, lacks basic extensions, and may cause instability. The separate HASVK driver exists but is not used on this system. | | **Gen7** (Bay Trail) | 22nm | HD Graphics (Bay Trail) | `i915` | `crocus` | `ANV`[(incomplete)](https://lists.debian.org/debian-user/2023/07/msg00550.html) | `conformanceVersion = 0.0.0.0` Support is experimental up to Vulkan 1.2, lacks basic extensions, and may cause instability. The separate HASVK driver exists but is not used on this system. |
| **Gen7.5** (Haswell) | 22nm | HD Graphics 4600, Iris Pro 5200 | `i915` | `crocus` | `hasvk` | Vulkan support via community driver `hasvk` (Vulkan 1.3). | | **Gen7.5** (Haswell) | 22nm | HD Graphics 4600, Iris Pro 5200 | `i915` | `crocus` | `hasvk` | Vulkan support via community driver `hasvk` (Vulkan 1.3). |
| **Gen8** (Broadwell) | 14nm | HD Graphics 5300, Iris Pro 6200, Iris 6100 | `i915` | `iris` | `hasvk` | First generation at 14nm, `iris` becomes the main OpenGL driver. | | **Gen8** (Broadwell) | 14nm | HD Graphics 5300, Iris Pro 6200, Iris 6100 | `i915` | `iris` | `hasvk` | First generation at 14nm, `iris` becomes the main OpenGL driver. |
| **Gen9** (Skylake) | 14nm | HD Graphics 530, Iris 540/550 | `i915` | `iris` | `anv` | Mature architecture with strong Linux support. Major performance boost for iGPU. | | **Gen9** (Skylake) | 14nm | HD Graphics 530, Iris 540/550 | `i915` | `iris` | `anv` | Mature architecture with strong Linux support. Major performance boost for iGPU. |
| **Gen9.5** (Kaby Lake, Coffee Lake, Comet Lake) | 14nm+ / 14nm++ | UHD Graphics 620/630, UHD 610/630 | `i915` | `iris` | `anv` | Process node optimization for 14nm. "UHD" replaces "HD" in naming convention. | | **Gen9.5** (Kaby Lake, Coffee Lake, Comet Lake) | 14nm+ / 14nm++ | UHD Graphics 620/630, UHD 610/630 | `i915` | `iris` | `anv` | Process node optimization for 14nm. "UHD" replaces "HD" in naming convention. |
@@ -64,19 +67,19 @@ This "detect-then-deploy" model prevents users from installing unnecessary drive
--- ---
#### Intel Details: #### Intel Details
1. **Kernel Driver Transition (`i915` to `xe`)**: The [`i915`](https://www.kernel.org/doc/html/v4.9/gpu/i915.html) driver is reaching its scalability limits. [Xe](https://www.kernel.org/doc/html/v6.8/gpu/rfc/xe.html) is the path for modern hardware, though it still requires forcing and is under development, it already shows significant improvements in various areas. 1. **Kernel Driver Transition (`i915` to `xe`)**: The [`i915`](https://www.kernel.org/doc/html/v4.9/gpu/i915.html) driver is reaching its scalability limits. [Xe](https://www.kernel.org/doc/html/v6.8/gpu/rfc/xe.html) is the path for modern hardware, though it still requires forcing and is under development, it already shows significant improvements in various areas.
2. **Mesa Drivers (User Space)**: 2. **Mesa Drivers (User Space)**:
* **OpenGL**: * **OpenGL**:
* **Legacy Hardware (Gen5-Gen8)**: The classic `i965` driver was **officially removed from Mesa in version 24.1**. **[`crocus`](https://www.phoronix.com/news/Intel-Crocus-Default-Gallium3D)** (Gallium3D) is the only active driver for this legacy hardware. * **Legacy Hardware (Gen5-Gen8)**: The classic `i965` driver was **officially removed from Mesa in version 24.1**. **[`crocus`](https://www.phoronix.com/news/Intel-Crocus-Default-Gallium3D)** (Gallium3D) is the only active driver for this legacy hardware.
* **Modern Hardware (Gen9 and Xe)**: **`iris`** is the standard driver. It works excellently on both iGPUs and Arc dGPUs (Alchemist/Battlemage). * **Modern Hardware (Gen9 and Xe)**: **`iris`** is the standard driver. It works excellently on both iGPUs and Arc dGPUs (Alchemist/Battlemage).
* **Vulkan**: * **Vulkan**:
* **Old Hardware about Ivy Bridge and Bay Trail (Gen7)**: Although the ANV/HASVK drivers expose these GPUs as Vulkan devices (reporting API versions as high as 1.2 or 1.3), their state is completely non-compliant (conformanceVersion = 0.0.0.0). The support is purely theoretical, it lacks basic hardware features (e.g., texture swizzle on Ivy Bridge) and is unstable or unusable for real-world applications. Because of this, in Mesa 22.3, the Gen7/Gen8 Vulkan code was separated from the main driver (ANV) and moved to the legacy HASVK driver to avoid hindering the development of modern hardware. You can read the technical details of this decision [here](https://www.phoronix.com/news/Intel-HASVK-Old-Vulkan-Gen7-8). * **Old Hardware about Ivy Bridge and Bay Trail (Gen7)**: Although the ANV/HASVK drivers expose these GPUs as Vulkan devices (reporting API versions as high as 1.2 or 1.3), their state is completely non-compliant (conformanceVersion = 0.0.0.0). The support is purely theoretical, it lacks basic hardware features (e.g., texture swizzle on Ivy Bridge) and is unstable or unusable for real-world applications. Because of this, in Mesa 22.3, the Gen7/Gen8 Vulkan code was separated from the main driver (ANV) and moved to the legacy HASVK driver to avoid hindering the development of modern hardware. You can read the technical details of this decision [here](https://www.phoronix.com/news/Intel-HASVK-Old-Vulkan-Gen7-8).
* **Legacy Hardware (Gen7.5 - Gen8)**: Uses **[`hasvk`](https://www.phoronix.com/news/Intel-ANV-HASVK-Split-Merged)**, a community-maintained driver (not directly by Intel engineers), offering Vulkan 1.2? on 2013-era hardware. * **Legacy Hardware (Gen7.5 - Gen8)**: Uses **[`hasvk`](https://www.phoronix.com/news/Intel-ANV-HASVK-Split-Merged)**, a community-maintained driver (not directly by Intel engineers), offering Vulkan 1.2? on 2013-era hardware.
*Additionally, in early 2024, the compiler code shared between `iris` and `anv` for [Gen8](https://www.phoronix.com/news/Intel-Mesa-Splitting-Gen8) was also isolated, following the same principle: to enable faster development for modern hardware without breaking Broadwell support*. *Additionally, in early 2024, the compiler code shared between `iris` and `anv` for [Gen8](https://www.phoronix.com/news/Intel-Mesa-Splitting-Gen8) was also isolated, following the same principle: to enable faster development for modern hardware without breaking Broadwell support*.
* **Modern Hardware (Gen9+)**: **[`anv`](https://docs.mesa3d.org/drivers/anv.html)** is Intel's official driver. On recent hardware (Gen12+, Arc) it reaches the **Vulkan 1.4 standard**. * **Modern Hardware (Gen9+)**: **[`anv`](https://docs.mesa3d.org/drivers/anv.html)** is Intel's official driver. On recent hardware (Gen12+, Arc) it reaches the **Vulkan 1.4 standard**.
3. **New Hardware Support Status**: Support for very recent iGPUs (such as Lunar Lake and Panther Lake) often requires very recent versions of the Linux kernel (6.8/6.11 branch or higher) and Mesa library (24.2+), plus updated firmware (`linux-firmware`). 3. **New Hardware Support Status**: Support for very recent iGPUs (such as Lunar Lake and Panther Lake) often requires very recent versions of the Linux kernel (6.8/6.11 branch or higher) and Mesa library (24.2+), plus updated firmware (`linux-firmware`).
--- ---
@@ -89,31 +92,53 @@ AMD's open-source support is divided by architecture families, each mapped to a
| **TeraScale 1**<br>*(R600/R700)* | Radeon HD 2000, HD 3000, HD 4000 | `radeon` | `r600` | **Not Applicable** | Starting point of the `r600` driver in Mesa. Supports up to OpenGL 3.3. Architecture is completely obsolete, only useful for very basic 2D/3D desktop graphics. | | **TeraScale 1**<br>*(R600/R700)* | Radeon HD 2000, HD 3000, HD 4000 | `radeon` | `r600` | **Not Applicable** | Starting point of the `r600` driver in Mesa. Supports up to OpenGL 3.3. Architecture is completely obsolete, only useful for very basic 2D/3D desktop graphics. |
| **TeraScale 2**<br>*(Evergreen)* | Radeon HD 5000, HD 6000<br>*(and some low-end HD 7000)* | `radeon` | `r600` | **Not Applicable** | Last evolution of TeraScale. OpenGL support stalled at version 3.3. **No Vulkan support exists or will exist** due to hardware architecture limitations. | | **TeraScale 2**<br>*(Evergreen)* | Radeon HD 5000, HD 6000<br>*(and some low-end HD 7000)* | `radeon` | `r600` | **Not Applicable** | Last evolution of TeraScale. OpenGL support stalled at version 3.3. **No Vulkan support exists or will exist** due to hardware architecture limitations. |
| **TeraScale 3**<br>*(Northern Islands)* | Radeon HD 6000, HD 7000 (low-end) | `radeon` | `r600` | **Not Applicable** | Intermediate architecture between TeraScale 2 and GCN. OpenGL support remains at 3.3. **No Vulkan support**. Last generation before the jump to GCN. | | **TeraScale 3**<br>*(Northern Islands)* | Radeon HD 6000, HD 7000 (low-end) | `radeon` | `r600` | **Not Applicable** | Intermediate architecture between TeraScale 2 and GCN. OpenGL support remains at 3.3. **No Vulkan support**. Last generation before the jump to GCN. |
| **GCN 1.0 / 1.1**<br>*(gfx6 / gfx7)* | Radeon HD 7700, R7 200, R9 200/300 | `radeon` (default)<br>`amdgpu` (forced) | `radeonsi` | `RADV` (Vulkan 1.3) | **⚠️ Requires manual configuration:** The kernel loads `radeon` by default. To use `radeonsi`/`RADV`, pass to the kernel: `amdgpu.si_support=1 amdgpu.cik_support=1 radeon.si_support=0 radeon.cik_support=0`. | | **GCN 1.0 / 1.1**<br>*(gfx6 / gfx7)* | Radeon HD 7700, R7 200, R9 200/300 | `radeon` (default)<br>`amdgpu` (forced) | `radeonsi` | `RADV` (Vulkan 1.3) | First generation 28nm processor with Vulkan support. The kernel loads the `radeon` module by default. The script injects the system parameters to use `RADV`. |
| **GCN 3.0**<br>*(gfx8 / gfx8.1)* | Radeon R9 285, R9 Fury X, R9 Nano | `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | Third generation of GCN, direct predecessor to Polaris. Introduces efficiency improvements and initial support for Vulkan 1.3. | | **GCN 3.0**<br>*(gfx8 / gfx8.1)* | Radeon R9 285, R9 Fury X, R9 Nano | `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | Third generation of GCN, direct predecessor to Polaris. Introduces efficiency improvements and initial support for Vulkan 1.3. |
| **GCN 4.0**<br>*(Polaris, gfx8.0)* | Radeon RX 400, RX 500, Radeon Pro WX | `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | First generation to use the `amdgpu` KMD natively and by default without tricks. Sweet spot for stability of older hardware in current Linux. No Ray Tracing hardware support. | | **GCN 4.0**<br>*(Polaris, gfx8.0)* | Radeon RX 400, RX 500, Radeon Pro WX | `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | First generation to use the `amdgpu` KMD natively and by default without tricks. Sweet spot for stability of older hardware in current Linux. No Ray Tracing hardware support. |
| **GCN 5.0**<br>*(Vega, gfx9)* | Radeon RX Vega, Radeon VII, APUs Raven Ridge | `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | Last GCN generation. Significant improvements to the `radeonsi` driver for this hardware. On Vega, using "Override" in RADV sometimes improves performance over default shader cache. | | **GCN 5.0**<br>*(Vega, gfx9)* | Radeon RX Vega, Radeon VII, APUs Raven Ridge | `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | Last GCN generation. Significant improvements to the `radeonsi` driver for this hardware. On Vega, using "Override" in RADV sometimes improves performance over default shader cache. |
| **RDNA 1**<br>*(gfx10)* | Radeon RX 5000 | `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | Architectural jump. Introduces Variable Rate Shading (VRS) support. Mesa drivers quickly achieved performance parity with the proprietary Windows driver on this generation. | | **RDNA 1**<br>*(gfx10)* | Radeon RX 5000 | `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | Architectural jump. Introduces Variable Rate Shading (VRS) support. Mesa drivers quickly achieved performance parity with the proprietary Windows driver on this generation. |
| **RDNA 2**<br>*(gfx10.3)* | Radeon RX 6000, Steam Deck (Van Gogh) | `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | First generation with hardware **Ray Tracing** in AMD. In Mesa, this is handled through the `VK_KHR_ray_tracing_pipeline` extension. This architecture is in the Steam Deck, which massively accelerated RADV development. | | **RDNA 2**<br>*(gfx10.3)* | Radeon RX 6000, Steam Deck (Van Gogh) | `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | First generation with hardware **Ray Tracing** in AMD. In Mesa, this is handled through the `VK_KHR_ray_tracing_pipeline` extension. This architecture is in the Steam Deck, which massively accelerated RADV development. |
| **RDNA 3**<br>*(gfx11)* | Radeon RX 7000 | `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | Introduces **Mesh Shaders** in AMD hardware ([`VK_EXT_mesh_shader`](https://github.com/KhronosGroup/Vulkan-Docs/blob/main/proposals/VK_EXT_mesh_shader.adoc) extension). Requires a relatively recent Linux kernel (6.1+) for complete and stable graphics controller support. | | **RDNA 3**<br>*(gfx11)* | Radeon RX 7000 | `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | Introduces **Mesh Shaders** in AMD hardware ([`VK_EXT_mesh_shader`](https://github.com/KhronosGroup/Vulkan-Docs/blob/main/proposals/VK_EXT_mesh_shader.adoc) extension). Requires a relatively recent Linux kernel (6.1+) for complete and stable graphics controller support. |
| **RDNA 3.5**<br>*(gfx11.5)* | APUs Strix Point/Halo, Krackan Point, Gorgon Halo| `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | Intermediate update to RDNA 3. Shares many features with RDNA 3 (gfx11). Support in drivers (kernel, Mesa, LLVM) is integrated as part of the GFX11 family. | | **RDNA 3.5**<br>*(gfx11.5)* | APUs Strix Point/Halo, Krackan Point, Gorgon Halo | `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | Intermediate update to RDNA 3. Shares many features with RDNA 3 (gfx11). Support in drivers (kernel, Mesa, LLVM) is integrated as part of the GFX11 family. |
| **RDNA 4**<br>*(gfx12)* | Radeon RX 9000 | `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | Latest generation to date. RADV jumps to full support for **Vulkan 1.4** across the entire GFX8+ line (GCN 3 onwards). **Current context:** AMD has officially discontinued their other open Vulkan driver (AMDVLK), leaving | **RDNA 4**<br>*(gfx12)* | Radeon RX 9000 | `amdgpu` | `radeonsi` | `RADV` (Vulkan 1.4) | Latest generation to date. RADV jumps to full support for **Vulkan 1.4** across the entire GFX8+ line (GCN 3 onwards). **Current context:** AMD has officially discontinued their other open Vulkan driver (AMDVLK), leaving
#### AMD GCN Migration via GRUB Parameters
For older AMD GCN 1.0/1.1 GPUs (`gfx6`/`gfx7`), the script forces the modern `amdgpu` driver via kernel parameters injected into `GRUB_CMDLINE_LINUX_DEFAULT`. The migration is handled in `gpu.sh:_force_amdgpu()` with a **duplicate guard** to prevent repeated parameter injection:
```bash
local params="radeon.si_support=0 radeon.cik_support=0 amdgpu.si_support=1 amdgpu.cik_support=1"
# Duplicate guard — skip if already present
if grep -q "amdgpu.si_support=1" "$file" 2>/dev/null; then
_msg "AMD GCN" "amdgpu parameters already present in GRUB.\nNo changes made." 8 50
return
fi
# Insert params at the beginning of GRUB_CMDLINE_LINUX_DEFAULT
if ! sudo grep -q "amdgpu.si_support=1" "$file"; then
sudo sed -i -E "/^GRUB_CMDLINE_LINUX_DEFAULT=/ s/\"([^\"]*)\"/\"${params} \1\"/" "$file"
fi
```
The guard checks both `grep -q` (read-only) and `sudo grep -q` (with elevated permissions) to handle systems where `/etc/default/grub` requires root access. If the parameters are already present, the function exits early with a message rather than duplicating the entry.
#### Additional notes & carifications #### Additional notes & carifications
1. **Regarding GCN Nomenclature**: Names like "GCN 1.0", "1.1", "1.2" were created by the press as a convenient abbreviation, since AMD only started officially numbering their GCN revisions (gen 1 to 4) later. The table now uses more standard terminology. 1. **Regarding GCN Nomenclature**: Names like "GCN 1.0", "1.1", "1.2" were created by the press as a convenient abbreviation, since AMD only started officially numbering their GCN revisions (gen 1 to 4) later. The table now uses more standard terminology.
2. **Relationship Between Drivers and Architectures**: 2. **Relationship Between Drivers and Architectures**:
* The `radeonsi` driver (OpenGL) and `RADV` (Vulkan) are siblings within the Mesa 3D project. Both depend on the [`amdgpu` kernel](https://docs.kernel.org/gpu/amdgpu/index.html). * The `radeonsi` driver (OpenGL) and `RADV` (Vulkan) are siblings within the Mesa 3D project. Both depend on the [`amdgpu` kernel](https://docs.kernel.org/gpu/amdgpu/index.html).
* The old [`radeon`](https://wiki.freedesktop.org/xorg/radeon/) driver (for TeraScale) is incompatible with modern Mesa drivers (`radeonsi`/`RADV`). * The old [`radeon`](https://wiki.freedesktop.org/xorg/radeon/) driver (for TeraScale) is incompatible with modern Mesa drivers (`radeonsi`/`RADV`).
* **Important milestone**: Starting from Linux kernel 6.19, the `amdgpu` driver will include support for older generations of [AMD GPUs](https://wiki.gentoo.org/wiki/AMDGPU) (such as TeraScale and early GCN) that were previously only supported by the `radeon` driver, unifying support. * **Important milestone**: Starting from Linux kernel 6.19, the `amdgpu` driver will include support for older generations of [AMD GPUs](https://wiki.gentoo.org/wiki/AMDGPU) (such as TeraScale and early GCN) that were previously only supported by the `radeon` driver, unifying support.
3. **Vulkan Support in RADV**: Mesa documentation indicates that [RADV supports Vulkan 1.4 for all GFX8 GPUs (GCN 3 onwards) and newer](https://docs.mesa3d.org/drivers/radv.html#supported-hardware). This includes RDNA 3 and RDNA 3.5 architectures, not just RDNA 4. 3. **Vulkan Support in RADV**: Mesa documentation indicates that [RADV supports Vulkan 1.4 for all GFX8 GPUs (GCN 3 onwards) and newer](https://docs.mesa3d.org/drivers/radv.html#supported-hardware). This includes RDNA 3 and RDNA 3.5 architectures, not just RDNA 4.
4. **RDNA 3.5 Status**: It is an intermediate update that shares the architectural base of RDNA 3 (gfx11). The identifiers `gfx1150` and `gfx1151` correspond to this generation. Support in Mesa drivers and the kernel has been integrated progressively. 4. **RDNA 3.5 Status**: It is an intermediate update that shares the architectural base of RDNA 3 (gfx11). The identifiers `gfx1150` and `gfx1151` correspond to this generation. Support in Mesa drivers and the kernel has been integrated progressively.
--- ---
### 5. **NVIDIA Hardware & Driver Support** ### 5. **NVIDIA Hardware & Driver Support**
#### Nvidia Legacy (Fermi to Pascal): #### Nvidia Legacy (Fermi to Pascal)
These generations depend **exclusively** on the proprietary driver and closed stack. There is no support for the open kernel module nor NVK. These generations depend **exclusively** on the proprietary driver and closed stack. There is no support for the open kernel module nor NVK.
| Architecture | Last Driver with Support | Kernel Module (KMD) | Proprietary Vulkan Support | NVK (Mesa) Support | Max CUDA Version | Notes and Particularities | | Architecture | Last Driver with Support | Kernel Module (KMD) | Proprietary Vulkan Support | NVK (Mesa) Support | Max CUDA Version | Notes and Particularities |
@@ -125,7 +150,8 @@ These generations depend **exclusively** on the proprietary driver and closed st
--- ---
#### Nvidia: modern era and """Open Source""" (Turing to Blackwell): #### Nvidia: modern era and "Open Source" (Turing to Blackwell)
Starting with Turing, NVIDIA introduced the **open kernel module**. From driver 525, this module is the default. Additionally, it's the range where community driver **NVK** (in Mesa) shines. Starting with Turing, NVIDIA introduced the **open kernel module**. From driver 525, this module is the default. Additionally, it's the range where community driver **NVK** (in Mesa) shines.
| Architecture | Compatible Active Drivers | Kernel Module (KMD) | Proprietary Vulkan Support | NVK (Mesa) Support | Max CUDA Version | Notes and Particularities | | Architecture | Compatible Active Drivers | Kernel Module (KMD) | Proprietary Vulkan Support | NVK (Mesa) Support | Max CUDA Version | Notes and Particularities |
@@ -135,10 +161,11 @@ Starting with Turing, NVIDIA introduced the **open kernel module**. From driver
| **Ada Lovelace**<br>*(AD100/102/103/104)* | 525.xx to 610+ | `nvidia` (**Open Module**) | **Vulkan 1.3** | **Yes** (Vulkan 1.3) | **CUDA 12.8+** | NVK added full Ada support recently. Proprietary driver still required if hardware Ray Tracing or DLSS 3 (Frame Generation) is needed, as NVK does not yet implement these proprietary extensions. | | **Ada Lovelace**<br>*(AD100/102/103/104)* | 525.xx to 610+ | `nvidia` (**Open Module**) | **Vulkan 1.3** | **Yes** (Vulkan 1.3) | **CUDA 12.8+** | NVK added full Ada support recently. Proprietary driver still required if hardware Ray Tracing or DLSS 3 (Frame Generation) is needed, as NVK does not yet implement these proprietary extensions. |
| **Blackwell**<br>*(GB100/102/202)* | [570.xx](https://docs.nvidia.com/datacenter/tesla/tesla-release-notes-570-211-01/index.html) to 610+ | `nvidia` (**Open Module**) | **Vulkan 1.3** | **Yes** (In development) | **CUDA 12.8+** | Latest generation architecture (RTX 5090/5080). NVK support is landing in the most recent kernel versions (6.12+) and Mesa (24.3+). Requires very updated `linux-firmware`. | | **Blackwell**<br>*(GB100/102/202)* | [570.xx](https://docs.nvidia.com/datacenter/tesla/tesla-release-notes-570-211-01/index.html) to 610+ | `nvidia` (**Open Module**) | **Vulkan 1.3** | **Yes** (In development) | **CUDA 12.8+** | Latest generation architecture (RTX 5090/5080). NVK support is landing in the most recent kernel versions (6.12+) and Mesa (24.3+). Requires very updated `linux-firmware`. |
#### 💡 Quick context glossary for documentation: #### 💡 Quick context glossary for documentation
* **Open Module:** Starting with driver 515, [NVIDIA releases code that interacts directly with the Linux kernel under MIT/GPL license](https://developer.nvidia.com/blog/nvidia-releases-open-source-gpu-kernel-modules/). However, the GPU still requires loading a proprietary closed microcode called **GSP (GPU System Processor)** to boot.
* **NVK:** It is the open-source Vulkan driver developed by Red Hat and the community, integrated into the [Mesa project](https://docs.mesa3d.org/drivers/nvk.html). It's the 100% free alternative to `libGLX_nvidia.so`. Does not require NVIDIA proprietary driver installed to function (only kernel firmware). * **Open Module:** Starting with driver 515, [NVIDIA releases code that interacts directly with the Linux kernel under MIT/GPL license](https://developer.nvidia.com/blog/nvidia-releases-open-source-gpu-kernel-modules/). However, the GPU still requires loading a proprietary closed microcode called **GSP (GPU System Processor)** to boot.
* **CUDA Drop:** When NVIDIA removes an architecture from new drivers (e.g., Pascal in 555), the CUDA version used by that GPU freezes forever (in this case, CUDA 12.0). Cannot run applications compiled for CUDA 12.1 or higher. * **NVK:** It is the open-source Vulkan driver developed by Red Hat and the community, integrated into the [Mesa project](https://docs.mesa3d.org/drivers/nvk.html). It's the 100% free alternative to `libGLX_nvidia.so`. Does not require NVIDIA proprietary driver installed to function (only kernel firmware).
* **CUDA Drop:** When NVIDIA removes an architecture from new drivers (e.g., Pascal in 555), the CUDA version used by that GPU freezes forever (in this case, CUDA 12.0). Cannot run applications compiled for CUDA 12.1 or higher.
--- ---
@@ -147,16 +174,17 @@ Starting with Turing, NVIDIA introduced the **open kernel module**. From driver
When the script detects Intel or AMD hardware, it triggers a specific installation sequence designed to maximize [API support](https://mesamatrix.net/) (OpenGL/Vulkan/VA-API). When the script detects Intel or AMD hardware, it triggers a specific installation sequence designed to maximize [API support](https://mesamatrix.net/) (OpenGL/Vulkan/VA-API).
**Core Components Installed:** **Core Components Installed:**
* **`libgl1-mesa-dri`**: Provides the core OpenGL implementation for 64-bit systems. The script ensures `libgl1-mesa-dri:i386` is included if Wine or legacy applications are required, preventing architecture mismatches.
* **`mesa-vulkan-drivers`**: Installs `RADV` (AMD) and `anv` (Intel). This enables Vulkan 1.2/1.3 support on modern hardware. * **`libgl1-mesa-dri`**: Provides the core OpenGL implementation for 64-bit systems. The script ensures `libgl1-mesa-dri:i386` is included if Wine or legacy applications are required, preventing architecture mismatches.
* **`va-driver-all` / `vdpau-va-driver`**: Ensures video decoding acceleration is available for media players like VLC or MPV. * **`mesa-vulkan-drivers`**: Installs `RADV` (AMD) and `anv` (Intel). This enables Vulkan 1.2/1.3 support on modern hardware.
* **`va-driver-all` / `vdpau-va-driver`**: Ensures video decoding acceleration is available for media players like VLC or MPV.
**Vendor-Specific Logic:** **Vendor-Specific Logic:**
| Vendor | Kernel Driver (KMD) | Mesa User-Space Driver | VAAPI Backend Strategy | | Vendor | Kernel Driver (KMD) | Mesa User-Space Driver | VAAPI Backend Strategy |
| :--- | :--- | :--- | :--- | | :--- | :--- | :--- | :--- |
| **Intel Gen < 8** | `i915` | `crocus` / `iris` | Installs [`i965-va-driver-shaders`](https://github.com/intel/intel-vaapi-driver/). Legacy path for older CPUs. | | **Intel Gen < 8** | `i915` | `crocus` / `iris` | Installs [`i965-va-driver-shaders`](https://github.com/intel/intel-vaapi-driver/). Legacy path for older CPUs. |
| **Intel Gen 8+** | `i915` | `iris` / `anv` | Installs [`intel-media-va-driver-non-free](https://github.com/intel/media-driver). Modern, preferred backend for Broadwell+. | | **Intel Gen 8+** | `i915` | `iris` / `anv` | Installs [`intel-media-va-driver-non-free`](https://github.com/intel/media-driver). Modern, preferred backend for Broadwell+. |
| **AMD GCN/RDNA** | `amdgpu` | `radeonsi` (GL) + `RADV` (VK) | Uses standard `va-driver-all`. Requires kernel param tuning for older GCN. | | **AMD GCN/RDNA** | `amdgpu` | `radeonsi` (GL) + `RADV` (VK) | Uses standard `va-driver-all`. Requires kernel param tuning for older GCN. |
**Critical Consistency Check:** **Critical Consistency Check:**
@@ -166,35 +194,42 @@ The script enforces the installation of 32-bit Mesa libraries (`libgl1-mesa-dri:
### 7.**NVIDIA Driver Management & Kernel Compatibility** ### 7.**NVIDIA Driver Management & Kernel Compatibility**
The NVIDIA driver installation process is inherently complex due to proprietary components, kernel version constraints, and DKMS (Dynamic Kernel Module Support) module compilation. This section outlines how the script navigates these challenges by distinguishing between stable and backports kernels, handling Blackwell architecture GPUs via CUDA v590, and providing appropriate warnings for potential compatibility issues. The NVIDIA driver installation process is inherently complex due to proprietary components, kernel version constraints, and DKMS (Dynamic Kernel Module Support) module compilation. This section outlines how the script navigates these challenges by distinguishing between stable and backports kernels, handling Blackwell architecture GPUs via the CUDA repository (production branches v590 / v595), and providing appropriate warnings for potential compatibility issues.
#### **Kernel Compatibility** #### **Kernel Compatibility**
- **Stable Kernels**: Use `linux-image-amd64`. Compatible with standard NVIDIA `.deb` packages (e.g., `nvidia-driver-535`) and DKMS modules.
- **Backports Kernels**: Detected via `is_backports_kernel()`. Newer kernels may cause DKMS compilation failures due to driver version lag. The script warns users or suggests using the NVIDIA enterprise repository or manual header compilation (`linux-headers-$(uname -r)`).
#### **Blackwell Architecture & CUDA v590** * **Stable Kernels**: Use `linux-image-amd64`. Compatible with standard NVIDIA `.deb` packages (e.g., `nvidia-driver-535`) and DKMS modules.
- **Detection**: `_helpers.sh` function `is_nvidia_blackwell()` identifies GPUs via PCI IDs `10de:24xx`, `0x29000x29BF`, and `0x2B800x31FF`. * **Backports Kernels**: Detected via `is_backports_kernel()`. Newer kernels may cause DKMS compilation failures due to driver version lag. The script warns users or suggests using the NVIDIA enterprise repository or manual header compilation (`linux-headers-$(uname -r)`).
- **Reason for v590**: Debian 13 (Trixie) stable drivers only support up to v550, which lacks Blackwell (GB20x) architecture. The NVIDIA CUDA repository provides production branch v590 with unified driver packages. Specifically, the goal is to install the latest version of the nvidia-driver from the 590 branch, which would be [590.48.01](https://download.nvidia.com/XFree86/Linux-x86_64/590.48.01/README/supportedchips.html).
- **Extrepo Mechanism**: Enables `nvidia-cuda` repository via `extrepo`, creates APT pinning in `/etc/apt/preferences.d/block-nvidia` to lock to version `590.*`, and installs `nvidia-driver-pinning-590`, `nvidia-driver`, and `firmware-nvidia-gsp`. #### **Blackwell Architecture & CUDA v590/v595 (Production Branches)**
* **Detection**: `_helpers.sh` function `is_nvidia_blackwell()` identifies GPUs via PCI IDs `10de:24xx`, `0x29000x29BF`, and `0x2B800x31FF`. The same check gates both CUDA branches — Blackwell is unsupported by Debian stable regardless of the selected CUDA version.
* **Reason for v590/v595**: Debian 13 (Trixie) stable drivers only support up to v550, which lacks Blackwell (GB20x) architecture. The NVIDIA CUDA repository provides two production branches with unified driver packages: **v590**(current long-lived production, [590.48.01](https://download.nvidia.com/XFree86/Linux-x86_64/590.48.01/README/supportedchips.html)) and **v595** ([595.91.07](https://download.nvidia.com/XFree86/Linux-x86_64/595.91.07/README/supportedchips.html)newer production branch, same GB20x support with more recent fixes/features). Both branches expose the same unified metapackage and replace the need for a distro-packaged driver on Blackwell hardware.
* **CUDA Repository Enablement**: On Debian 13 (Trixie) — the only release that exposes `590` and `595` (`_show_nvidia_version_menu` gates them behind `DEBIAN_VERSION == 13`) — the script enables the `nvidia-cuda` repository via `extrepo` (`sudo apt install -y extrepo` if missing, then `sudo extrepo enable nvidia-cuda`). After enabling, the script always runs an explicit `apt update`, then installs `nvidia-driver-pinning-<ver>` if available (official NVIDIA pinning, optional and version-specific for 590 vs 595), and finally installs the unified metapackage `nvidia-open` plus `firmware-nvidia-gsp` (pulled as a transitive dependency). No manual pinning file is written; if `apt install` fails, the real `apt` error is shown and the installation aborts.
#### **Installation Flow** #### **Installation Flow**
```bash
if [ "$HAS_NVIDIA" = true ]; then
if [ "$(is_backports_kernel)" == "true" ] && \
{ [ "$DEBIAN_CODENAME" != "trixie" ] || ! is_nvidia_blackwell; }; then
# Warn about DKMS compatibility or use enterprise repo The NVIDIA flow is driven by `_install_nvidia_stack` (dispatcher in `modules/gpu.sh`):
offer_nvidia_enterprise_repo
fi
if _confirm "NVIDIA Driver"; then 1. **Plan** — `_msg` with detected GPUs, then `_pause`.
install_nvidia_driver # Installs latest stable (535/550) or v590 for Blackwell 2. **Manage menu** (`_nvidia_manage_menu`): "Install / Change NVIDIA Driver Version" or "Remove NVIDIA Driver and Restore Nouveau".
fi 3. **Version menu** (`_show_nvidia_version_menu`): Debian 12 → v535 (Recommended) / v470 (Kepler); Debian 13 → v550 (Recommended) / v590 / v595 (NVIDIA CUDA Repo).
fi 4. **Dispatch by hardware**: Kepler → `nvidia-tesla-470-driver`; Fermi → veto with message; Turing+ → `_install_nvidia_standard` (Debian stable); Blackwell on Trixie → CUDA repo v590.
``` 5. **CUDA repo (590/595)**: two separate APT transactions — `nvidia-driver-pinning-<ver>` (version lock, mandatory) then `nvidia-open` (driver + open kernel modules, firmware via transitive dependency).
6. **Secure Boot warning**: If Secure Boot is active (`mokutil --sb-state` reports `SecureBoot enabled`), the script displays a warning that the NVIDIA DKMS module is compiled but **NOT signed**. The user must sign the module with MOK or disable Secure Boot in BIOS before rebooting:
```
WARNING: Secure Boot is enabled. The NVIDIA DKMS module is compiled but NOT signed.
You MUST sign the module with MOK or disable Secure Boot in BIOS before rebooting.
```
Installation continues — Secure Boot does not block DKMS compilation, but the module will fail to load until signed.
7. **Post-install**: `/etc/modprobe.d/nvidia-wayland.conf` (written with `|| return 1` protection) + DKMS verification.
> Note: Debian 12 (Bookworm) backports reached EOL (2026-08-09); the NVIDIA flow on Bookworm only uses the stable repository.
--- ---
### 8.**NVIDIA Driver Management & Kernel Compatibility** ### 9.**NVIDIA Driver Compatibility Matrix**
Depending on your GPU generation and your Debian ecosystem, you must select the appropriate legacy or current driver series. The following table details the verified compatibility matrix across different Debian versions and hardware architectures: Depending on your GPU generation and your Debian ecosystem, you must select the appropriate legacy or current driver series. The following table details the verified compatibility matrix across different Debian versions and hardware architectures:
@@ -206,13 +241,16 @@ Depending on your GPU generation and your Debian ecosystem, you must select the
| **[550.163.01](https://us.download.nvidia.com/XFree86/Linux-x86_64/550.163.01/README/supportedchips.html)** | **Debian 13** (Trixie) | Maxwell to Ada Lovelace | Current stable standard. Blackwell not officially supported yet. | | **[550.163.01](https://us.download.nvidia.com/XFree86/Linux-x86_64/550.163.01/README/supportedchips.html)** | **Debian 13** (Trixie) | Maxwell to Ada Lovelace | Current stable standard. Blackwell not officially supported yet. |
#### **Critical Hardware Notes:** #### **Critical Hardware Notes:**
* **Kepler (GeForce vs. Quadro)**: The last driver supporting true Kepler architecture is version **470**. If a user has a GTX 680 or similar, they must stay on Debian 11 or use the 470 driver branch in Bookworm/Trixie manually.
* **Fermi (GTX 400/500)**: Support ended with driver 390. These GPUs are incompatible with modern kernels and drivers beyond Debian 11. * **Kepler (GeForce vs. Quadro)**: The last driver supporting true Kepler architecture is version **470**. If a user has a GTX 680 or similar, they must stay on Debian 11 or use the 470 driver branch in Bookworm/Trixie manually.
* **Volta (Titan V / V100)**: Excellent longevity, supported from 390 through 550+. * **Fermi (GTX 400/500)**: Support ended with driver 390. These GPUs are incompatible with modern kernels and drivers beyond Debian 11.
* **Blackwell (RTX 5000)**: Not officially supported by standard Debian drivers yet. The script provides a path to the Enterprise Repo for users who need this hardware to function immediately. * **Volta (Titan V / V100)**: Excellent longevity, supported from 390 through 550+.
* **Blackwell (RTX 5000)**: Not officially supported by standard Debian drivers yet. The script provides a path to the Enterprise Repo for users who need this hardware to function immediately.
#### **Kepler Interception in Bookworm:** #### **Kepler Interception in Bookworm:**
When Kepler is detected on Bookworm, `nvidia.sh` bypasses `nvidia-detect` (which might recommend v535) and forces installation of `nvidia-tesla-470-driver`:
When Kepler is detected on Bookworm, `nvidia.sh` forces installation of `nvidia-tesla-470-driver` (the modern v535/v550 branches do not support Kepler):
```bash ```bash
if [ "$is_kepler" = "true" ] && [ "$DEBIAN_CODENAME" = "bookworm" ]; then if [ "$is_kepler" = "true" ] && [ "$DEBIAN_CODENAME" = "bookworm" ]; then
nv_pkg="nvidia-tesla-470-driver" nv_pkg="nvidia-tesla-470-driver"
@@ -222,21 +260,22 @@ fi
--- ---
### 9. Performance Monitoring & Telemetry Tools ### 10. Performance Monitoring & Telemetry Tools
To ensure the graphics stack is functioning correctly, `gpu.sh` offers an optional installation of telemetry tools. These allow users to verify GPU utilization, memory usage, and codec support post-installation. To ensure the graphics stack is functioning correctly, `gpu.sh` offers an optional installation of telemetry tools. These allow users to verify GPU utilization, memory usage, and codec support post-installation.
* **Universal ([`nvtop`](https://github.com/Syllo/nvtop))**: * **Universal ([`nvtop`](https://github.com/Syllo/nvtop))**:
* A cross-platform tool that displays real-time metrics for NVIDIA, AMD, and Intel GPUs in a terminal interface (similar to `htop`). * A cross-platform tool that displays real-time metrics for NVIDIA, AMD, and Intel GPUs in a terminal interface (similar to `htop`).
* **Debian 11 Constraint**: In Debian 11 Bullseye, `nvtop` support is limited primarily to NVIDIA GPUs. The script warns users of this limitation on older releases. * **Debian 11 Constraint**: In Debian 11 Bullseye, `nvtop` support is limited primarily to NVIDIA GPUs. The script warns users of this limitation on older releases.
* **AMD Specific ([`radeontop`](https://github.com/clbr/radeontop))**: * **AMD Specific ([`radeontop`](https://github.com/clbr/radeontop))**:
* Provides detailed metrics for AMD GPUs (GPU usage, memory utilization, power consumption). Essential for verifying that the `amdgpu` driver is active and not falling back to software rendering. * Provides detailed metrics for AMD GPUs (GPU usage, memory utilization, power consumption). Essential for verifying that the `amdgpu` driver is active and not falling back to software rendering.
* **Intel Specific ([`intel-gpu-tools`](https://github.com/ChrisCummins/intel-gpu-tools))**: * **Intel Specific ([`intel-gpu-tools`](https://github.com/ChrisCummins/intel-gpu-tools))**:
* Only installed if the detected Intel hardware supports it (Gen 6+). Provides information on GPU usage via `inotify` or `/sys/class/drm`. * Only installed if the detected Intel hardware supports it (Gen 6+). Provides information on GPU usage via `inotify` or `/sys/class/drm`.
* **Codec Verification ([`vainfo`](https://github.com/intel/libva-utils))**: * **Codec Verification ([`vainfo`](https://github.com/intel/libva-utils))**:
* The script runs `vainfo` to verify that VAAPI is correctly configured. This confirms whether the system can utilize hardware acceleration for video decoding (e.g., H.264, HEVC) via Intel QuickSync or AMD Video Core Plus. * The script runs `vainfo` to verify that VAAPI is correctly configured. This confirms whether the system can utilize hardware acceleration for video decoding (e.g., H.264, HEVC) via Intel QuickSync or AMD Video Core Plus.
**Installation Command Logic:** **Installation Command Logic:**
```bash ```bash
if _confirm "Install Telemetry Tools"; then if _confirm "Install Telemetry Tools"; then
case "$GPU_TYPE" in case "$GPU_TYPE" in
+126 -51
View File
@@ -1,77 +1,152 @@
## Option 6: Debian Backports Kernel Integration # Option 7: Kernel Variants (Stable, Backports, RT, Cloud)
### 1. Why a Backports Kernel? ## 1. What Does This Component Do?
The decision to integrate the Debian Backports kernel into `debianito.sh` is driven by the fundamental architectural conflict between **Stability** and **Hardware Enablement**. The **Kernel** module (`modules/kernel.sh`) manages which Linux kernel your system boots. Unlike a simple `apt install`, it enforces **atomic installation of image + headers** and validates repository state before touching the boot chain. The menu (`show_kernel_menu`) offers four distinct kernel flavours plus a Backports path that is only available on Debian 13 (Trixie):
Debian Stable (including Debian 13 "Trixie") prioritizes long-term reliability. As a result, its kernel version is frozen at a Long Term Support (LTS) release—in this case, Linux 6.12 LTS. While 6.12 is robust and secure, it represents a snapshot of the upstream kernel from late 2024/early 2025. It does not include the rapid stream of hardware enablement, scheduler refinements, or power management optimizations that occur in subsequent releases (e.g., Linux 7.0+). | Key | Variant | Package | Use Case |
| ----- | --------- | --------- | ---------- |
| `stable` | Stable | `linux-image-amd64` | Default Debian kernel (6.12 LTS on Trixie). Maximum stability. |
| `backports` | Backports | `linux-image-amd64` from `trixie-backports` | Newer kernel (e.g., 7.x) for recent hardware. **Trixie only**, requires backports enabled. |
| `rt` | Real-Time | `linux-image-rt-amd64` | Preempt-RT kernel for low-latency / audio production. Warns on NVIDIA. |
| `cloud` | Cloud | `linux-image-cloud-amd64` | Minimal kernel for VMs, containers, and cloud images. |
For users with modern hardware released between 2025 and 2026, this freeze creates a compatibility gap: All variants install the matching **headers** package (`linux-headers-amd64`, `linux-headers-rt-amd64`, `linux-headers-cloud-amd64`) in the same transaction — critical for DKMS modules (NVIDIA, VirtualBox, ZFS).
* **New Architectures:** CPUs like Intel Arrow Lake/Panther Lake or AMD Zen 5 require specific microcode, scheduler hints (e.g., "slow workload hints"), and CXL support that are absent in the frozen 6.12 LTS branch.
* **Graphics Performance:** New GPUs (Intel Battlemage) may lack optimized power states (like D3cold enablement) or improved driver integration found in newer kernels.
* **Filesystem Integrity:** Advanced features like XFS self-healing or Btrfs remap-tree improvements are exclusive to newer kernel versions.
The `kernel.sh` module leverages the Debian Backports repository (`trixie-backports`) as a "best-effort" bridge. This allows users to opt-in to Kernel 7.0+ without abandoning the Stable base entirely. The script ensures that this upgrade is treated as an exception, providing access to modern enablement while maintaining the safety net of the Stable ecosystem for core system packages. > **Position in menu:** This is Option 7 in the current `debianito.sh` main menu. Previous documentation listed it as Option 6 (Backports only). The module was expanded to support RT and Cloud kernels after the initial release.
### 2. Synchronized Installation Pipeline (Kernel + Headers) ---
A critical engineering principle in kernel management is **Atomicity**. Installing a new kernel image without its corresponding headers breaks the build chain for third-party modules (such as NVIDIA DKMS, VirtualBox, or ZFS). The `install_kernel_backports` function enforces this by ensuring the installation command targets both components. ## 2. Why Offer Backports at All?
**The Installation Command Logic:** Debian Stable freezes its kernel at an LTS release (6.12 LTS on Trixie). This is intentional for reliability, but creates a hardware enablement gap for machines released in 2025-2026:
The script utilizes `apt` with a specific target release flag to pull packages from the backports suite:
- **New CPUs** (Intel Arrow Lake / Panther Lake, AMD Zen 5) need scheduler hints, CXL, and microcode not in 6.12
- **New GPUs** (Intel Battlemage D3cold, NVIDIA Blackwell) need power-state and firmware support added after 6.12
- **Filesystem fixes** (XFS self-healing, Btrfs remap-tree) land only in newer kernels
The `trixie-backports` repository provides a **best-effort newer kernel** without moving the rest of the system to Testing. Debian backports kernels receive security updates but are not LTS themselves.
This is why the menu shows `backports` only when `DEBIAN_VERSION == 13` and greys it out otherwise. Bookworm backports is intentionally not offered — its EOL was 2026-08-09 and the NVIDIA path on Bookworm no longer uses backports.
---
## 3. The Installation Pipeline: Image + Headers Atomically
### Function: `_install_kernel_package` (`kernel.sh`)
```bash ```bash
sudo apt install -y -t ${DEBIAN_CODENAME}-backports linux-image-amd64 _install_kernel_package "linux-image-amd64" "Backports" "-t trixie-backports"
_install_kernel_package "linux-image-rt-amd64" "RT" ""
``` ```
While Debian's dependency resolver often pulls headers automatically when installing `linux-image`, explicit documentation and engineering best practices dictate that the system must be configured to ensure both are present. The pipeline operates as follows: Execution steps:
1. **Target Specification (`-t`):** The flag `-t ${DEBIAN_CODENAME}-backports` explicitly directs APT to ignore the Stable repository for this specific transaction, ensuring the latest backported version is selected rather than a cached Stable package. 1. **Availability check**`apt-cache show <pkg>` must succeed. If the package does not exist for the current Debian version, a whiptail message `Kernel not available` is shown and the function returns.
2. **Image Package:** `linux-image-amd64` contains the bootable kernel binary and associated modules. 2. **Hardware warnings** (flavour-specific):
3. **Headers Dependency:** Although often implicit, the documentation mandates that `linux-headers-amd64` must be present for DKMS drivers to recompile successfully after a reboot. If these are missing, external drivers may fail to load until manually rebuilt against the new headers. - **Backports + NVIDIA** (`GPU_TYPE == "nvidia"`): `_confirm "Kernel" "WARNING: Backports kernel changes the kernel version. Your NVIDIA driver will need recompilation (DKMS)."`. Users can still proceed — DKMS will rebuild on next boot if headers match.
- **RT + NVIDIA**: `_msg "Kernel — RT" "Ensure your NVIDIA driver supports the RT kernel. Some proprietary drivers may not work correctly."`. Not a blocker, but informs that some closed drivers fail with PREEMPT_RT.
3. **Version resolution** for the confirmation dialog:
This synchronized approach ensures that when the system boots into the new kernel, all dependent modules have access to the correct symbol tables and build environment provided by the matching headers. ```bash
# Backports path
ver=$(apt-cache madison linux-image-amd64 | grep trixie-backports | awk '{print $3}' | head -1)
headers_ver=$(apt-cache madison linux-headers-amd64 | grep trixie-backports | awk '{print $3}' | head -1)
# Stable/RT/Cloud path
ver=$(apt-cache show linux-image-amd64 | sed -n 's/^Version: //p' | grep -v '~bpo' | head -1)
```
### 3. Safety Mechanisms and Atomic Operation The dialog shows `Image: linux-image-amd64 (6.12.22-1)` + `Headers: linux-headers-amd64 (6.12.22-1)` + `From: Trixie-backports` when a backports flag is present.
4. **User confirmation** — `whiptail --yesno "Install Backports kernel? Image: ... Headers: ..."` with the version string. Declining aborts with `Skipping.`.
5. **Atomic install**:
To prevent boot loops or system instability, `kernel.sh` implements several safety checks before executing any installation commands: ```bash
sudo apt install -y [-t trixie-backports] linux-image-amd64 linux-headers-amd64
sudo apt install -y linux-image-rt-amd64 linux-headers-rt-amd64
sudo apt install -y linux-image-cloud-amd64 linux-headers-cloud-amd64
```
* **Pre-flight Repository Validation:** Both image and headers are passed in a **single `apt` transaction**. This guarantees the symbol tables match and DKMS can rebuild. The helper `_run_cmd "Kernel"` prints the command, captures the exit code, and pauses for the user to review output.
The function begins with a strict check using `is_backports_enabled()`. If the backports repository is not active in `/etc/apt/sources.list`, the script halts and instructs the user to enable it via Option 3. This prevents accidental dependency conflicts or installation failures due to missing sources. 6. **Post-install** — prints `Backports kernel installed. Reboot to use it.` and pauses. The new kernel is added to `/boot` alongside the old one; GRUB will show both at next boot. The script does not remove the old kernel — rollback is simply rebooting into the previous entry.
* **Hardware Compatibility Warnings:** ---
The script detects if an NVIDIA GPU is present (`GPU_TYPE == "nvidia"`). In this scenario, a warning is displayed: *"WARNING: may break NVIDIA driver."*. This alerts the user that proprietary drivers might require DKMS recompilation against the new headers.
* **Bootloader Update (GRUB):** ## 4. Menu Logic: `show_kernel_menu`
Although not explicitly shown in the minimal `kernel.sh` snippet provided, standard kernel engineering practice dictates that after a successful installation, the bootloader must be updated to register the new entry:
```bash
sudo update-grub
```
This ensures the new kernel appears in the GRUB menu and can be set as the default.
* **Fallback Preservation:** ```bash
The script does not remove the previous kernel. Debian's package manager retains older kernels, preserving them in `/boot`. If the new backports kernel fails to boot (e.g., due to a hardware incompatibility), the user can simply select the previous stable version from the GRUB menu during startup. This "Rollback Safety" is inherent to the Debian Stable model and is reinforced by the script's non-destructive installation approach. show_kernel_menu() {
while true; do
items=("stable" "Install linux-image-amd64")
[ "$DEBIAN_VERSION" = "13" ] && items+=("backports" "Install from backports")
items+=("rt" "Install linux-image-rt-amd64 (Preempt-RT)")
items+=("cloud" "Install linux-image-cloud-amd64")
items+=("back" "Return to main menu")
choice=$(whiptail --menu "Kernel Installation" "Select kernel variant:" 16 65 5 "${items[@]}")
### 4. Critical Interconnection with Other Modules (Script Ecosystem) case "$choice" in
stable) _install_kernel_package "linux-image-amd64" "Stable" "" ;;
backports)
if [ "$(is_backports_enabled)" != "true" ]; then
whiptail --msgbox "Backports repository is not enabled.\nUse option 4 (Configure repositories) to enable backports before installing."
else
_install_kernel_package "linux-image-amd64" "Backports" "-t ${DEBIAN_CODENAME}-backports"
fi ;;
rt) _install_kernel_package "linux-image-rt-amd64" "RT" "" ;;
cloud) _install_kernel_package "linux-image-cloud-amd64" "Cloud" "" ;;
back) break ;;
esac
done
}
```
The Backports Kernel module does not operate in isolation; it relies on a tightly coupled ecosystem within `debianito.sh` to ensure full functionality: Key details:
* **Option 4: Firmware & Wireless Drivers:** - **Backports visibility** — The `backports` entry is only appended when `DEBIAN_VERSION == 13`. On Bullseye/Bookworm it does not appear.
New kernels often introduce support for new hardware IDs, but they require corresponding firmware blobs (e.g., `firmware-misc-nonfree`). If the user installs Kernel 7.0+ without updating their firmware repository, wireless cards or specific storage controllers may remain unfunctional. The script ensures that Option 4 is logically dependent on a compatible kernel state. - **Backports guard** — Selecting `backports` without backports enabled shows a message pointing to **Option 4 (Configure Repositories)**. No install is attempted.
- **Loop** — The menu is a `while true` loop; the user can install multiple variants sequentially (e.g., Stable + RT) before returning with `back` or `ESC`.
* **Option 5: Graphics Drivers (NVIDIA DKMS):** ---
For systems with NVIDIA hardware, the installation of a new kernel triggers a dependency chain for `nvidia-dkms`. If the user has proprietary drivers installed, they must be recompiled against the new headers provided by the backports kernel. The script's detection logic (`HAS_NVIDIA`) allows it to warn users or trigger DKMS rebuilds automatically if integrated into a larger workflow.
* **Bullseye-Specific Logic:** ## 5. Safety Mechanisms
As seen in `debianito.sh`, the Backports Kernel module is conditionally loaded based on the Debian version:
```bash
if [ "$DEBIAN_VERSION" = "11" ]; then
_msg "Not Available" ...
else
install_kernel_backports || true
fi
```
This ensures that legacy systems (Debian 11 Bullseye) do not attempt to use a backports workflow that may not be supported or stable in older architectures, while newer versions (Bookworm/Trixie) utilize the full feature set.
* **Gaming & Extras:** | Mechanism | How It Works |
The Backports kernel is often recommended for gaming due to improved scheduler performance and low-latency networking features found in Linux 7.0+. By linking Option 6 with `gaming.sh`, users can ensure their hardware is tuned correctly before launching high-performance applications. | ----------- | -------------- |
| **Pre-flight `is_backports_enabled`** | `utils.sh:is_backports_enabled` greps `/etc/apt/sources.list` and `/etc/apt/sources.list.d/*.sources` / `*.list` for `trixie-backports`. Prevents `apt -t` from failing with `E: Release not found`. |
| **NVIDIA RT warning** | `utils.sh:GPU_TYPE` is set at startup by `detect_gpu` (lspci). RT kernels change scheduling semantics; some `nvidia.ko` builds reject `PREEMPT_RT`. |
| **Atomic image+headers** | Both packages in one `apt` call. If headers are missing, `dkms` will fail at boot — so they are never installed separately. |
| **Fallback preservation** | `apt` never removes the running kernel. `/boot` retains `vmlinuz-*` and `initrd.img-*` for both. GRUB keeps both entries; if the new kernel panics, select the old one. |
| **Version-aware messaging** | The confirmation dialog always shows the exact version string (`apt-cache madison` / `apt-cache show`) so users know they are not reinstalling the same package. |
GRUB update is **not** explicitly called — `linux-image-*` postinst triggers `update-grub` (or `kernel-install` on systemd-boot) automatically. If GRUB is broken, use **Option 12 (Boot Rescue + GRUB)** to rebuild it.
---
## 6. Interconnection with Other Modules
- **Option 4: Repositories** — Must enable `trixie-backports` before `Kernel → backports` is usable. The kernel menu explicitly checks `is_backports_enabled` and directs the user there if missing.
- **Option 5: Firmware** — Newer kernels expose new hardware IDs (e.g., `8086:7e40` for Panther Lake). Without updated `firmware-linux-nonfree` or `firmware-iwlwifi`, the new kernel will show the device but fail to load firmware. Run Firmware after a kernel upgrade if WiFi/storage is not recognized.
- **Option 6: Graphics Drivers** — NVIDIA `dkms` needs the exact `linux-headers-*` version. The atomic install ensures headers match. On Bookworm the NVIDIA path deliberately avoids backports kernels; on Trixie a backports kernel + Maxwell/Pascal GPU is forced to the stable NVIDIA driver (`v550`) to avoid `v590` incompatibility.
- **Gaming (`gaming.sh`)** — The backports kernel is sometimes recommended for gaming (scheduler latency, `SCHED_EXT`), but not required. Benchmarks show <3% difference for most titles; enable it only for newer hardware that needs it.
---
## 7. Verification After Installation
```bash
uname -r # Should show the new kernel after reboot
dpkg -l linux-image-amd64 | grep ^ii
dpkg -l linux-headers-amd64 | grep ^ii
ls -l /boot/vmlinuz-* # Both old and new kernels present
grep -E 'menuentry' /boot/grub/grub.cfg | head -5 # GRUB entries
```
If the new kernel fails to boot, hold `ESC` (or `Shift` on BIOS) at power-on, select **Advanced options for Debian** → previous kernel version.
---
## References
- [Debian Backports — backports.debian.org](https://backports.debian.org/)
- [Debian Kernel Handbook](https://kernel-handbook.alioth.debian.org/)
- [PREEMPT_RT — wiki.debian.org/RealTime](https://wiki.debian.org/RealTime)
- [Installing a new kernel — wiki.debian.org/DebianKernel](https://wiki.debian.org/DebianKernel)
+25 -6
View File
@@ -1,10 +1,11 @@
## Option 3: Advanced Repository Configuration # Option 4: Repository Configuration
### 1. What Does This Component Do? ### 1. What Does This Component Do?
The repository configuration module is the foundational engine of Debianito that establishes and maintains a secure, up-to-date package management environment for your Debian system. It performs **idempotent, atomic operations** to configure APT sources with precision while protecting against corruption through automatic rollback mechanisms. The repository configuration module is the foundational engine of Debianito that establishes and maintains a secure, up-to-date package management environment for your Debian system. It performs **idempotent, atomic operations** to configure APT sources with precision while protecting against corruption through automatic rollback mechanisms.
At its core, this component: At its core, this component:
- Detects your current repository format (Classic `.list` vs modern DEB822 `.sources`) - Detects your current repository format (Classic `.list` vs modern DEB822 `.sources`)
- Backs up existing configurations before any modifications - Backs up existing configurations before any modifications
- Enables critical non-free components required for hardware drivers and proprietary software - Enables critical non-free components required for hardware drivers and proprietary software
@@ -20,19 +21,23 @@ This is not just about "adding repositories"—it's about **system integrity ass
The script intelligently adapts to your Debian version and existing repository structure: The script intelligently adapts to your Debian version and existing repository structure:
#### Classic Format (`/etc/apt/sources.list`) #### Classic Format (`/etc/apt/sources.list`)
- **Structure**: Human-readable text with `deb` lines - **Structure**: Human-readable text with `deb` lines
- **Use Case**: Debian 11 (Bullseye) through Debian 12 (Bookworm) default - **Use Case**: Debian 11 (Bullseye) through Debian 12 (Bookworm) default
- **Characteristics**: Linear, comment-friendly, widely understood by all APT tools - **Characteristics**: Linear, comment-friendly, widely understood by all APT tools
- **Example**: - **Example**:
```bash ```bash
deb https://deb.debian.org/debian bookworm main contrib non-free non-free-firmware deb https://deb.debian.org/debian bookworm main contrib non-free non-free-firmware
``` ```
#### Modern DEB822 Format (`/etc/apt/sources.list.d/debian.sources`) #### Modern DEB822 Format (`/etc/apt/sources.list.d/debian.sources`)
- **Structure**: Declarative YAML-like format with `Types`, `URIs`, and `Suites` blocks - **Structure**: Declarative YAML-like format with `Types`, `URIs`, and `Suites` blocks
- **Use Case**: Debian 13 (Trixie) default, future-proofing for newer releases - **Use Case**: Debian 13 (Trixie) default, future-proofing for newer releases
- **Characteristics**: Machine-parseable, structured, supports complex repository hierarchies - **Characteristics**: Machine-parseable, structured, supports complex repository hierarchies
- **Example**: - **Example**:
```yaml ```yaml
Types: deb Types: deb
URIs: https://deb.debian.org/debian URIs: https://deb.debian.org/debian
@@ -41,7 +46,9 @@ Components: main contrib non-free non-free-firmware
``` ```
#### Migration Logic #### Migration Logic
The script automatically detects your current format and offers migration options: The script automatically detects your current format and offers migration options:
- On Debian 13 (Trixie): Prompts to migrate TO DEB822 or stay with Classic - On Debian 13 (Trixie): Prompts to migrate TO DEB822 or stay with Classic
- Format changes are atomic—backup is created before any modification - Format changes are atomic—backup is created before any modification
- Old files are renamed with `.disabled` extension rather than deleted - Old files are renamed with `.disabled` extension rather than deleted
@@ -52,7 +59,6 @@ The script automatically detects your current format and offers migration option
The `configure_repos()` function in `repos.sh` executes the following sequence: The `configure_repos()` function in `repos.sh` executes the following sequence:
```bash ```bash
┌─────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────┐
│ INITIAL DETECTION PHASE │ │ INITIAL DETECTION PHASE │
@@ -111,6 +117,11 @@ The `configure_repos()` function in `repos.sh` executes the following sequence:
│ ├── Creates appropriate file(s) │ ├── Creates appropriate file(s)
│ └── Includes main + backports if enabled │ │ └── Includes main + backports if enabled │
│ │ │ │
│ 8b. Branch Migration (if applicable)
│ ├── _write_branch_sources() → writes new branch sources │
│ ├── If failure → _restore_backup() || true
│ └── return 1
│ │
│ 9. Update Package Lists │ │ 9. Update Package Lists │
│ └── sudo apt update │ │ └── sudo apt update │
└─────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────┘
@@ -119,7 +130,6 @@ The `configure_repos()` function in `repos.sh` executes the following sequence:
│ POST-EXECUTION PHASE │ │ POST-EXECUTION PHASE │
├─────────────────────────────────────────────────────────────┤ ├─────────────────────────────────────────────────────────────┤
│ 10. Success Path │ │ 10. Success Path │
│ ├── REPOS_CONFIGURED=true
│ ├── Cleanup disabled files │ │ ├── Cleanup disabled files │
│ └── Optional: Upgrade system if packages available │ │ └── Optional: Upgrade system if packages available │
│ │ │ │
@@ -130,9 +140,11 @@ The `configure_repos()` function in `repos.sh` executes the following sequence:
``` ```
**Key Safety Mechanisms:** **Key Safety Mechanisms:**
- **Atomic Operations**: Backup created before any write operation - **Atomic Operations**: Backup created before any write operation
- **Idempotency Check**: `content_differs()` prevents unnecessary modifications - **Idempotency Check**: `content_differs()` prevents unnecessary modifications
- **Rollback on Failure**: If `apt update` fails, original configuration is restored - **Rollback on Failure**: If `apt update` fails, original configuration is restored via `restore_previous_repos()`
- **Branch Migration Rollback**: `_write_branch_sources()` failure triggers `_restore_backup() || true`
- **Disabled File Extension**: Old formats renamed with `.disabled` rather than deleted - **Disabled File Extension**: Old formats renamed with `.disabled` rather than deleted
--- ---
@@ -142,7 +154,7 @@ The `configure_repos()` function in `repos.sh` executes the following sequence:
The script enables specific APT component branches that are essential for hardware functionality and software availability: The script enables specific APT component branches that are essential for hardware functionality and software availability:
| Component | Purpose | Critical For | Debian Version Notes | | Component | Purpose | Critical For | Debian Version Notes |
|-----------|---------|--------------|---------------------| | ----------- | --------- | -------------- | --------------------- |
| **main** | Free, open-source software (Debian official) | All packages | Always enabled | | **main** | Free, open-source software (Debian official) | All packages | Always enabled |
| **contrib** | Free software that uses non-free components | Proprietary codecs, drivers | Enabled in all versions | | **contrib** | Free software that uses non-free components | Proprietary codecs, drivers | Enabled in all versions |
| **non-free** | Non-free firmware and proprietary software | NVIDIA GPU drivers, Wi-Fi firmware | Required for hardware support | | **non-free** | Non-free firmware and proprietary software | NVIDIA GPU drivers, Wi-Fi firmware | Required for hardware support |
@@ -161,12 +173,14 @@ deb https://deb.debian.org/debian bookworm main contrib non-free non-free-firmwa
``` ```
**Impact of Missing `non-free-firmware`:** **Impact of Missing `non-free-firmware`:**
- ❌ Wi-Fi adapters won't work without firmware blobs - ❌ Wi-Fi adapters won't work without firmware blobs
- ❌ Bluetooth devices may fail to initialize - ❌ Bluetooth devices may fail to initialize
- ❌ Some GPU drivers require proprietary microcode - ❌ Some GPU drivers require proprietary microcode
- ❌ Embedded hardware (Raspberry Pi, etc.) becomes unusable - ❌ Embedded hardware (Raspberry Pi, etc.) becomes unusable
The script ensures all four components are present because: The script ensures all four components are present because:
1. **Hardware Compatibility**: Modern Debian kernels depend on these for out-of-the-box functionality 1. **Hardware Compatibility**: Modern Debian kernels depend on these for out-of-the-box functionality
2. **Security Updates**: `non-free-firmware` receives security patches separately 2. **Security Updates**: `non-free-firmware` receives security patches separately
3. **Future-Proofing**: Newer hardware releases firmware in this component exclusively 3. **Future-Proofing**: Newer hardware releases firmware in this component exclusively
@@ -188,6 +202,7 @@ The backports integration is a sophisticated feature that enables access to newe
``` ```
**Return Values:** **Return Values:**
- `"standalone-deb822"` → Separate `.sources` file (recommended) - `"standalone-deb822"` → Separate `.sources` file (recommended)
- `"standalone-classic"` → Separate `.list` file - `"standalone-classic"` → Separate `.list` file
- `"embedded-deb822"` → Inside `debian.sources` - `"embedded-deb822"` → Inside `debian.sources`
@@ -231,7 +246,7 @@ The backports integration is a sophisticated feature that enables access to newe
The script includes a detailed explanation because backports enable critical features: The script includes a detailed explanation because backports enable critical features:
| Feature | Without Backports | With Backports | | Feature | Without Backports | With Backports |
|---------|-------------------|----------------| | --------- | ------------------- | ---------------- |
| **Linux Kernel** | Stable kernel only (e.g., 6.1-6.12) | Newer kernels (e.g., 6.x/7.x series) | | **Linux Kernel** | Stable kernel only (e.g., 6.1-6.12) | Newer kernels (e.g., 6.x/7.x series) |
| **GPU "Drivers"** | Latest Mesa from stable | Latest Mesa from testing | | **GPU "Drivers"** | Latest Mesa from stable | Latest Mesa from testing |
| **Wi-Fi Firmware** | Older firmware versions | Newest firmware for modern cards | | **Wi-Fi Firmware** | Older firmware versions | Newest firmware for modern cards |
@@ -240,6 +255,7 @@ The script includes a detailed explanation because backports enable critical fea
#### Backports Warning System #### Backports Warning System
The script includes safeguards: The script includes safeguards:
- Only enabled if user explicitly confirms - Only enabled if user explicitly confirms
- Warns about potential compatibility issues - Warns about potential compatibility issues
- Can be disabled anytime via Option 3 again - Can be disabled anytime via Option 3 again
@@ -250,6 +266,7 @@ The script includes safeguards:
### Technical Implementation Notes ### Technical Implementation Notes
**Idempotency Guarantee:** **Idempotency Guarantee:**
```bash ```bash
# content_differs() ensures no duplicate writes # content_differs() ensures no duplicate writes
if [ "$current" = "$generated" ]; then if [ "$current" = "$generated" ]; then
@@ -259,6 +276,7 @@ return 0 # Changes required
``` ```
**Atomic Backup Mechanism:** **Atomic Backup Mechanism:**
```bash ```bash
backup_current_repos() { backup_current_repos() {
REPO_BACKUP_DIR=$(mktemp -d) REPO_BACKUP_DIR=$(mktemp -d)
@@ -276,6 +294,7 @@ restore_previous_repos() {
**Component Activation Pattern:** **Component Activation Pattern:**
All four components are written in a single operation to prevent partial configurations: All four components are written in a single operation to prevent partial configurations:
```bash ```bash
Components: main contrib non-free non-free-firmware # Atomic write Components: main contrib non-free non-free-firmware # Atomic write
# Not written as separate lines to avoid merge conflicts # Not written as separate lines to avoid merge conflicts
+54 -49
View File
@@ -1,72 +1,77 @@
## Option 9: Swap # Option 10: Swap Management
### 1. What does this component do? ### 1. What does this component do?
This module is responsible for the secure management of disk-based swap space within the `debianito` environment. Unlike standard Linux tools that might overwrite existing configurations or conflict with memory compression features (like ZRAM), this script operates as a **priority-aware, persistent swap manager**. This module is responsible for the secure management of disk-based swap space within the `debianito` environment. Unlike standard Linux tools that might overwrite existing configurations or conflict with memory compression features (like ZRAM), this script operates as a **priority-aware, persistent swap manager**.
Its primary functions include: Its primary functions include:
* **Dynamic Allocation:** Creating and resizing swapfiles based on detected RAM capacity without requiring physical partition changes.
* **Priority Integration:** Explicitly setting the swap priority (`pri=10`) to ensure it sits below ZRAM (which uses `priority=100`). This prevents the system from using disk I/O for memory swapping until compressed RAM is exhausted, optimizing performance. * **Dynamic Allocation:** Creating and resizing swapfiles based on detected RAM capacity without requiring physical partition changes.
* **Persistence Management:** Safely editing `/etc/fstab` with a unique tag (`# debianito-managed-swap`) to ensure swap survives reboots without corrupting manual entries. * **Priority Integration:** Explicitly setting the swap priority (`pri=10`) to ensure it sits below ZRAM (which uses `priority=100`). This prevents the system from using disk I/O for memory swapping until compressed RAM is exhausted, optimizing performance.
* **Safety Locking:** Prevents concurrent operations using file locking mechanisms to avoid race conditions during active system usage. * **Persistence Management:** Safely editing `/etc/fstab` with a unique tag (`# debianito-managed-swap`) to ensure swap survives reboots without corrupting manual entries.
* **Safety Locking:** Prevents concurrent operations using file locking mechanisms to avoid race conditions during active system usage.
### 2. How does it work? ### 2. How does it work?
The script leverages several advanced Linux subsystems and safety protocols: The script leverages several advanced Linux subsystems and safety protocols:
1. **File System Detection:** It identifies the filesystem type of the target partition (e.g., `ext4`, `btrfs`). For Btrfs, it applies specific flags (`chattr +C` for copy-on-write optimization) to prevent performance degradation during swap operations. 1. **File System Detection:** It identifies the filesystem type of the target partition (e.g., `ext4`, `btrfs`). For Btrfs, it applies specific flags (`chattr +C` for copy-on-write optimization) to prevent performance degradation during swap operations.
2. **Allocation Strategy:** It prefers `fallocate` for instant space reservation on supported filesystems, falling back to `dd if=/dev/zero` for compatibility or zeroing requirements (like Btrfs). 2. **Allocation Strategy:** It prefers `fallocate` for instant space reservation on supported filesystems, falling back to `dd if=/dev/zero` for compatibility or zeroing requirements (like Btrfs).
3. **Fstab Validation:** Before writing changes to `/etc/fstab`, it creates a temporary file and validates the syntax using `findmnt --verify`. If validation fails, the script aborts and restores the original state. 3. **Fstab Validation:** Before writing changes to `/etc/fstab`, it creates a temporary file and validates the syntax using `findmnt --verify`. If validation fails, the script aborts and restores the original state.
4. **Concurrency Control:** It utilizes `flock` on `/run/lock/debianito-swap.lock`. This ensures that if another process is modifying swap settings (e.g., a system update), this script will wait or exit gracefully to prevent filesystem corruption. 4. **Concurrency Control:** It utilizes `flock` on `/run/lock/debianito-swap.lock`. This ensures that if another process is modifying swap settings (e.g., a system update), this script will wait or exit gracefully to prevent filesystem corruption.
5. **Swappiness Tuning:** It configures `vm.swappiness` via both runtime (`sysctl -w`) and persistent (`/etc/sysctl.d/99-swappiness-debianito.conf`) mechanisms, defaulting to values that favor RAM usage over disk swapping (e.g., 10-20). 5. **Swappiness Tuning:** It configures `vm.swappiness` via both runtime (`sysctl -w`) and persistent (`/etc/sysctl.d/99-swappiness-debianito.conf`) mechanisms, defaulting to values that favor RAM usage over disk swapping (e.g., 10-20).
### 3. The Logical Decision Tree (Step by Step) ### 3. The Logical Decision Tree (Step by Step)
The execution flow follows a strict logical tree designed for safety and idempotency: The execution flow follows a strict logical tree designed for safety and idempotency:
1. **Initialization & Locking:** 1. **Initialization & Locking:**
* The `manage_swap()` function attempts to acquire an exclusive lock (`flock -n`). If the lock is held by another process, it immediately exits with a "Busy" message to prevent conflicts. * The `manage_swap()` function attempts to acquire an exclusive lock (`flock -n`). If the lock is held by another process, it immediately exits with a "Busy" message to prevent conflicts.
2. **Menu Selection Loop:** 2. **Menu Selection Loop:**
* Enters a continuous loop presenting options (Status, Create, Remove, Swappiness). * Enters a continuous loop presenting options (Status, Create, Remove, Swappiness).
* Breaks only when the user selects "Back to main menu". * Breaks only when the user selects "Back to main menu".
3. **Action Execution Paths:** 3. **Action Execution Paths:**
* **Path A: Status Check (`_swap_current_status`)** * **Path A: Status Check (`_swap_current_status`)**
* Reads active swap entries via `swapon --show`. * Reads active swap entries via `swapon --show`.
* Reads current swappiness from `/proc/sys/vm/swappiness`. * Reads current swappiness from `/proc/sys/vm/swappiness`.
* Parses `/etc/fstab` for managed tags. * Parses `/etc/fstab` for managed tags.
* **Path B: Create/Resize (`_swap_create_file`)** * **Path B: Create/Resize (`_swap_create_file`)**
* **Recommendation:** Calculates optimal size based on RAM (e.g., 2GB for >16GB RAM, 4GB for 8-16GB). * **Recommendation:** Calculates optimal size based on RAM (e.g., 2GB for >16GB RAM, 4GB for 8-16GB).
* **Btrfs Check:** If the filesystem is Btrfs, it warns about `nodatacow` requirements and hibernation limitations. * **Btrfs Check:** If the filesystem is Btrfs, it warns about `nodatacow` requirements and hibernation limitations.
* **Existence Check:** If `/swapfile` exists, it prompts to confirm recreation (deleting old data first via `swapoff`). * **Existence Check:** If `/swapfile` exists, it prompts to confirm recreation (deleting old data first via `swapoff`).
* **Allocation:** Uses `fallocate` or `dd` to zero the file. Sets permissions (`chmod 600`) and initializes swap (`mkswap`). * **Allocation:** Uses `fallocate` or `dd` to zero the file. Sets permissions (`chmod 600`) and initializes swap (`mkswap`).
* **Persistence:** Attempts to write the new entry to `/etc/fstab`. If validation fails, it cleans up (removes file) before exiting. * **Persistence:** Attempts to write the new entry to `/etc/fstab`. If validation fails, it cleans up (removes file) before exiting.
* **Path C: Remove (`_swap_remove_file`)** * **Path C: Remove (`_swap_remove_file`)**
* Checks for the unique `SWAP_FSTAB_TAG` in fstab. * Checks for the unique `SWAP_FSTAB_TAG` in fstab.
* Confirms user intent to delete. * Confirms user intent to delete.
* Executes `swapoff`, removes the fstab line, and deletes the physical file. * Executes `swapoff`, removes the fstab line, and deletes the physical file.
* **Path D: Swappiness (`_swap_set_swappiness`)** * **Path D: Swappiness (`_swap_set_swappiness`)**
* Validates input (0-100 integer). * Validates input (0-100 integer).
* Writes a temporary sysctl config file. * Writes a temporary sysctl config file.
* Applies changes immediately via `sysctl -w`. * Applies changes immediately via `sysctl -w`.
### 4. What does each menu item do and what does it mean? ### 4. What does each menu item do and what does it mean?
Each option in the swap management submenu serves a specific technical purpose: Each option in the swap management submenu serves a specific technical purpose:
* **Option 1: Show current swap & swappiness** * **Option 1: Show current swap & swappiness**
* **Technical Action:** Aggregates data from `/proc/swaps`, `/proc/sys/vm/swappiness`, and `/etc/fstab`. * **Technical Action:** Aggregates data from `/proc/swaps`, `/proc/sys/vm/swappiness`, and `/etc/fstab`.
* **Significance:** Provides an audit trail of the current memory management state. It verifies if ZRAM is active (implied by priority check) and how much disk swap is currently in use. * **Significance:** Provides an audit trail of the current memory management state. It verifies if ZRAM is active (implied by priority check) and how much disk swap is currently in use.
* **Option 2: Create / resize swapfile** * **Option 2: Create / resize swapfile**
* **Technical Action:** Allocates a new block device file (`/swapfile`) or expands an existing one. Sets the `pri=10` flag to ensure it acts as a secondary memory layer after ZRAM fills up. * **Technical Action:** Allocates a new block device file (`/swapfile`) or expands an existing one. Sets the `pri=10` flag to ensure it acts as a secondary memory layer after ZRAM fills up.
* **Significance:** Essential for systems with low RAM that need overflow protection without installing physical partitions. The "Resize" capability allows adapting to new hardware configurations dynamically. * **Significance:** Essential for systems with low RAM that need overflow protection without installing physical partitions. The "Resize" capability allows adapting to new hardware configurations dynamically.
* **Option 3: Remove swapfile** * **Option 3: Remove swapfile**
* **Technical Action:** Disables the swapfile (`swapoff`), removes it from `/etc/fstab`, and deletes the file from disk. * **Technical Action:** Disables the swapfile (`swapoff`), removes it from `/etc/fstab`, and deletes the file from disk.
* **Significance:** Useful for troubleshooting, freeing up disk space (e.g., on SSDs where write cycles are a concern), or migrating to ZRAM-only configurations if RAM is sufficient. * **Significance:** Useful for troubleshooting, freeing up disk space (e.g., on SSDs where write cycles are a concern), or migrating to ZRAM-only configurations if RAM is sufficient.
* **Option 4: Change swappiness** * **Option 4: Change swappiness**
* **Technical Action:** Modifies the kernel parameter `vm.swappiness`. * **Technical Action:** Modifies the kernel parameter `vm.swappiness`.
* **Significance:** Controls the "aggressiveness" of swapping. A lower value (e.g., 10) tells the kernel to keep data in RAM longer, only using swap as a last resort. This is critical for desktop performance and battery life on laptops. * **Significance:** Controls the "aggressiveness" of swapping. A lower value (e.g., 10) tells the kernel to keep data in RAM longer, only using swap as a last resort. This is critical for desktop performance and battery life on laptops.
* **Option 5: Back to main menu** * **Option 5: Back to main menu**
* **Technical Action:** Releases the file lock (`exec 9>&-`) and terminates the submenu loop. * **Technical Action:** Releases the file lock (`exec 9>&-`) and terminates the submenu loop.
* **Significance:** Returns control to the user, ensuring no swap operations are running in the background before they navigate to other system configurations. * **Significance:** Returns control to the user, ensuring no swap operations are running in the background before they navigate to other system configurations.
+24 -11
View File
@@ -1,11 +1,20 @@
## Option 1: Hardware Detection & System Information # Option 1: Hardware Detection & System Information
### 1. What Does This Component Do? ### 1. What Does This Component Do?
This component serves as the **System Abstraction Layer** and diagnostic engine of the Debianito script. It is not merely a display utility; it acts as the foundational state initializer that runs prior to the main menu loop (`main_menu`). Its primary function is to perform pre-flight hardware enumeration, OS validation, and environment checks in "cold" mode (before any configuration changes are made). This component serves as the **System Abstraction Layer** and diagnostic engine of the Debianito script. It is not merely a display utility; it acts as the foundational state initializer that runs prior to the main menu loop (`main_menu`). Its primary function is to perform pre-flight hardware enumeration, OS validation, and environment checks in "cold" mode (before any configuration changes are made).
**Pre-flight initialization** (`debianito.sh` startup sequence):
1. **Dependency auto-install**: The script checks for `whiptail` and `lsb-release`, installing them automatically if missing — ensuring the TUI and version detection work on minimal systems.
2. **`lspci` guard and cache**: `command -v lspci &>/dev/null` validates availability before execution. If present, the full `lspci -nn` output is captured once into the global variable `LSPCI_OUTPUT`. All subsequent GPU, Ethernet, and network detection reads from this cache — avoiding redundant `lspci` invocations and ensuring consistent data throughout the session.
3. **APT update deduplication**: The helper `_ensure_apt_updated` prevents redundant `apt update` calls by tracking whether the package lists have been refreshed recently. This is critical for performance when multiple modules (repos, firmware, GPU, kernel) each need to verify repository state.
4. **State refresh flag**: `STATE_REFRESHED=true` is set before `;;` in every `case` branch of the main menu loop, ensuring that each menu entry starts with a clean, consistent state rather than stale cached data.
By populating global variables such as `DEBIAN_VERSION`, `GPU_TYPE`, `CPU_SUMMARY`, and network interface states, it ensures that the subsequent menu options have access to accurate context. This prevents the user from making blind decisions—for example, attempting to install proprietary drivers on a system without detected hardware or selecting repositories incompatible with the current Debian codename. It transforms raw kernel data into actionable configuration parameters. By populating global variables such as `DEBIAN_VERSION`, `GPU_TYPE`, `CPU_SUMMARY`, and network interface states, it ensures that the subsequent menu options have access to accurate context. This prevents the user from making blind decisions—for example, attempting to install proprietary drivers on a system without detected hardware or selecting repositories incompatible with the current Debian codename. It transforms raw kernel data into actionable configuration parameters.
### 2. System Commands Used (Technical Mapping) ### 2. System Commands Used (Technical Mapping)
The following table details the native Linux tools and file descriptors utilized by `utils.sh` to extract specific diagnostic data points. This mapping demonstrates reliance on standard, non-intrusive system utilities rather than proprietary binaries. The following table details the native Linux tools and file descriptors utilized by `utils.sh` to extract specific diagnostic data points. This mapping demonstrates reliance on standard, non-intrusive system utilities rather than proprietary binaries.
| Feature | Command / Tool | Technical Purpose & Logic | | Feature | Command / Tool | Technical Purpose & Logic |
@@ -13,24 +22,28 @@ The following table details the native Linux tools and file descriptors utilized
| **OS Version** | `lsb_release -cs`, `/etc/os-release` | Parses `VERSION_CODENAME` to determine Debian release (Bullseye, Bookworm, Trixie). Critical for selecting correct repository backports. | | **OS Version** | `lsb_release -cs`, `/etc/os-release` | Parses `VERSION_CODENAME` to determine Debian release (Bullseye, Bookworm, Trixie). Critical for selecting correct repository backports. |
| **CPU Info** | `/proc/cpuinfo` | Reads `model name` and counts cores/threads. Provides cosmetic summary without needing heavy tools like `lscpu`. | | **CPU Info** | `/proc/cpuinfo` | Reads `model name` and counts cores/threads. Provides cosmetic summary without needing heavy tools like `lscpu`. |
| **Memory** | `/proc/meminfo` | Extracts `MemTotal` to calculate RAM in GB. Used for compatibility warnings with specific software packages. | | **Memory** | `/proc/meminfo` | Extracts `MemTotal` to calculate RAM in GB. Used for compatibility warnings with specific software packages. |
| **GPU Detection** | `lspci -nn`, `nvidia-smi` | Identifies VGA/3D controllers via PCI IDs (`10de` for NVIDIA). Checks driver versions via `dpkg` if `nvidia-smi` fails. | | **GPU Detection** | `command -v lspci` guard → cached `LSPCI_OUTPUT` | `lspci -nn` output is cached in the global variable `LSPCI_OUTPUT` at startup. All subsequent GPU detection (PCI/USB buses, Ethernet, network) reads from this cache instead of re-running `lspci`. Identifies VGA/3D controllers via PCI IDs (`10de` for NVIDIA). Checks driver versions via `dpkg` if `nvidia-smi` fails. |
| **Network (Eth)** | `ip -o link show` | Enumerates Ethernet interfaces, state (UP/DOWN), and IP addresses using the `iproute2` suite. | | **Network (Eth)** | `ip -o link show` | Enumerates Ethernet interfaces, state (UP/DOWN), and IP addresses using the `iproute2` suite. |
| **Network (Wi-Fi)** | `iwgetid`, `lspci` | Identifies wireless chipsets via PCI and retrieves SSID/Connection status for network diagnostics. | | **Network (Wi-Fi)** | `iwgetid`, `lspci` | Identifies wireless chipsets via PCI and retrieves SSID/Connection status for network diagnostics. |
| **Storage** | `lsblk -d -o NAME,SIZE,ROTA` | Distinguishes between NVMe (`nvme`), SSD (RoT=0), and HDD (RoT=1) to provide storage topology summary. | | **Storage** | `lsblk -d -o NAME,SIZE,ROTA` | Distinguishes between NVMe (`nvme`), SSD (RoT=0), and HDD (RoT=1) to provide storage topology summary. |
| **Display Server**| Environment Vars (`XDG_SESSION_TYPE`) | Checks `WAYLAND_DISPLAY` vs `DISPLAY` variables to determine if the system is running Wayland, X11, or TTY. | | **Display Server** | Environment Vars (`XDG_SESSION_TYPE`) | Checks `WAYLAND_DISPLAY` vs `DISPLAY` variables to determine if the system is running Wayland, X11, or TTY. |
### 3. Strategic Importance for the Script ### 3. Strategic Importance for the Script
This diagnostic phase is vital for engineering stability and user experience (UX) integrity within the script architecture: This diagnostic phase is vital for engineering stability and user experience (UX) integrity within the script architecture:
* **Context-Aware Configuration:** The detection of `HAS_NVIDIA`, `HAS_AMD`, or `HAS_INTEL` directly dictates which sub-modules are loaded in `debianito.sh`. If no GPU is detected, graphics driver menus are skipped. This prevents "false positive" installation prompts that confuse the user. * **Context-Aware Configuration:** The detection of `HAS_NVIDIA`, `HAS_AMD`, or `HAS_INTEL` directly dictates which sub-modules are loaded in `debianito.sh`. If no GPU is detected, graphics driver menus are skipped. This prevents "false positive" installation prompts that confuse the user.
* **Repository Compatibility Guardrails:** The `detect_debian_version` function validates the OS against supported codenames (11, 12, 13). It specifically triggers Bullseye-specific logic (`configure_repos_bullseye`) only when necessary, preventing repository errors on newer or older distributions. * **Repository Compatibility Guardrails:** The `detect_debian_version` function validates the OS against supported codenames (11, 12, 13). It specifically triggers Bullseye-specific logic (`configure_repos_bullseye`) only when necessary, preventing repository errors on newer or older distributions.
* **Time Synchronization Safety:** The `check_system_time` function prevents package installation failures caused by clock skew (which breaks GPG signatures in APT). By offering an automated NTP sync before proceeding, it ensures the integrity of the entire software supply chain within the script. * **APT Update Deduplication:** The `_ensure_apt_updated` helper tracks whether `apt update` has been run recently. Multiple modules (repos, firmware, GPU, kernel) share a single update cycle, preventing redundant network calls and inconsistent package state between modules.
* **Root/Sudo Enforcement:** Early execution of `check_root` and `check_sudo` enforces security best practices. It prevents accidental privilege escalation or silent failures that often occur when scripts run with incorrect permissions. * **State Refresh Consistency:** `STATE_REFRESHED=true` is set before `;;` in every `case` branch of the main menu loop, ensuring each menu entry starts with a clean state and preventing stale variable propagation between sequential selections.
* **Time Synchronization Safety:** The `check_system_time` function prevents package installation failures caused by clock skew (which breaks GPG signatures in APT). By offering an automated NTP sync before proceeding, it ensures the integrity of the entire software supply chain within the script.
* **Root/Sudo Enforcement:** Early execution of `check_root` and `check_sudo` enforces security best practices. It prevents accidental privilege escalation or silent failures that often occur when scripts run with incorrect permissions.
### 4. Formatting and UX in the Terminal ### 4. Formatting and UX in the Terminal
The raw data collected by these functions is processed into a human-readable format before being passed to the TUI (Text User Interface) via `whiptail`. The raw data collected by these functions is processed into a human-readable format before being passed to the TUI (Text User Interface) via `whiptail`.
* **Structured String Assembly:** Functions like `_show_sysinfo` build multi-line strings (`msg+="...")`, appending newlines and conditional logic. This ensures that if multiple GPUs are found, they are listed sequentially with drivers identified below each entry. * **Structured String Assembly:** Functions like `_show_sysinfo` build multi-line strings (`msg+="...")`, appending newlines and conditional logic. This ensures that if multiple GPUs are found, they are listed sequentially with drivers identified below each entry.
* **Visual Hierarchy:** The data is organized into logical blocks (OS, Hardware, GPU, Network) with clear separators (`───`). This allows the user to quickly scan specific subsystems without scrolling through a monolithic log. * **Visual Hierarchy:** The data is organized into logical blocks (OS, Hardware, GPU, Network) with clear separators (`───`). This allows the user to quickly scan specific subsystems without scrolling through a monolithic log.
* **Conditional Rendering:** The script checks for command availability (e.g., `if ! command -v ip &>/dev/null`) before attempting to parse network data. If tools are missing, it gracefully degrades to a warning message rather than crashing the TUI. * **Conditional Rendering:** The script checks for command availability (e.g., `if ! command -v lspci &>/dev/null` guards GPU detection, `if ! command -v ip &>/dev/null` guards network data). If tools are missing, it gracefully degrades to a warning message rather than crashing the TUI. When `lspci` is present, its output is cached in `LSPCI_OUTPUT` for all subsequent detection calls.
* **TUI Integration:** The final formatted string is passed to `_msg`, which wraps the output in a `whiptail --msgbox`. This ensures the diagnostic information appears as a modal dialog with consistent dimensions and styling (colors defined globally in `debianito.sh`), maintaining a professional look regardless of the underlying terminal emulator. * **TUI Integration:** The final formatted string is passed to `_msg`, which wraps the output in a `whiptail --msgbox`. This ensures the diagnostic information appears as a modal dialog with consistent dimensions and styling (colors defined globally in `debianito.sh`), maintaining a professional look regardless of the underlying terminal emulator.
+216
View File
@@ -0,0 +1,216 @@
# Option 3: System Preferences
## 1. What Does This Component Do?
The **System Preferences** module (`modules/system/system_prefs.sh` + `modules/system/audio.sh`) consolidates first-boot personalization into a single menu. It is the only place in Debianito where **locale, timezone, and audio** are configured together — settings that Debian's installer often leaves at generic defaults and that affect every subsequent module.
It groups three independent preference domains behind one entry point:
| Sub-menu | Script | What It Configures |
| ---------- | -------- | --------------------- |
| **Date, Time & Timezone** | `system_prefs.sh:_prefs_date_time` | System clock, NTP sync, `tzdata` |
| **Language, Locales & Keyboard** | `system_prefs.sh:_prefs_locale_keyboard` | `locales`, `keyboard-configuration` |
| **Audio & Sound Stack** | `system/audio.sh:_prefs_audio_menu` | PipeWire, ALSA, pavucontrol, pulsemixer, playerctl |
The menu itself is `_system_preferences_menu` in `system_prefs.sh` — a simple `while true` loop with `whiptail --menu`:
```
1 Date, Time & Timezone
2 Language, Locales & Keyboard
3 Audio & Sound Stack
4 Back to main menu
```
> **Note:** This option was added after the initial repository setup. The main `README.md` menu previously started directly at "Configure Repositories". All Quick Start guides now reference System Preferences as Step 3.
---
## 2. Date, Time & Timezone
### Function: `_prefs_date_time` (`system_prefs.sh`)
```
Current system date/time: 2026-03-15 14:22
Timezone: America/Santiago
→ Confirm "Change the system timezone (dpkg-reconfigure tzdata)?"
→ sudo dpkg-reconfigure tzdata
→ _ensure_time_synced
```
**What it does technically:**
1. Prints the current date/time (`date '+%Y-%m-%d %H:%M'`) and timezone (`timedatectl show -p Timezone --value`).
2. Prompts via `_confirm "Timezone"` to run `sudo dpkg-reconfigure tzdata` — the Debian-standard interactive timezone selector (ncurses).
3. Calls `_ensure_time_synced` from `utils.sh` regardless of the answer:
- Forces `timedatectl set-ntp true`
- Validates the timezone is not `n/a` or `Etc/UTC`; if it is and a display is available, opens `tzdata` again
- Ensures `systemd-timesyncd` is installed, enabled and restarted
- Waits 2 seconds and checks `timedatectl show --property=NTPSynchronized --value` for `yes`
**Why it matters:** An incorrect clock breaks APT GPG verification (`Release file is not valid yet`) and TLS certificates. The script runs a similar check automatically at startup (`_ensure_time_synced` in `debianito.sh` line 108), but this menu allows the user to fix timezone manually without re-running the whole script.
---
## 3. Language, Locales & Keyboard
### Function: `_prefs_locale_keyboard` (`system_prefs.sh`)
```bash
sudo dpkg-reconfigure locales
sudo dpkg-reconfigure keyboard-configuration
```
**What it does technically:**
- **`dpkg-reconfigure locales`** — Opens the Debian locales selector (e.g., `en_US.UTF-8`, `es_CL.UTF-8`). Generates the selected locales via `locale-gen` and updates `/etc/default/locale`. No reboot is required, but a re-login is needed for the new `LANG` to take effect.
- **`dpkg-reconfigure keyboard-configuration`** — Configures `/etc/default/keyboard` (`XKBMODEL`, `XKBLAYOUT`, `XKBVARIANT`, `XKBOPTIONS`) and, on console, the keymap via `setupcon`. This affects both X11/Wayland and TTY.
Both commands are run with `env LC_ALL=C LANGUAGE=C` to guarantee the debconf dialogs render in English even when the current locale is broken.
This option has **no detection logic** — it delegates entirely to Debian's standard tools. It is idempotent and safe to run repeatedly.
---
## 4. Audio & Sound Stack
### Function: `_prefs_audio_menu` (`system/audio.sh`)
This is the most complex sub-menu. It presents a checklist built dynamically based on system state:
#### 4.1 Menu Construction
```bash
items+=("pipewire-audio" "PipeWire Audio Stack (Bluetooth Hi-Res)" $state)
items+=("alsa-utils" "ALSA Utilities (alsa-utils, alsa-ucm-conf)" $state)
# headless check — pavucontrol is GUI-only
if ! _is_headless; then
items+=("pavucontrol" "Volume Control GUI (pavucontrol)" $state)
fi
items+=("pulsemixer" "Terminal audio mixer (pulsemixer)" $state)
items+=("playerctl" "Multimedia key controller (playerctl)" $state)
```
- **`_state <pkg>`** (in `utils.sh`) returns `ON` if `dpkg -l <pkg>` shows `^ii`, otherwise `OFF`.
- **`_is_headless`** returns true when both `$DISPLAY` and `$WAYLAND_DISPLAY` are empty — in that case `pavucontrol` is hidden because it requires a GUI.
- Package name for PipeWire varies by Debian version:
- Debian 11 Bullseye → `pipewire` (the `pipewire-audio` metapackage does not exist)
- Debian 12/13 → `pipewire-audio`
The checklist is shown via `whiptail --checklist` with the title **"Audio & Sound"**.
#### 4.2 PipeWire Installation Logic: `_install_pipewire_standard`
This function handles the **PipeWire Audio Stack with Bluetooth Hi-Res codecs** — the core of modern Linux audio.
**Codec package resolution:**
```bash
bt_pkgs="libldacbt-abr2 libldacbt-enc2 libopenaptx0 libspa-0.2-bluetooth"
# Transitional package name: libfdk-aac2t64 on Trixie (64-bit time_t), libfdk-aac2 on older
if apt-cache show libfdk-aac2t64; then bt_pkgs+=" libfdk-aac2t64"
elif apt-cache show libfdk-aac2; then bt_pkgs+=" libfdk-aac2"
fi
```
These packages provide **LDAC** (Sony), **aptX** (Qualcomm), and **AAC** (via FDK) Bluetooth codecs that are not in the default PipeWire installation.
**Version selection (Trixie only, when backports is enabled):**
| Condition | Dialog | Effect |
| ----------- | -------- | -------- |
| Already installed + backports available | `Upgrade to backports vX?` (Yes/No) | `sudo apt install --reinstall -t trixie-backports pipewire-audio $bt_pkgs` + `systemctl --user restart wireplumber pipewire pipewire-pulse` |
| Not installed + backports available | `Backports vX` vs `Stable vY` (Backports/Stable buttons) | Installs from chosen repository; on Trixie `apt_target="-t trixie-backports"` if Backports chosen |
| No backports | `Install PipeWire vX with Hi-Res codecs?` | Installs from stable |
**Per-Debian-version install commands:**
```bash
# Debian 11 Bullseye
sudo apt install -y pipewire libspa-0.2-bluetooth pipewire-alsa libspa-0.2-jack $bt_pkgs
# Debian 12 Bookworm
sudo apt install -y pipewire-audio $bt_pkgs
# Debian 13 Trixie
sudo apt install -y [-t trixie-backports] pipewire-audio $bt_pkgs
```
After installation on Debian 12/13, user PipeWire services are restarted:
```bash
systemctl --user restart wireplumber pipewire pipewire-pulse
```
#### 4.3 Other Audio Packages
| Package | Purpose | Install Guard |
| --------- | --------- | --------------- |
| `alsa-utils` + `alsa-ucm-conf` | ALSA CLI tools (`aplay`, `amixer`, `alsamixer`) and UCM configs for modern sound cards | `is_installed alsa-utils` |
| `pavucontrol` | GTK GUI volume control (PulseAudio/PipeWire compatible). Hidden in headless mode. | `is_installed pavucontrol` |
| `pulsemixer` | Terminal (ncurses) mixer — works in TTY and headless | `is_installed pulsemixer` |
| `playerctl` | MPRIS CLI to control media players via keyboard shortcuts | `is_installed playerctl` |
Each package is installed via `_run_install <pkg>` which confirms the version via `apt-cache policy` before installing.
---
## 5. Logical Execution Flow
```
┌──────────────────────────────────────────────────────────┐
│ _system_preferences_menu (system_prefs.sh) │
├──────────────────────────────────────────────────────────┤
│ whiptail --menu "System Preferences" │
│ 1 Date, Time & Timezone │
│ 2 Language, Locales & Keyboard │
│ 3 Audio & Sound Stack │
│ 4 Back to main menu │
└──────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
_prefs_date_time _prefs_locale_ _prefs_audio
keyboard → _prefs_audio_menu
│ │ │
│ │ ┌───────┴────────┐
│ │ │ Dynamic checklist│
│ │ │ based on │
│ │ │ _state + headless│
│ │ └───────┬────────┘
│ │ │
│ │ pipewire-audio ──→ _install_pipewire_standard
│ │ alsa-utils ──→ apt install alsa-utils
│ │ pavucontrol ──→ apt install pavucontrol
│ │ pulsemixer ──→ apt install pulsemixer
│ │ playerctl ──→ apt install playerctl
```
---
## 6. Integration with Other Modules
- **Firmware (`firmware.sh`)** — Bluetooth firmware packages (`firmware-iwlwifi`, etc.) are separate from the Bluetooth *stack* (`bluez`). This menu complements firmware by ensuring the audio side of Bluetooth (PipeWire codecs) is ready.
- **Desktop & Display (`desktop_display.sh`)** — XFCE/LXDE installations often need audio configured afterwards. Running System Preferences → Audio after a new desktop ensures the correct mixer is available.
- **Gaming (`gaming.sh`)** — Many games require PipeWire/PulseAudio for voice chat. The gaming module assumes audio is already functional.
- **Time sync (`utils.sh:_ensure_time_synced`)** — Also called automatically at script startup. This menu is the manual override.
---
## 7. Detection & State Variables
| Variable / Function | Source | Used Here |
| --------------------- | -------- | ----------- |
| `DEBIAN_VERSION` (`11`/`12`/`13`) | `utils.sh:detect_debian_version` | PipeWire package name + install path |
| `AUDIO_SERVER` (`pipewire`/`pulseaudio`/`none`) | `utils.sh:detect_audio_server` | Bluetooth integration in `firmware.sh` |
| `is_backports_enabled` | `utils.sh:is_backports_enabled` | PipeWire backports version choice (Trixie) |
| `_is_headless` | `utils.sh:_is_headless` | Hides `pavucontrol` in TTY/SSH |
| `_state <pkg>` | `utils.sh:_state` | Checklist ON/OFF state |
| `_ensure_time_synced` | `utils.sh:_ensure_time_synced` | Called after timezone change |
---
## References
- [Debian TimeZone Config — wiki.debian.org/TimeZoneChanges](https://wiki.debian.org/TimeZoneChanges)
- [Debian Locales — wiki.debian.org/Locale](https://wiki.debian.org/Locale)
- [PipeWire — wiki.debian.org/PipeWire](https://wiki.debian.org/PipeWire)
- [PipeWire Bluetooth Codecs — GitLab PipeWire wiki](https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/FAQ#bluetooth)
+66 -51
View File
@@ -1,80 +1,95 @@
## Option 2: User Privileges & Feedback # Option 2: User Privileges & Feedback
### 1. What does this component do? ### 1. What does this component do?
This component serves as a centralized utility suite designed to streamline administrative access, enhance usability during system maintenance, and correct common permission inconsistencies found in fresh Debian installations or environments where `sudo` usage has been mishandled. It acts as an automated "First-Time User" setup tool that bridges the gap between strict Linux security policies (where standard users cannot modify system files) and practical daily workflow needs (such as installing software without constant password prompts). This component serves as a centralized utility suite designed to streamline administrative access, enhance usability during system maintenance, and correct common permission inconsistencies found in fresh Debian installations or environments where `sudo` usage has been mishandled. It acts as an automated "First-Time User" setup tool that bridges the gap between strict Linux security policies (where standard users cannot modify system files) and practical daily workflow needs (such as installing software without constant password prompts).
At a high level, it manages four critical aspects of user privilege: At a high level, it manages four critical aspects of user privilege:
1. **Elevated Permissions:** Ensures the current user has membership in the `sudo` group.
2. **Workflow Efficiency:** Configures specific commands to run without authentication (NOPASSWD) for maintenance tasks. 1. **Elevated Permissions:** Ensures the current user has membership in the `sudo` group.
3. **Data Integrity:** Repairs ownership issues on the home directory caused by accidental root-level file creation. 2. **Workflow Efficiency:** Configures specific commands to run without authentication (NOPASSWD) for maintenance tasks.
4. **User Experience:** Modifies terminal behavior during password entry to provide visual feedback. 3. **Data Integrity:** Repairs ownership issues on the home directory caused by accidental root-level file creation.
4. **User Experience:** Modifies terminal behavior during password entry to provide visual feedback.
### 2. What exactly does it do and why ### 2. What exactly does it do and why
The script executes a sub-menu loop that allows the user to toggle between four distinct configurations. Each option addresses a specific pain point in Linux administration: The script executes a sub-menu loop that allows the user to toggle between four distinct configurations. Each option addresses a specific pain point in Linux administration:
* **Sudo Group Membership (Option 1):** * **Sudo Group Membership (Option 1):**
* **Action:** Checks if the current username exists within the `/etc/group` file under the `sudo` group entry. If absent, it adds the user via `usermod -aG sudo`. * **Action:** Checks if the current username exists within the `/etc/group` file under the `sudo` group entry. If absent, it adds the user via `usermod -aG sudo`.
* **Why:** By default, Debian creates a standard user without administrative rights to prevent accidental system damage. This ensures the user can execute privileged commands (`sudo`) immediately after installation or recovery. * **Why:** By default, Debian creates a standard user without administrative rights to prevent accidental system damage. This ensures the user can execute privileged commands (`sudo`) immediately after installation or recovery.
* **Passwordless Sudo (Option 2):** * **Passwordless Sudo (Option 2):**
* **Action:** Creates an isolated configuration file in `/etc/sudoers.d/` containing `NOPASSWD` rules for specific binaries (e.g., `/usr/bin/apt`, `/sbin/reboot`). It enforces strict path matching to prevent privilege escalation risks. * **Action:** Creates an isolated configuration file in `/etc/sudoers.d/` containing `NOPASSWD` rules for specific binaries (e.g., `/usr/bin/apt`, `/sbin/reboot`). It enforces strict path matching to prevent privilege escalation risks.
* **Why:** Frequent password prompts interrupt workflows during updates or system reboots. This allows automation and quick access for maintenance tasks without compromising security on other commands. * **Why:** Frequent password prompts interrupt workflows during updates or system reboots. This allows automation and quick access for maintenance tasks without compromising security on other commands.
* **Repair Home Directory Ownership (Option 3):** * **Repair Home Directory Ownership (Option 3):**
* **Action:** Scans the user's home directory (`/home/$USER`) to verify if files are owned by `root` (UID 0) instead of the user. If a mismatch is found, it recursively resets ownership via `chown -R`. * **Action:** Scans the user's home directory (`/home/$USER`) to verify if files are owned by `root` (UID 0) instead of the user. If a mismatch is found, it recursively resets ownership via `chown -R`.
* **Why:** Misconfigured file permissions often occur when users attempt to fix issues using root privileges directly in their home folders. This restores data integrity so applications can read/write their own configuration files without permission errors. * **Why:** Misconfigured file permissions often occur when users attempt to fix issues using root privileges directly in their home folders. This restores data integrity so applications can read/write their own configuration files without permission errors.
* **Sudo Password Feedback (Option 4):** * **Sudo Password Feedback (Option 4):**
* **Action:** Toggles the `Defaults pwfeedback` directive within a dedicated sudoers file. When enabled, typing a password displays asterisks (`****`) instead of being hidden. * **Action:** Toggles the `Defaults pwfeedback` directive within a dedicated sudoers file. When enabled, typing a password displays asterisks (`****`) instead of being hidden.
* **Why:** Linux terminals hide input by default to prevent shoulder surfing. This option improves usability for users who need visual confirmation that their keystrokes are registering correctly, reducing the risk of typos in complex passwords. * **Why:** Linux terminals hide input by default to prevent shoulder surfing. This option improves usability for users who need visual confirmation that their keystrokes are registering correctly, reducing the risk of typos in complex passwords.
### 3. The Logical Decision Tree (Step-by-Step) ### 3. The Logical Decision Tree (Step-by-Step)
The execution flow is governed by `sudo_config.sh`, which acts as a state machine within the main menu loop. Below is the chronological logic for each option: The execution flow is governed by `sudo_config.sh`, which acts as a state machine within the main menu loop. Below is the chronological logic for each option:
**Entry Point:** **Entry Point:**
1. The script enters the `config_sudo()` function and loops until the user selects "Back to main menu".
2. It presents a Whiptail menu with options 15. 1. The script enters the `config_sudo()` function and loops until the user selects "Back to main menu".
2. It presents a Whiptail menu with options 15.
**Option 1: Sudo Group Membership (`_check_sudo_group`)** **Option 1: Sudo Group Membership (`_check_sudo_group`)**
* **Step A:** Execute `groups "$USER"` via pipe to grep for `\bsudo\b`.
* **Decision:** * **Step A:** Execute `groups "$USER"` via pipe to grep for `\bsudo\b`.
* *If Match:* Display success message ("User is already in sudo group"). Exit function. * **Decision:**
* *If No Match:* Prompt user with a confirmation dialog asking if they want to add the user to the `sudo` group. * *If Match:* Display success message ("User is already in sudo group"). Exit function.
* *On Confirm:* Execute `sudo usermod -aG sudo "$USER"`. If successful, display message instructing logout/login for changes to take effect. If failure, log error and return status 1. * *If No Match:* Prompt user with a confirmation dialog asking if they want to add the user to the `sudo` group.
* *On Confirm:* Execute `sudo usermod -aG sudo "$USER"`. If successful, display message instructing logout/login for changes to take effect. If failure, log error and return status 1.
**Option 2: Passwordless Sudo (`_configure_nopasswd`)** **Option 2: Passwordless Sudo (`_configure_nopasswd`)**
* **Step A:** Check if `/etc/sudoers.d/${USER}-nopasswd` exists.
* *If Exists:* Prompt to remove the configuration (restore password prompts). If confirmed, delete file and notify success. Return function. * **Step A:** Check if `/etc/sudoers.d/${USER}-nopasswd` exists.
* *If Not Exists:* Prompt user to configure NOPASSWD for maintenance commands. * *If Exists:* Prompt to remove the configuration (restore password prompts). If confirmed, delete file and notify success. Return function.
* *On Confirm:* Display a checklist menu allowing selection of `apt`, `systemctl`, or `power` commands. * *If Not Exists:* Prompt user to configure NOPASSWD for maintenance commands.
* **Step B:** Process selected commands: * *On Confirm:* Display a checklist menu allowing selection of `apt`, `systemctl`, or `power` commands.
* Construct the content string based on selections, explicitly defining paths (e.g., `/usr/bin/apt`, `/sbin/shutdown`) to ensure compatibility across Debian versions. * **Step B:** Process selected commands:
* **Step C:** Write configuration: * Construct the content string based on selections, explicitly defining paths (e.g., `/usr/bin/apt`, `/sbin/shutdown`) to ensure compatibility across Debian versions.
* Pipe content to `sudo tee /etc/sudoers.d/${USER}-nopasswd`. * **Step C:** Write configuration:
* Set file permissions to `0440` (readable only by root and owner). * Pipe content to `sudo tee /etc/sudoers.d/${USER}-nopasswd`.
* Notify success or failure. * Set file permissions to `0440` (readable only by root and owner).
* Notify success or failure.
**Option 3: Repair Home Directory Ownership (`_repair_home_ownership`)** **Option 3: Repair Home Directory Ownership (`_repair_home_ownership`)**
* **Step A:** Resolve the absolute path of `$HOME`. If directory does not exist, notify error and return status 1.
* **Step B:** Retrieve User ID (UID) using `id -u "$USER"`. * **Step A:** Resolve the home directory path securely using `getent passwd "${SUDO_USER:-$USER}"` instead of the legacy insecure `eval echo "~$USER"` pattern. This prevents command injection and ensures correct resolution across all shell environments:
* **Step C:** Check current owner UID of `$HOME` using `stat -c '%u'`.
* *If Match:* Notify that ownership is correct and exit. ```bash
* *If Mismatch:* Identify the expected username for the conflicting UID. Prompt user to confirm repair. home=$(getent passwd "${SUDO_USER:-$USER}" | cut -d: -f6)
* *On Confirm:* Execute `sudo chown -R "$USER:$USER" "$home"`. If successful, notify success. If failure, log error and return status 1. ```
* **Step B:** Retrieve User ID (UID) using `id -u "$USER"`.
* **Step C:** Check current owner UID of `$HOME` using `stat -c '%u'`.
* *If Match:* Notify that ownership is correct and exit.
* *If Mismatch:* Identify the expected username for the conflicting UID. Prompt user to confirm repair.
* *On Confirm:* Execute `sudo chown -R "$USER:$USER" "$home"`. If successful, notify success. If failure, log error and return status 1.
**Option 4: Sudo Password Feedback (`_toggle_pwfeedback`)** **Option 4: Sudo Password Feedback (`_toggle_pwfeedback`)**
* **Step A:** Check if `/etc/sudoers.d/pwfeedback` exists.
* *If Exists:* Prompt to disable asterisks (restore hidden input). If confirmed, delete file and notify success. Return function. * **Step A:** Check if `/etc/sudoers.d/pwfeedback` exists.
* *If Not Exists:* Prompt user to enable visual feedback. * *If Exists:* Prompt to disable asterisks (restore hidden input). If confirmed, delete file and notify success. Return function.
* *On Confirm:* Write `Defaults pwfeedback` to `/etc/sudoers.d/pwfeedback`. * *If Not Exists:* Prompt user to enable visual feedback.
* **Step B:** Verify write permission. If successful, notify success; otherwise, log error and return status 1. * *On Confirm:* Write `Defaults pwfeedback` to `/etc/sudoers.d/pwfeedback`.
* **Step B:** Verify write permission. If successful, notify success; otherwise, log error and return status 1.
### 4. Compatibility with all Debian ### 4. Compatibility with all Debian
This module is designed for universal compatibility across the Debian family (Bullseye, Bookworm, Trixie, etc.) due to its reliance on standard POSIX-compliant tools and strict path handling. This module is designed for universal compatibility across the Debian family (Bullseye, Bookworm, Trixie, etc.) due to its reliance on standard POSIX-compliant tools and strict path handling.
* **Architecture Independence:** The script utilizes `usermod`, `chown`, and `grep` which are available on all x86_64, arm64, and i386 Debian architectures. * **Architecture Independence:** The script utilizes `usermod`, `chown`, and `grep` which are available on all x86_64, arm64, and i386 Debian architectures.
* **Version Agnosticism (Debian 11+):** * **Version Agnosticism (Debian 11+):**
* **Sudoers Syntax:** The script writes to `/etc/sudoers.d/`, a directory introduced in `sudo` version 1.9.0p5 (available since Debian 7). It avoids editing the master file (`/etc/sudoers`) directly, preventing lockfile issues and syntax errors regardless of the specific Debian version's sudo configuration style. * **Sudoers Syntax:** The script writes to `/etc/sudoers.d/`, a directory introduced in `sudo` version 1.9.0p5 (available since Debian 7). It avoids editing the master file (`/etc/sudoers`) directly, preventing lockfile issues and syntax errors regardless of the specific Debian version's sudo configuration style.
* **Path Hardening:** The NOPASSWD logic explicitly includes both `/usr/bin` and `/bin` paths for commands like `apt`. This ensures that on older Debian versions (e.g., Bullseye) where binaries might reside in different locations or symlinks differ, the permissions remain valid. * **Path Hardening:** The NOPASSWD logic explicitly includes both `/usr/bin` and `/bin` paths for commands like `apt`. This ensures that on older Debian versions (e.g., Bullseye) where binaries might reside in different locations or symlinks differ, the permissions remain valid.
* **Security Best Practices:** By isolating configurations into separate files (`/etc/sudoers.d/`) and setting restrictive permissions (`0440`), it adheres to Debian's security guidelines for `sudo`. This ensures that even on older systems with stricter default policies, the configuration is accepted without requiring a full system reboot or sudo upgrade. * **Security Best Practices:** By isolating configurations into separate files (`/etc/sudoers.d/`) and setting restrictive permissions (`0440`), it adheres to Debian's security guidelines for `sudo`. This ensures that even on older systems with stricter default policies, the configuration is accepted without requiring a full system reboot or sudo upgrade.
* **Importance:** Consistent behavior across versions means users can migrate between Debian releases (e.g., from 11 to 12) without needing to manually reconfigure these specific privileges, ensuring a stable and secure environment regardless of the underlying OS version. * **Importance:** Consistent behavior across versions means users can migrate between Debian releases (e.g., from 11 to 12) without needing to manually reconfigure these specific privileges, ensuring a stable and secure environment regardless of the underlying OS version.
+99 -56
View File
@@ -1,4 +1,4 @@
# Option 8: ZRAM Configuration & Memory Optimization # Option 9: ZRAM Configuration & Memory Optimization
## 1. The Science of ZRAM vs. Traditional Swap ## 1. The Science of ZRAM vs. Traditional Swap
@@ -7,11 +7,11 @@
Traditional swap storage operates on a fundamental latency gap that becomes critical under memory pressure: Traditional swap storage operates on a fundamental latency gap that becomes critical under memory pressure:
| Storage Medium | Latency Range | Write Amplification | SSD Wear Impact | | Storage Medium | Latency Range | Write Amplification | SSD Wear Impact |
|---------------|---------------|---------------------|-----------------| | --------------- | --------------- | --------------------- | ----------------- |
| **DRAM (RAM)** | ~1050 nanoseconds | None | Zero | | **DRAM (RAM)** | ~1050 nanoseconds | None | Zero |
| **NVMe SSD** | ~2070 microseconds | 1.2x3.0x | Moderate to High | | **NVMe SSD** | ~2070 microseconds | 1.2x3.0x | Moderate to High |
| **SATA SSD** | ~100200 microseconds | 1.5x4.0x | High | | **SATA SSD** | ~100200 microseconds | 1.5x4.0x | High |
| **HDD** | ~510 milliseconds | N/A (mechanical) | Irrelevant | | **HDD** | ~510 milliseconds | N/A (mechanical) | Irrelevant |
When a Linux system experiences memory pressure, the kernel must decide what to swap out. Traditional swap writes pages directly to disk storage: When a Linux system experiences memory pressure, the kernel must decide what to swap out. Traditional swap writes pages directly to disk storage:
@@ -74,10 +74,13 @@ The script follows a deterministic flow to ensure safe, reproducible configurati
│ │ │ │
│ 3. Size Calculation Logic │ │ 3. Size Calculation Logic │
│ ┌──────────────────────────────────────────────┐ │ │ ┌──────────────────────────────────────────────┐ │
│ │ half_ram_mb = ((RAM_KB / 1024 / 1024 + 1) │ │ ram_gb <= 8 ? 50% : 4096 MB fixed │ │
│ │ / 2) * 1024 │ │ │ │ recommended_mb = (ram_gb <= 8) │ │
│ │ ? (RAM_KB/1024/1024 + 1) │ │
│ │ / 2 * 1024 │ │
│ │ : 4096 │ │
│ └──────────────────────────────────────────────┘ │ │ └──────────────────────────────────────────────┘ │
│ └─ Result: ~50% of total physical RAM in MB │ └─ Result: 50% RAM if ≤8 GB, else fixed 4096 MB
│ │ │ │
│ 4. Configuration Confirmation │ │ 4. Configuration Confirmation │
│ ├─ Display summary with algorithm, size, priority=100 │ │ ├─ Display summary with algorithm, size, priority=100 │
@@ -86,14 +89,21 @@ The script follows a deterministic flow to ensure safe, reproducible configurati
│ 5. Package Installation │ │ 5. Package Installation │
│ sudo apt install -y zram-tools │ │ sudo apt install -y zram-tools │
│ │ │ │
│ 6. Configuration File Write │ 6. Reset Existing ZRAM Device
│ sudo swapoff /dev/zram0 (ignore errors) │
│ sudo modprobe -r zram (ignore errors) │
│ └─ Guarantees the old device is released before │
│ applying the new configuration │
│ │
│ 7. Configuration File Write │
│ /etc/default/zramswap │ │ /etc/default/zramswap │
│ ALGO=$algo │ │ ALGO=$algo │
│ SIZE=$zram_size │ │ SIZE=$zram_size │
│ PRIORITY=100 │ │ PRIORITY=100 │
│ │ │ │
7. Service Restart │ 8. Service Restart │
│ sudo systemctl restart zramswap │ sudo systemctl restart zramswap || true || true
│ └─ Verify: comp_algorithm shows [algo]; sudo zramctl │
└─────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────┘
``` ```
@@ -102,24 +112,44 @@ The script follows a deterministic flow to ensure safe, reproducible configurati
The script uses this formula to determine ZRAM size: The script uses this formula to determine ZRAM size:
```bash ```bash
half_ram_mb=$(( ((RAM_KB / 1024 / 1024 + 1) / 2) * 1024 )) ram_gb=$(( RAM_KB / 1024 / 1024 ))
if [ "$ram_gb" -le 8 ]; then
recommended_mb=$(( ((RAM_KB / 1024 / 1024 + 1) / 2) * 1024 ))
else
recommended_mb=4096
fi
``` ```
**Breakdown:** **Breakdown:**
- `RAM_KB`: Total RAM in kilobytes from `/proc/meminfo`
- `/ 1024 / 1024`: Convert KB to MB
- `+ 1`: Add rounding buffer for odd values
- `/ 2`: Target approximately 50% of total RAM
- `* 1024`: Round back to nearest MB
**Example:** - `RAM_KB`: Total RAM in kilobytes from `/proc/meminfo`
- `/ 1024 / 1024`: Convert KB to GB
- `+ 1`: Add rounding buffer for odd values
- **≤8 GB**: Target 50% of total RAM (generous swap for low-memory systems)
- **>8 GB**: Fixed 4096 MB — avoids excessive RAM reservation on high-memory machines while still providing meaningful swap space
**Examples:**
``` ```
System with 8 GB (8388608 KB) RAM: System with 4 GB (4194304 KB) RAM (<=8 GB):
half_ram_mb = ((8388608 / 1024 / 1024 + 1) / 2) * 1024 recommended_mb = ((4194304 / 1024 / 1024 + 1) / 2) * 1024
= ((8 + 1) / 2) * 1024 = ((4 + 1) / 2) * 1024
= (9 / 2) * 1024 = (5 / 2) * 1024
= 4.5 * 1024 = 2 * 1024
= 4608 MB (~4.5 GB) = 2048 MB (2 GB)
System with 8 GB (8388608 KB) RAM (<=8 GB):
recommended_mb = ((8388608 / 1024 / 1024 + 1) / 2) * 1024
= ((8 + 1) / 2) * 1024
= (9 / 2) * 1024
= 4 * 1024
= 4096 MB (4 GB)
System with 16 GB (16777216 KB) RAM (>8 GB):
recommended_mb = 4096 MB (fixed)
System with 32 GB (33554432 KB) RAM (>8 GB):
recommended_mb = 4096 MB (fixed)
``` ```
### Priority Configuration (`PRIORITY=100`) ### Priority Configuration (`PRIORITY=100`)
@@ -134,39 +164,51 @@ This prevents thrashing where pages bounce between slow disk swap and fast RAM-b
--- ---
## 3. Kernel Parameter Tuning (`sysctl`) ## 3. Priority & Swappiness Integration
### Essential VM Parameters for Aggressive ZRAM Usage ### How ZRAM Coexists with Disk Swap
While the current script focuses on `zram-tools` configuration, optimal performance requires complementary kernel parameter tuning: The script does **not** hardcode `vm.swappiness` or watermark tuning. Instead, it uses a **priority-based swap hierarchy** combined with an explicit swappiness control in the Swap module:
| Swap Device | Priority | Config Location | When It Is Used |
|-------------|----------|-----------------|-----------------|
| **ZRAM** | `100` | `/etc/default/zramswap` (`PRIORITY=100`) | **First** — kernel prefers higher priority |
| **Disk swapfile** (`/swapfile`) | `10` | `/etc/fstab` (`pri=10`) + `# debianito-managed-swap` tag | **Second** — only after ZRAM device is full |
This is implemented in `zram.sh:_zram_create` (writes `PRIORITY=100`) and `swap.sh:_swap_create_file` (writes `pri=10`). Priority is the canonical Linux `swapon` mechanism: `swapon --show` lists `PRIO` and the kernel always fills the highest-priority device first.
### Swappiness Is Managed Separately
Swappiness (`vm.swappiness`, 0100, default 60 on Debian) controls **how eagerly the kernel swaps at all**, regardless of which device is preferred.
- The ZRAM module **does not change swappiness**. Changing it would affect both ZRAM and disk swap in ways that are workload-specific.
- To tune it, use **Option 10 → Swap Management → 4. Change swappiness** (`swap.sh:_swap_set_swappiness`):
```bash
cat /proc/sys/vm/swappiness # current value
# Persistent config
/etc/sysctl.d/99-swappiness-debianito.conf → vm.swappiness=<value>
# Applied immediately
sudo sysctl -w vm.swappiness=<value>
```
- Recommended starting points (not enforced by the script):
- **General desktop**: `60` (Debian default)
- **Gaming / 8 GB or less**: `80100` — allows ZRAM to be used earlier, trading CPU for reduced disk I/O
- **ZRAM-only, no disk swap**: `100150` is safe because swap *is* RAM (compressed); there is no SSD wear cost
> **Previous documentation** recommended `vm.swappiness = 180` plus `watermark_*` and `page-cluster` tuning for ZRAM. Those values are **not written by the current script** and are omitted here to avoid drifting from the implemented behavior. If you need watermark tuning, add it manually to `/etc/sysctl.d/` and validate with your workload.
### Verifying the Hierarchy
```bash ```bash
# Recommended sysctl configuration for ZRAM systems sudo swapon --show
vm.swappiness = 180 # NAME TYPE SIZE USED PRIO
vm.watermark_boost_factor = 0 # /dev/zram0 partition 4G 0B 100
vm.watermark_scale_factor = 125 # /swapfile file 4G 0B 10
vm.page-cluster = 0 cat /proc/sys/vm/swappiness
``` ```
### Parameter Explanations
| Parameter | Value | Purpose |
|-----------|-------|---------|
| **`vm.swappiness`** | `180200` | Aggressively prefer swap over keeping pages in RAM. Higher values (up to 200) are ideal for ZRAM because it's faster than disk swap. Default 60 is too conservative for memory-constrained systems. |
| **`vm.watermark_boost_factor`** | `0` | Disable additional watermark boosting that could cause premature page reclaim |
| **`vm.watermark_scale_factor`** | `125` | Adjust low-memory watermark thresholds to trigger swap earlier when RAM is constrained |
| **`vm.page-cluster`** | `0` | Disable page clustering. Research shows this reduces unnecessary sequential reads during swap operations, improving ZRAM efficiency by ~15% in gaming workloads |
### Why High Swappiness for ZRAM?
Traditional wisdom suggests keeping swappiness low (2040) to avoid swapping frequently. However:
- **ZRAM is faster than disk**: Microseconds vs milliseconds
- **Thrashing prevention**: Higher swappiness moves pages to ZRAM before they hit slow disk swap
- **Effective RAM expansion**: Compressed pages in ZRAM can store 23x more data, effectively increasing available memory
The Pop!_OS project and Linux kernel documentation both recommend values beyond 100 for in-memory swap scenarios like ZRAM/ZSWAP.
--- ---
## 4. Service Lifecycle and Validation ## 4. Service Lifecycle and Validation
@@ -174,10 +216,11 @@ The Pop!_OS project and Linux kernel documentation both recommend values beyond
### Safe Service Initialization ### Safe Service Initialization
```bash ```bash
sudo systemctl restart zramswap sudo systemctl restart zramswap || true
``` ```
**Why `restart` instead of `start`:** **Why `restart` instead of `start`:**
- Ensures previous configuration is cleanly terminated - Ensures previous configuration is cleanly terminated
- Prevents orphaned processes from conflicting with new settings - Prevents orphaned processes from conflicting with new settings
- Reloads systemd unit files if they were modified during installation - Reloads systemd unit files if they were modified during installation
@@ -191,13 +234,14 @@ sudo zramctl
``` ```
**Output Interpretation:** **Output Interpretation:**
``` ```
NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT
/dev/zram0 lz4 4G 2.1G 318.6M 424.9M [SWAP] /dev/zram0 lz4 4G 2.1G 318.6M 424.9M [SWAP]
``` ```
| Column | Meaning | | Column | Meaning |
|--------|---------| | -------- | --------- |
| **NAME** | Device identifier (/dev/zram0) | | **NAME** | Device identifier (/dev/zram0) |
| **ALGORITHM** | Active compression algorithm (lz4, zstd, etc.) | | **ALGORITHM** | Active compression algorithm (lz4, zstd, etc.) |
| **DISKSIZE** | Maximum uncompressed data capacity configured | | **DISKSIZE** | Maximum uncompressed data capacity configured |
@@ -229,7 +273,7 @@ watch -n 5 'free -h && zramctl'
### Troubleshooting Indicators ### Troubleshooting Indicators
| Symptom | Likely Cause | Solution | | Symptom | Likely Cause | Solution |
|---------|--------------|----------| | --------- | -------------- | ---------- |
| `DATA` equals `DISKSIZE` but `COMPR` is near zero | System under memory pressure, ZRAM not being used | Increase `vm.swappiness` or check if physical swap has lower priority | | `DATA` equals `DISKSIZE` but `COMPR` is near zero | System under memory pressure, ZRAM not being used | Increase `vm.swappiness` or check if physical swap has lower priority |
| High CPU usage with low compression ratio | Incompressible data (e.g., encrypted files) | Consider backing device for incompressible pages | | High CPU usage with low compression ratio | Incompressible data (e.g., encrypted files) | Consider backing device for incompressible pages |
| Service fails to start | Missing dependencies (`zram-tools`, kernel module) | Run `sudo apt install zram-tools` and verify `modprobe zram` | | Service fails to start | Missing dependencies (`zram-tools`, kernel module) | Run `sudo apt install zram-tools` and verify `modprobe zram` |
@@ -242,8 +286,7 @@ To ensure ZRAM persists across reboots, the script writes configuration to `/etc
echo "zram" | sudo tee /etc/modules-load.d/zram.conf echo "zram" | sudo tee /etc/modules-load.d/zram.conf
``` ```
### References
### References:
- [https://docs.kernel.org/admin-guide/blockdev/zram.html](https://docs.kernel.org/admin-guide/blockdev/zram.html) - [https://docs.kernel.org/admin-guide/blockdev/zram.html](https://docs.kernel.org/admin-guide/blockdev/zram.html)
- [https://wiki.debian.org/ZRam](https://wiki.debian.org/ZRam) - [https://wiki.debian.org/ZRam](https://wiki.debian.org/ZRam)
+354 -324
View File
@@ -61,20 +61,21 @@ Instalar?"; then
_cat_customization_bullseye() { _cat_customization_bullseye() {
local sub local sub
sub=$(_menu "Customization (Bullseye)" "Select type:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ sub=$(
"1" "Desktop Themes (GTK/KDE)" \ _menu "Customization (Bullseye)" "Select type:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"2" "Icon Themes" \ "1" "Desktop Themes (GTK/KDE)" \
"3" "Cursor Themes" \ "2" "Icon Themes" \
"4" "Fonts" \ "3" "Cursor Themes" \
"5" "Terminals" \ "4" "Fonts" \
) "5" "Terminals"
)
[ -z "$sub" ] && return [ -z "$sub" ] && return
case $sub in case $sub in
1) _cat_themes_bullseye ;; 1) _cat_themes_bullseye ;;
2) _cat_icons_bullseye ;; 2) _cat_icons_bullseye ;;
3) _cat_cursors_bullseye ;; 3) _cat_cursors_bullseye ;;
4) _cat_fonts_bullseye ;; 4) _cat_fonts_bullseye ;;
5) _cat_terminals ;; 5) _cat_terminals ;;
esac esac
} }
@@ -82,17 +83,19 @@ _cat_themes_bullseye() {
local item_count=6 local item_count=6
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "Desktop Themes (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(
"arc-theme" "Arc GTK theme" "$(_state arc-theme)" \ _checklist "Desktop Themes (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \
"blackbird-gtk-theme" "Blackbird GTK theme" "$(_state blackbird-gtk-theme)" \ "arc-theme" "Arc GTK theme" "$(_state arc-theme)" \
"bluebird-gtk-theme" "Bluebird GTK theme" "$(_state bluebird-gtk-theme)" \ "blackbird-gtk-theme" "Blackbird GTK theme" "$(_state blackbird-gtk-theme)" \
"breeze-gtk-theme" "Breeze GTK theme (KDE port)" "$(_state breeze-gtk-theme)" \ "bluebird-gtk-theme" "Bluebird GTK theme" "$(_state bluebird-gtk-theme)" \
"greybird-gtk-theme" "Greybird GTK theme" "$(_state greybird-gtk-theme)" \ "breeze-gtk-theme" "Breeze GTK theme (KDE port)" "$(_state breeze-gtk-theme)" \
"numix-gtk-theme" "Numix GTK theme" "$(_state numix-gtk-theme)" \ "greybird-gtk-theme" "Greybird GTK theme" "$(_state greybird-gtk-theme)" \
) "numix-gtk-theme" "Numix GTK theme" "$(_state numix-gtk-theme)"
)
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
! is_installed "$pkg" && _run_install "$pkg" || echo "$pkg already installed." ! is_installed "$pkg" && _run_install "$pkg" || echo "$pkg already installed."
done done
@@ -101,24 +104,25 @@ _cat_themes_bullseye() {
_cat_icons_bullseye() { _cat_icons_bullseye() {
local items=( local items=(
"breeze-icon-theme" "Breeze icon theme" "$(_state breeze-icon-theme)" "breeze-icon-theme" "Breeze icon theme" "$(_state breeze-icon-theme)"
"deepin-icon-theme" "Deepin icon theme" "$(_state deepin-icon-theme)" "deepin-icon-theme" "Deepin icon theme" "$(_state deepin-icon-theme)"
"moka-icon-theme" "Moka icon theme" "$(_state moka-icon-theme)" "moka-icon-theme" "Moka icon theme" "$(_state moka-icon-theme)"
"numix-icon-theme" "Numix icon theme" "$(_state numix-icon-theme)" "numix-icon-theme" "Numix icon theme" "$(_state numix-icon-theme)"
"numix-icon-theme-circle" "Numix Circle icon theme" "$(_state numix-icon-theme-circle)" "numix-icon-theme-circle" "Numix Circle icon theme" "$(_state numix-icon-theme-circle)"
"obsidian-icon-theme" "Obsidian icon theme" "$(_state obsidian-icon-theme)" "obsidian-icon-theme" "Obsidian icon theme" "$(_state obsidian-icon-theme)"
"papirus-icon-theme" "Papirus icon theme" "$(_state papirus-icon-theme)" "papirus-icon-theme" "Papirus icon theme" "$(_state papirus-icon-theme)"
"paper-icon-theme" "Paper icon theme" "$(_state paper-icon-theme)" "paper-icon-theme" "Paper icon theme" "$(_state paper-icon-theme)"
"suru-icon-theme" "Suru icon theme" "$(_state suru-icon-theme)" "suru-icon-theme" "Suru icon theme" "$(_state suru-icon-theme)"
) )
local item_count=${#items[@]} local item_count=${#items[@]}
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "Icon Themes (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(_checklist "Icon Themes (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \
"${items[@]}" ) "${items[@]}")
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
! is_installed "$pkg" && _run_install "$pkg" || echo "$pkg already installed." ! is_installed "$pkg" && _run_install "$pkg" || echo "$pkg already installed."
done done
@@ -129,16 +133,18 @@ _cat_cursors_bullseye() {
local item_count=5 local item_count=5
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "Cursor Themes (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(
"breeze-cursor-theme" "Breeze cursors (KDE)" "$(_state breeze-cursor-theme)" \ _checklist "Cursor Themes (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \
"chameleon-cursor-theme" "Chameleon cursors" "$(_state chameleon-cursor-theme)" \ "breeze-cursor-theme" "Breeze cursors (KDE)" "$(_state breeze-cursor-theme)" \
"dmz-cursor-theme" "DMZ cursors" "$(_state dmz-cursor-theme)" \ "chameleon-cursor-theme" "Chameleon cursors" "$(_state chameleon-cursor-theme)" \
"oxygencursors" "Oxygen cursors (KDE legacy)" "$(_state oxygencursors)" \ "dmz-cursor-theme" "DMZ cursors" "$(_state dmz-cursor-theme)" \
"xcursor-themes" "X11 base cursors" "$(_state xcursor-themes)" \ "oxygencursors" "Oxygen cursors (KDE legacy)" "$(_state oxygencursors)" \
) "xcursor-themes" "X11 base cursors" "$(_state xcursor-themes)"
)
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
! is_installed "$pkg" && _run_install "$pkg" || echo "$pkg already installed." ! is_installed "$pkg" && _run_install "$pkg" || echo "$pkg already installed."
done done
@@ -149,15 +155,17 @@ _cat_fonts_bullseye() {
local item_count=4 local item_count=4
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "Fonts (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(
"fonts-firacode" "Fira Code monospace font" "$(_state fonts-firacode)" \ _checklist "Fonts (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \
"fonts-noto" "Noto fonts (Google)" "$(_state fonts-noto)" \ "fonts-firacode" "Fira Code monospace font" "$(_state fonts-firacode)" \
"fonts-dejavu-core" "DejaVu core fonts" "$(_state fonts-dejavu-core)" \ "fonts-noto" "Noto fonts (Google)" "$(_state fonts-noto)" \
"ttf-mscorefonts-installer" "Microsoft Core Fonts" "$(_state ttf-mscorefonts-installer)" \ "fonts-dejavu-core" "DejaVu core fonts" "$(_state fonts-dejavu-core)" \
) "ttf-mscorefonts-installer" "Microsoft Core Fonts" "$(_state ttf-mscorefonts-installer)"
)
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
! is_installed "$pkg" && _run_install "$pkg" || echo "$pkg already installed." ! is_installed "$pkg" && _run_install "$pkg" || echo "$pkg already installed."
done done
@@ -169,29 +177,34 @@ _cat_download_bullseye() {
local item_count1=2 local item_count1=2
local lista_alto1=$((item_count1 > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count1)) local lista_alto1=$((item_count1 > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count1))
choices1=$(_checklist "Downloaders" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto1 \ choices1=$(
"aria2" "Multiprotocol downloader (CLI)" "$(_state aria2)" \ _checklist "Downloaders" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto1 \
"filezilla" "FTP/SFTP client (GUI)" "$(_state filezilla)" \ "aria2" "Multiprotocol downloader (CLI)" "$(_state aria2)" \
) "filezilla" "FTP/SFTP client (GUI)" "$(_state filezilla)"
)
clear clear
local item_count2=8 local item_count2=8
local lista_alto2=$((item_count2 > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count2)) local lista_alto2=$((item_count2 > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count2))
choices2=$(_checklist "Torrent Clients" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto2 \ choices2=$(
"deluge" "BitTorrent client (GTK)" "$(_state deluge)" \ _checklist "Torrent Clients" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto2 \
"deluged" "BitTorrent daemon/server" "$(_state deluged)" \ "deluge" "BitTorrent client (GTK)" "$(_state deluge)" \
"mktorrent" "Torrent metainfo creator (CLI)" "$(_state mktorrent)" \ "deluged" "BitTorrent daemon/server" "$(_state deluged)" \
"qbittorrent" "BitTorrent client (Qt)" "$(_state qbittorrent)" \ "mktorrent" "Torrent metainfo creator (CLI)" "$(_state mktorrent)" \
"qbittorrent-nox" "BitTorrent WebUI/CLI" "$(_state qbittorrent-nox)" \ "qbittorrent" "BitTorrent client (Qt)" "$(_state qbittorrent)" \
"transmission-cli" "BitTorrent client (CLI)" "$(_state transmission-cli)" \ "qbittorrent-nox" "BitTorrent WebUI/CLI" "$(_state qbittorrent-nox)" \
"transmission-gtk" "BitTorrent client (GTK)" "$(_state transmission-gtk)" \ "transmission-cli" "BitTorrent client (CLI)" "$(_state transmission-cli)" \
"transmission-qt" "BitTorrent client (Qt)" "$(_state transmission-qt)" \ "transmission-gtk" "BitTorrent client (GTK)" "$(_state transmission-gtk)" \
) "transmission-qt" "BitTorrent client (Qt)" "$(_state transmission-qt)"
)
clear clear
local cleaned local cleaned
cleaned=$(echo "$choices1 $choices2" | tr -d '"') cleaned=$(echo "$choices1 $choices2" | tr -d '"')
[ -z "$cleaned" ] && { echo "No download tools selected."; return; } [ -z "$cleaned" ] && {
echo "No download tools selected."
return
}
for pkg in $cleaned; do for pkg in $cleaned; do
if ! is_installed "$pkg"; then if ! is_installed "$pkg"; then
@@ -207,39 +220,41 @@ _cat_internet_bullseye() {
local item_count=11 local item_count=11
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "Internet (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(
"chromium" "Chromium web browser" "$(_state chromium)" \ _checklist "Internet (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \
"dillo" "Lightweight graphical browser" "$(_state dillo)" \ "chromium" "Chromium web browser" "$(_state chromium)" \
"elinks" "Text-mode web browser" "$(_state elinks)" \ "dillo" "Lightweight graphical browser" "$(_state dillo)" \
"epiphany-browser" "GNOME web browser" "$(_state epiphany-browser)" \ "elinks" "Text-mode web browser" "$(_state elinks)" \
"falkon" "KDE web browser (QtWebEngine)" "$(_state falkon)" \ "epiphany-browser" "GNOME web browser" "$(_state epiphany-browser)" \
"firefox-esr" "Firefox ESR (official Debian)" "$(_state firefox-esr)" \ "falkon" "KDE web browser (QtWebEngine)" "$(_state falkon)" \
"konqueror" "KDE file manager / web browser" "$(_state konqueror)" \ "firefox-esr" "Firefox ESR (official Debian)" "$(_state firefox-esr)" \
"qutebrowser" "Keyboard-driven browser (Qt)" "$(_state qutebrowser)" \ "konqueror" "KDE file manager / web browser" "$(_state konqueror)" \
"thunderbird" "Email client" "$(_state thunderbird)" \ "qutebrowser" "Keyboard-driven browser (Qt)" "$(_state qutebrowser)" \
"torbrowser-launcher" "Tor Browser launcher" "$(_state torbrowser-launcher)" \ "thunderbird" "Email client" "$(_state thunderbird)" \
"w3m" "Text-mode browser + deps" "$(_state w3m)" \ "torbrowser-launcher" "Tor Browser launcher" "$(_state torbrowser-launcher)" \
) "w3m" "Text-mode browser + deps" "$(_state w3m)"
)
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
case $pkg in case $pkg in
w3m) w3m)
local need=() local need=()
! is_installed "w3m" && need+=("w3m") ! is_installed "w3m" && need+=("w3m")
! is_installed "w3m-img" && need+=("w3m-img") ! is_installed "w3m-img" && need+=("w3m-img")
! is_installed "ca-certificates" && need+=("ca-certificates") ! is_installed "ca-certificates" && need+=("ca-certificates")
! is_installed "xsel" && need+=("xsel") ! is_installed "xsel" && need+=("xsel")
[ ${#need[@]} -gt 0 ] && _run_install_batch "${need[@]}" || echo "Already installed." [ ${#need[@]} -gt 0 ] && _run_install_batch "${need[@]}" || echo "Already installed."
;; ;;
*) *)
if ! is_installed "$pkg"; then if ! is_installed "$pkg"; then
_run_install "$pkg" _run_install "$pkg"
else else
echo "$pkg already installed." echo "$pkg already installed."
fi fi
;; ;;
esac esac
done done
echo -e "${GREEN}Internet tools installed.${NC}" echo -e "${GREEN}Internet tools installed.${NC}"
@@ -249,13 +264,15 @@ _cat_players_bullseye() {
local item_count=2 local item_count=2
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "Media Players (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(
"mpv" "Lightweight media player" "$(_state mpv)" \ _checklist "Media Players (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \
"vlc" "VLC media player" "$(_state vlc)" \ "mpv" "Lightweight media player" "$(_state mpv)" \
) "vlc" "VLC media player" "$(_state vlc)"
)
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
if ! is_installed "$pkg"; then if ! is_installed "$pkg"; then
_run_install "$pkg" _run_install "$pkg"
@@ -270,24 +287,26 @@ _cat_design_bullseye() {
local item_count=13 local item_count=13
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "Multimedia & Design (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(
"ardour" "Digital audio workstation" "$(_state ardour)" \ _checklist "Multimedia & Design (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \
"audacity" "Audio editor/recorder" "$(_state audacity)" \ "ardour" "Digital audio workstation" "$(_state ardour)" \
"blender" "3D modeling/animation suite" "$(_state blender)" \ "audacity" "Audio editor/recorder" "$(_state audacity)" \
"ffmpeg" "Multimedia framework (CLI)" "$(_state ffmpeg)" \ "blender" "3D modeling/animation suite" "$(_state blender)" \
"gimp" "Image editor" "$(_state gimp)" \ "ffmpeg" "Multimedia framework (CLI)" "$(_state ffmpeg)" \
"handbrake" "Video transcoder (DVD ripper)" "$(_state handbrake)" \ "gimp" "Image editor" "$(_state gimp)" \
"inkscape" "Vector graphics editor" "$(_state inkscape)" \ "handbrake" "Video transcoder (DVD ripper)" "$(_state handbrake)" \
"kdenlive" "Video editor (KDE)" "$(_state kdenlive)" \ "inkscape" "Vector graphics editor" "$(_state inkscape)" \
"krita" "Digital painting/illustration" "$(_state krita)" \ "kdenlive" "Video editor (KDE)" "$(_state kdenlive)" \
"obs-studio" "Screen recording/streaming" "$(_state obs-studio)" \ "krita" "Digital painting/illustration" "$(_state krita)" \
"openshot-qt" "Video editor (simple)" "$(_state openshot-qt)" \ "obs-studio" "Screen recording/streaming" "$(_state obs-studio)" \
"scribus" "Desktop publishing (DTP)" "$(_state scribus)" \ "openshot-qt" "Video editor (simple)" "$(_state openshot-qt)" \
"shotcut" "Video editor (cross-platform)" "$(_state shotcut)" \ "scribus" "Desktop publishing (DTP)" "$(_state scribus)" \
) "shotcut" "Video editor (cross-platform)" "$(_state shotcut)"
)
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
if ! is_installed "$pkg"; then if ! is_installed "$pkg"; then
_run_install "$pkg" _run_install "$pkg"
@@ -302,20 +321,22 @@ _cat_programming_bullseye() {
local item_count=9 local item_count=9
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "Code Editors & IDEs (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(
"vim" "Classic terminal editor" "$(_state vim)" \ _checklist "Code Editors & IDEs (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \
"vim-gtk3" "Vim with GTK3 GUI" "$(_state vim-gtk3)" \ "vim" "Classic terminal editor" "$(_state vim)" \
"neovim" "Modern vim fork" "$(_state neovim)" \ "vim-gtk3" "Vim with GTK3 GUI" "$(_state vim-gtk3)" \
"nano" "Simple terminal editor" "$(_state nano)" \ "neovim" "Modern vim fork" "$(_state neovim)" \
"emacs" "Extensible editor / IDE" "$(_state emacs)" \ "nano" "Simple terminal editor" "$(_state nano)" \
"kate" "KDE advanced text editor" "$(_state kate)" \ "emacs" "Extensible editor / IDE" "$(_state emacs)" \
"mousepad" "Xfce text editor" "$(_state mousepad)" \ "kate" "KDE advanced text editor" "$(_state kate)" \
"gedit" "GNOME text editor" "$(_state gedit)" \ "mousepad" "Xfce text editor" "$(_state mousepad)" \
"geany" "Lightweight IDE" "$(_state geany)" \ "gedit" "GNOME text editor" "$(_state gedit)" \
) "geany" "Lightweight IDE" "$(_state geany)"
)
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
if ! is_installed "$pkg"; then if ! is_installed "$pkg"; then
_run_install "$pkg" _run_install "$pkg"
@@ -330,62 +351,64 @@ _cat_dev_bullseye() {
local item_count=14 local item_count=14
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "Servers & Dev Tools (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(
"apache2" "Apache web server" "$(_state apache2)" \ _checklist "Servers & Dev Tools (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \
"build-essential" "C/C++ build tools (gcc, make)" "$(_state build-essential)" \ "apache2" "Apache web server" "$(_state apache2)" \
"docker" "Docker container runtime" "$(_state docker.io)" \ "build-essential" "C/C++ build tools (gcc, make)" "$(_state build-essential)" \
"mariadb-server" "MariaDB database server" "$(_state mariadb-server)" \ "docker" "Docker container runtime" "$(_state docker.io)" \
"netcat-openbsd" "TCP/IP networking utility" "$(_state netcat-openbsd)" \ "mariadb-server" "MariaDB database server" "$(_state mariadb-server)" \
"nginx" "Nginx web server" "$(_state nginx)" \ "netcat-openbsd" "TCP/IP networking utility" "$(_state netcat-openbsd)" \
"openssh-server" "SSH server" "$(_state openssh-server)" \ "nginx" "Nginx web server" "$(_state nginx)" \
"openssl" "OpenSSL cryptography toolkit" "$(_state openssl)" \ "openssh-server" "SSH server" "$(_state openssh-server)" \
"postgresql" "PostgreSQL database server" "$(_state postgresql)" \ "openssl" "OpenSSL cryptography toolkit" "$(_state openssl)" \
"python3-pip" "Python 3 pip + venv + dev" "$(_state python3-pip)" \ "postgresql" "PostgreSQL database server" "$(_state postgresql)" \
"redis-server" "Redis key-value store" "$(_state redis-server)" \ "python3-pip" "Python 3 pip + venv + dev" "$(_state python3-pip)" \
"sqlite3" "SQLite database engine" "$(_state sqlite3)" \ "redis-server" "Redis key-value store" "$(_state redis-server)" \
"jellyfin" "Jellyfin Media Server (Web GUI on port 8096)" OFF \ "sqlite3" "SQLite database engine" "$(_state sqlite3)" \
"openjdk-dev-env" "Adoptium Temurin JDK (17, 21, 25 LTS)$(_any_jdk_installed_desc)" "$(_any_jdk_state)" \ "jellyfin" "Jellyfin Media Server (Web GUI on port 8096)" OFF \
) "openjdk-dev-env" "Adoptium Temurin JDK (17, 21, 25 LTS)$(_any_jdk_installed_desc)" "$(_any_jdk_state)"
)
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
case $pkg in case $pkg in
docker) docker)
local need=() local need=()
! is_installed "docker.io" && need+=("docker.io") ! is_installed "docker.io" && need+=("docker.io")
! is_installed "docker-compose" && need+=("docker-compose") ! is_installed "docker-compose" && need+=("docker-compose")
if [ ${#need[@]} -gt 0 ]; then if [ ${#need[@]} -gt 0 ]; then
_run_install_batch "${need[@]}" _run_install_batch "${need[@]}"
else else
echo "Docker already installed." echo "Docker already installed."
fi fi
;; ;;
python3-pip) python3-pip)
local need=() local need=()
! is_installed "python3-pip" && need+=("python3-pip") ! is_installed "python3-pip" && need+=("python3-pip")
! is_installed "python3-venv" && need+=("python3-venv") ! is_installed "python3-venv" && need+=("python3-venv")
! is_installed "python3-dev" && need+=("python3-dev") ! is_installed "python3-dev" && need+=("python3-dev")
if [ ${#need[@]} -gt 0 ]; then if [ ${#need[@]} -gt 0 ]; then
_run_install_batch "${need[@]}" _run_install_batch "${need[@]}"
else else
echo "Python 3 tools already installed." echo "Python 3 tools already installed."
fi fi
;; ;;
jellyfin) jellyfin)
install_jellyfin install_jellyfin
;; ;;
openjdk-dev-env) openjdk-dev-env)
_install_dev_java _install_dev_java
;; ;;
*) *)
if ! is_installed "$pkg"; then if ! is_installed "$pkg"; then
_run_install "$pkg" _run_install "$pkg"
else else
echo "$pkg already installed." echo "$pkg already installed."
fi fi
;; ;;
esac esac
done done
echo -e "${GREEN}Servers & dev tools installed.${NC}" echo -e "${GREEN}Servers & dev tools installed.${NC}"
@@ -394,28 +417,30 @@ _cat_security_bullseye() {
local item_count=5 local item_count=5
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "Security & Networking (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(
"wireshark" "Network protocol analyzer (GUI)" "$(_state wireshark)" \ _checklist "Security & Networking (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \
"tcpdump" "Command-line packet analyzer" "$(_state tcpdump)" \ "wireshark" "Network protocol analyzer (GUI)" "$(_state wireshark)" \
"fail2ban" "Brute-force protection daemon" "$(_state fail2ban)" \ "tcpdump" "Command-line packet analyzer" "$(_state tcpdump)" \
"ufw" "Uncomplicated firewall" "$(_state ufw)" \ "fail2ban" "Brute-force protection daemon" "$(_state fail2ban)" \
"clamav" "Antivirus engine (ClamAV)" "$(_state clamav)" \ "ufw" "Uncomplicated firewall" "$(_state ufw)" \
) "clamav" "Antivirus engine (ClamAV)" "$(_state clamav)"
)
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
case $pkg in case $pkg in
clamav) clamav)
_install_clamav _install_clamav
;; ;;
*) *)
if ! is_installed "$pkg"; then if ! is_installed "$pkg"; then
_run_install "$pkg" _run_install "$pkg"
else else
echo "$pkg already installed." echo "$pkg already installed."
fi fi
;; ;;
esac esac
done done
echo -e "${GREEN}Security & networking tools installed.${NC}" echo -e "${GREEN}Security & networking tools installed.${NC}"
@@ -425,104 +450,106 @@ _cat_general_bullseye() {
local item_count=22 local item_count=22
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "System Tools (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(
"compress" "Compression tools (zip, unrar, p7zip)" "$(_state zip)" \ _checklist "System Tools (Bullseye)" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \
"conky" "System monitor for desktop" "$(_state conky)" \ "compress" "Compression tools (zip, unrar, p7zip)" "$(_state zip)" \
"cpu-x" "CPU-X (alternative to CPU-Z)" "$(_state cpu-x)" \ "conky-all" "System monitor for desktop" "$(_state conky-all)" \
"curl-wget" "HTTP transfer tools (curl, wget)" "$(_state curl)" \ "cpu-x" "CPU-X (alternative to CPU-Z)" "$(_state cpu-x)" \
"flatpak" "Flatpak sandbox (Bullseye native)" "$(_state flatpak)" \ "curl-wget" "HTTP transfer tools (curl, wget)" "$(_state curl)" \
"fwupd" "Firmware update daemon" "$(_state fwupd)" \ "flatpak" "Flatpak sandbox (Bullseye native)" "$(_state flatpak)" \
"gnome-disk-utility" "Disk management GUI" "$(_state gnome-disk-utility)" \ "fwupd" "Firmware update daemon" "$(_state fwupd)" \
"gparted" "Partition editor" "$(_state gparted)" \ "gnome-disk-utility" "Disk management GUI" "$(_state gnome-disk-utility)" \
"htop" "Interactive process viewer" "$(_state htop)" \ "gparted" "Partition editor" "$(_state gparted)" \
"inxi" "System information tool" "$(_state inxi)" \ "htop" "Interactive process viewer" "$(_state htop)" \
"jq" "JSON command-line processor" "$(_state jq)" \ "inxi" "System information tool" "$(_state inxi)" \
"kvm" "QEMU/KVM virtualization" "$(_state virt-manager)" \ "jq" "JSON command-line processor" "$(_state jq)" \
"lshw" "List hardware details" "$(_state lshw)" \ "kvm" "QEMU/KVM virtualization" "$(_state virt-manager)" \
"mc" "Midnight Commander" "$(_state mc)" \ "lshw" "List hardware details" "$(_state lshw)" \
"nvme-cli" "NVMe SSD health monitoring" "$(_state nvme-cli)" \ "mc" "Midnight Commander" "$(_state mc)" \
"ncdu" "Disk usage analyzer" "$(_state ncdu)" \ "nvme-cli" "NVMe SSD health monitoring" "$(_state nvme-cli)" \
"psensor" "Temperature monitor" "$(_state psensor)" \ "ncdu" "Disk usage analyzer" "$(_state ncdu)" \
"timeshift" "System restore snapshots" "$(_state timeshift)" \ "psensor" "Temperature monitor" "$(_state psensor)" \
"tmux" "Terminal multiplexer" "$(_state tmux)" \ "timeshift" "System restore snapshots" "$(_state timeshift)" \
"wine" "Windows compatibility layer" "$(_state wine)" \ "tmux" "Terminal multiplexer" "$(_state tmux)" \
"bleachbit" "System cleaner (GUI)" "$(_state bleachbit)" \ "wine" "Windows compatibility layer" "$(_state wine)" \
"gdebi" "Install .deb packages with deps (GUI)" "$(_state gdebi)" \ "bleachbit" "System cleaner (GUI)" "$(_state bleachbit)" \
) "gdebi" "Install .deb packages with deps (GUI)" "$(_state gdebi)"
)
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
case $pkg in case $pkg in
compress) compress)
local need=() local need=()
! is_installed "zip" && need+=("zip") ! is_installed "zip" && need+=("zip")
! is_installed "unzip" && need+=("unzip") ! is_installed "unzip" && need+=("unzip")
! is_installed "rar" && need+=("rar") ! is_installed "rar" && need+=("rar")
! is_installed "unrar" && need+=("unrar") ! is_installed "unrar" && need+=("unrar")
! is_installed "p7zip-full" && need+=("p7zip-full") ! is_installed "p7zip-full" && need+=("p7zip-full")
! is_installed "p7zip-rar" && need+=("p7zip-rar") ! is_installed "p7zip-rar" && need+=("p7zip-rar")
[ ${#need[@]} -gt 0 ] && _run_install_batch "${need[@]}" [ ${#need[@]} -gt 0 ] && _run_install_batch "${need[@]}"
;; ;;
curl-wget) curl-wget)
local need=() local need=()
! is_installed "curl" && need+=("curl") ! is_installed "curl" && need+=("curl")
! is_installed "wget" && need+=("wget") ! is_installed "wget" && need+=("wget")
[ ${#need[@]} -gt 0 ] && _run_install_batch "${need[@]}" || echo "Already installed." [ ${#need[@]} -gt 0 ] && _run_install_batch "${need[@]}" || echo "Already installed."
;; ;;
kvm) kvm)
if ! is_installed "virt-manager"; then if ! is_installed "virt-manager"; then
_run_cmd "KVM" "sudo apt install -y qemu-system-x86 qemu-utils libvirt-daemon-system libvirt-clients bridge-utils virt-manager" "Installing KVM..." _run_cmd "KVM" "sudo apt install -y qemu-system-x86 qemu-utils libvirt-daemon-system libvirt-clients bridge-utils virt-manager" "Installing KVM..."
sudo adduser "$USER" libvirt 2>/dev/null || true sudo adduser "$USER" libvirt 2>/dev/null || true
sudo adduser "$USER" kvm 2>/dev/null || true sudo adduser "$USER" kvm 2>/dev/null || true
else
echo "QEMU/KVM already installed."
fi
;;
flatpak)
if ! is_installed "flatpak"; then
_run_cmd "Flatpak" "sudo apt install -y flatpak" "Installing Flatpak..."
flatpak remote-add --if-not-exists flathub \
https://dl.flathub.org/repo/flathub.flatpakrepo
echo -e "${GREEN}Flatpak + Flathub installed.${NC}"
else
echo "Flatpak already installed."
fi
;;
wine)
if ! is_installed "wine64"; then
_run_cmd "Wine" "sudo apt install -y --no-install-recommends wine64 fonts-wine" "Installing Wine (64-bit only)..."
local wine_ver
wine_ver=$(wine --version 2>/dev/null)
if [ -n "$wine_ver" ]; then
echo -e "${GREEN}Wine (64-bit) installed: ${wine_ver}${NC}"
else else
echo "QEMU/KVM already installed." echo -e "${YELLOW}Wine installed but version check failed.${NC}"
fi fi
;; else
flatpak) echo "Wine64 already installed."
if ! is_installed "flatpak"; then fi
_run_cmd "Flatpak" "sudo apt install -y flatpak" "Installing Flatpak..." ;;
flatpak remote-add --if-not-exists flathub \ fwupd)
https://dl.flathub.org/repo/flathub.flatpakrepo if ! is_installed "fwupd"; then
echo -e "${GREEN}Flatpak + Flathub installed.${NC}" _run_cmd "fwupd" "sudo apt install -y fwupd" "Installing fwupd..."
else fi
echo "Flatpak already installed." if _confirm "Firmware Scan" "Scan for firmware updates now?"; then
fi sudo fwupdmgr refresh --force 2>/dev/null || true
;; sudo fwupdmgr get-updates 2>&1 || true
wine) _pause
if ! is_installed "wine64"; then fi
_run_cmd "Wine" "sudo apt install -y --no-install-recommends wine64 fonts-wine" "Installing Wine (64-bit only)..." ;;
local wine_ver nvme-cli)
wine_ver=$(wine --version 2>/dev/null) _run_install "nvme-cli"
if [ -n "$wine_ver" ]; then ;;
echo -e "${GREEN}Wine (64-bit) installed: ${wine_ver}${NC}" *)
else if ! is_installed "$pkg"; then
echo -e "${YELLOW}Wine installed but version check failed.${NC}" _run_install "$pkg"
fi else
else echo "$pkg already installed."
echo "Wine64 already installed." fi
fi ;;
;;
fwupd)
if ! is_installed "fwupd"; then
_run_cmd "fwupd" "sudo apt install -y fwupd" "Installing fwupd..."
fi
if _confirm "Firmware Scan" "Scan for firmware updates now?"; then
sudo fwupdmgr refresh --force 2>/dev/null || true
sudo fwupdmgr get-updates 2>&1 || true
_pause
fi
;;
nvme-cli)
_run_install "nvme-cli"
;;
*)
if ! is_installed "$pkg"; then
_run_install "$pkg"
else
echo "$pkg already installed."
fi
;;
esac esac
done done
echo -e "${GREEN}System tools installed.${NC}" echo -e "${GREEN}System tools installed.${NC}"
@@ -531,18 +558,19 @@ _cat_general_bullseye() {
_cat_fetch_bullseye() { _cat_fetch_bullseye() {
local items=( local items=(
"neofetch" "System info fetcher" "$(_state neofetch)" "neofetch" "System info fetcher" "$(_state neofetch)"
"screenfetch" "System info (BSD/Linux)" "$(_state screenfetch)" "screenfetch" "System info (BSD/Linux)" "$(_state screenfetch)"
"linuxlogo" "Linux logo + system info" "$(_state linuxlogo)" "linuxlogo" "Linux logo + system info" "$(_state linuxlogo)"
) )
local item_count=${#items[@]} local item_count=${#items[@]}
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "Fetch Tools (Bullseye)" "Select system info tools:" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(_checklist "Fetch Tools (Bullseye)" "Select system info tools:" $TUI_ALTO $TUI_ANCHO $lista_alto \
"${items[@]}" ) "${items[@]}")
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
if ! is_installed "$pkg"; then if ! is_installed "$pkg"; then
_run_install "$pkg" _run_install "$pkg"
@@ -562,41 +590,42 @@ install_extras_bullseye() {
while true; do while true; do
local cat_choice local cat_choice
cat_choice=$(_menu "Extra Software — Bullseye" "Select a category:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ cat_choice=$(
"0" "Essential Pack" \ _menu "Extra Software — Bullseye" "Select a category:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"1" "Customization System" \ "0" "Essential Pack" \
"2" "Download & Network" \ "1" "Customization System" \
"3" "Internet (Browsers, Email)" \ "2" "Download & Network" \
"4" "Communication" \ "3" "Internet (Browsers, Email)" \
"5" "Media Players" \ "4" "Communication" \
"6" "Multimedia & Design" \ "5" "Media Players" \
"7" "Code Editors & IDEs" \ "6" "Multimedia & Design" \
"8" "Servers & Dev Tools" \ "7" "Code Editors & IDEs" \
"9" "Security & Networking" \ "8" "Servers & Dev Tools" \
"10" "Software Centers" \ "9" "Security & Networking" \
"11" "System Tools" \ "10" "Software Centers" \
"12" "Fetch / System Info" \ "11" "System Tools" \
"13" "Back to main menu" \ "12" "Fetch / System Info" \
) "13" "Back to main menu"
)
[ -z "$cat_choice" ] && return [ -z "$cat_choice" ] && return
clear clear
case "$cat_choice" in case "$cat_choice" in
0) _quick_install_bullseye ;; 0) _quick_install_bullseye ;;
1) _cat_customization_bullseye ;; 1) _cat_customization_bullseye ;;
2) _cat_download_bullseye ;; 2) _cat_download_bullseye ;;
3) _cat_internet_bullseye ;; 3) _cat_internet_bullseye ;;
4) _cat_communication ;; 4) _cat_communication ;;
5) _cat_players_bullseye ;; 5) _cat_players_bullseye ;;
6) _cat_design_bullseye ;; 6) _cat_design_bullseye ;;
7) _cat_programming_bullseye ;; 7) _cat_programming_bullseye ;;
8) _cat_dev_bullseye ;; 8) _cat_dev_bullseye ;;
9) _cat_security_bullseye ;; 9) _cat_security_bullseye ;;
10) _cat_software_centers_bullseye ;; 10) _cat_software_centers_bullseye ;;
11) _cat_general_bullseye ;; 11) _cat_general_bullseye ;;
12) _cat_fetch_bullseye ;; 12) _cat_fetch_bullseye ;;
13) return ;; 13) return ;;
esac esac
clear clear
done done
@@ -604,11 +633,12 @@ install_extras_bullseye() {
_cat_software_centers_bullseye() { _cat_software_centers_bullseye() {
local sc_choice local sc_choice
sc_choice=$(_menu "Software Centers" "Choose a software store to install:" 12 65 3 \ sc_choice=$(
"gnome-software" "Software Center for GNOME" \ _menu "Software Centers" "Choose a software store to install:" 12 65 3 \
"plasma-discover" "Software manager for Plasma" \ "gnome-software" "Software Center for GNOME" \
"synaptic" "Classic APT package manager (GTK)" \ "plasma-discover" "Software manager for Plasma" \
) "synaptic" "Classic APT package manager (GTK)"
)
[ -z "$sc_choice" ] && return [ -z "$sc_choice" ] && return
if [ "$sc_choice" = "synaptic" ]; then if [ "$sc_choice" = "synaptic" ]; then
+24 -23
View File
@@ -14,8 +14,8 @@ check_bullseye_archive_phase() {
current_year=$(date +%Y) current_year=$(date +%Y)
current_month=$(date +%-m) current_month=$(date +%-m)
if [ "$current_year" -gt 2026 ] || \ if [ "$current_year" -gt 2026 ] ||
{ [ "$current_year" -eq 2026 ] && [ "$current_month" -ge 9 ]; }; then { [ "$current_year" -eq 2026 ] && [ "$current_month" -ge 9 ]; }; then
BULLSEYE_USE_ARCHIVE=true BULLSEYE_USE_ARCHIVE=true
fi fi
@@ -33,7 +33,8 @@ No security updates will be available." 12 60
install_nvidia_bullseye() { install_nvidia_bullseye() {
echo -e "${YELLOW}NVIDIA GPU detected (Bullseye mode).${NC}" echo -e "${YELLOW}NVIDIA GPU detected (Bullseye mode).${NC}"
local is_fermi; is_fermi=$(is_nvidia_fermi) local is_fermi
is_fermi=$(is_nvidia_fermi)
local nv_pkg="" local nv_pkg=""
local gpu_gen="" local gpu_gen=""
@@ -108,13 +109,13 @@ install_gaming_bullseye() {
local choices local choices
choices=$(_checklist "Gaming Setup — Bullseye" \ choices=$(_checklist "Gaming Setup — Bullseye" \
"Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"i386" "Enable 32-bit (i386) architecture" ON \ "i386" "Enable 32-bit (i386) architecture" ON \
"steam" "Steam (requires 32-bit support)" ON \ "steam" "Steam (requires 32-bit support)" ON \
"mangohud" "Performance overlay (Vulkan/OpenGL)" ON \ "mangohud" "Performance overlay (Vulkan/OpenGL)" ON \
"gamemode" "Game performance optimization" OFF \ "gamemode" "Game performance optimization" OFF \
"goverlay" "MangoHud config GUI" ON \ "goverlay" "MangoHud config GUI" ON \
"java" "Minecraft Java Runtime" OFF \ "java" "Minecraft Java Runtime" OFF \
"lutris" "Lutris + Wine (requires 32-bit support)" OFF \ "lutris" "Lutris + Wine (requires 32-bit support)" OFF \
"retroarch" "RetroArch Emulator Frontend" OFF) "retroarch" "RetroArch Emulator Frontend" OFF)
if [ -z "$choices" ]; then if [ -z "$choices" ]; then
@@ -128,7 +129,7 @@ install_gaming_bullseye() {
local need_32bit=false local need_32bit=false
for p in $cleaned; do for p in $cleaned; do
case $p in steam|lutris) need_32bit=true ;; esac case $p in steam | lutris) need_32bit=true ;; esac
done done
echo "$cleaned" | grep -qw i386 && need_32bit=true echo "$cleaned" | grep -qw i386 && need_32bit=true
@@ -139,7 +140,7 @@ install_gaming_bullseye() {
if $need_32bit && ! dpkg --print-foreign-architectures 2>/dev/null | grep -q i386; then if $need_32bit && ! dpkg --print-foreign-architectures 2>/dev/null | grep -q i386; then
echo -e "${YELLOW}Enabling i386 architecture...${NC}" echo -e "${YELLOW}Enabling i386 architecture...${NC}"
sudo dpkg --add-architecture i386 sudo dpkg --add-architecture i386
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." _ensure_apt_updated
fi fi
if $need_32bit; then if $need_32bit; then
@@ -153,20 +154,20 @@ install_gaming_bullseye() {
for pkg in $install_list; do for pkg in $install_list; do
case $pkg in case $pkg in
steam) steam)
if ensure_contrib_repo; then if ensure_contrib_repo; then
install_steam install_steam
else else
echo -e "${YELLOW}Skipping Steam installation (contrib repository not enabled).${NC}" echo -e "${YELLOW}Skipping Steam installation (contrib repository not enabled).${NC}"
fi fi
;; ;;
java) install_minecraft_java ;; java) install_minecraft_java ;;
mangohud) install_mangohud ;; mangohud) install_mangohud ;;
gamemode) install_gamemode ;; gamemode) install_gamemode ;;
goverlay) install_goverlay ;; goverlay) install_goverlay ;;
lutris) install_lutris ;; lutris) install_lutris ;;
retroarch) install_retroarch ;; retroarch) install_retroarch ;;
*) _run_install "$pkg" ;; *) _run_install "$pkg" ;;
esac esac
done done
+307 -156
View File
@@ -11,13 +11,164 @@ manage_desktop_display() {
[ -z "$choice" ] && break [ -z "$choice" ] && break
clear clear
case "$choice" in case "$choice" in
1) _msg "Coming Soon" "Desktop Environment management will be available in a future update." 10 60 ;; 1) desktop_environment_menu ;;
2) display_manager_menu ;; 2) display_manager_menu ;;
3) break ;; 3) break ;;
esac esac
done done
} }
desktop_environment_menu() {
while true; do
local -a env_items=()
env_items+=("1" "XFCE")
env_items+=("2" "LXDE")
env_items+=("3" "Back")
# Future desktop environments: add "3" "GNOME", "4" "KDE", ... here
# and a matching case below calling its own menu (e.g. gnome_menu).
local choice
choice=$(_menu "Desktop Environment" \
"Select a desktop environment:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"${env_items[@]}")
[ -z "$choice" ] && break
clear
case "$choice" in
1) xfce_menu ;;
2) lxde_menu ;;
3) break ;;
esac
done
}
lxde_menu() {
local choice
choice=$(_radiolist "LXDE" \
"Select an option:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"1" "LXDE (Escritorio completo)" OFF \
"2" "LXDE Core (Instalación mínima)" OFF)
[ -z "$choice" ] && return 0
clear
case "$(echo "$choice" | tr -d '"')" in
1) _install_lxde_full ;;
2) _install_lxde_core ;;
esac
}
_install_lxde_full() {
echo -e "${GREEN}Installing LXDE (Full) + LightDM...${NC}"
echo "lightdm shared/default-x-display-manager select lightdm" | sudo debconf-set-selections
_run_cmd "LXDE Full" "sudo apt install -y lxde lightdm" \
"Installing LXDE (Full Meta Package) + LightDM..."
sudo systemctl enable lightdm
echo -e "${GREEN}LXDE installed. LightDM enabled.${NC}"
}
_install_lxde_core() {
echo -e "${GREEN}Installing LXDE Core + LightDM...${NC}"
echo "lightdm shared/default-x-display-manager select lightdm" | sudo debconf-set-selections
_run_cmd "LXDE Core" "sudo apt install -y lxde-core lightdm" \
"Installing LXDE Core (Minimal) + LightDM..."
sudo systemctl enable lightdm
echo -e "${GREEN}LXDE Core installed. LightDM enabled.${NC}"
}
xfce_menu() {
while true; do
local -a xf_items=()
xf_items+=("1" "XFCE (Full Meta Package)")
xf_items+=("2" "XFCE (Minimal Core)")
[ "$DEBIAN_VERSION" = "13" ] && xf_items+=("3" "XFCE Wayland (Experimental — labwc)")
xf_items+=("4" "XFCE Custom (Choose packages)")
xf_items+=("5" "Back")
local choice
choice=$(_menu "XFCE" \
"Select an option:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"${xf_items[@]}")
[ -z "$choice" ] && break
clear
case "$choice" in
1) _install_xfce_full ;;
2) _install_xfce_minimal ;;
3) _install_xfce_wayland ;;
4) _install_xfce_custom ;;
5) break ;;
esac
done
}
_install_xfce_full() {
_run_cmd "XFCE Full" "sudo apt install -y xfce4 xfce4-goodies xfce4-power-manager" \
"Installing XFCE (Full Meta Package)..."
_xfce_polkit_rules
}
_install_xfce_minimal() {
_run_cmd "XFCE Minimal" "sudo apt install -y xfce4" \
"Installing XFCE (Minimal Core)..."
_xfce_polkit_rules
}
_install_xfce_wayland() {
_run_cmd "XFCE Wayland" "sudo apt install -y xfce4 labwc" \
"Installing XFCE + labwc (Wayland, experimental)..."
_msg "XFCE Wayland" "labwc is EXPERIMENTAL on XFCE 4.20.\n\nAfter reboot, select the Wayland session\nfrom the login screen." 12 65
_xfce_polkit_rules
}
_install_xfce_custom() {
local -a items=()
for pkg in thunar xfdesktop4 xfwm4 xfce4-panel xfce4-terminal \
xfce4-screenshooter ristretto mousepad xfce4-session \
xfce4-settings xfce4-power-manager; do
items+=("$pkg" "$pkg" "$(_state "$pkg")")
done
local choices
choices=$(_checklist "XFCE Custom" \
"Select the XFCE packages to install:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"${items[@]}")
[ -z "$choices" ] && return
local cleaned
cleaned=$(echo "$choices" | tr -d '"')
[ -z "$cleaned" ] && return
_run_cmd "XFCE Custom" "sudo apt install -y $cleaned" \
"Installing selected XFCE packages..."
_xfce_polkit_rules
}
_xfce_polkit_rules() {
is_installed xfce4-power-manager || return 0
local rules_dir="/etc/polkit-1/rules.d"
sudo mkdir -p "$rules_dir"
cat <<'EOF' | sudo tee "$rules_dir/85-suspend.rules" >/dev/null
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.login1.suspend" &&
subject.isInGroup("users")) {
return polkit.Result.YES;
}
});
EOF
cat <<'EOF' | sudo tee "$rules_dir/89-backlight.rules" >/dev/null
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.upower.backlight" &&
subject.isInGroup("backlight")) {
return polkit.Result.YES;
}
});
EOF
if ! getent group backlight >/dev/null 2>&1; then
sudo groupadd --system backlight || true
fi
local de_user="${SUDO_USER:-$USER}"
if [ -n "$de_user" ] && ! id -nG "$de_user" 2>/dev/null | grep -qw backlight; then
sudo usermod -aG backlight "$de_user" || true
fi
sudo systemctl restart polkit.service 2>/dev/null || true
echo -e "${GREEN}Polkit rules installed (suspend + backlight). User '${de_user}' added to 'backlight' group.${NC}"
}
display_manager_menu() { display_manager_menu() {
while true; do while true; do
local -a dm_items=() local -a dm_items=()
@@ -37,26 +188,26 @@ display_manager_menu() {
[ -z "$choice" ] && break [ -z "$choice" ] && break
clear clear
case "$choice" in case "$choice" in
1) lightdm_config_menu ;; 1) lightdm_config_menu ;;
2) configure_gdm3 ;; 2) configure_gdm3 ;;
3) configure_sddm ;; 3) configure_sddm ;;
4) 4)
if [ "$DEBIAN_VERSION" = "12" ] || [ "$DEBIAN_VERSION" = "13" ]; then if [ "$DEBIAN_VERSION" = "12" ] || [ "$DEBIAN_VERSION" = "13" ]; then
configure_greetd configure_greetd
else else
break break
fi fi
;; ;;
5) break ;; 5) break ;;
esac esac
done done
} }
lightdm_config_menu() { lightdm_config_menu() {
local -a items=() local -a items=()
items+=("install_lightdm" "Install LightDM & GTK Greeter" "$(_state lightdm)") items+=("install_lightdm" "Install LightDM & GTK Greeter" "$(_state lightdm)")
items+=("enable_userlist" "Enable user list at login screen" "OFF") items+=("enable_userlist" "Enable user list at login screen" "OFF")
items+=("enable_autologin" "Enable autologin for current user" "OFF") items+=("enable_autologin" "Enable autologin for current user" "OFF")
local choices local choices
choices=$(_checklist "LightDM Configuration" \ choices=$(_checklist "LightDM Configuration" \
"Select options to apply:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ "Select options to apply:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
@@ -70,34 +221,34 @@ lightdm_config_menu() {
cleaned=$(echo "$choices" | tr -d '"') cleaned=$(echo "$choices" | tr -d '"')
for item in $cleaned; do for item in $cleaned; do
case $item in case $item in
install_lightdm) install_lightdm)
if ! is_installed lightdm || ! is_installed lightdm-gtk-greeter-settings; then if ! is_installed lightdm || ! is_installed lightdm-gtk-greeter-settings; then
echo "lightdm shared/default-x-display-manager select lightdm" | sudo debconf-set-selections echo "lightdm shared/default-x-display-manager select lightdm" | sudo debconf-set-selections
_run_cmd "LightDM" "sudo apt install -y lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings" "Installing LightDM & GTK Greeter..." _run_cmd "LightDM" "sudo apt install -y lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings" "Installing LightDM & GTK Greeter..."
else else
echo -e "${GREEN}[LightDM] LightDM and GTK Greeter settings are already installed, skipping...${NC}" echo -e "${GREEN}[LightDM] LightDM and GTK Greeter settings are already installed, skipping...${NC}"
fi fi
;; ;;
enable_userlist) enable_userlist)
local conf="/etc/lightdm/lightdm.conf.d/50-debianito-userlist.conf" local conf="/etc/lightdm/lightdm.conf.d/50-debianito-userlist.conf"
sudo mkdir -p "$(dirname "$conf")" sudo mkdir -p "$(dirname "$conf")"
if echo "[Seat:*] if echo "[Seat:*]
greeter-hide-users=false" | sudo tee "$conf" > /dev/null; then greeter-hide-users=false" | sudo tee "$conf" >/dev/null; then
echo -e "${GREEN}User list enabled in LightDM.${NC}" echo -e "${GREEN}User list enabled in LightDM.${NC}"
else else
echo -e "${RED}Failed to write configuration.${NC}" echo -e "${RED}Failed to write configuration.${NC}"
fi fi
;; ;;
enable_autologin) enable_autologin)
local dm_conf="/etc/lightdm/lightdm.conf" local dm_conf="/etc/lightdm/lightdm.conf"
local lightdm_user="${SUDO_USER:-$USER}" local lightdm_user="${SUDO_USER:-$USER}"
sudo sed -i 's/^#[[:space:]]*autologin-user[[:space:]=].*/autologin-user='"$lightdm_user"'/' "$dm_conf" sudo sed -i 's/^#[[:space:]]*autologin-user[[:space:]=].*/autologin-user='"$lightdm_user"'/' "$dm_conf"
sudo sed -i 's/^#[[:space:]]*autologin-user-timeout[[:space:]=].*/autologin-user-timeout=0/' "$dm_conf" sudo sed -i 's/^#[[:space:]]*autologin-user-timeout[[:space:]=].*/autologin-user-timeout=0/' "$dm_conf"
echo -e "${GREEN}Autologin enabled for user: ${lightdm_user}${NC}" echo -e "${GREEN}Autologin enabled for user: ${lightdm_user}${NC}"
;; ;;
esac esac
done done
_pause _pause
} }
configure_greetd() { configure_greetd() {
@@ -121,47 +272,47 @@ configure_greetd() {
[ -z "$choice" ] && return [ -z "$choice" ] && return
clear clear
case "$choice" in case "$choice" in
1) 1)
echo "greetd shared/default-x-display-manager select greetd" | sudo debconf-set-selections
_run_cmd "greetd" "sudo apt install -y greetd" "Installing greetd..."
_msg "greetd" "Warning: greetd was installed but NOT configured.\n\nYou must manually create /etc/greetd/config.toml\nto be able to log in.\n\nSee 'man greetd' and 'man 5 greetd-sessions'."
;;
2)
if [ "$DEBIAN_VERSION" = "12" ]; then
if [ "$(is_backports_enabled)" != true ]; then
_write_deb822_backports "bookworm"
_ensure_apt_updated
fi
_run_cmd "greetd" "sudo apt install -y -t bookworm-backports tuigreet greetd" "Installing greetd + tuigreet..."
else
_run_cmd "greetd" "sudo apt install -y greetd tuigreet" "Installing greetd + tuigreet..."
fi
_msg "greetd" "Warning: greetd was installed but NOT configured.\n\nYou must manually create /etc/greetd/config.toml\nto be able to log in.\n\nSee 'man greetd' and 'man 5 greetd-sessions'."
;;
3)
if [ "$DEBIAN_VERSION" = "13" ]; then
echo "greetd shared/default-x-display-manager select greetd" | sudo debconf-set-selections echo "greetd shared/default-x-display-manager select greetd" | sudo debconf-set-selections
_run_cmd "greetd" "sudo apt install -y greetd" "Installing greetd..." _run_cmd "greetd" "sudo apt install -y greetd gtkgreet" "Installing greetd + gtkgreet..."
_msg "greetd" "Warning: greetd was installed but NOT configured.\n\nYou must manually create /etc/greetd/config.toml\nto be able to log in.\n\nSee 'man greetd' and 'man 5 greetd-sessions'." _msg "greetd" "Warning: greetd was installed but NOT configured.\n\nYou must manually create /etc/greetd/config.toml\nto be able to log in.\n\nSee 'man greetd' and 'man 5 greetd-sessions'."
;; else
2) return
if [ "$DEBIAN_VERSION" = "12" ]; then fi
if [ "$(is_backports_enabled)" != true ]; then ;;
_write_deb822_backports "bookworm" 4)
sudo apt update -qq if [ "$DEBIAN_VERSION" = "13" ]; then
fi echo "greetd shared/default-x-display-manager select greetd" | sudo debconf-set-selections
_run_cmd "greetd" "sudo apt install -y -t bookworm-backports tuigreet greetd" "Installing greetd + tuigreet..." _run_cmd "greetd" "sudo apt install -y greetd nwg-hello" "Installing greetd + nwg-hello..."
else
_run_cmd "greetd" "sudo apt install -y greetd tuigreet" "Installing greetd + tuigreet..."
fi
_msg "greetd" "Warning: greetd was installed but NOT configured.\n\nYou must manually create /etc/greetd/config.toml\nto be able to log in.\n\nSee 'man greetd' and 'man 5 greetd-sessions'." _msg "greetd" "Warning: greetd was installed but NOT configured.\n\nYou must manually create /etc/greetd/config.toml\nto be able to log in.\n\nSee 'man greetd' and 'man 5 greetd-sessions'."
;; fi
3) ;;
if [ "$DEBIAN_VERSION" = "13" ]; then 5)
echo "greetd shared/default-x-display-manager select greetd" | sudo debconf-set-selections if [ "$DEBIAN_VERSION" = "13" ]; then
_run_cmd "greetd" "sudo apt install -y greetd gtkgreet" "Installing greetd + gtkgreet..." echo "greetd shared/default-x-display-manager select greetd" | sudo debconf-set-selections
_msg "greetd" "Warning: greetd was installed but NOT configured.\n\nYou must manually create /etc/greetd/config.toml\nto be able to log in.\n\nSee 'man greetd' and 'man 5 greetd-sessions'." _run_cmd "greetd" "sudo apt install -y greetd wlgreet" "Installing greetd + wlgreet..."
else _msg "greetd" "Warning: greetd was installed but NOT configured.\n\nYou must manually create /etc/greetd/config.toml\nto be able to log in.\n\nSee 'man greetd' and 'man 5 greetd-sessions'."
return fi
fi ;;
;; 6) return ;;
4)
if [ "$DEBIAN_VERSION" = "13" ]; then
echo "greetd shared/default-x-display-manager select greetd" | sudo debconf-set-selections
_run_cmd "greetd" "sudo apt install -y greetd nwg-hello" "Installing greetd + nwg-hello..."
_msg "greetd" "Warning: greetd was installed but NOT configured.\n\nYou must manually create /etc/greetd/config.toml\nto be able to log in.\n\nSee 'man greetd' and 'man 5 greetd-sessions'."
fi
;;
5)
if [ "$DEBIAN_VERSION" = "13" ]; then
echo "greetd shared/default-x-display-manager select greetd" | sudo debconf-set-selections
_run_cmd "greetd" "sudo apt install -y greetd wlgreet" "Installing greetd + wlgreet..."
_msg "greetd" "Warning: greetd was installed but NOT configured.\n\nYou must manually create /etc/greetd/config.toml\nto be able to log in.\n\nSee 'man greetd' and 'man 5 greetd-sessions'."
fi
;;
6) return ;;
esac esac
done done
} }
@@ -169,12 +320,12 @@ configure_greetd() {
configure_gdm3() { configure_gdm3() {
while true; do while true; do
local items_enabled=() local items_enabled=()
items_enabled+=("install" "Install/Reinstall gdm3 (Set as default)" "$(_state gdm3)") items_enabled+=("install" "Install/Reinstall gdm3 (Set as default)" "$(_state gdm3)")
items_enabled+=("userlist" "Hide user list (disable-user-list)" "OFF") items_enabled+=("userlist" "Hide user list (disable-user-list)" "OFF")
items_enabled+=("autologin" "Configure Autologin" "OFF") items_enabled+=("autologin" "Configure Autologin" "OFF")
if [ "$DEBIAN_VERSION" = "12" ] || [ "$DEBIAN_VERSION" = "13" ]; then if [ "$DEBIAN_VERSION" = "12" ] || [ "$DEBIAN_VERSION" = "13" ]; then
if [ "$HAS_NVIDIA" = true ]; then if [ "$HAS_NVIDIA" = true ]; then
items_enabled+=("wayland" "Force Enable Wayland on NVIDIA (Risk!)" "OFF") items_enabled+=("wayland" "Force Enable Wayland on NVIDIA (Risk!)" "OFF")
fi fi
fi fi
local choice local choice
@@ -189,50 +340,50 @@ configure_gdm3() {
cleaned=$(echo "$choice" | tr -d '"') cleaned=$(echo "$choice" | tr -d '"')
for item in $cleaned; do for item in $cleaned; do
case $item in case $item in
install) install)
echo "gdm3 shared/default-x-display-manager select gdm3" | sudo debconf-set-selections echo "gdm3 shared/default-x-display-manager select gdm3" | sudo debconf-set-selections
_run_cmd "GDM3" "sudo apt install -y gdm3" "Installing gdm3..." _run_cmd "GDM3" "sudo apt install -y gdm3" "Installing gdm3..."
;; ;;
userlist) userlist)
local greeter_conf="/etc/gdm3/greeter.dconf-defaults" local greeter_conf="/etc/gdm3/greeter.dconf-defaults"
if sudo grep -q '^disable-user-list=true' "$greeter_conf" 2>/dev/null; then if sudo grep -q '^disable-user-list=true' "$greeter_conf" 2>/dev/null; then
sudo sed -i 's/^disable-user-list=true/# disable-user-list=true/' "$greeter_conf" sudo sed -i 's/^disable-user-list=true/# disable-user-list=true/' "$greeter_conf"
echo -e "${GREEN}User list is now VISIBLE.${NC}" echo -e "${GREEN}User list is now VISIBLE.${NC}"
else else
sudo sed -i 's/^#[[:space:]]*disable-user-list=true/disable-user-list=true/' "$greeter_conf" sudo sed -i 's/^#[[:space:]]*disable-user-list=true/disable-user-list=true/' "$greeter_conf"
echo -e "${GREEN}User list is now HIDDEN.${NC}" echo -e "${GREEN}User list is now HIDDEN.${NC}"
fi
sudo dpkg-reconfigure gdm3 >/dev/null 2>&1
;;
autologin)
local daemon_conf="/etc/gdm3/daemon.conf"
local username
username=$(whiptail --title "GDM3 Autologin" \
--inputbox "Enter username to autologin (leave empty to DISABLE autologin):" \
10 60 "" 3>&1 1>&2 2>&3 || true)
if [ -n "$username" ]; then
sudo sed -i 's/^# *AutomaticLoginEnable[[:space:]=].*/AutomaticLoginEnable=true/' "$daemon_conf"
sudo sed -i 's/^# *AutomaticLogin[[:space:]=].*/AutomaticLogin='"$username"'/' "$daemon_conf"
echo -e "${GREEN}Autologin enabled for user: ${username}${NC}"
else
sudo sed -i 's/^AutomaticLoginEnable[[:space:]=].*/# AutomaticLoginEnable=false/' "$daemon_conf"
sudo sed -i 's/^AutomaticLogin[[:space:]=].*/# AutomaticLogin=/' "$daemon_conf"
echo -e "${GREEN}Autologin disabled.${NC}"
fi
;;
wayland)
local rules_link="/etc/udev/rules.d/61-gdm.rules"
if [ -L "$rules_link" ] || [ -f "$rules_link" ]; then
sudo rm -f "$rules_link"
echo -e "${GREEN}Reverted. Wayland will be disabled by default on next reboot.${NC}"
elif [ -f "/lib/udev/rules.d/61-gdm.rules" ]; then
if _confirm "Wayland on NVIDIA" \
"Force-enable Wayland on NVIDIA?\n\nRisk: This may break graphics or cause instability.\nProceed?"; then
sudo ln -s /dev/null "$rules_link"
echo -e "${GREEN}Wayland override created. Reboot required.${NC}"
fi fi
sudo dpkg-reconfigure gdm3 >/dev/null 2>&1 fi
;; ;;
autologin)
local daemon_conf="/etc/gdm3/daemon.conf"
local username
username=$(whiptail --title "GDM3 Autologin" \
--inputbox "Enter username to autologin (leave empty to DISABLE autologin):" \
10 60 "" 3>&1 1>&2 2>&3 || true)
if [ -n "$username" ]; then
sudo sed -i 's/^# *AutomaticLoginEnable[[:space:]=].*/AutomaticLoginEnable=true/' "$daemon_conf"
sudo sed -i 's/^# *AutomaticLogin[[:space:]=].*/AutomaticLogin='"$username"'/' "$daemon_conf"
echo -e "${GREEN}Autologin enabled for user: ${username}${NC}"
else
sudo sed -i 's/^AutomaticLoginEnable[[:space:]=].*/# AutomaticLoginEnable=false/' "$daemon_conf"
sudo sed -i 's/^AutomaticLogin[[:space:]=].*/# AutomaticLogin=/' "$daemon_conf"
echo -e "${GREEN}Autologin disabled.${NC}"
fi
;;
wayland)
local rules_link="/etc/udev/rules.d/61-gdm.rules"
if [ -L "$rules_link" ] || [ -f "$rules_link" ]; then
sudo rm -f "$rules_link"
echo -e "${GREEN}Reverted. Wayland will be disabled by default on next reboot.${NC}"
elif [ -f "/lib/udev/rules.d/61-gdm.rules" ]; then
if _confirm "Wayland on NVIDIA" \
"Force-enable Wayland on NVIDIA?\n\nRisk: This may break graphics or cause instability.\nProceed?"; then
sudo ln -s /dev/null "$rules_link"
echo -e "${GREEN}Wayland override created. Reboot required.${NC}"
fi
fi
;;
esac esac
done done
_pause _pause
@@ -251,37 +402,37 @@ configure_sddm() {
[ -z "$choice" ] && return [ -z "$choice" ] && return
clear clear
case "$choice" in case "$choice" in
1) 1)
echo "sddm shared/default-x-display-manager select sddm" | sudo debconf-set-selections echo "sddm shared/default-x-display-manager select sddm" | sudo debconf-set-selections
_run_cmd "SDDM" "sudo apt install -y sddm" "Installing SDDM..." _run_cmd "SDDM" "sudo apt install -y sddm" "Installing SDDM..."
;; ;;
2) 2)
local sddm_session="" local sddm_session=""
local sddm_user="${SUDO_USER:-$USER}" local sddm_user="${SUDO_USER:-$USER}"
if [ -f /usr/share/wayland-sessions/plasmawayland.desktop ]; then if [ -f /usr/share/wayland-sessions/plasmawayland.desktop ]; then
sddm_session="plasmawayland" sddm_session="plasmawayland"
elif [ -f /usr/share/wayland-sessions/lxqt-wayland.desktop ]; then elif [ -f /usr/share/wayland-sessions/lxqt-wayland.desktop ]; then
sddm_session="lxqt-wayland" sddm_session="lxqt-wayland"
elif [ -f /usr/share/xsessions/plasma.desktop ]; then elif [ -f /usr/share/xsessions/plasma.desktop ]; then
sddm_session="plasma" sddm_session="plasma"
elif [ -f /usr/share/xsessions/lxqt.desktop ]; then elif [ -f /usr/share/xsessions/lxqt.desktop ]; then
sddm_session="lxqt" sddm_session="lxqt"
fi fi
sudo mkdir -p /etc/sddm.conf.d sudo mkdir -p /etc/sddm.conf.d
cat << EOF | sudo tee /etc/sddm.conf.d/autologin.conf > /dev/null cat <<EOF | sudo tee /etc/sddm.conf.d/autologin.conf >/dev/null
[Autologin] [Autologin]
User=${sddm_user} User=${sddm_user}
Session=${sddm_session} Session=${sddm_session}
Relogin=false Relogin=false
EOF EOF
if [ -n "$sddm_session" ]; then if [ -n "$sddm_session" ]; then
echo -e "${GREEN}Autologin enabled for user ${sddm_user}, session: ${sddm_session}.${NC}" echo -e "${GREEN}Autologin enabled for user ${sddm_user}, session: ${sddm_session}.${NC}"
else else
echo -e "${YELLOW}Autologin enabled for user ${sddm_user}. No session set (SDDM will use default).${NC}" echo -e "${YELLOW}Autologin enabled for user ${sddm_user}. No session set (SDDM will use default).${NC}"
fi fi
_pause _pause
;; ;;
3) return ;; 3) return ;;
esac esac
done done
} }
+1 -1
View File
@@ -39,7 +39,7 @@ install_extras() {
"7" "Code Editors & IDEs" \ "7" "Code Editors & IDEs" \
"8" "Servers & Dev Tools" \ "8" "Servers & Dev Tools" \
"9" "Security & Networking" \ "9" "Security & Networking" \
"10" "Software Centers" \ "10" "Software Center & Flatpak" \
"11" "Office & Productivity" \ "11" "Office & Productivity" \
"12" "System Tools" \ "12" "System Tools" \
"13" "Fetch / System Info" \ "13" "Fetch / System Info" \
+185
View File
@@ -0,0 +1,185 @@
#!/usr/bin/env bash
# audio.sh — Audio & Sound (PipeWire, ALSA, PulseAudio tools)
_cat_audio() {
local headless=false
_is_headless && headless=true
local -a items=()
local pw_label="PipeWire Audio Stack (Bluetooth Hi-Res)"
local pw_state; pw_state=$(_state "pipewire-audio")
items+=(
"pipewire-audio" "$pw_label" "$pw_state"
)
local alsa_state; alsa_state=$(_state "alsa-utils")
items+=(
"alsa-utils" "ALSA Utilities (alsa-utils, alsa-ucm-conf)" "$alsa_state"
)
if ! $headless; then
local pavu_state; pavu_state=$(_state "pavucontrol")
items+=(
"pavucontrol" "Volume Control GUI (pavucontrol)" "$pavu_state"
)
fi
local pulsemixer_state; pulsemixer_state=$(_state "pulsemixer")
local playerctl_state; playerctl_state=$(_state "playerctl")
items+=(
"pulsemixer" "Terminal audio mixer (pulsemixer)" "$pulsemixer_state"
"playerctl" "Multimedia key controller (playerctl)" "$playerctl_state"
)
local item_count=${#items[@]}
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices
choices=$(_checklist "Audio & Sound" "Check [*] the packages you want installed.\n" \
$TUI_ALTO $TUI_ANCHO $lista_alto "${items[@]}")
clear
[ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do
case $pkg in
pipewire-audio) _install_pipewire_standard ;;
alsa-utils)
if ! is_installed "alsa-utils"; then
_run_install "alsa-utils alsa-ucm-conf"
else
echo "alsa-utils already installed."
fi
;;
pavucontrol)
if ! is_installed "pavucontrol"; then
_run_install "pavucontrol"
else
echo "pavucontrol already installed."
fi
;;
pulsemixer)
if ! is_installed "pulsemixer"; then
_run_install "pulsemixer"
else
echo "pulsemixer already installed."
fi
;;
playerctl)
if ! is_installed "playerctl"; then
_run_install "playerctl"
else
echo "playerctl already installed."
fi
;;
esac
done
echo -e "${GREEN}Audio & Sound setup complete.${NC}"
}
_install_pipewire_standard() {
local bt_pkgs="libldacbt-abr2 libldacbt-enc2 libopenaptx0 libspa-0.2-bluetooth"
if apt-cache show libfdk-aac2t64 &>/dev/null; then
bt_pkgs+=" libfdk-aac2t64"
elif apt-cache show libfdk-aac2 &>/dev/null; then
bt_pkgs+=" libfdk-aac2"
fi
# ── Resolve versions (needed for both installed and not-installed branches) ──
local stable_ver=""
stable_ver=$(apt-cache policy pipewire-audio 2>/dev/null | awk 'NR==3 {print $2; exit}') || true
local bpo_ver=""
if [ "$DEBIAN_VERSION" = "13" ] && [ "$(is_backports_enabled)" = "true" ]; then
bpo_ver=$(apt-cache madison pipewire-audio 2>/dev/null | \
grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1) || true
fi
local pkg_check="pipewire-audio"
[ "$DEBIAN_VERSION" = "11" ] && pkg_check="pipewire"
# ── Already installed branch ──
if is_installed "$pkg_check"; then
if [ -n "$bpo_ver" ]; then
local current_ver
current_ver=$(dpkg -l "$pkg_check" 2>/dev/null | awk '/^ii/{print $3}') || true
if _confirm "PipeWire" \
"PipeWire ${current_ver:+v${current_ver} }already installed.\n\nUpgrade to backports version v${bpo_ver}?"; then
echo "Upgrading PipeWire Audio Stack..."
echo "-> Target version: v${bpo_ver} (from ${DEBIAN_CODENAME}-backports)"
echo "-> Including Bluetooth Hi-Res codecs (LDAC, aptX, AAC)"
_run_cmd "PipeWire" \
"sudo apt install -y --reinstall -t ${DEBIAN_CODENAME}-backports pipewire-audio $bt_pkgs" \
"Upgrading PipeWire from backports..."
if [ "$DEBIAN_VERSION" != "11" ]; then
echo "Restarting PipeWire services..."
systemctl --user restart wireplumber pipewire pipewire-pulse 2>/dev/null || true
echo -e "${GREEN}PipeWire services restarted.${NC}"
fi
return
fi
fi
echo "$pkg_check already installed."
return
fi
# ── Confirm dialog ──
local apt_target="" pw_ver="" pw_src=""
if [ -n "$bpo_ver" ]; then
local msg="Backports repository is enabled.\n\n"
msg+="Available versions:\n"
msg+=" - Stable: v${stable_ver:-unknown}\n"
msg+=" - Backports: v${bpo_ver}\n\n"
msg+="Install from Backports (Recommended for newer hardware)\nor from Stable (more conservative)?"
if _confirm_custom "PipeWire Install" "$msg" "Backports" "Stable" 14 70; then
apt_target="-t ${DEBIAN_CODENAME}-backports"
pw_ver="$bpo_ver"
pw_src="from ${DEBIAN_CODENAME}-backports"
else
pw_ver="$stable_ver"
fi
else
local msg="PipeWire Audio Stack (v${stable_ver:-unknown})\n"
msg+="will be installed along with Bluetooth Hi-Res\n"
msg+="codecs (LDAC, aptX, AAC).\n\n"
msg+="Continue with installation?"
if ! _confirm "PipeWire Install" "$msg" 12 65; then
echo "PipeWire installation cancelled."
return
fi
pw_ver="$stable_ver"
fi
echo "Installing PipeWire Audio Stack..."
echo "-> Detected version: ${pw_ver:-unknown} ${pw_src:+($pw_src)}"
echo "-> Including Bluetooth Hi-Res codecs (LDAC, aptX, AAC)"
case "$DEBIAN_VERSION" in
11)
_run_cmd "PipeWire" \
"sudo apt install -y pipewire libspa-0.2-bluetooth pipewire-alsa libspa-0.2-jack $bt_pkgs" \
"Installing PipeWire (Bullseye basic mode)..."
echo -e "${GREEN}PipeWire installed (Bullseye basic mode).${NC}"
;;
12)
_run_cmd "PipeWire" \
"sudo apt install -y pipewire-audio $bt_pkgs" \
"Installing pipewire-audio meta-package (Bookworm)..."
echo -e "${GREEN}PipeWire audio stack installed.${NC}"
;;
13)
_run_cmd "PipeWire" \
"sudo apt install -y $apt_target pipewire-audio $bt_pkgs" \
"Installing pipewire-audio meta-package (Trixie)..."
echo -e "${GREEN}PipeWire audio stack installed.${NC}"
;;
esac
if [ "$DEBIAN_VERSION" != "11" ]; then
echo "Restarting PipeWire services..."
systemctl --user restart wireplumber pipewire pipewire-pulse 2>/dev/null || true
echo -e "${GREEN}PipeWire services restarted.${NC}"
fi
}
+22 -18
View File
@@ -6,7 +6,7 @@ _install_signal() {
if [ ! -f /etc/apt/sources.list.d/extrepo_signal.sources ]; then if [ ! -f /etc/apt/sources.list.d/extrepo_signal.sources ]; then
_run_cmd "Signal" "sudo extrepo enable signal" "Enabling Signal repository..." _run_cmd "Signal" "sudo extrepo enable signal" "Enabling Signal repository..."
fi fi
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." _ensure_apt_updated
if ! is_installed "signal-desktop"; then if ! is_installed "signal-desktop"; then
_run_cmd "Signal" "sudo apt install -y signal-desktop" "Installing Signal..." _run_cmd "Signal" "sudo apt install -y signal-desktop" "Installing Signal..."
echo -e "${GREEN}Signal installed.${NC}" echo -e "${GREEN}Signal installed.${NC}"
@@ -50,13 +50,16 @@ _cat_communication() {
fi fi
local -a items=() local -a items=()
local signal_state; signal_state=$(_state "signal-desktop") local signal_state
local telegram_state; telegram_state=$(_state "telegram-desktop") signal_state=$(_state "signal-desktop")
local hexchat_state; hexchat_state=$(_state "hexchat") local telegram_state
telegram_state=$(_state "telegram-desktop")
local hexchat_state
hexchat_state=$(_state "hexchat")
items+=( items+=(
"signal-desktop" "Signal Private Messenger (extrepo)" "$signal_state" "signal-desktop" "Signal Private Messenger (extrepo)" "$signal_state"
"telegram-desktop" "Telegram Desktop messaging" "$telegram_state" "telegram-desktop" "Telegram Desktop messaging" "$telegram_state"
"hexchat" "IRC client (HexChat)" "$hexchat_state" "hexchat" "IRC client (HexChat)" "$hexchat_state"
) )
local item_count=${#items[@]} local item_count=${#items[@]}
@@ -67,19 +70,20 @@ _cat_communication() {
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
case $pkg in case $pkg in
signal-desktop) _install_signal ;; signal-desktop) _install_signal ;;
telegram-desktop) _install_telegram ;; telegram-desktop) _install_telegram ;;
hexchat) hexchat)
if ! is_installed "hexchat"; then if ! is_installed "hexchat"; then
_run_install "hexchat" _run_install "hexchat"
echo -e "${GREEN}hexchat installed.${NC}" echo -e "${GREEN}hexchat installed.${NC}"
else else
echo "hexchat already installed." echo "hexchat already installed."
fi fi
;; ;;
esac esac
done done
echo -e "${GREEN}Communication tools installed.${NC}" echo -e "${GREEN}Communication tools installed.${NC}"
+1 -1
View File
@@ -8,7 +8,7 @@ _enable_jellyfin_repo() {
fi fi
_run_cmd "Jellyfin" "sudo extrepo enable jellyfin" "Enabling Jellyfin repository..." _run_cmd "Jellyfin" "sudo extrepo enable jellyfin" "Enabling Jellyfin repository..."
fi fi
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." _ensure_apt_updated
} }
install_jellyfin() { install_jellyfin() {
+186 -126
View File
@@ -16,13 +16,13 @@ _enable_mozilla_repo() {
_run_cmd "Mozilla" "sudo extrepo enable mozilla" "Enabling Mozilla repository..." _run_cmd "Mozilla" "sudo extrepo enable mozilla" "Enabling Mozilla repository..."
fi fi
if [ ! -f /etc/apt/preferences.d/mozilla ]; then if [ ! -f /etc/apt/preferences.d/mozilla ]; then
sudo tee /etc/apt/preferences.d/mozilla > /dev/null << 'EOF' sudo tee /etc/apt/preferences.d/mozilla >/dev/null <<'EOF'
Package: * Package: *
Pin: origin packages.mozilla.org Pin: origin packages.mozilla.org
Pin-Priority: 1000 Pin-Priority: 1000
EOF EOF
fi fi
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." _ensure_apt_updated
} }
_enable_floorp_repo() { _enable_floorp_repo() {
@@ -30,7 +30,7 @@ _enable_floorp_repo() {
_ensure_extrepo _ensure_extrepo
_run_cmd "Floorp" "sudo extrepo enable floorp" "Enabling Floorp repository..." _run_cmd "Floorp" "sudo extrepo enable floorp" "Enabling Floorp repository..."
fi fi
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." _ensure_apt_updated
} }
install_palemoon() { install_palemoon() {
@@ -60,7 +60,7 @@ install_palemoon() {
else else
_ensure_extrepo _ensure_extrepo
_run_cmd "Pale Moon" "sudo extrepo enable ${REPO_PALEMOON}" "Enabling ${REPO_PALEMOON}..." _run_cmd "Pale Moon" "sudo extrepo enable ${REPO_PALEMOON}" "Enabling ${REPO_PALEMOON}..."
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." _ensure_apt_updated
fi fi
if ! is_installed "palemoon"; then if ! is_installed "palemoon"; then
@@ -76,7 +76,7 @@ _enable_librewolf_repo() {
_ensure_extrepo _ensure_extrepo
_run_cmd "LibreWolf" "sudo extrepo enable librewolf" "Enabling LibreWolf repository..." _run_cmd "LibreWolf" "sudo extrepo enable librewolf" "Enabling LibreWolf repository..."
fi fi
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." _ensure_apt_updated
} }
_enable_tailscale_repo() { _enable_tailscale_repo() {
@@ -84,7 +84,7 @@ _enable_tailscale_repo() {
_ensure_extrepo _ensure_extrepo
_run_cmd "Tailscale" "sudo extrepo enable tailscale" "Enabling Tailscale repository..." _run_cmd "Tailscale" "sudo extrepo enable tailscale" "Enabling Tailscale repository..."
fi fi
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." _ensure_apt_updated
} }
_enable_mullvad_repo() { _enable_mullvad_repo() {
@@ -92,14 +92,14 @@ _enable_mullvad_repo() {
_ensure_extrepo _ensure_extrepo
_run_cmd "Mullvad" "sudo extrepo enable mullvad" "Enabling Mullvad repository..." _run_cmd "Mullvad" "sudo extrepo enable mullvad" "Enabling Mullvad repository..."
fi fi
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." _ensure_apt_updated
} }
install_protonvpn() { install_protonvpn() {
if [ ! -f /etc/apt/sources.list.d/extrepo_protonvpn.sources ]; then if [ ! -f /etc/apt/sources.list.d/extrepo_protonvpn.sources ]; then
_ensure_extrepo _ensure_extrepo
_run_cmd "ProtonVPN" "sudo extrepo enable protonvpn stable" "Enabling ProtonVPN repository (stable suite)..." _run_cmd "ProtonVPN" "sudo extrepo enable protonvpn stable" "Enabling ProtonVPN repository (stable suite)..."
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." _ensure_apt_updated
else else
echo "ProtonVPN repository already enabled." echo "ProtonVPN repository already enabled."
fi fi
@@ -119,136 +119,172 @@ _cat_internet() {
_is_headless && headless=true _is_headless && headless=true
local -a items=() local -a items=()
if ! $headless; then if ! $headless; then
local chromium_state; chromium_state=$(_state "chromium") local chromium_state
local dillo_state; dillo_state=$(_state "dillo") chromium_state=$(_state "chromium")
local epiphany_state; epiphany_state=$(_state "epiphany-browser") local dillo_state
local falkon_state; falkon_state=$(_state "falkon") dillo_state=$(_state "dillo")
local epiphany_state
epiphany_state=$(_state "epiphany-browser")
local falkon_state
falkon_state=$(_state "falkon")
local firefox_state="OFF" local firefox_state="OFF"
if command -v firefox &>/dev/null && ! is_installed "firefox-esr"; then if command -v firefox &>/dev/null && ! is_installed "firefox-esr"; then
firefox_state="ON" firefox_state="ON"
fi fi
local firefox_esr_state local firefox_esr_state
firefox_esr_state=$(_state "firefox-esr") firefox_esr_state=$(_state "firefox-esr")
local floorp_state; floorp_state=$(_state "floorp") local floorp_state
local konqueror_state; konqueror_state=$(_state "konqueror") floorp_state=$(_state "floorp")
local librewolf_state; librewolf_state=$(_state "librewolf") local konqueror_state
local palemoon_state; palemoon_state=$(_state "palemoon") konqueror_state=$(_state "konqueror")
local privacybrowser_state; privacybrowser_state=$(_state "privacybrowser") local librewolf_state
local qutebrowser_state; qutebrowser_state=$(_state "qutebrowser") librewolf_state=$(_state "librewolf")
local thunderbird_state; thunderbird_state=$(_state "thunderbird") local palemoon_state
local torbrowser_state; torbrowser_state=$(_state "torbrowser-launcher") palemoon_state=$(_state "palemoon")
local mullvadbrowser_state; mullvadbrowser_state=$(_state "mullvad-browser") local privacybrowser_state
local protonvpn_state; protonvpn_state=$(_state "protonvpn") privacybrowser_state=$(_state "privacybrowser")
local qutebrowser_state
qutebrowser_state=$(_state "qutebrowser")
local thunderbird_state
thunderbird_state=$(_state "thunderbird")
local torbrowser_state
torbrowser_state=$(_state "torbrowser-launcher")
local mullvadbrowser_state
mullvadbrowser_state=$(_state "mullvad-browser")
local protonvpn_state
protonvpn_state=$(_state "protonvpn")
items+=( items+=(
"chromium" "Chromium web browser" "$chromium_state" "chromium" "Chromium web browser" "$chromium_state"
"dillo" "Lightweight graphical browser" "$dillo_state" "dillo" "Lightweight graphical browser" "$dillo_state"
"epiphany-browser" "GNOME web browser" "$epiphany_state" "epiphany-browser" "GNOME web browser" "$epiphany_state"
"falkon" "KDE web browser (QtWebEngine)" "$falkon_state" "falkon" "KDE web browser (QtWebEngine)" "$falkon_state"
"firefox" "Firefox from Mozilla (replaces ESR)" "$firefox_state" "firefox" "Firefox from Mozilla (replaces ESR)" "$firefox_state"
"firefox-esr" "Firefox ESR (official Debian + locale auto)" "$firefox_esr_state" "firefox-esr" "Firefox ESR (official Debian + locale auto)" "$firefox_esr_state"
"floorp" "Firefox-based browser (extrepo)" "$floorp_state" "floorp" "Firefox-based browser (extrepo)" "$floorp_state"
"konqueror" "KDE file manager / web browser" "$konqueror_state" "konqueror" "KDE file manager / web browser" "$konqueror_state"
"librewolf" "Privacy-focused Firefox fork (extrepo)" "$librewolf_state" "librewolf" "Privacy-focused Firefox fork (extrepo)" "$librewolf_state"
"palemoon" "Classic Firefox-derived browser (extrepo)" "$palemoon_state" "palemoon" "Classic Firefox-derived browser (extrepo)" "$palemoon_state"
"privacybrowser" "Privacy-focused web browser" "$privacybrowser_state" "privacybrowser" "Privacy-focused web browser" "$privacybrowser_state"
"qutebrowser" "Keyboard-driven browser (Qt)" "$qutebrowser_state" "qutebrowser" "Keyboard-driven browser (Qt)" "$qutebrowser_state"
"thunderbird" "Email client" "$thunderbird_state" "thunderbird" "Email client" "$thunderbird_state"
"torbrowser-launcher" "Tor Browser launcher" "$torbrowser_state" "torbrowser-launcher" "Tor Browser launcher" "$torbrowser_state"
"mullvad-browser" "Mullvad privacy browser" "$mullvadbrowser_state" "mullvad-browser" "Mullvad privacy browser" "$mullvadbrowser_state"
"protonvpn" "ProtonVPN client" "$protonvpn_state" "protonvpn" "ProtonVPN client" "$protonvpn_state"
) )
fi fi
local elinks_state; elinks_state=$(_state "elinks") local elinks_state
local riseupvpn_state; riseupvpn_state=$(_state "riseup-vpn") elinks_state=$(_state "elinks")
local w3m_state; w3m_state=$(_state "w3m") local riseupvpn_state
local tailscale_state; tailscale_state=$(_state "tailscale") riseupvpn_state=$(_state "riseup-vpn")
local mullvad_state; mullvad_state=$(_state "mullvad-vpn") local w3m_state
w3m_state=$(_state "w3m")
local tailscale_state
tailscale_state=$(_state "tailscale")
local mullvad_state
mullvad_state=$(_state "mullvad-vpn")
items+=( items+=(
"elinks" "Text-mode web browser" "$elinks_state" "elinks" "Text-mode web browser" "$elinks_state"
"riseup-vpn" "Riseup VPN client" "$riseupvpn_state" "riseup-vpn" "Riseup VPN client" "$riseupvpn_state"
"w3m" "Text-mode browser + deps (w3m-img)" "$w3m_state" "w3m" "Text-mode browser + deps (w3m-img)" "$w3m_state"
"tailscale" "Zero-config VPN & mesh networking" "$tailscale_state" "tailscale" "Zero-config VPN & mesh networking" "$tailscale_state"
"mullvad-vpn" "Mullvad VPN client (WireGuard)" "$mullvad_state" "mullvad-vpn" "Mullvad VPN client (WireGuard)" "$mullvad_state"
) )
local item_count=${#items[@]} local item_count=${#items[@]}
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "Internet" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(
"${items[@]}" \ _checklist "Internet" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \
) "${items[@]}"
)
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
if echo "$cleaned" | grep -q "firefox" && echo "$cleaned" | grep -q "firefox-esr"; then local has_firefox=false
_msg "Firefox" "You selected both Firefox (Mozilla) and Firefox ESR.\nPlease choose only one Firefox variant." 10 60 local has_firefox_esr=false
return local fchoice=""
for _p in $cleaned; do
[ "$_p" = "firefox" ] && has_firefox=true
[ "$_p" = "firefox-esr" ] && has_firefox_esr=true
done
if $has_firefox && $has_firefox_esr; then
fchoice=$(_menu "Firefox" "You selected both Firefox (Mozilla) and Firefox ESR.\nWhat do you want to do?" 12 60 3 \
"mozilla" "Remove Firefox ESR — keep Firefox" \
"esr" "Remove Firefox — keep Firefox ESR" \
"both" "Keep both variants")
[ -z "$fchoice" ] && return
case "$fchoice" in
mozilla) cleaned=$(printf '%s\n' $cleaned | grep -vx "firefox-esr" | tr '\n' ' ') ;;
esr) cleaned=$(printf '%s\n' $cleaned | grep -vx "firefox" | tr '\n' ' ') ;;
esac
fi fi
for pkg in $cleaned; do for pkg in $cleaned; do
case $pkg in case $pkg in
firefox) firefox)
install_firefox_mozilla install_firefox_mozilla "$fchoice"
;; ;;
firefox-esr) firefox-esr)
install_firefox_esr install_firefox_esr "$fchoice"
;; ;;
floorp) floorp)
_enable_floorp_repo _enable_floorp_repo
_run_install floorp _run_install floorp
echo -e "${GREEN}Floorp installed.${NC}" echo -e "${GREEN}Floorp installed.${NC}"
;; ;;
librewolf) librewolf)
_enable_librewolf_repo _enable_librewolf_repo
_run_install librewolf _run_install librewolf
echo -e "${GREEN}LibreWolf installed.${NC}" echo -e "${GREEN}LibreWolf installed.${NC}"
;; ;;
palemoon) palemoon)
install_palemoon install_palemoon
;; ;;
tailscale) tailscale)
_enable_tailscale_repo _enable_tailscale_repo
_run_install tailscale _run_install tailscale
echo -e "${GREEN}Tailscale installed.${NC}" echo -e "${GREEN}Tailscale installed.${NC}"
;; ;;
mullvad-vpn) mullvad-vpn)
_enable_mullvad_repo _enable_mullvad_repo
_run_install mullvad-vpn _run_install mullvad-vpn
echo -e "${GREEN}Mullvad VPN installed.${NC}" echo -e "${GREEN}Mullvad VPN installed.${NC}"
;; ;;
mullvad-browser) mullvad-browser)
_enable_mullvad_repo _enable_mullvad_repo
_run_install mullvad-browser _run_install mullvad-browser
echo -e "${GREEN}Mullvad Browser installed.${NC}" echo -e "${GREEN}Mullvad Browser installed.${NC}"
;; ;;
protonvpn) protonvpn)
install_protonvpn install_protonvpn
;; ;;
riseup-vpn) riseup-vpn)
install_backports_or_stable riseup-vpn install_backports_or_stable riseup-vpn
;; ;;
w3m) w3m)
local need=() local need=()
! is_installed "w3m" && need+=("w3m") ! is_installed "w3m" && need+=("w3m")
! is_installed "w3m-img" && need+=("w3m-img") ! is_installed "w3m-img" && need+=("w3m-img")
! is_installed "ca-certificates" && need+=("ca-certificates") ! is_installed "ca-certificates" && need+=("ca-certificates")
! is_installed "xsel" && need+=("xsel") ! is_installed "xsel" && need+=("xsel")
if [ ${#need[@]} -gt 0 ]; then if [ ${#need[@]} -gt 0 ]; then
_run_install_batch w3m w3m-img ca-certificates xsel _run_install_batch w3m w3m-img ca-certificates xsel
else else
echo "w3m already installed." echo "w3m already installed."
fi fi
;; ;;
*) *)
if ! is_installed "$pkg"; then if ! is_installed "$pkg"; then
_run_install "$pkg" _run_install "$pkg"
else else
echo "$pkg already installed." echo "$pkg already installed."
fi fi
;; ;;
esac esac
done done
@@ -256,6 +292,7 @@ _cat_internet() {
} }
install_firefox_mozilla() { install_firefox_mozilla() {
local fchoice="${1:-}"
if [ "$DEBIAN_VERSION" -lt 12 ] 2>/dev/null; then if [ "$DEBIAN_VERSION" -lt 12 ] 2>/dev/null; then
_msg "Firefox" "Mozilla Firefox is only available on\nDebian 12 (Bookworm) and 13 (Trixie).\n\nSkipping installation." 10 60 _msg "Firefox" "Mozilla Firefox is only available on\nDebian 12 (Bookworm) and 13 (Trixie).\n\nSkipping installation." 10 60
return 1 return 1
@@ -267,13 +304,24 @@ install_firefox_mozilla() {
fi fi
if is_installed "firefox-esr"; then if is_installed "firefox-esr"; then
if _confirm "Firefox ESR" "Firefox ESR is installed.\nRemove it before installing Mozilla Firefox?"; then case "$fchoice" in
echo "Removing Firefox ESR..." both)
echo -e "${CYAN}[INFO] Keeping Firefox ESR (both selected).${NC}"
;;
mozilla)
echo "Removing Firefox ESR (as selected)..."
sudo apt remove -y firefox-esr sudo apt remove -y firefox-esr
else ;;
echo "Keeping Firefox ESR." *)
return if _confirm "Firefox ESR" "Firefox ESR is installed.\nRemove it before installing Mozilla Firefox?"; then
fi echo "Removing Firefox ESR..."
sudo apt remove -y firefox-esr
else
echo "Keeping Firefox ESR."
return
fi
;;
esac
fi fi
_enable_mozilla_repo _enable_mozilla_repo
@@ -282,19 +330,31 @@ install_firefox_mozilla() {
} }
install_firefox_esr() { install_firefox_esr() {
local fchoice="${1:-}"
if is_installed "firefox-esr"; then if is_installed "firefox-esr"; then
echo "Firefox ESR is already installed." echo "Firefox ESR is already installed."
return return
fi fi
if command -v firefox &>/dev/null; then if command -v firefox &>/dev/null; then
if _confirm "Firefox" "Mozilla Firefox is installed.\nRemove it before installing Firefox ESR?"; then case "$fchoice" in
echo "Removing Mozilla Firefox..." both)
echo -e "${CYAN}[INFO] Keeping Mozilla Firefox (both selected).${NC}"
;;
esr)
echo "Removing Mozilla Firefox (as selected)..."
sudo apt remove -y firefox sudo apt remove -y firefox
else ;;
echo "Keeping Mozilla Firefox." *)
return if _confirm "Firefox" "Mozilla Firefox is installed.\nRemove it before installing Firefox ESR?"; then
fi echo "Removing Mozilla Firefox..."
sudo apt remove -y firefox
else
echo "Keeping Mozilla Firefox."
return
fi
;;
esac
fi fi
_run_cmd "Firefox ESR" "sudo apt install -y firefox-esr" "Installing Firefox ESR..." _run_cmd "Firefox ESR" "sudo apt install -y firefox-esr" "Installing Firefox ESR..."
+13 -6
View File
@@ -10,17 +10,21 @@ _enable_temurin_repo() {
_run_cmd "extrepo" "sudo apt install -y extrepo" "Installing extrepo..." _run_cmd "extrepo" "sudo apt install -y extrepo" "Installing extrepo..."
fi fi
_run_cmd "Temurin" "sudo extrepo enable temurin" "Enabling Adoptium Temurin repository..." _run_cmd "Temurin" "sudo extrepo enable temurin" "Enabling Adoptium Temurin repository..."
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." _ensure_apt_updated
} }
install_minecraft_java() { install_minecraft_java() {
local choices local choices
choices=$(_checklist "Java Runtimes for Minecraft" \ choices=$(_checklist "Java Runtimes for Minecraft" \
"Select Java version(s) to install:" 14 65 3 \ "Select Java version(s) to install:" 15 65 4 \
"8" "Java 8 — Classic mods & Minecraft <= 1.16.5" OFF \ "8" "Java 8 — Classic mods & Minecraft <= 1.16.5" OFF \
"17" "Java 17 — Minecraft 1.17 to 1.20.4" ON \ "17" "Java 17 — Minecraft 1.17 to 1.20.4" ON \
"21" "Java 21 — Modern Minecraft >= 1.20.5 & 1.21+" OFF) "21" "Java 21 — Modern Minecraft >= 1.20.5 & 1.21+" OFF \
[ -z "$choices" ] && { echo "No Java version selected."; return; } "25" "Java 25 — Minecraft 26+" OFF)
[ -z "$choices" ] && {
echo "No Java version selected."
return
}
_enable_temurin_repo _enable_temurin_repo
local cleaned local cleaned
cleaned=$(echo "$choices" | tr -d '"') cleaned=$(echo "$choices" | tr -d '"')
@@ -37,7 +41,10 @@ _install_dev_java() {
"17" "Java 17 LTS Development Kit" \ "17" "Java 17 LTS Development Kit" \
"21" "Java 21 LTS Development Kit" \ "21" "Java 21 LTS Development Kit" \
"25" "Java 25 LTS Development Kit") "25" "Java 25 LTS Development Kit")
[ -z "$ver" ] && { echo "No JDK version selected."; return; } [ -z "$ver" ] && {
echo "No JDK version selected."
return
}
_enable_temurin_repo _enable_temurin_repo
_run_install "temurin-${ver}-jdk" _run_install "temurin-${ver}-jdk"
} }
+13 -11
View File
@@ -10,7 +10,7 @@ _enable_onlyoffice_repo() {
fi fi
_run_cmd "OnlyOffice" "sudo extrepo enable onlyoffice-desktopeditors" "Enabling OnlyOffice repository..." _run_cmd "OnlyOffice" "sudo extrepo enable onlyoffice-desktopeditors" "Enabling OnlyOffice repository..."
fi fi
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." _ensure_apt_updated
} }
install_onlyoffice() { install_onlyoffice() {
@@ -36,7 +36,7 @@ install_joplin() {
if [ ! -f /etc/apt/sources.list.d/extrepo_joplin.sources ]; then if [ ! -f /etc/apt/sources.list.d/extrepo_joplin.sources ]; then
_run_cmd "Joplin" "sudo extrepo enable joplin" "Enabling Joplin repository..." _run_cmd "Joplin" "sudo extrepo enable joplin" "Enabling Joplin repository..."
fi fi
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." _ensure_apt_updated
if ! is_installed "joplin"; then if ! is_installed "joplin"; then
_run_cmd "Joplin" "sudo apt install -y joplin" "Installing Joplin..." _run_cmd "Joplin" "sudo apt install -y joplin" "Installing Joplin..."
echo -e "${GREEN}Joplin installed.${NC}" echo -e "${GREEN}Joplin installed.${NC}"
@@ -84,8 +84,8 @@ _cat_office() {
local -a items=() local -a items=()
if ! $headless; then if ! $headless; then
items+=( items+=(
"onlyoffice" "OnlyOffice Desktop Editors (extrepo)" OFF "onlyoffice" "OnlyOffice Desktop Editors (extrepo)" OFF
"libreoffice" "LibreOffice (backports on Bookworm/Trixie)" OFF "libreoffice" "LibreOffice (backports on Bookworm/Trixie)" OFF
) )
if [ "$DEBIAN_VERSION" = "12" ] || [ "$DEBIAN_VERSION" = "13" ]; then if [ "$DEBIAN_VERSION" = "12" ] || [ "$DEBIAN_VERSION" = "13" ]; then
items+=( items+=(
@@ -97,18 +97,20 @@ _cat_office() {
local item_count=${#items[@]} local item_count=${#items[@]}
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "Office & Productivity" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(
"${items[@]}" \ _checklist "Office & Productivity" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \
) "${items[@]}"
)
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
case $pkg in case $pkg in
onlyoffice) install_onlyoffice ;; onlyoffice) install_onlyoffice ;;
libreoffice) install_libreoffice_bpo ;; libreoffice) install_libreoffice_bpo ;;
joplin) install_joplin ;; joplin) install_joplin ;;
esac esac
done done
} }
+51 -38
View File
@@ -5,64 +5,77 @@ _cat_programming() {
local headless=false local headless=false
_is_headless && headless=true _is_headless && headless=true
local -a items=() local -a items=()
local vim_state; vim_state=$(_state "vim") local vim_state
local neovim_state; neovim_state=$(_state "neovim") vim_state=$(_state "vim")
local hx_state; hx_state=$(_state "hx") local neovim_state
local nano_state; nano_state=$(_state "nano") neovim_state=$(_state "neovim")
local emacs_state; emacs_state=$(_state "emacs") local hx_state
hx_state=$(_state "hx")
local nano_state
nano_state=$(_state "nano")
local emacs_state
emacs_state=$(_state "emacs")
items+=( items+=(
"vim" "Classic terminal editor" "$vim_state" "vim" "Classic terminal editor" "$vim_state"
"neovim" "Modern vim fork" "$neovim_state" "neovim" "Modern vim fork" "$neovim_state"
"hx" "Helix modal editor (Rust)" "$hx_state" "hx" "Helix modal editor (Rust)" "$hx_state"
"nano" "Simple terminal editor" "$nano_state" "nano" "Simple terminal editor" "$nano_state"
"emacs" "Extensible editor / IDE" "$emacs_state" "emacs" "Extensible editor / IDE" "$emacs_state"
) )
if ! $headless; then if ! $headless; then
local vimgtk_state; vimgtk_state=$(_state "vim-gtk3") local vimgtk_state
local kate_state; kate_state=$(_state "kate") vimgtk_state=$(_state "vim-gtk3")
local mousepad_state; mousepad_state=$(_state "mousepad") local kate_state
local gedit_state; gedit_state=$(_state "gedit") kate_state=$(_state "kate")
local geany_state; geany_state=$(_state "geany") local mousepad_state
local gte_state; gte_state=$(_state "gnome-text-editor") mousepad_state=$(_state "mousepad")
local gedit_state
gedit_state=$(_state "gedit")
local geany_state
geany_state=$(_state "geany")
local gte_state
gte_state=$(_state "gnome-text-editor")
local codium_state="OFF" local codium_state="OFF"
if command -v codium &>/dev/null; then if command -v codium &>/dev/null; then
codium_state="ON" codium_state="ON"
fi fi
items+=( items+=(
"vim-gtk3" "Vim with GTK3 GUI" "$vimgtk_state" "vim-gtk3" "Vim with GTK3 GUI" "$vimgtk_state"
"kate" "KDE advanced text editor" "$kate_state" "kate" "KDE advanced text editor" "$kate_state"
"mousepad" "Xfce text editor" "$mousepad_state" "mousepad" "Xfce text editor" "$mousepad_state"
"gedit" "GNOME text editor" "$gedit_state" "gedit" "GNOME text editor" "$gedit_state"
"geany" "Lightweight IDE" "$geany_state" "geany" "Lightweight IDE" "$geany_state"
"gnome-text-editor" "GNOME modern text editor" "$gte_state" "gnome-text-editor" "GNOME modern text editor" "$gte_state"
"vscodium" "VS Code open-source (extrepo)" "$codium_state" "vscodium" "VS Code open-source (extrepo)" "$codium_state"
) )
fi fi
local item_count=${#items[@]} local item_count=${#items[@]}
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "Programming Applications" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(
"${items[@]}" \ _checklist "Programming Applications" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \
) "${items[@]}"
)
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
case $pkg in case $pkg in
vscodium) vscodium)
install_vscodium install_vscodium
;; ;;
*) *)
if ! is_installed "$pkg"; then if ! is_installed "$pkg"; then
_run_install "$pkg" _run_install "$pkg"
else else
echo "$pkg already installed." echo "$pkg already installed."
fi fi
;; ;;
esac esac
done done
@@ -76,7 +89,7 @@ _enable_vscodium_repo() {
fi fi
_run_cmd "VSCodium" "sudo extrepo enable vscodium" "Enabling VSCodium repository..." _run_cmd "VSCodium" "sudo extrepo enable vscodium" "Enabling VSCodium repository..."
fi fi
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." _ensure_apt_updated
} }
install_vscodium() { install_vscodium() {
+84 -36
View File
@@ -1,4 +1,4 @@
# software_centers.sh — Standalone Software Center installer # software_centers.sh — Standalone Software Center + Flatpak installer
_cat_software_centers() { _cat_software_centers() {
local headless=false local headless=false
@@ -7,46 +7,94 @@ _cat_software_centers() {
echo "Software centers require a GUI — skipping." echo "Software centers require a GUI — skipping."
return return
fi fi
local de_type local de_type
de_type=$(_detect_desktop_type) de_type=$(_detect_desktop_type)
local sc_choice
sc_choice=$(_menu "Software Centers" "Choose a software store to install:" 12 65 3 \
"gnome-software" "Software Center for GNOME" \
"plasma-discover" "Software manager for Plasma" \
"synaptic" "Classic APT package manager (GTK)" \
)
[ -z "$sc_choice" ] && return
if [ "$sc_choice" = "synaptic" ]; then local -a items=()
_run_cmd "Install" "sudo apt install -y synaptic" "Installing synaptic..." local gs_state; gs_state=$(_state "gnome-software")
echo -e "${GREEN}synaptic installed.${NC}" local pd_state; pd_state=$(_state "plasma-discover")
return local sy_state; sy_state=$(_state "synaptic")
fi local fp_state; fp_state=$(_state "flatpak")
items+=(
"gnome-software" "Software Center for GNOME" "$gs_state"
"plasma-discover" "Software manager for Plasma" "$pd_state"
"synaptic" "Classic APT package manager (GTK)" "$sy_state"
"flatpak" "Flatpak sandbox + Flathub" "$fp_state"
)
if { [ "$de_type" = "qt" ] && [ "$sc_choice" = "gnome-software" ]; } || \ local item_count=${#items[@]}
{ [ "$de_type" = "gtk" ] && [ "$sc_choice" = "plasma-discover" ]; }; then local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
_msg "Warning" "Warning: This store requires extra background libraries \ local choices
choices=$(_checklist "Software Center & Flatpak" \
"Check [*] the packages you want installed.\n" \
$TUI_ALTO $TUI_ANCHO $lista_alto "${items[@]}")
clear
[ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do
case $pkg in
gnome-software)
if [ "$de_type" = "qt" ]; then
_msg "Warning" "Warning: This store requires extra background libraries \
and may look visually inconsistent with your current desktop environment." and may look visually inconsistent with your current desktop environment."
! _confirm "Continue?" "Install anyway?" && return ! _confirm "Continue?" "Install anyway?" && continue
fi fi
_run_cmd "Install" "sudo apt install -y gnome-software" "Installing GNOME Software..."
echo -e "${GREEN}gnome-software installed.${NC}"
;;
plasma-discover)
if [ "$de_type" = "gtk" ]; then
_msg "Warning" "Warning: This store requires extra background libraries \
and may look visually inconsistent with your current desktop environment."
! _confirm "Continue?" "Install anyway?" && continue
fi
_run_cmd "Install" "sudo apt install -y plasma-discover" "Installing Plasma Discover..."
echo -e "${GREEN}plasma-discover installed.${NC}"
;;
synaptic)
_run_cmd "Install" "sudo apt install -y synaptic" "Installing synaptic..."
echo -e "${GREEN}synaptic installed.${NC}"
;;
flatpak)
if ! is_installed "flatpak"; then
_run_cmd "Flatpak" "sudo apt install -y flatpak" "Installing Flatpak..."
else
echo "Flatpak already installed."
fi
flatpak remote-add --if-not-exists flathub \
https://dl.flathub.org/repo/flathub.flatpakrepo
echo "Flathub repository added."
_run_cmd "Install" "sudo apt install -y $sc_choice" "Installing ${sc_choice}..." if command -v plasma-discover &>/dev/null; then
if ! is_installed "plasma-discover-backend-flatpak" 2>/dev/null; then
if _confirm "Discover Backend" "Install Flatpak backend for Plasma Discover?"; then
_run_cmd "Backend" "sudo apt install -y plasma-discover-backend-flatpak" "Installing Flatpak backend..."
fi
fi
elif command -v gnome-software &>/dev/null; then
if ! is_installed "gnome-software-plugin-flatpak" 2>/dev/null; then
if _confirm "GNOME Plugin" "Install Flatpak plugin for GNOME Software?"; then
_run_cmd "Plugin" "sudo apt install -y gnome-software-plugin-flatpak" "Installing Flatpak plugin..."
fi
fi
else
if [ "$de_type" = "qt" ]; then
if _confirm "Software Center" "Install Plasma Discover for Flatpak management?"; then
_run_cmd "Discover" "sudo apt install -y plasma-discover plasma-discover-backend-flatpak" "Installing Discover..."
fi
else
if _confirm "Software Center" "Install GNOME Software for Flatpak management?"; then
_run_cmd "GNOME Software" "sudo apt install -y gnome-software gnome-software-plugin-flatpak" "Installing GNOME Software..."
fi
fi
fi
echo -e "${GREEN}A reboot is recommended.${NC}"
;;
esac
done
if _confirm "Flatpak Support" "Do you want to enable Flatpak support for this software center?"; then echo -e "${GREEN}Software center & Flatpak setup complete.${NC}"
local bpkg
if [ "$sc_choice" = "gnome-software" ]; then
bpkg="gnome-software-plugin-flatpak"
else
bpkg="plasma-discover-backend-flatpak"
fi
if ! is_installed "flatpak"; then
_run_cmd "Flatpak" "sudo apt install -y flatpak" "Installing Flatpak..."
fi
_run_cmd "Plugin" "sudo apt install -y $bpkg" "Installing $bpkg..."
flatpak remote-add --if-not-exists flathub \
https://dl.flathub.org/repo/flathub.flatpakrepo
echo "Flathub repository added."
fi
echo -e "${GREEN}Software store installed.${NC}"
} }
+213 -220
View File
@@ -7,10 +7,14 @@ _detect_desktop_type() {
desktop="${desktop,,}" desktop="${desktop,,}"
case "$desktop" in case "$desktop" in
*kde*|*lxqt*|*razor*|*plasma*) *kde* | *lxqt* | *razor* | *plasma*)
echo "qt"; return ;; echo "qt"
*gnome*|*xfce*|*cinnamon*|*mate*|*lxde*|*budgie*|*sway*|*hyprland*|*i3*|*bspwm*|*openbox*|*fluxbox*) return
echo "gtk"; return ;; ;;
*gnome* | *xfce* | *cinnamon* | *mate* | *lxde* | *budgie* | *sway* | *hyprland* | *i3* | *bspwm* | *openbox* | *fluxbox*)
echo "gtk"
return
;;
esac esac
echo "gtk" echo "gtk"
@@ -20,263 +24,252 @@ _cat_general() {
local headless=false local headless=false
_is_headless && headless=true _is_headless && headless=true
local -a items=() local -a items=()
local btop_state; btop_state=$(_state "btop") local btop_state
btop_state=$(_state "btop")
local compress_state local compress_state
if is_installed "zip" && is_installed "unzip" && is_installed "p7zip-full"; then if is_installed "zip" && is_installed "unzip" && is_installed "p7zip-full"; then
compress_state="ON" compress_state="ON"
else else
compress_state="OFF" compress_state="OFF"
fi fi
local cpufetch_state; cpufetch_state=$(_state "cpufetch") local cpufetch_state
local cpu_x_state; cpu_x_state=$(_state "cpu-x") cpufetch_state=$(_state "cpufetch")
local cpu_x_state
cpu_x_state=$(_state "cpu-x")
local curl_wget_state local curl_wget_state
if is_installed "curl" && is_installed "wget"; then if is_installed "curl" && is_installed "wget"; then
curl_wget_state="ON" curl_wget_state="ON"
else else
curl_wget_state="OFF" curl_wget_state="OFF"
fi fi
local extrepo_state; extrepo_state=$(_state "extrepo") local extrepo_state
local flatpak_state; flatpak_state=$(_state "flatpak") extrepo_state=$(_state "extrepo")
local fwupd_state; fwupd_state=$(_state "fwupd") local fwupd_state
local htop_state; htop_state=$(_state "htop") fwupd_state=$(_state "fwupd")
local inxi_state; inxi_state=$(_state "inxi") local htop_state
local jq_state; jq_state=$(_state "jq") htop_state=$(_state "htop")
local kvm_state; kvm_state=$(_state "virt-manager") local inxi_state
local lshw_state; lshw_state=$(_state "lshw") inxi_state=$(_state "inxi")
local mc_state; mc_state=$(_state "mc") local jq_state
local nala_state; nala_state=$(_state "nala") jq_state=$(_state "jq")
local ncdu_state; ncdu_state=$(_state "ncdu") local kvm_state
local tmux_state; tmux_state=$(_state "tmux") kvm_state=$(_state "virt-manager")
local wine_state; wine_state=$(_state "wine") local lshw_state
local nvme_state; nvme_state=$(_state "nvme-cli") lshw_state=$(_state "lshw")
local mc_state
mc_state=$(_state "mc")
local nala_state
nala_state=$(_state "nala")
local ncdu_state
ncdu_state=$(_state "ncdu")
local tmux_state
tmux_state=$(_state "tmux")
local wine_state
wine_state=$(_state "wine")
local nvme_state
nvme_state=$(_state "nvme-cli")
items+=( items+=(
"btop" "Resource monitor (fancy top)" "$btop_state" "btop" "Resource monitor (fancy top)" "$btop_state"
"compress" "Compression tools (zip, unrar, 7z)" "$compress_state" "compress" "Compression tools (zip, unrar, 7z)" "$compress_state"
"cpufetch" "CPU info fetcher" "$cpufetch_state" "cpufetch" "CPU info fetcher" "$cpufetch_state"
"cpu-x" "CPU-X (alternative to CPU-Z)" "$cpu_x_state" "cpu-x" "CPU-X (alternative to CPU-Z)" "$cpu_x_state"
"curl-wget" "HTTP transfer tools (curl, wget)" "$curl_wget_state" "curl-wget" "HTTP transfer tools (curl, wget)" "$curl_wget_state"
"extrepo" "External repository manager" "$extrepo_state" "extrepo" "External repository manager" "$extrepo_state"
"flatpak" "Flatpak sandbox + Flathub" "$flatpak_state" "fwupd" "Firmware update daemon" "$fwupd_state"
"fwupd" "Firmware update daemon" "$fwupd_state" "htop" "Interactive process viewer" "$htop_state"
"htop" "Interactive process viewer" "$htop_state" "inxi" "System information tool" "$inxi_state"
"inxi" "System information tool" "$inxi_state" "jq" "JSON command-line processor" "$jq_state"
"jq" "JSON command-line processor" "$jq_state" "kvm" "QEMU/KVM virtualization" "$kvm_state"
"kvm" "QEMU/KVM virtualization" "$kvm_state" "lshw" "List hardware details" "$lshw_state"
"lshw" "List hardware details" "$lshw_state" "mc" "Midnight Commander (file manager)" "$mc_state"
"mc" "Midnight Commander (file manager)" "$mc_state" "nala" "APT frontend (parallel downloads)" "$nala_state"
"nala" "APT frontend (parallel downloads)" "$nala_state" "ncdu" "Disk usage analyzer (ncurses)" "$ncdu_state"
"ncdu" "Disk usage analyzer (ncurses)" "$ncdu_state" "nvme-cli" "NVMe SSD health monitoring" "$nvme_state"
"nvme-cli" "NVMe SSD health monitoring" "$nvme_state" "tmux" "Terminal multiplexer" "$tmux_state"
"tmux" "Terminal multiplexer" "$tmux_state" "wine" "Windows compatibility layer" "$wine_state"
"wine" "Windows compatibility layer" "$wine_state"
) )
if ! $headless; then if ! $headless; then
local bleachbit_state; bleachbit_state=$(_state "bleachbit") local bleachbit_state
local conky_state; conky_state=$(_state "conky") bleachbit_state=$(_state "bleachbit")
local gdebi_state; gdebi_state=$(_state "gdebi") local conky_state
local corectrl_state; corectrl_state=$(_state "corectrl") conky_state=$(_state "conky-all")
local dcgtk_state; dcgtk_state=$(_state "doublecmd-gtk") local gdebi_state
local dcqt_state; dcqt_state=$(_state "doublecmd-qt") gdebi_state=$(_state "gdebi")
local disks_state; disks_state=$(_state "gnome-disk-utility") local corectrl_state
local gparted_state; gparted_state=$(_state "gparted") corectrl_state=$(_state "corectrl")
local hardinfo_state; hardinfo_state=$(_state "hardinfo") local dcgtk_state
local psensor_state; psensor_state=$(_state "psensor") dcgtk_state=$(_state "doublecmd-gtk")
local timeshift_state; timeshift_state=$(_state "timeshift") local dcqt_state
dcqt_state=$(_state "doublecmd-qt")
local disks_state
disks_state=$(_state "gnome-disk-utility")
local gparted_state
gparted_state=$(_state "gparted")
local hardinfo_state
hardinfo_state=$(_state "hardinfo")
local psensor_state
psensor_state=$(_state "psensor")
local timeshift_state
timeshift_state=$(_state "timeshift")
items+=( items+=(
"bleachbit" "System cleaner (GUI)" "$bleachbit_state" "bleachbit" "System cleaner (GUI)" "$bleachbit_state"
"conky" "System monitor for desktop" "$conky_state" "conky-all" "System monitor for desktop" "$conky_state"
"gdebi" "Install .deb packages with deps" "$gdebi_state" "gdebi" "Install .deb packages with deps" "$gdebi_state"
"corectrl" "AMD GPU control (CoreCtrl)" "$corectrl_state" "corectrl" "AMD GPU control (CoreCtrl)" "$corectrl_state"
"doublecmd-gtk" "Dual-panel file manager (GTK)" "$dcgtk_state" "doublecmd-gtk" "Dual-panel file manager (GTK)" "$dcgtk_state"
"doublecmd-qt" "Dual-panel file manager (Qt)" "$dcqt_state" "doublecmd-qt" "Dual-panel file manager (Qt)" "$dcqt_state"
"gnome-disk-utility" "Disk management GUI" "$disks_state" "gnome-disk-utility" "Disk management GUI" "$disks_state"
"gparted" "GNOME partition editor" "$gparted_state" "gparted" "GNOME partition editor" "$gparted_state"
"hardinfo" "Graphical system profiler" "$hardinfo_state" "hardinfo" "Graphical system profiler" "$hardinfo_state"
"psensor" "Hardware temperature monitor" "$psensor_state" "psensor" "Hardware temperature monitor" "$psensor_state"
"timeshift" "System restore snapshots" "$timeshift_state" "timeshift" "System restore snapshots" "$timeshift_state"
) )
fi fi
local item_count=${#items[@]} local item_count=${#items[@]}
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count)) local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices local choices
choices=$(_checklist "System Tools" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \ choices=$(
"${items[@]}" \ _checklist "System Tools" "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $lista_alto \
) "${items[@]}"
)
clear clear
[ -z "$choices" ] && return [ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"') local cleaned
cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do for pkg in $cleaned; do
case $pkg in case $pkg in
compress) compress)
local need=() local need=()
! is_installed "zip" && need+=("zip") ! is_installed "zip" && need+=("zip")
! is_installed "unzip" && need+=("unzip") ! is_installed "unzip" && need+=("unzip")
! is_installed "rar" && need+=("rar") ! is_installed "rar" && need+=("rar")
! is_installed "unrar" && need+=("unrar") ! is_installed "unrar" && need+=("unrar")
! is_installed "p7zip-full" && need+=("p7zip-full") ! is_installed "p7zip-full" && need+=("p7zip-full")
! is_installed "p7zip-rar" && need+=("p7zip-rar") ! is_installed "p7zip-rar" && need+=("p7zip-rar")
if [ ${#need[@]} -gt 0 ]; then if [ ${#need[@]} -gt 0 ]; then
_run_install_batch "${need[@]}" _run_install_batch "${need[@]}"
echo -e "${GREEN}Compression utilities installed.${NC}" echo -e "${GREEN}Compression utilities installed.${NC}"
fi fi
;; ;;
curl-wget) curl-wget)
local need=() local need=()
! is_installed "curl" && need+=("curl") ! is_installed "curl" && need+=("curl")
! is_installed "wget" && need+=("wget") ! is_installed "wget" && need+=("wget")
if [ ${#need[@]} -gt 0 ]; then if [ ${#need[@]} -gt 0 ]; then
_run_install_batch "${need[@]}" _run_install_batch "${need[@]}"
else else
echo "curl and wget already installed." echo "curl and wget already installed."
fi fi
;; ;;
extrepo) extrepo)
install_backports_or_stable extrepo install_backports_or_stable extrepo
;; ;;
flatpak) fwupd)
if ! is_installed "flatpak"; then if ! is_installed "fwupd"; then
_run_cmd "Flatpak" "sudo apt install -y flatpak" "Installing Flatpak..." _run_cmd "fwupd" "sudo apt install -y fwupd" "Installing fwupd..."
else else
echo "Flatpak already installed." echo "fwupd already installed."
fi fi
flatpak remote-add --if-not-exists flathub \ if _confirm "Firmware Scan" "Scan for firmware updates now?\n\nThis will run:\n fwupdmgr refresh\n fwupdmgr get-updates\n fwupdmgr update (if available)"; then
https://dl.flathub.org/repo/flathub.flatpakrepo _run_cmd "fwupd" "sudo fwupdmgr refresh --force" "Refreshing firmware metadata..."
echo "Flathub repository added." echo ""
echo "Checking for firmware updates..."
if command -v plasma-discover &>/dev/null; then sudo fwupdmgr get-updates 2>&1 || true
if ! is_installed "plasma-discover-backend-flatpak" 2>/dev/null; then if sudo fwupdmgr get-updates 2>&1 | grep -q "available"; then
if _confirm "Discover Backend" "Install Flatpak backend for Plasma Discover?"; then if _confirm "Firmware Update" "Firmware updates are available.\nInstall them now?"; then
_run_cmd "Backend" "sudo apt install -y plasma-discover-backend-flatpak" "Installing Flatpak backend..." _run_cmd "fwupd" "sudo fwupdmgr update -y" "Installing firmware updates..."
fi
fi
elif command -v gnome-software &>/dev/null; then
if ! is_installed "gnome-software-plugin-flatpak" 2>/dev/null; then
if _confirm "GNOME Plugin" "Install Flatpak plugin for GNOME Software?"; then
_run_cmd "Plugin" "sudo apt install -y gnome-software-plugin-flatpak" "Installing Flatpak plugin..."
fi
fi
else
local de_type
de_type=$(_detect_desktop_type)
if [ "$de_type" = "qt" ]; then
if _confirm "Software Center" "Install Plasma Discover for Flatpak management?"; then
_run_cmd "Discover" "sudo apt install -y plasma-discover plasma-discover-backend-flatpak" "Installing Discover..."
fi
else else
if _confirm "Software Center" "Install GNOME Software for Flatpak management?"; then echo "Skipping firmware update."
_run_cmd "GNOME Software" "sudo apt install -y gnome-software gnome-software-plugin-flatpak" "Installing GNOME Software..." _pause
fi
fi fi
fi
echo -e "${GREEN}A reboot is recommended.${NC}"
;;
fwupd)
if ! is_installed "fwupd"; then
_run_cmd "fwupd" "sudo apt install -y fwupd" "Installing fwupd..."
else else
echo "fwupd already installed." echo "No firmware updates available."
fi
if _confirm "Firmware Scan" "Scan for firmware updates now?\n\nThis will run:\n fwupdmgr refresh\n fwupdmgr get-updates\n fwupdmgr update (if available)"; then
_run_cmd "fwupd" "sudo fwupdmgr refresh --force" "Refreshing firmware metadata..."
echo ""
echo "Checking for firmware updates..."
sudo fwupdmgr get-updates 2>&1 || true
if sudo fwupdmgr get-updates 2>&1 | grep -q "available"; then
if _confirm "Firmware Update" "Firmware updates are available.\nInstall them now?"; then
_run_cmd "fwupd" "sudo fwupdmgr update -y" "Installing firmware updates..."
else
echo "Skipping firmware update."
_pause
fi
else
echo "No firmware updates available."
_pause _pause
fi
fi fi
echo -e "${GREEN}fwupd setup complete.${NC}" fi
_pause echo -e "${GREEN}fwupd setup complete.${NC}"
;; _pause
kvm) ;;
if ! is_installed "virt-manager"; then kvm)
_run_cmd "KVM" "sudo apt install -y qemu-system-x86 qemu-utils libvirt-daemon-system libvirt-clients bridge-utils virt-manager" "Installing KVM..." if ! is_installed "virt-manager"; then
sudo adduser "$USER" libvirt 2>/dev/null || true _run_cmd "KVM" "sudo apt install -y qemu-system-x86 qemu-utils libvirt-daemon-system libvirt-clients bridge-utils virt-manager" "Installing KVM..."
sudo adduser "$USER" kvm 2>/dev/null || true sudo adduser "$USER" libvirt 2>/dev/null || true
echo -e "${GREEN}QEMU/KVM installed. A reboot is recommended.${NC}" sudo adduser "$USER" kvm 2>/dev/null || true
echo -e "${GREEN}QEMU/KVM installed. A reboot is recommended.${NC}"
else
echo "QEMU/KVM already installed."
fi
;;
wine)
if ! is_installed "wine64"; then
_run_cmd "Wine" "sudo apt install -y --no-install-recommends wine64 fonts-wine" "Installing Wine (64-bit only)..."
local wine_ver
wine_ver=$(wine --version 2>/dev/null)
if [ -n "$wine_ver" ]; then
echo -e "${GREEN}Wine (64-bit) installed: ${wine_ver}${NC}"
else else
echo "QEMU/KVM already installed." echo -e "${YELLOW}Wine installed but version check failed.${NC}"
fi fi
;; else
wine) echo "Wine64 already installed."
if ! is_installed "wine64"; then fi
_run_cmd "Wine" "sudo apt install -y --no-install-recommends wine64 fonts-wine" "Installing Wine (64-bit only)..." ;;
local wine_ver nvme-cli)
wine_ver=$(wine --version 2>/dev/null) if ! timeout 2 lsblk -d -o TRAN 2>/dev/null | grep -q "^nvme$"; then
if [ -n "$wine_ver" ]; then echo "No NVMe controller detected. Skipping."
echo -e "${GREEN}Wine (64-bit) installed: ${wine_ver}${NC}" continue
else fi
echo -e "${YELLOW}Wine installed but version check failed.${NC}" if ! is_installed "nvme-cli"; then
fi _run_cmd "nvme-cli" "sudo apt install -y nvme-cli" "Installing nvme-cli..."
else fi
echo "Wine64 already installed." local nvme_devs=()
fi while read -r dev; do
;; nvme_devs+=("$dev")
nvme-cli) done < <(timeout 2 lsblk -d -o NAME,TRAN 2>/dev/null | awk '$2 == "nvme" {print $1}')
if ! lsblk -d -o TRAN 2>/dev/null | grep -q "^nvme$"; then if [ ${#nvme_devs[@]} -eq 0 ]; then
echo "No NVMe controller detected. Skipping." echo "No NVMe block devices found for health check."
continue continue
fi fi
if ! is_installed "nvme-cli"; then local dev_list=""
_run_cmd "nvme-cli" "sudo apt install -y nvme-cli" "Installing nvme-cli..." local dev
fi for dev in "${nvme_devs[@]}"; do
local nvme_devs=() [ -n "$dev_list" ] && dev_list+=", "
while read -r dev; do dev_list+="/dev/${dev}"
nvme_devs+=("$dev") done
done < <(lsblk -d -o NAME,TRAN 2>/dev/null | awk '$2 == "nvme" {print $1}') if _confirm "NVMe Health" "Run smart-log on ${#nvme_devs[@]} NVMe device(s): ${dev_list}?"; then
if [ ${#nvme_devs[@]} -eq 0 ]; then echo ""
echo "No NVMe block devices found for health check."
continue
fi
local dev_list=""
local dev
for dev in "${nvme_devs[@]}"; do for dev in "${nvme_devs[@]}"; do
[ -n "$dev_list" ] && dev_list+=", " local cw="" temp="" pu=""
dev_list+="/dev/${dev}" while IFS= read -r line; do
done case "$line" in
if _confirm "NVMe Health" "Run smart-log on ${#nvme_devs[@]} NVMe device(s): ${dev_list}?"; then *critical_warning*) cw="${line##*: }" ;;
*temperature*) temp="${line##*: }" ;;
*percentage_used*) pu="${line##*: }" ;;
esac
done < <(sudo nvme smart-log "/dev/${dev}" 2>/dev/null || true)
echo -e "${YELLOW}━━━ /dev/${dev} ━━━${NC}"
echo -e " ${GREEN}Critical Warning:${NC} ${cw:-N/A}"
echo -e " ${GREEN}Temperature:${NC} ${temp:-N/A}"
echo -e " ${GREEN}Percentage Used:${NC} ${pu:-N/A}"
echo "" echo ""
for dev in "${nvme_devs[@]}"; do done
local cw="" temp="" pu="" _pause
while IFS= read -r line; do fi
case "$line" in ;;
*critical_warning*) cw="${line##*: }" ;; *)
*temperature*) temp="${line##*: }" ;; if ! is_installed "$pkg"; then
*percentage_used*) pu="${line##*: }" ;; _run_install "$pkg"
esac else
done < <(sudo nvme smart-log "/dev/${dev}" 2>/dev/null || true) echo "$pkg already installed."
echo -e "${YELLOW}━━━ /dev/${dev} ━━━${NC}" fi
echo -e " ${GREEN}Critical Warning:${NC} ${cw:-N/A}" ;;
echo -e " ${GREEN}Temperature:${NC} ${temp:-N/A}"
echo -e " ${GREEN}Percentage Used:${NC} ${pu:-N/A}"
echo ""
done
_pause
fi
;;
*)
if ! is_installed "$pkg"; then
_run_install "$pkg"
else
echo "$pkg already installed."
fi
;;
esac esac
done done
echo -e "${GREEN}System tools installed.${NC}" echo -e "${GREEN}System tools installed.${NC}"
_pause _pause
} }
+171 -125
View File
@@ -17,7 +17,7 @@ _detect_all_network_devices() {
PCI_NET_DEVS=() PCI_NET_DEVS=()
while IFS= read -r line; do while IFS= read -r line; do
PCI_NET_DEVS+=("$line") PCI_NET_DEVS+=("$line")
done < <(lspci -nn 2>/dev/null | grep -iE 'network controller|ethernet controller' || true) done < <(echo "$LSPCI_OUTPUT" | grep -iE 'network controller|ethernet controller' || true)
USB_WIFI_DEVS=() USB_WIFI_DEVS=()
while IFS= read -r line; do while IFS= read -r line; do
@@ -29,7 +29,7 @@ _detect_all_network_devices() {
PCI_BT_DEVS=() PCI_BT_DEVS=()
while IFS= read -r line; do while IFS= read -r line; do
PCI_BT_DEVS+=("$line") PCI_BT_DEVS+=("$line")
done < <(lspci -nn 2>/dev/null | grep -i 'Bluetooth controller' || true) done < <(echo "$LSPCI_OUTPUT" | grep -i 'Bluetooth controller' || true)
USB_BT_DEVS=() USB_BT_DEVS=()
while IFS= read -r line; do while IFS= read -r line; do
@@ -86,16 +86,16 @@ _detect_firmware_needs() {
[[ "$vendor_lc" != *intel* && "$vendor_lc" != *realtek* && "$vendor_lc" != *atheros* && "$vendor_lc" != *qualcomm* && "$vendor_lc" != *mediatek* ]] && continue [[ "$vendor_lc" != *intel* && "$vendor_lc" != *realtek* && "$vendor_lc" != *atheros* && "$vendor_lc" != *qualcomm* && "$vendor_lc" != *mediatek* ]] && continue
case "$vendor_lc" in case "$vendor_lc" in
*intel*) *intel*)
if echo "$dev" | grep -qiE 'wireless|wi-fi|wlan|802\.11'; then if echo "$dev" | grep -qiE 'wireless|wi-fi|wlan|802\.11'; then
pkg="firmware-iwlwifi" pkg="firmware-iwlwifi"
else else
pkg="firmware-intel-misc" pkg="firmware-intel-misc"
fi fi
;; ;;
*realtek*) pkg="firmware-realtek" ;; *realtek*) pkg="firmware-realtek" ;;
*atheros*|*qualcomm*) pkg="firmware-atheros" ;; *atheros* | *qualcomm*) pkg="firmware-atheros" ;;
*mediatek*) pkg="firmware-mediatek" ;; *mediatek*) pkg="firmware-mediatek" ;;
esac esac
local short_dev local short_dev
@@ -115,29 +115,6 @@ _detect_firmware_needs() {
mapfile -t _DETECTED_FW_PKGS < <(printf '%s\n' "${_DETECTED_FW_PKGS[@]}" | sort -u) mapfile -t _DETECTED_FW_PKGS < <(printf '%s\n' "${_DETECTED_FW_PKGS[@]}" | sort -u)
} }
# ── Broadcom chip classification helpers ──
_is_broadcom_brcm() {
local id="$1"
for supported in 4357 4358 4360 4727 43a0 43a1 43a2 43b1; do
[ "$id" = "$supported" ] && return 0
done
return 1
}
_is_broadcom_b43() {
local id="$1"
_is_broadcom_brcm "$id" && return 1
local dec=$((16#$id))
if [ "$dec" -ge $((16#4301)) ] && [ "$dec" -le $((16#4331)) ]; then return 0; fi
if [ "$dec" -ge $((16#4336)) ] && [ "$dec" -le $((16#4338)) ]; then return 0; fi
case "$id" in 4352) return 0 ;; esac
return 1
}
_is_broadcom_b43legacy() {
[ "$1" = "4302" ] || [ "$1" = "4306" ]
}
# ── Build plan string ── # ── Build plan string ──
_build_firmware_plan() { _build_firmware_plan() {
local plan="" local plan=""
@@ -176,7 +153,8 @@ _build_firmware_plan() {
if ! $has_bt; then if ! $has_bt; then
for dev in "${USB_WIFI_DEVS[@]}"; do for dev in "${USB_WIFI_DEVS[@]}"; do
if echo "$dev" | grep -qi 'bluetooth'; then if echo "$dev" | grep -qi 'bluetooth'; then
has_bt=true; break has_bt=true
break
fi fi
done done
fi fi
@@ -189,13 +167,14 @@ _build_firmware_plan() {
plan+=" [+] bluez + bluez-tools + bluez-obexd (base stack)\n" plan+=" [+] bluez + bluez-tools + bluez-obexd (base stack)\n"
fi fi
case "${DESKTOP_ENV:-other}" in case "${DESKTOP_ENV:-other}" in
kde) plan+=" [+] bluedevil (KDE applet)\n" kde)
if [ "${AUDIO_SERVER:-}" = "pipewire" ]; then plan+=" [+] bluedevil (KDE applet)\n"
plan+="pipewire-pulse + wireplumber (if missing)\n" if [ "${AUDIO_SERVER:-}" = "pipewire" ]; then
fi plan+=" → pipewire-pulse + wireplumber (if missing)\n"
;; fi
gnome) plan+=" (already in gnome-control-center)\n" ;; ;;
*) plan+=" [+] blueman (GTK Bluetooth manager)\n" ;; gnome) plan+=" (already in gnome-control-center)\n" ;;
*) plan+=" [+] blueman (GTK Bluetooth manager)\n" ;;
esac esac
plan+=" → Bluetooth service will be enabled\n" plan+=" → Bluetooth service will be enabled\n"
else else
@@ -228,133 +207,200 @@ _install_detected_firmware() {
done done
if [ ${#to_install[@]} -gt 0 ]; then if [ ${#to_install[@]} -gt 0 ]; then
_run_cmd "Firmware" "sudo DEBIAN_FRONTEND=noninteractive apt install -y ${to_install[*]}" \ _run_cmd "Firmware" "sudo DEBIAN_FRONTEND=noninteractive apt install -y ${to_install[*]}" \
"Installing network firmware packages..." "Installing network firmware packages..." || true
fi fi
} }
# ── Wireless handler (Broadcom 3-tier) ── # ── Wireless handler (Broadcom single-path wl) ──
_handle_wireless() { _handle_wireless() {
local installed_any=false local installed_any=false
local wl_build_failed=false
if [ ${#PCI_NET_DEVS[@]} -eq 0 ] && [ ${#USB_WIFI_DEVS[@]} -eq 0 ]; then if [ ${#PCI_NET_DEVS[@]} -eq 0 ] && [ ${#USB_WIFI_DEVS[@]} -eq 0 ]; then
_detect_all_network_devices _detect_all_network_devices
fi fi
for dev in "${PCI_NET_DEVS[@]}"; do for dev in "${PCI_NET_DEVS[@]}"; do
local bcm_id local bcm_id dev_id
bcm_id=$(echo "$dev" | grep -oP '14e4:[0-9a-fA-F]+' || true) bcm_id=$(echo "$dev" | grep -oP '14e4:[0-9a-fA-F]+' || true)
[ -z "$bcm_id" ] && continue [ -z "$bcm_id" ] && continue
local dev_id
dev_id=$(echo "$bcm_id" | cut -d: -f2 | tr '[:upper:]' '[:lower:]') dev_id=$(echo "$bcm_id" | cut -d: -f2 | tr '[:upper:]' '[:lower:]')
if _is_broadcom_brcm "$dev_id"; then # --- Dependencies verification ---
if ! is_installed "firmware-brcm80211"; then if ! is_installed "linux-headers-amd64" || ! is_installed "dkms"; then
_run_cmd "Broadcom" "sudo DEBIAN_FRONTEND=noninteractive apt install -y firmware-brcm80211" \ if ! apt-cache show linux-headers-amd64 dkms >/dev/null 2>&1; then
"Installing firmware-brcm80211..." _msg "Broadcom Error" "linux-headers-amd64 or dkms are not available in your repositories. Cannot compile Broadcom driver.\n\nEnsure repositories are enabled and run:\n sudo apt install linux-headers-amd64 dkms"
else
echo " --> firmware-brcm80211 already installed."
fi
installed_any=true
elif _is_broadcom_b43 "$dev_id"; then
if ! dpkg -l firmware-b43-installer >/dev/null 2>&1; then
_run_install_pkg firmware-b43-installer
fi
if [ ! -d /lib/firmware/b43 ] || [ -z "$(ls -A /lib/firmware/b43 2>/dev/null)" ]; then
_msg "b43 Firmware Warning" \
"The firmware-b43-installer package was installed, but the\n\
proprietary firmware download appears to have failed\n\
(no files found in /lib/firmware/b43).\n\n\
To fix this, connect a wired network and run:\n\
sudo dpkg-reconfigure firmware-b43-installer\n\n\
After the firmware is downloaded, reboot the system." 14 75
_pause
else
installed_any=true
fi
elif _is_broadcom_b43legacy "$dev_id"; then
_run_install_pkg firmware-b43legacy-installer
installed_any=true
else
local bcm_ver header_ver
bcm_ver=$(apt-cache policy broadcom-sta-dkms 2>/dev/null | awk 'NR==3 {print $2; exit}')
header_ver=$(apt-cache policy linux-headers-$(uname -r) 2>/dev/null | awk 'NR==3 {print $2; exit}')
if ! apt-cache policy "linux-headers-$(uname -r)" 2>/dev/null | grep -q "Candidate: [^ (none)]"; then
_msg "Broadcom Error" \
"linux-headers-$(uname -r) not available.\n\nCannot compile broadcom-sta-dkms without kernel headers." 10 60
_pause _pause
continue continue
fi fi
fi
if _confirm "Broadcom WiFi" "Install Broadcom driver?\n\nRequired for this chipset. Compiles a kernel module.\n\n broadcom-sta-dkms ${bcm_ver:-unknown}\n linux-headers-$(uname -r) ${header_ver:-unknown}\n\nProceed?"; then # --- Confirmation ---
_run_cmd "Broadcom" "sudo DEBIAN_FRONTEND=noninteractive apt install -y linux-headers-$(uname -r) broadcom-sta-dkms" \ if ! _confirm "Broadcom WiFi" "Detected Broadcom wireless device.\n\nInstall broadcom-sta-dkms, dkms, and wireless-tools?"; then
"Installing Broadcom driver..." continue
fi
local has_broadcom_bt=false # --- Step-by-step installation ---
for btdev in "${PCI_BT_DEVS[@]}"; do _run_cmd "Broadcom Deps" "sudo DEBIAN_FRONTEND=noninteractive apt install -y dkms wireless-tools linux-headers-amd64" || true
if echo "$btdev" | grep -qi 'broadcom'; then _run_cmd "Broadcom Driver" "sudo DEBIAN_FRONTEND=noninteractive apt install -y broadcom-sta-dkms" || true
has_broadcom_bt=true
break # --- Persist blacklist of conflicting modules ---
fi local blacklist_conf="/etc/modprobe.d/blacklist-broadcom.conf"
done local blacklist_content="blacklist b43\nblacklist b43legacy\nblacklist brcmsmac\nblacklist bcma\nblacklist ssb"
if $has_broadcom_bt; then echo -e "$blacklist_content" | sudo tee "$blacklist_conf" >/dev/null || true
echo -e "${YELLOW}Broadcom combo card (WiFi + Bluetooth) detected.${NC}"
cat > /etc/modprobe.d/broadcom-combo.conf <<'EOF' # --- Update initramfs and load module ---
# Broadcom combo: ensure btusb loads after wl _run_cmd "Initramfs" "sudo update-initramfs -u" || true
softdep wl post: btusb _run_cmd "Modprobe" "sudo modprobe -r b43 b43legacy b44 bcma brcmsmac brcmfmac ssb wl 2>/dev/null || true" "Removing conflicting modules" || true
EOF _run_cmd "Modprobe" "sudo modprobe wl" || true
echo -e "${YELLOW}A reboot may be required for Bluetooth to work correctly.${NC}"
# --- Combo BT (unchanged) ---
local has_broadcom_bt=false
local btdev
for btdev in "${PCI_BT_DEVS[@]}"; do
if echo "$btdev" | grep -qi 'broadcom'; then
has_broadcom_bt=true
break
fi
done
if $has_broadcom_bt; then
echo -e "${YELLOW}[+] Broadcom WiFi+BT combo card detected.${NC}"
sudo mkdir -p /etc/modprobe.d
printf 'softdep wl post: btusb\n' | sudo tee /etc/modprobe.d/broadcom-combo.conf >/dev/null || true
echo -e "${YELLOW} A reboot may be required for Bluetooth support.${NC}"
fi
# --- Post-DKMS verification (Fix 5, unchanged) ---
if ! ls /lib/modules/$(uname -r)/updates/dkms/wl.ko* 2>/dev/null | grep -q .; then
_msg "Broadcom DKMS Build Failed" "The wl module was not built by DKMS.\n\nPossible causes:\n- Missing build tools (build-essential, dkms)\n- Kernel update without headers\n- Incompatible kernel version\n\nTry: sudo dpkg-reconfigure broadcom-sta-dkms"
if _confirm "Broadcom" "Rebuild the Broadcom driver now?"; then
_run_cmd "Broadcom" "sudo dpkg-reconfigure broadcom-sta-dkms" || true
if ls /lib/modules/$(uname -r)/updates/dkms/wl.ko* 2>/dev/null | grep -q .; then
:
else
local dmesg_out
dmesg_out=$(sudo dmesg | tail -20 2>/dev/null || echo "(dmesg unavailable)")
_msg "Broadcom DKMS Still Failed" "dpkg-reconfigure did not produce wl.ko either.\n\nLast kernel messages:\n${dmesg_out}\n\nYou may need to check build logs or report a bug against broadcom-sta-dkms."
_pause
wl_build_failed=true
continue
fi fi
else
echo "Broadcom proprietary driver installed. A reboot may be required." wl_build_failed=true
_pause continue
installed_any=true
fi fi
fi fi
done
for dev in "${USB_WIFI_DEVS[@]}"; do _msg "Network Warning" "The script is about to unload current WiFi kernel modules to load the Broadcom driver.\n\nIf you are connected via SSH over WiFi, YOUR CONNECTION WILL DROP. Please reconnect after a few seconds."
if echo "$dev" | grep -qi '0a5c'; then sudo modprobe -r b43 b43legacy b44 bcma brcmsmac brcmfmac ssb wl 2>/dev/null || true
_msg "USB Broadcom" "USB Broadcom adapter detected:\n\n ${dev}\n\nIf the adapter is not recognized after base firmware\ninstallation, ndiswrapper may be needed as a last\nresort.\n\nNote: Linux 5.15+ has improved support for many\nUSB Broadcom adapters." 12 65 sudo modprobe wl 2>/dev/null || true
# --- Verificación de carga ---
if lsmod | grep -q '^wl '; then
echo -e "${GREEN}[+] Broadcom WiFi activated (wl module loaded).${NC}"
_pause
installed_any=true
else
echo -e "${YELLOW}[+] Broadcom driver installed but wl module did not load.${NC}"
echo -e "${YELLOW} A system reboot is required.${NC}"
_pause
installed_any=true
fi fi
done done
if ! $installed_any; then # --- USB Broadcom (unchanged) ---
local usb_dev
for usb_dev in "${USB_WIFI_DEVS[@]}"; do
if echo "$usb_dev" | grep -qi '0a5c'; then
_msg "USB Broadcom" "USB Broadcom device detected (0a5c).\n\nLinux does not have native drivers for most USB Broadcom WiFi chips.\nndiswrapper may be needed as a last resort."
_pause
fi
done
# --- Mensaje final (unchanged) ---
if ! $installed_any && ! $wl_build_failed; then
echo "No special WiFi firmware needed -- base firmware-linux-nonfree covers this system." echo "No special WiFi firmware needed -- base firmware-linux-nonfree covers this system."
_pause _pause
fi fi
} }
# ── Ensure non-free repository is enabled ── # ── Ensure non-free repository is enabled ──
# Token-exact check for the "non-free" component. "non-free-firmware"
# contains the substring but is a different component, so word-boundary
# matching (\b) would produce false positives.
_has_nonfree_component() {
local file="$1"
grep -qE '^[^#]*[[:space:]]non-free([[:space:]]|$)' "$file" 2>/dev/null
}
_ensure_nonfree_repo() { _ensure_nonfree_repo() {
local nonfree_found=false local nonfree_found=false
if [ -f /etc/apt/sources.list ] && grep -Eq '^[^#]*\bnon-free\b' /etc/apt/sources.list 2>/dev/null; then if [ -f /etc/apt/sources.list ] && _has_nonfree_component /etc/apt/sources.list; then
nonfree_found=true nonfree_found=true
fi fi
if ! $nonfree_found && [ -d /etc/apt/sources.list.d ]; then if ! $nonfree_found && [ -d /etc/apt/sources.list.d ]; then
if grep -qr 'Components:.*\bnon-free\b' /etc/apt/sources.list.d/*.sources 2>/dev/null; then for f in /etc/apt/sources.list.d/*.sources /etc/apt/sources.list.d/*.list; do
nonfree_found=true [ -f "$f" ] || continue
fi if _has_nonfree_component "$f"; then
nonfree_found=true
break
fi
done
fi fi
if $nonfree_found; then if $nonfree_found; then
return 0 return 0
fi fi
if _confirm "non-free Repository" "Component 'non-free' (and 'non-free-firmware') is required for WiFi/Bluetooth/GPU firmware.\n\nAdd them to your APT repositories?"; then if ! _confirm "non-free Repository" "Component 'non-free' (and 'non-free-firmware') is required for WiFi/Bluetooth/GPU firmware.\n\nAdd them to your APT repositories?"; then
return 1
fi
# No active sources at all → bootstrap a complete configuration
if ! has_active_deb_sources; then
backup_current_repos
if ! bootstrap_repositories "main contrib non-free non-free-firmware"; then
return 1
fi
else
if [ -f /etc/apt/sources.list ]; then if [ -f /etc/apt/sources.list ]; then
sudo sed -i '/^deb / { /non-free/! s/\(main[^ ]*\)/\1 non-free non-free-firmware/ }' /etc/apt/sources.list # Add each missing component after "main", never duplicating
sudo sed -i -E '/^deb / { /(^|[[:space:]])non-free([[:space:]]|$)/! s/(main[^[:space:]]*)/\1 non-free/ }' /etc/apt/sources.list
# non-free-firmware does not exist on Bullseye
if [ "$DEBIAN_VERSION" != "11" ]; then
sudo sed -i -E '/^deb / { /(^|[[:space:]])non-free-firmware([[:space:]]|$)/! s/(main[^[:space:]]*)/\1 non-free-firmware/ }' /etc/apt/sources.list
fi
fi fi
if [ -d /etc/apt/sources.list.d ]; then if [ -d /etc/apt/sources.list.d ]; then
for f in /etc/apt/sources.list.d/*.sources; do for f in /etc/apt/sources.list.d/*.sources; do
[ -f "$f" ] || continue [ -f "$f" ] || continue
sudo sed -i '/^Components:/ { /non-free/! s/$/ non-free non-free-firmware/ }' "$f" sudo sed -i -E '/^Components:/ { /(^|[[:space:]])non-free([[:space:]]|$)/! s/$/ non-free/ }' "$f"
if [ "$DEBIAN_VERSION" != "11" ]; then
sudo sed -i -E '/^Components:/ { /(^|[[:space:]])non-free-firmware([[:space:]]|$)/! s/$/ non-free-firmware/ }' "$f"
fi
done done
fi fi
sudo apt update
echo -e "${GREEN}non-free repository enabled.${NC}"
return 0
fi fi
return 1
# Verify the component was actually added before reporting success
local nonfree_ok=false
[ -f /etc/apt/sources.list ] && _has_nonfree_component /etc/apt/sources.list && nonfree_ok=true
if ! $nonfree_ok && [ -d /etc/apt/sources.list.d ]; then
for f in /etc/apt/sources.list.d/*.sources /etc/apt/sources.list.d/*.list; do
[ -f "$f" ] || continue
if _has_nonfree_component "$f"; then
nonfree_ok=true
break
fi
done
fi
if ! $nonfree_ok; then
echo -e "${RED}Failed to enable non-free repository. Check your APT sources.${NC}"
return 1
fi
_ensure_apt_updated
echo -e "${GREEN}non-free repository enabled.${NC}"
return 0
} }
# ── Main entry point ── # ── Main entry point ──
@@ -384,7 +430,7 @@ install_firmware() {
# 4. Install base firmware meta-package (unchanged logic) # 4. Install base firmware meta-package (unchanged logic)
local fw_pkg="firmware-linux-nonfree" local fw_pkg="firmware-linux-nonfree"
local fw_bpo local fw_bpo
fw_bpo=$(apt-cache madison "$fw_pkg" 2>/dev/null | \ fw_bpo=$(apt-cache madison "$fw_pkg" 2>/dev/null |
grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1) grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1)
local fw_stable local fw_stable
@@ -395,7 +441,7 @@ install_firmware() {
local current_ver local current_ver
current_ver=$(dpkg -l "$fw_pkg" 2>/dev/null | awk '/^ii/{print $3}') current_ver=$(dpkg -l "$fw_pkg" 2>/dev/null | awk '/^ii/{print $3}')
if _confirm "Firmware" "firmware-linux-nonfree ${current_ver} already installed.\n\nUpgrade to backports version ${fw_bpo}?\n\nBackports often includes newer hardware support."; then if _confirm "Firmware" "firmware-linux-nonfree ${current_ver} already installed.\n\nUpgrade to backports version ${fw_bpo}?\n\nBackports often includes newer hardware support."; then
_run_cmd "Firmware" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports $fw_pkg" "Upgrading firmware..." _run_cmd "Firmware" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports $fw_pkg" "Upgrading firmware..." || true
fi fi
else else
echo "$fw_pkg already installed." echo "$fw_pkg already installed."
@@ -412,15 +458,15 @@ install_firmware() {
msg+=" 2025/2026: recent GPUs, processors, WiFi.\n\n" msg+=" 2025/2026: recent GPUs, processors, WiFi.\n\n"
msg+="Choose version:" msg+="Choose version:"
if _confirm_custom "Firmware" "$msg" "Backports" "Stable"; then if _confirm_custom "Firmware" "$msg" "Backports" "Stable"; then
_run_cmd "Firmware" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports $fw_pkg" "Installing firmware from backports..." _run_cmd "Firmware" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports $fw_pkg" "Installing firmware from backports..." || true
else else
_run_cmd "Firmware" "sudo apt install -y $fw_pkg" "Installing firmware from stable..." _run_cmd "Firmware" "sudo apt install -y $fw_pkg" "Installing firmware from stable..." || true
fi fi
else else
msg+=" Version: ${fw_stable}\n\n" msg+=" Version: ${fw_stable}\n\n"
msg+="Install it?" msg+="Install it?"
if _confirm "Firmware" "$msg"; then if _confirm "Firmware" "$msg"; then
_run_cmd "Firmware" "sudo apt install -y $fw_pkg" "Installing firmware..." _run_cmd "Firmware" "sudo apt install -y $fw_pkg" "Installing firmware..." || true
fi fi
fi fi
echo -e "${GREEN}Base firmware installed.${NC}" echo -e "${GREEN}Base firmware installed.${NC}"
+55 -36
View File
@@ -27,7 +27,18 @@ ensure_contrib_repo() {
return 0 return 0
fi fi
if _confirm "contrib Repository" "Component 'contrib' is required for Steam.\n\nAdd 'contrib' to your APT repositories?"; then if ! _confirm "contrib Repository" "Component 'contrib' is required for Steam.\n\nAdd 'contrib' to your APT repositories?"; then
echo -e "${YELLOW}contrib repository not enabled. Steam installation may fail.${NC}"
return 1
fi
# No active sources at all → bootstrap a complete configuration
if ! has_active_deb_sources; then
backup_current_repos
if ! bootstrap_repositories "main contrib"; then
return 1
fi
else
if [ -f /etc/apt/sources.list ]; then if [ -f /etc/apt/sources.list ]; then
sudo sed -i '/^deb / { /contrib/! s/main/main contrib/ }' /etc/apt/sources.list sudo sed -i '/^deb / { /contrib/! s/main/main contrib/ }' /etc/apt/sources.list
fi fi
@@ -37,13 +48,21 @@ ensure_contrib_repo() {
sudo sed -i '/^Components:/ { /contrib/! s/$/ contrib/ }' "$f" sudo sed -i '/^Components:/ { /contrib/! s/$/ contrib/ }' "$f"
done done
fi fi
sudo apt update
echo -e "${GREEN}contrib repository enabled.${NC}"
return 0
fi fi
echo -e "${YELLOW}contrib repository not enabled. Steam installation may fail.${NC}" # Verify the component was actually added before reporting success
return 1 local contrib_ok=false
[ -f /etc/apt/sources.list ] && grep -Eq '^[^#]*\bcontrib\b' /etc/apt/sources.list 2>/dev/null && contrib_ok=true
[ -d /etc/apt/sources.list.d ] && grep -qr 'Components:.*\bcontrib\b' /etc/apt/sources.list.d/*.sources 2>/dev/null && contrib_ok=true
[ -d /etc/apt/sources.list.d ] && grep -qrE '^[^#]*\bcontrib\b' /etc/apt/sources.list.d/*.list 2>/dev/null && contrib_ok=true
if ! $contrib_ok; then
echo -e "${RED}Failed to enable contrib repository. Check your APT sources.${NC}"
return 1
fi
_ensure_apt_updated
echo -e "${GREEN}contrib repository enabled.${NC}"
return 0
} }
install_gaming() { install_gaming() {
@@ -53,15 +72,15 @@ install_gaming() {
local choices local choices
choices=$(_checklist "Gaming Setup" \ choices=$(_checklist "Gaming Setup" \
"Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ "Check [*] the packages you want installed/updated on your system.\n" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"i386" "Enable 32-bit (i386) architecture" ON \ "i386" "Enable 32-bit (i386) architecture" ON \
"steam" "Steam (requires 32-bit support)" ON \ "steam" "Steam (requires 32-bit support)" ON \
"mangohud" "Performance overlay (Vulkan/OpenGL)" ON \ "mangohud" "Performance overlay (Vulkan/OpenGL)" ON \
"gamemode" "Game performance optimization" OFF \ "gamemode" "Game performance optimization" OFF \
"goverlay" "MangoHud config GUI" ON \ "goverlay" "MangoHud config GUI" ON \
"heroic" "Heroic Launcher (Epic/GOG)" OFF \ "heroic" "Heroic Launcher (Epic/GOG)" OFF \
"java" "Minecraft Java Runtime" OFF \ "java" "Minecraft Java Runtime" OFF \
"openrgb" "OpenRGB (RGB lighting control)" OFF \ "openrgb" "OpenRGB (RGB lighting control)" OFF \
"lutris" "Lutris + Wine (requires 32-bit support)" OFF \ "lutris" "Lutris + Wine (requires 32-bit support)" OFF \
"retroarch" "RetroArch Emulator Frontend" OFF) "retroarch" "RetroArch Emulator Frontend" OFF)
if [ -z "$choices" ]; then if [ -z "$choices" ]; then
@@ -76,7 +95,7 @@ install_gaming() {
# 2. Determine if 32-bit is needed (steam, lutris, or explicit i386 toggle) # 2. Determine if 32-bit is needed (steam, lutris, or explicit i386 toggle)
local need_32bit=false local need_32bit=false
for p in $cleaned; do for p in $cleaned; do
case $p in steam|lutris) need_32bit=true ;; esac case $p in steam | lutris) need_32bit=true ;; esac
done done
echo "$cleaned" | grep -qw i386 && need_32bit=true echo "$cleaned" | grep -qw i386 && need_32bit=true
@@ -89,7 +108,7 @@ install_gaming() {
if $need_32bit && ! dpkg --print-foreign-architectures 2>/dev/null | grep -q i386; then if $need_32bit && ! dpkg --print-foreign-architectures 2>/dev/null | grep -q i386; then
echo -e "${YELLOW}Enabling i386 architecture (required by selection)...${NC}" echo -e "${YELLOW}Enabling i386 architecture (required by selection)...${NC}"
sudo dpkg --add-architecture i386 sudo dpkg --add-architecture i386
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." _ensure_apt_updated
fi fi
# 4. Install 32-bit graphics drivers only if 32-bit is needed # 4. Install 32-bit graphics drivers only if 32-bit is needed
@@ -105,28 +124,28 @@ install_gaming() {
# 5. Install selected packages # 5. Install selected packages
for pkg in $install_list; do for pkg in $install_list; do
case $pkg in case $pkg in
steam) steam)
if ensure_contrib_repo; then if ensure_contrib_repo; then
install_steam install_steam
else else
echo -e "${YELLOW}Skipping Steam installation (contrib repository not enabled).${NC}" echo -e "${YELLOW}Skipping Steam installation (contrib repository not enabled).${NC}"
fi fi
;; ;;
heroic) install_heroic ;; heroic) install_heroic ;;
java) install_minecraft_java ;; java) install_minecraft_java ;;
mangohud) install_mangohud ;; mangohud) install_mangohud ;;
gamemode) install_gamemode ;; gamemode) install_gamemode ;;
goverlay) install_goverlay ;; goverlay) install_goverlay ;;
openrgb) openrgb)
if [ "$DEBIAN_VERSION" = "11" ]; then if [ "$DEBIAN_VERSION" = "11" ]; then
echo "OpenRGB requires Debian 12+." echo "OpenRGB requires Debian 12+."
continue continue
fi fi
install_openrgb install_openrgb
;; ;;
lutris) install_lutris ;; lutris) install_lutris ;;
retroarch) install_retroarch ;; retroarch) install_retroarch ;;
*) _run_install "$pkg" ;; *) _run_install "$pkg" ;;
esac esac
done done
+45 -1
View File
@@ -29,7 +29,51 @@ _install_mesa_32bit() {
return return
fi fi
_run_cmd "Mesa 32-bit" "sudo apt install -y ${install_list[*]}" \ # ── Resolve versions for display ──
local rep_pkg="${base_pkgs[0]}"
local stable_ver=""
stable_ver=$(apt-cache policy "$rep_pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}') || true
local bpo_ver=""
if [ "$DEBIAN_VERSION" = "13" ] && [ "$(is_backports_enabled)" = "true" ]; then
bpo_ver=$(apt-cache madison "$rep_pkg" 2>/dev/null | \
grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1) || true
fi
local check_pkg="libgl1-mesa-dri:i386"
# ── Already installed branch ──
if is_installed "$check_pkg"; then
if [ -n "$bpo_ver" ]; then
local current_ver
current_ver=$(dpkg -l "$check_pkg" 2>/dev/null | awk '/^ii/{print $3}') || true
if _confirm "Mesa 32-bit" \
"Mesa 32-bit libraries ${current_ver:+v${current_ver} }already installed.\n\nReinstall from backports v${bpo_ver}?"; then
echo "Reinstalling Mesa 32-bit from backports..."
_run_cmd "Mesa 32-bit" \
"sudo apt install -y --reinstall -t ${DEBIAN_CODENAME}-backports ${install_list[*]}" \
"Reinstalling Mesa 32-bit from backports..."
echo -e "${GREEN}Mesa 32-bit libraries reinstalled.${NC}"
return
fi
fi
echo "Mesa 32-bit libraries already installed."
return
fi
# ── Not installed branch ──
local apt_target=""
if [ -n "$bpo_ver" ]; then
local msg="Backports repository is enabled.\n\n"
msg+="Available versions for Mesa 32-bit:\n"
msg+=" - Stable: v${stable_ver:-unknown}\n"
msg+=" - Backports: v${bpo_ver}\n\n"
msg+="Install from Backports or Stable?"
if _confirm_custom "Mesa 32-bit" "$msg" "Backports" "Stable" 14 70; then
apt_target="-t ${DEBIAN_CODENAME}-backports"
fi
fi
_run_cmd "Mesa 32-bit" "sudo apt install -y $apt_target ${install_list[*]}" \
"Installing Mesa drivers (${#install_list[@]} packages)..." "Installing Mesa drivers (${#install_list[@]} packages)..."
echo -e "${GREEN}Mesa 32-bit libraries installed.${NC}" echo -e "${GREEN}Mesa 32-bit libraries installed.${NC}"
} }
+4 -4
View File
@@ -26,7 +26,7 @@ install_lutris() {
} }
install_openrgb() { install_openrgb() {
local deb_suffix local deb_suffix=""
case "$DEBIAN_CODENAME" in case "$DEBIAN_CODENAME" in
bookworm) deb_suffix="bookworm" ;; bookworm) deb_suffix="bookworm" ;;
trixie) deb_suffix="trixie" ;; trixie) deb_suffix="trixie" ;;
@@ -41,14 +41,14 @@ install_openrgb() {
_run_cmd "OpenRGB" "sudo apt install -y curl jq" "Installing dependencies..." _run_cmd "OpenRGB" "sudo apt install -y curl jq" "Installing dependencies..."
local json local json=""
json=$(curl -s --connect-timeout 10 \ json=$(curl -s --connect-timeout 10 \
"https://codeberg.org/api/v1/repos/OpenRGB/OpenRGB/releases?limit=1") || { "https://codeberg.org/api/v1/repos/OpenRGB/OpenRGB/releases?limit=1") || {
echo -e "${RED}Could not fetch OpenRGB releases from Codeberg API.${NC}" echo -e "${RED}Could not fetch OpenRGB releases from Codeberg API.${NC}"
return 1 return 1
} }
local deb_url sha256 local deb_url="" sha256=""
while IFS=' ' read -r url hash; do while IFS=' ' read -r url hash; do
deb_url="$url" deb_url="$url"
sha256="$hash" sha256="$hash"
@@ -87,7 +87,7 @@ install_openrgb() {
if ! grep -q "^i2c-dev" /etc/modules 2>/dev/null; then if ! grep -q "^i2c-dev" /etc/modules 2>/dev/null; then
echo "i2c-dev" | sudo tee -a /etc/modules >/dev/null echo "i2c-dev" | sudo tee -a /etc/modules >/dev/null
fi fi
sudo usermod -aG i2c "$USER" sudo usermod -aG i2c "${USER:-}"
sudo udevadm control --reload-rules && sudo udevadm trigger sudo udevadm control --reload-rules && sudo udevadm trigger
sudo setcap cap_sys_rawio=ep /usr/bin/openrgb 2>/dev/null || true sudo setcap cap_sys_rawio=ep /usr/bin/openrgb 2>/dev/null || true
+134 -45
View File
@@ -5,9 +5,27 @@ _GPU_DIR="${MODULES_DIR}/gpu"
source "${_GPU_DIR}/_helpers.sh" source "${_GPU_DIR}/_helpers.sh"
source "${_GPU_DIR}/amd_intel.sh" source "${_GPU_DIR}/amd_intel.sh"
source "${_GPU_DIR}/nvidia.sh" source "${_GPU_DIR}/nvidia.sh"
source "${_GPU_DIR}/nvidia_manage.sh"
# Consumed by gaming.sh to know which NVIDIA driver path was taken # Consumed by gaming.sh to know which NVIDIA driver path was taken
NVIDIA_DRIVER_MODE="" NVIDIA_DRIVER_MODE=""
# Set by _show_nvidia_version_menu(): "470" | "535" | "550" | "590" | "595" | "auto"
NVIDIA_SELECTED_VERSION=""
# Aviso informativo post-instalación NVIDIA: Debian bug #1109409
# (GDM3 + NVIDIA + Wayland → pantalla negra). Solo informa, nunca
# cambia configuración de GDM3 ni aborta la instalación.
_warn_nvidia_gnome_wayland() {
command -v gdm3 &>/dev/null || return 0
gnome-shell --version 2>/dev/null | grep -qi "shell 4[0-9]" || return 0
case "$NVIDIA_DRIVER_MODE" in
stable | backports | cuda-repo | extrepo) ;;
*) return 0 ;;
esac
echo -e "${YELLOW}WARNING: Debian bug #1109409 may affect GDM3 + NVIDIA + Wayland.${NC}"
echo -e "${YELLOW}If you see a black screen after reboot, select 'GNOME on Xorg' at login.${NC}"
echo -e "${YELLOW}Or temporarily disable Wayland: sudo nano /etc/gdm3/daemon.conf${NC}"
}
_install_amd_intel_stack() { _install_amd_intel_stack() {
if [ "$GPU_TYPE" = "unknown" ] || [ -z "$GPU_TYPE" ]; then if [ "$GPU_TYPE" = "unknown" ] || [ -z "$GPU_TYPE" ]; then
@@ -15,7 +33,7 @@ _install_amd_intel_stack() {
local ref_ver local ref_ver
ref_ver=$(apt-cache policy mesa-vulkan-drivers 2>/dev/null | awk 'NR==3 {print $2; exit}') ref_ver=$(apt-cache policy mesa-vulkan-drivers 2>/dev/null | awk 'NR==3 {print $2; exit}')
local ref_bpo_ver local ref_bpo_ver
ref_bpo_ver=$(apt-cache madison mesa-vulkan-drivers 2>/dev/null | \ ref_bpo_ver=$(apt-cache madison mesa-vulkan-drivers 2>/dev/null |
grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1) grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1)
local comp_line="Components: Vulkan, OpenGL, GLX, EGL, VA-API (64-bit)" local comp_line="Components: Vulkan, OpenGL, GLX, EGL, VA-API (64-bit)"
@@ -61,11 +79,13 @@ _install_amd_intel_stack() {
local desc local desc
desc=$(echo "$gpu_line" | sed -E 's/.*: //; s/ *\(rev.*//') desc=$(echo "$gpu_line" | sed -E 's/.*: //; s/ *\(rev.*//')
plan+=" GPU ${gpu_count}: ${desc}\n" plan+=" GPU ${gpu_count}: ${desc}\n"
done < <(lspci -nn | grep -E "VGA|3D" || true) done < <(echo "$LSPCI_OUTPUT" | grep -E "VGA|3D" || true)
plan+="\nPlanned components:\n" plan+="\nPlanned components:\n"
if $HAS_INTEL; then if $HAS_INTEL; then
local _gen; _gen=$(get_intel_generation) local _gen
local _va; [ "$_gen" = "gen7-" ] && _va="i965-va-driver-shaders" || _va="intel-media-va-driver-non-free" _gen=$(get_intel_generation)
local _va
[ "$_gen" = "gen7-" ] && _va="i965-va-driver-shaders" || _va="intel-media-va-driver-non-free"
plan+=" [+] Intel firmware + ${_va}\n" plan+=" [+] Intel firmware + ${_va}\n"
fi fi
if $HAS_AMD; then if $HAS_AMD; then
@@ -136,7 +156,9 @@ _apply_amd_gcn_grub_fix() {
sudo cp "$file" "$backup" sudo cp "$file" "$backup"
sudo sed -i "/^GRUB_CMDLINE_LINUX_DEFAULT=/ s/\"$*/${params}&/" "$file" if ! sudo grep -q "amdgpu.si_support=1" "$file"; then
sudo sed -i -E "/^GRUB_CMDLINE_LINUX_DEFAULT=/ s/\"([^\"]*)\"/\"${params} \1\"/" "$file"
fi
if _confirm "AMD GCN — GRUB" "Parameters added:\n\n ${params}\n\nRun update-grub now?" 12 65; then if _confirm "AMD GCN — GRUB" "Parameters added:\n\n ${params}\n\nRun update-grub now?" 12 65; then
if sudo update-grub >/dev/null 2>&1; then if sudo update-grub >/dev/null 2>&1; then
@@ -165,70 +187,137 @@ _install_nvidia_stack() {
local desc local desc
desc=$(echo "$gpu_line" | sed -E 's/.*: //; s/ *\(rev.*//') desc=$(echo "$gpu_line" | sed -E 's/.*: //; s/ *\(rev.*//')
plan+=" GPU ${gpu_count}: ${desc}\n" plan+=" GPU ${gpu_count}: ${desc}\n"
done < <(lspci -nn | grep -E "VGA|3D" || true) done < <(echo "$LSPCI_OUTPUT" | grep -E "VGA|3D" || true)
plan+="\nPlanned:\n [+] NVIDIA proprietary driver" plan+="\nPlanned:\n [+] NVIDIA proprietary driver"
_msg "NVIDIA Stack — Plan" "$plan" 14 65 _msg "NVIDIA Stack — Plan" "$plan" 14 65
if ! _confirm "NVIDIA Stack" "Install the NVIDIA proprietary driver?"; then _pause "Press Enter to continue..."
echo "Skipping NVIDIA driver installation."
return
fi
NVIDIA_DRIVER_MODE="" NVIDIA_DRIVER_MODE=""
if [ "$DEBIAN_VERSION" = "11" ]; then if _nvidia_driver_installed; then
install_nvidia_bullseye if ! _nvidia_manage_menu; then
return
fi
fi
elif [ "$DEBIAN_VERSION" = "12" ]; then if [ "$DEBIAN_VERSION" = "11" ]; then
if [ "$(is_nvidia_kepler)" = "true" ]; then if type install_nvidia_bullseye &>/dev/null; then
if type _install_nvidia_bookworm_kepler &>/dev/null; then install_nvidia_bullseye
else
_msg "NVIDIA — Bullseye" "The Bullseye NVIDIA module is not available.\n\nNo NVIDIA driver was installed." 10 60
NVIDIA_DRIVER_MODE=""
fi
else
if ! _show_nvidia_version_menu; then
echo "Skipping NVIDIA driver installation."
return
fi
local nv_arch=""
case "$NVIDIA_SELECTED_VERSION" in
470)
# Legacy 470 (Kepler/Tesla) — forced, regardless of auto-detection
_install_nvidia_bookworm_kepler
;;
535)
if [ "$(is_nvidia_kepler)" = "true" ]; then
_install_nvidia_bookworm_kepler _install_nvidia_bookworm_kepler
elif [ "$(is_nvidia_fermi)" = "true" ]; then
_msg "NVIDIA Fermi — Bookworm" \
"Fermi GPUs (GF1xx) are not supported\nin Debian 12 (Bookworm).\nThe nvidia-legacy-390xx driver is\nnot available in this version.\n\nNo NVIDIA driver will be installed."
NVIDIA_DRIVER_MODE=""
else else
_install_nvidia_standard _install_nvidia_standard
fi fi
elif [ "$(is_nvidia_fermi)" = "true" ]; then ;;
_msg "NVIDIA Fermi — Bookworm" \ 550)
"Fermi GPUs (GF1xx) are not supported\nin Debian 12 (Bookworm).\nThe nvidia-legacy-390xx driver is\nnot available in this version.\n\nNo NVIDIA driver will be installed." nv_arch=$(detect_nvidia_arch "$NVIDIA_GPU_DEVICE_ID")
NVIDIA_DRIVER_MODE="" case "$nv_arch" in
elif [ "$(is_backports_kernel)" = "true" ]; then legacy)
_install_nvidia_bookworm_bpo _msg "NVIDIA — Trixie" \
else "Kepler and Fermi GPUs are not supported\nin Debian 13 (Trixie).\n\nThe nvidia-legacy drivers are not available\nin this version of Debian.\n\nNo NVIDIA driver will be installed."
_install_nvidia_standard NVIDIA_DRIVER_MODE=""
fi ;;
blackwell)
elif [ "$DEBIAN_VERSION" = "13" ]; then _msg "NVIDIA — Blackwell (v550)" \
if [ "$(is_nvidia_blackwell)" = "true" ]; then "Your Blackwell GPU is NOT supported by the official\nDebian v550 driver.\n\nPlease select v590 or v595 (NVIDIA CUDA Repo)\nin the driver menu." 14 65
_install_nvidia_cuda_repo NVIDIA_DRIVER_MODE=""
elif [ "$(is_nvidia_kepler)" = "true" ] || [ "$(is_nvidia_fermi)" = "true" ]; then ;;
_msg "NVIDIA — Trixie" \ maxwell | pascal | volta)
"Kepler and Fermi GPUs are not supported\nin Debian 13 (Trixie).\n\nThe nvidia-legacy drivers are not available\nin this version of Debian.\n\nNo NVIDIA driver will be installed." if [ "$(is_backports_kernel)" = "true" ]; then
NVIDIA_DRIVER_MODE="" local gpu_gen="Maxwell"
elif [ "$(is_backports_kernel)" = "true" ]; then [ "$nv_arch" = "pascal" ] && gpu_gen="Pascal"
if [ "$(is_nvidia_maxwell)" = "true" ] || [ "$(is_nvidia_pascal)" = "true" ]; then [ "$nv_arch" = "volta" ] && gpu_gen="Volta"
local gpu_gen="Maxwell" _msg "NVIDIA — Trixie + Backports" \
[ "$(is_nvidia_pascal)" = "true" ] && gpu_gen="Pascal" "INCOMPATIBILITY DETECTED: Your NVIDIA ${gpu_gen} GPU\n\
_msg "NVIDIA — Trixie + Backports" \
"INCOMPATIBILITY DETECTED: Your NVIDIA ${gpu_gen} GPU\n\
is NOT supported by the modern v590 driver.\n\n\ is NOT supported by the modern v590 driver.\n\n\
To run NVIDIA safely on Debian 13 (Trixie), you MUST use\n\ To run NVIDIA safely on Debian 13 (Trixie), you MUST use\n\
the official Debian v550 driver, which requires the\n\ the official Debian v550 driver, which requires the\n\
standard STABLE Kernel.\n\n\ standard STABLE Kernel.\n\n\
Forcing the stable driver path." 14 70 Forcing the stable driver path." 14 70
if ! _install_nvidia_standard; then
NVIDIA_DRIVER_MODE=""
return 1
fi
NVIDIA_DRIVER_MODE="stable"
else
_install_nvidia_standard
fi
;;
turing | ampere | ada)
_install_nvidia_standard _install_nvidia_standard
NVIDIA_DRIVER_MODE="stable" ;;
*)
if [ "$(is_backports_kernel)" = "true" ]; then
_install_nvidia_cuda_repo
else
_install_nvidia_standard
fi
;;
esac
;;
590 | 595)
nv_arch=$(detect_nvidia_arch "$NVIDIA_GPU_DEVICE_ID")
if [ "$nv_arch" = "maxwell" ] || [ "$nv_arch" = "pascal" ] || [ "$nv_arch" = "legacy" ]; then
local gpu_gen="Kepler/Fermi"
[ "$nv_arch" = "maxwell" ] && gpu_gen="Maxwell"
[ "$nv_arch" = "pascal" ] && gpu_gen="Pascal"
_msg "NVIDIA — v${NVIDIA_SELECTED_VERSION}" \
"Your NVIDIA ${gpu_gen} GPU is NOT supported by\nNVIDIA driver v${NVIDIA_SELECTED_VERSION}.\n\n\
Only Turing, Ampere, Ada and Blackwell GPUs are supported.\n\n\
No NVIDIA driver will be installed." 14 65
NVIDIA_DRIVER_MODE=""
else else
_install_nvidia_cuda_repo if ! _enable_cuda_repo; then
NVIDIA_DRIVER_MODE=""
_msg "CUDA Repo — Error" "Failed to enable the official NVIDIA CUDA repository.\n\nNo NVIDIA driver was installed." 10 60
return 1
fi
if _install_nvidia_cuda_repo "$NVIDIA_SELECTED_VERSION"; then
NVIDIA_DRIVER_MODE="cuda-repo"
else
NVIDIA_DRIVER_MODE=""
fi
fi fi
else ;;
*)
_install_nvidia_standard _install_nvidia_standard
fi ;;
esac
else
_install_nvidia_standard
fi fi
if [ -n "$NVIDIA_DRIVER_MODE" ]; then if [ -n "$NVIDIA_DRIVER_MODE" ]; then
_configure_nvidia_wayland "$NVIDIA_SELECTED_VERSION"
if _is_hybrid_laptop; then
echo -e "${CYAN}[INFO] Hybrid GPU (Optimus) detected.${NC}"
echo -e "PRIME offload is auto-configured by X.Org 1.20.7+ when using X11."
echo -e "After reboot, verify with: ${YELLOW}xrandr --listproviders | grep NVIDIA-G0${NC}"
echo -e "If not found, ensure BIOS boots on iGPU and nvidia-drm is loaded."
fi
offer_generic_tools offer_generic_tools
_warn_nvidia_gnome_wayland
local summary="NVIDIA: ${NVIDIA_DRIVER_MODE}\n" local summary="NVIDIA: ${NVIDIA_DRIVER_MODE}\n"
summary+="Tools: nvtop + vainfo" summary+="Tools: nvtop + vainfo"
_msg "NVIDIA Stack — Complete" "$summary" 10 55 _msg "NVIDIA Stack — Complete" "$summary" 10 55
+88 -108
View File
@@ -1,121 +1,82 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Shared helpers for GPU submodules # Shared helpers for GPU submodules
is_nvidia_kepler() { declare -A NVIDIA_FAMILY_MAP=(
local dev_id # Fermi / Kepler (Legacy: el shim se encarga de separarlos)
dev_id=$(lspci -nn | grep -iE "VGA|3D" | grep -i nvidia | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1) ["06"]="legacy" ["0D"]="legacy" ["0E"]="legacy"
[ -z "$dev_id" ] && { echo false; return; } ["0F"]="legacy" ["10"]="legacy" ["11"]="legacy" ["12"]="legacy"
# Maxwell
["13"]="maxwell" ["14"]="maxwell" ["16"]="maxwell" ["17"]="maxwell"
# Pascal + Volta (Misma política de driver clásico)
["15"]="pascal" ["1B"]="pascal" ["1C"]="pascal" ["1D"]="pascal"
# Turing
["1E"]="turing" ["1F"]="turing" ["21"]="turing"
# Ampere
["20"]="ampere" ["22"]="ampere" ["24"]="ampere" ["25"]="ampere"
# Hopper
["23"]="hopper"
# Ada Lovelace
["26"]="ada" ["27"]="ada" ["28"]="ada"
# Blackwell
["29"]="blackwell" ["2B"]="blackwell" ["2C"]="blackwell"
["2D"]="blackwell" ["2E"]="blackwell" ["31"]="blackwell"
)
local dev_int detect_nvidia_arch() {
dev_int=$((16#${dev_id,,})) [ -z "$1" ] && {
echo "unknown"
# Bloque 1: GK107 (escritorio + móvil) — 0x0FC0..0x0FFF return
if [ "$dev_int" -ge $((16#0FC0)) ] && [ "$dev_int" -le $((16#0FFF)) ]; then echo true; return; fi }
# Bloque 2: GK110/GK110B/GK210 acotado puro — 0x1000..0x103F local pci_id="${1^^}"
if [ "$dev_int" -ge $((16#1000)) ] && [ "$dev_int" -le $((16#103F)) ]; then echo true; return; fi local prefix="${pci_id:0:2}"
# Bloque 3: GK104/GK106 (completo) — 0x1180..0x11FF echo "${NVIDIA_FAMILY_MAP[$prefix]:-unknown}"
if [ "$dev_int" -ge $((16#1180)) ] && [ "$dev_int" -le $((16#11FF)) ]; then echo true; return; fi
# Bloque 4: GK208/GK208B (completo) — 0x1280..0x12BF
if [ "$dev_int" -ge $((16#1280)) ] && [ "$dev_int" -le $((16#12BF)) ]; then echo true; return; fi
echo false
} }
is_nvidia_fermi() { _is_nvidia_kepler_id() {
local dev_id local dev_id="$1"
dev_id=$(lspci -nn | grep -iE "VGA|3D" | grep -i nvidia | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1) [ -z "$dev_id" ] && return 1
[ -z "$dev_id" ] && { echo false; return; } local dev_int=$((16#${dev_id,,}))
[ "$dev_int" -ge $((16#0FC0)) ] && [ "$dev_int" -le $((16#0FFF)) ] && return 0
local dev_int [ "$dev_int" -ge $((16#1000)) ] && [ "$dev_int" -le $((16#103F)) ] && return 0
dev_int=$((16#${dev_id,,})) [ "$dev_int" -ge $((16#1180)) ] && [ "$dev_int" -le $((16#11FF)) ] && return 0
[ "$dev_int" -ge $((16#1280)) ] && [ "$dev_int" -le $((16#12BF)) ] && return 0
# GF100 / GF110 — GTX 480, GTX 580, Quadro 6000, Tesla C2050 return 1
if [ "$dev_int" -ge $((16#06C0)) ] && [ "$dev_int" -le $((16#06DF)) ]; then echo true; return; fi
# GF104 / GF114 — GTS 450, GTX 460M, GT 555M
if [ "$dev_int" -ge $((16#0DC0)) ] && [ "$dev_int" -le $((16#0DCF)) ]; then echo true; return; fi
# GF104 / GF108 — GT 445M, GT 435M, GT 550M
if [ "$dev_int" -ge $((16#0DD0)) ] && [ "$dev_int" -le $((16#0DDF)) ]; then echo true; return; fi
# GF108 — GT 440, GT 430, GT 520, GT 610, GT 620M, NVS 5400M
if [ "$dev_int" -ge $((16#0DE0)) ] && [ "$dev_int" -le $((16#0DEF)) ]; then echo true; return; fi
# GF108 — GT 525M, GT 540M, GT 550M, Quadro 600, Quadro 500M
if [ "$dev_int" -ge $((16#0DF0)) ] && [ "$dev_int" -le $((16#0DFF)) ]; then echo true; return; fi
# GF104 / GF114 — GTX 460, GTX 470M, GTX 485M
if [ "$dev_int" -ge $((16#0E22)) ] && [ "$dev_int" -le $((16#0E31)) ]; then echo true; return; fi
# GF119 — GT 520M, GT 610M, NVS 4200M
if [ "$dev_int" -ge $((16#1050)) ] && [ "$dev_int" -le $((16#105F)) ]; then echo true; return; fi
# GF110 — GTX 580, GTX 570, GTX 560 Ti, GTX 590
if [ "$dev_int" -ge $((16#1080)) ] && [ "$dev_int" -le $((16#108F)) ]; then echo true; return; fi
# GF110 — Tesla M2090, Quadro 5010M, Quadro 7000
if [ "$dev_int" -ge $((16#1090)) ] && [ "$dev_int" -le $((16#109F)) ]; then echo true; return; fi
# GF116 / GF119 — GTX 560, GTX 460 v2, GTX 555, GT 645
if [ "$dev_int" -ge $((16#1200)) ] && [ "$dev_int" -le $((16#120F)) ]; then echo true; return; fi
# GF116 / GF108 — GTX 550 Ti, GTS 450 rev, GT 545, GT 640 (Fermi)
if [ "$dev_int" -ge $((16#1240)) ] && [ "$dev_int" -le $((16#124F)) ]; then echo true; return; fi
echo false
} }
is_nvidia_maxwell() { # Normaliza la familia de arquitectura NVIDIA desambiguando Kepler/Fermi
local dev_id # (detect_nvidia_arch los agrupa como "legacy" vía rango de device IDs)
dev_id=$(lspci -nn | grep -iE "VGA|3D" | grep -i nvidia | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1) _get_nvidia_arch_family() {
[ -z "$dev_id" ] && { echo false; return; } local fam
fam=$(detect_nvidia_arch "$NVIDIA_GPU_DEVICE_ID")
local dev_int if [ "$fam" = "legacy" ]; then
dev_int=$((16#${dev_id,,})) if _is_nvidia_kepler_id "$NVIDIA_GPU_DEVICE_ID"; then
echo "kepler"
# GM108/GM107/GM204 — gama media/baja + Quadros M (incluye 980M/970M) else
if [ "$dev_int" -ge $((16#1340)) ] && [ "$dev_int" -le $((16#13FF)) ]; then echo true; return; fi echo "fermi"
# GM206 — GTX 960, GTX 950, Quadro M2000 fi
if [ "$dev_int" -ge $((16#1400)) ] && [ "$dev_int" -le $((16#14FF)) ]; then echo true; return; fi else
# GM200 — TITAN X, GTX 980 Ti echo "$fam"
if [ "$dev_int" -ge $((16#17C0)) ] && [ "$dev_int" -le $((16#17CF)) ]; then echo true; return; fi fi
# GM200 profesional — Quadro M6000, Tesla M40
if [ "$dev_int" -ge $((16#17F0)) ] && [ "$dev_int" -le $((16#17FF)) ]; then echo true; return; fi
echo false
} }
is_nvidia_pascal() { is_nvidia_kepler() { [ -n "$NVIDIA_GPU_DEVICE_ID" ] && [[ "$(detect_nvidia_arch "$NVIDIA_GPU_DEVICE_ID")" == "legacy" ]] && _is_nvidia_kepler_id "$NVIDIA_GPU_DEVICE_ID" && echo true || echo false; }
local dev_id is_nvidia_fermi() { [ -n "$NVIDIA_GPU_DEVICE_ID" ] && [[ "$(detect_nvidia_arch "$NVIDIA_GPU_DEVICE_ID")" == "legacy" ]] && ! _is_nvidia_kepler_id "$NVIDIA_GPU_DEVICE_ID" && echo true || echo false; }
dev_id=$(lspci -nn | grep -iE "VGA|3D" | grep -i nvidia | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1) is_nvidia_legacy() { [ -n "$NVIDIA_GPU_DEVICE_ID" ] && [[ "$(detect_nvidia_arch "$NVIDIA_GPU_DEVICE_ID")" == "legacy" ]] && echo true || echo false; }
[ -z "$dev_id" ] && { echo false; return; } is_nvidia_maxwell() { [ -n "$NVIDIA_GPU_DEVICE_ID" ] && [[ "$(detect_nvidia_arch "$NVIDIA_GPU_DEVICE_ID")" == "maxwell" ]] && echo true || echo false; }
is_nvidia_pascal() { [ -n "$NVIDIA_GPU_DEVICE_ID" ] && [[ "$(detect_nvidia_arch "$NVIDIA_GPU_DEVICE_ID")" == "pascal" ]] && echo true || echo false; }
local dev_int is_nvidia_volta() { [ -n "$NVIDIA_GPU_DEVICE_ID" ] && [[ "$(detect_nvidia_arch "$NVIDIA_GPU_DEVICE_ID")" == "volta" ]] && echo true || echo false; }
dev_int=$((16#${dev_id,,})) is_nvidia_turing() { [ -n "$NVIDIA_GPU_DEVICE_ID" ] && [[ "$(detect_nvidia_arch "$NVIDIA_GPU_DEVICE_ID")" == "turing" ]] && echo true || echo false; }
is_nvidia_ampere() { [ -n "$NVIDIA_GPU_DEVICE_ID" ] && [[ "$(detect_nvidia_arch "$NVIDIA_GPU_DEVICE_ID")" == "ampere" ]] && echo true || echo false; }
# GP100 — Tesla P100, Quadro GP100 is_nvidia_ada() { [ -n "$NVIDIA_GPU_DEVICE_ID" ] && [[ "$(detect_nvidia_arch "$NVIDIA_GPU_DEVICE_ID")" == "ada" ]] && echo true || echo false; }
if [ "$dev_int" -ge $((16#15F0)) ] && [ "$dev_int" -le $((16#15FF)) ]; then echo true; return; fi is_nvidia_blackwell() { [ -n "$NVIDIA_GPU_DEVICE_ID" ] && [[ "$(detect_nvidia_arch "$NVIDIA_GPU_DEVICE_ID")" == "blackwell" ]] && echo true || echo false; }
# GP102 — TITAN Xp, GTX 1080 Ti, Tesla P40, Quadro P6000
if [ "$dev_int" -ge $((16#1B00)) ] && [ "$dev_int" -le $((16#1B3F)) ]; then echo true; return; fi
# GP104 — GTX 1080, GTX 1070, Quadro P5000/P4000/P5200/P4200
if [ "$dev_int" -ge $((16#1B80)) ] && [ "$dev_int" -le $((16#1BBF)) ]; then echo true; return; fi
# GP106 + GP107 — GTX 1060, GTX 1050 Ti, GTX 1050, Quadro P2000/P1000/P620/P600
if [ "$dev_int" -ge $((16#1C00)) ] && [ "$dev_int" -le $((16#1CFF)) ]; then echo true; return; fi
# GP108 — GT 1030, GT 1010, MX150/250/350/330, Quadro P520
if [ "$dev_int" -ge $((16#1D00)) ] && [ "$dev_int" -le $((16#1D7F)) ]; then echo true; return; fi
echo false
}
is_nvidia_blackwell() {
local dev_id
dev_id=$(lspci -nn | grep -iE "VGA|3D" | grep -i nvidia | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1)
[ -z "$dev_id" ] && { echo false; return; }
local dev_int
dev_int=$((16#${dev_id,,}))
# Blackwell (GB20x) rango bajo: 0x2900 0x29BF
if [ "$dev_int" -ge $((16#2900)) ] && [ "$dev_int" -le $((16#29BF)) ]; then echo true; return; fi
# Blackwell (GB20x) rango alto: 0x2B80 0x31DF
if [ "$dev_int" -ge $((16#2B80)) ] && [ "$dev_int" -le $((16#31DF)) ]; then echo true; return; fi
echo false
}
is_amd_legacy_gcn() { is_amd_legacy_gcn() {
local dev_id local dev_id
dev_id=$(lspci -nn | grep -iE "VGA|3D" | grep -i amd | grep -oP '1002:\K[0-9a-fA-F]{4}' | head -n1) dev_id=$(echo "$LSPCI_OUTPUT" | grep -iE "VGA|3D" | grep -i amd | grep -oP '1002:\K[0-9a-fA-F]{4}' | head -n1)
[ -z "$dev_id" ] && { echo false; return; } [ -z "$dev_id" ] && {
echo false
return
}
local legacy_ids local legacy_ids
legacy_ids="6660|6664|6665|6667|6780|6784|6788|678a|6798|679a|679e|679f|3000|3001|6808|6809|6810|6811|6816|6817|6818|6819|6828|6829|682b|682c|6835|6837|683d|683f|6608|6609|6610|6611|6613|6617|1dcf|983d|6646|6649|664d|6650|6651|6658|665c|665d|67a0|67a1|67a2|67a8|67a9|67aa|67b0|67b1|67b8|67be|9830|9831|9832|9833|9834|9835|9836|9837|9838|9839|1304|1305|1306|1307|1309|130a|130b|130c|130d|130e|130f|1310|1311|1312|1313|1315|1316|1317|1318|131b|131c|131d|9850|9851|9852|9853|9854|9855|9856|9857|9858|9859|985a|985b|985c|985d|985e|985f" legacy_ids="6660|6664|6665|6667|6780|6784|6788|678a|6798|679a|679e|679f|3000|3001|6808|6809|6810|6811|6816|6817|6818|6819|6828|6829|682b|682c|6835|6837|683d|683f|6608|6609|6610|6611|6613|6617|1dcf|983d|6646|6649|664d|6650|6651|6658|665c|665d|67a0|67a1|67a2|67a8|67a9|67aa|67b0|67b1|67b8|67be|9830|9831|9832|9833|9834|9835|9836|9837|9838|9839|1304|1305|1306|1307|1309|130a|130b|130c|130d|130e|130f|1310|1311|1312|1313|1315|1316|1317|1318|131b|131c|131d|9850|9851|9852|9853|9854|9855|9856|9857|9858|9859|985a|985b|985c|985d|985e|985f"
@@ -139,7 +100,7 @@ _install_mesa_backports() {
for mpkg in "${mesa_pkgs[@]}"; do for mpkg in "${mesa_pkgs[@]}"; do
local bpo_ver local bpo_ver
bpo_ver=$(apt-cache madison "$mpkg" 2>/dev/null | \ bpo_ver=$(apt-cache madison "$mpkg" 2>/dev/null |
grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1) grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1)
if [ -n "$bpo_ver" ]; then if [ -n "$bpo_ver" ]; then
bpo_pkgs+=("$mpkg") bpo_pkgs+=("$mpkg")
@@ -159,7 +120,7 @@ _install_mesa_backports() {
local ref_ver local ref_ver
ref_ver=$(apt-cache policy mesa-vulkan-drivers 2>/dev/null | awk 'NR==3 {print $2; exit}') ref_ver=$(apt-cache policy mesa-vulkan-drivers 2>/dev/null | awk 'NR==3 {print $2; exit}')
local ref_bpo_ver local ref_bpo_ver
ref_bpo_ver=$(apt-cache madison mesa-vulkan-drivers 2>/dev/null | \ ref_bpo_ver=$(apt-cache madison mesa-vulkan-drivers 2>/dev/null |
grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1) grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1)
local comp_line="Components: Vulkan, OpenGL, GLX, EGL, VA-API (64-bit)" local comp_line="Components: Vulkan, OpenGL, GLX, EGL, VA-API (64-bit)"
@@ -211,10 +172,29 @@ offer_generic_tools() {
local tool_pkgs local tool_pkgs
tool_pkgs=$(pkg_versions nvtop vainfo) tool_pkgs=$(pkg_versions nvtop vainfo)
if _confirm "GPU Tools" "Install monitoring and info tools?\n\n${tool_pkgs}"; then if _confirm "GPU Tools" "Install monitoring and info tools?\n\n${tool_pkgs}"; then
_run_cmd "GPU Tools" "sudo apt install -y nvtop vainfo" "Installing GPU tools..." _run_cmd "GPU Tools" "sudo apt install -y nvtop vainfo" "Installing GPU tools..." || true
vainfo vainfo
_pause "vainfo output shown above." _pause "vainfo output shown above."
else else
echo "Skipping GPU monitoring tools." echo "Skipping GPU monitoring tools."
fi fi
} }
_is_hybrid_laptop() {
local gpu_count nvidia_count chassis
gpu_count=$(echo "$LSPCI_OUTPUT" | grep -ciE "VGA compatible|3D controller") || true
[ "$gpu_count" -lt 2 ] && return 1
# Defensa en profundidad: si TODAS las GPUs son NVIDIA (SLI o
# dual-GPU desktop), no hay iGPU Intel/AMD → no es híbrida.
nvidia_count=$(echo "$LSPCI_OUTPUT" | grep -iE "VGA compatible|3D controller" | grep -c "10de:") || true
[ "$nvidia_count" -ge "$gpu_count" ] && return 1
chassis=$(cat /sys/class/dmi/id/chassis_type 2>/dev/null || echo "0")
case "$chassis" in
8 | 9 | 10 | 11 | 14 | 30 | 31 | 32) return 0 ;;
esac
ls /sys/class/power_supply/ 2>/dev/null | grep -q "^BAT" && return 0
return 1
}
+298 -275
View File
@@ -1,206 +1,297 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# NVIDIA GPU driver installation — 3-CASE dispatch # NVIDIA GPU driver installation
# #
# CASE A : Trixie + backports kernel → Official NVIDIA CUDA Repo (Pinned v590) # CASE A : Trixie + backports kernel → Official NVIDIA CUDA Repo (Pinned v590)
# CASE B : Bookworm + backports kernel → Debian backports (-t bookworm-backports) # CASE B : Kernel stable (any distro) → Debian stable
# CASE C : Kernel stable (any distro) → Debian stable (optional backports) #
# Nota: Debian 12 (Bookworm) backports llegaron a EOL (2026-08-09);
# el flujo NVIDIA solo usa el repositorio estable para Debian 12.
# --- DEPRECATED (Replaced by _install_nvidia_stack in gpu.sh) --- # -------------------------------------------------------------------
install_nvidia_driver() { # Shared helper: enable NVIDIA CUDA repo
echo -e "${YELLOW}NVIDIA GPU detected.${NC}" # Debian 13 (Trixie): cuda-keyring (método oficial — extrepo roto)
NVIDIA_DRIVER_MODE="" # Debian 12 (Bookworm): extrepo nvidia-cuda (funciona)
# -------------------------------------------------------------------
_enable_cuda_repo() {
_is_cuda_repo_ready && return 0
local is_bpo_kernel; is_bpo_kernel=$(is_backports_kernel) if [ "$DEBIAN_VERSION" = "13" ]; then
local is_kepler; is_kepler=$(is_nvidia_kepler) # Método oficial NVIDIA: cuda-keyring (extrepo no configura
local is_maxwell; is_maxwell=$(is_nvidia_maxwell) # correctamente el repo en Trixie)
local is_pascal; is_pascal=$(is_nvidia_pascal) if dpkg -s cuda-keyring &>/dev/null; then
local is_blackwell; is_blackwell=$(is_nvidia_blackwell) return 0 # ya instalado → su .list ya existe
fi
# ── Blackwell: v550 no soporta GB20x → CUDA repo v590 ── if ! wget -q "https://developer.download.nvidia.com/compute/cuda/repos/debian13/x86_64/cuda-keyring_1.1-1_all.deb" \
if [ "$DEBIAN_CODENAME" = "trixie" ] && [ "$is_blackwell" = "true" ]; then -O /tmp/cuda-keyring.deb; then
_msg "NVIDIA Blackwell" \ rm -f /tmp/cuda-keyring.deb
"Your GPU is NVIDIA Blackwell architecture.\n\nDebian 13's nvidia-driver (v550) does not\nsupport Blackwell GPUs.\n\n\ _msg "CUDA Repo — Error" "Failed to download cuda-keyring.\n\nNo NVIDIA driver was installed." 10 60
The script will enable the official NVIDIA CUDA\nrepository and install the v590 production branch,\nwhich fully supports Blackwell (GB20x)." 14 65 return 1
_install_nvidia_cuda_repo fi
return if ! sudo dpkg -i /tmp/cuda-keyring.deb; then
rm -f /tmp/cuda-keyring.deb
_msg "CUDA Repo — Error" "Failed to install cuda-keyring.\n\nNo NVIDIA driver was installed." 10 60
return 1
fi
rm -f /tmp/cuda-keyring.deb
return 0
fi fi
# ── Veto: Kepler en Trixie no tiene driver disponible ── # Debian 12 (y otros): extrepo nvidia-cuda
if [ "$is_kepler" = "true" ] && [ "$DEBIAN_CODENAME" = "trixie" ]; then if ! command -v extrepo &>/dev/null; then
_msg "NVIDIA Kepler" \ _run_cmd "extrepo" "sudo apt install -y extrepo" "Installing extrepo..." || return 1
"Your GPU is NVIDIA Kepler architecture.\n\nThe nvidia-tesla-470 driver is not available\nin Debian 13 (Trixie).\n\nNo NVIDIA driver will be installed." 14 65 fi
_run_cmd "CUDA Repo" \
"sudo extrepo enable nvidia-cuda" \
"Enabling official NVIDIA CUDA repository..." || return 1
}
# -------------------------------------------------------------------
# Shared DKMS helpers: verify the NVIDIA module compiled for the
# currently running kernel; repair via dpkg-reconfigure if not
# -------------------------------------------------------------------
# Returns: 0 if the NVIDIA DKMS module shows "installed" for $(uname -r)
_nvidia_dkms_installed() {
local kernel line
kernel=$(uname -r)
line=$(dkms status 2>/dev/null | grep "^nvidia" | grep -F "$kernel" | grep ": installed" | head -1)
[ -n "$line" ]
}
# Returns 0 if Secure Boot is active (mokutil present and enabled)
_nvidia_secure_boot_enabled() {
command -v mokutil &>/dev/null || return 1
mokutil --sb-state 2>/dev/null | grep -q "SecureBoot enabled"
}
# Aviso no fatal: el módulo DKMS está compilado pero NO firmado.
# El usuario avanzado puede firmarlo con MOK; el novato necesita saber
# por qué verá pantalla negra tras reiniciar. Si mokutil falta, no se
# muestra nada (mokutil no viene preinstalado en Debian).
_warn_secure_boot() {
if _nvidia_secure_boot_enabled; then
echo -e "${RED}WARNING: Secure Boot is enabled. The NVIDIA DKMS module is compiled but NOT signed.${NC}"
echo -e "${RED}You MUST sign the module with MOK or disable Secure Boot in BIOS before rebooting.${NC}"
echo -e "${RED}See: https://wiki.debian.org/SecureBoot#Signing_kernel_modules${NC}"
fi
}
# Verify the DKMS build for the current kernel and repair it if needed.
# $@ = candidate dkms packages to reconfigure, in priority order
# (the first installed one is used for dpkg-reconfigure).
_verify_nvidia_dkms_build() {
local kernel
kernel=$(uname -r)
echo ""
echo "──────────────────────────────────────────────"
echo "Verifying DKMS module compilation for ${kernel}:"
if ! command -v dkms &>/dev/null; then
echo -e "${RED}(dkms not installed — DKMS build cannot be verified)${NC}"
echo "──────────────────────────────────────────────"
return 1 return 1
fi fi
# ── Bloqueo: Maxwell/Pascal no son compatibles con v590 ── dkms status 2>/dev/null | grep "^nvidia" || echo "(no nvidia DKMS module found)"
if [ "$DEBIAN_CODENAME" = "trixie" ] && [ "$is_bpo_kernel" = "true" ]; then
if [ "$is_maxwell" = "true" ] || [ "$is_pascal" = "true" ]; then if _nvidia_dkms_installed; then
local gpu_gen="Maxwell" _warn_secure_boot
[ "$is_pascal" = "true" ] && gpu_gen="Pascal" echo -e "${GREEN}DKMS module compiled for ${kernel}. Reboot required.${NC}"
local block_msg="INCOMPATIBILITY DETECTED: Your NVIDIA ${gpu_gen} GPU\n" echo "──────────────────────────────────────────────"
block_msg+="is NOT supported by the modern v590 driver.\n\n" return 0
block_msg+="To run NVIDIA safely on Debian 13 (Trixie), you MUST use\n"
block_msg+="the official Debian v550 driver, which requires the\n"
block_msg+="standard STABLE Kernel.\n\n"
block_msg+="The script will automatically downgrade your path to\n"
block_msg+="Stable Kernel mode for NVIDIA."
_msg "NVIDIA — Trixie + Backports" "$block_msg" 14 70
is_bpo_kernel=false
fi
fi fi
# ── Dispatch por casos ── echo -e "${YELLOW}DKMS module NOT compiled for ${kernel}. Repairing...${NC}"
if [ "$DEBIAN_CODENAME" = "trixie" ] && [ "$is_bpo_kernel" = "true" ]; then local pkg repaired=false
_install_nvidia_cuda_repo for pkg in "$@"; do
elif [ "$DEBIAN_CODENAME" = "bookworm" ] && [ "$is_bpo_kernel" = "true" ]; then if dpkg -l "$pkg" 2>/dev/null | grep -q "^ii"; then
_install_nvidia_bookworm_bpo _run_cmd "NVIDIA" "sudo dpkg-reconfigure $pkg" "Reconfiguring $pkg..."
repaired=true
break
fi
done
if ! $repaired; then
echo -e "${RED}No DKMS package found to reconfigure.${NC}"
fi
if _nvidia_dkms_installed; then
_warn_secure_boot
echo -e "${GREEN}DKMS module compiled successfully for ${kernel}. Reboot required.${NC}"
echo "──────────────────────────────────────────────"
return 0
else else
_install_nvidia_standard echo -e "${RED}DKMS module still not compiled for ${kernel}.${NC}"
echo "Check the build log manually:"
echo " /var/lib/dkms/nvidia*/.../build/make.log"
echo " dmesg | grep nvidia"
echo "──────────────────────────────────────────────"
return 1
fi fi
} }
# ------------------------------------------------------------------- # -------------------------------------------------------------------
# Shared helper: enable NVIDIA CUDA repo via extrepo # NVIDIA driver version selection (Debian 12/13)
# Sets the global NVIDIA_SELECTED_VERSION; first option is the default.
# Returns: 0 if a version was chosen, 1 if the user cancelled
# ------------------------------------------------------------------- # -------------------------------------------------------------------
_enable_cuda_repo() { _is_cuda_repo_ready() {
if [ ! -f /etc/apt/sources.list.d/extrepo_nvidia-cuda.sources ] && \ [ -f /etc/apt/sources.list.d/extrepo_nvidia-cuda.sources ] ||
! grep -qr 'developer.download.nvidia.com' /etc/apt/sources.list.d/ 2>/dev/null; then grep -qr 'developer.download.nvidia.com' /etc/apt/sources.list.d/ 2>/dev/null
if ! command -v extrepo &>/dev/null; then }
_run_cmd "extrepo" "sudo apt install -y extrepo" "Installing extrepo..."
fi _show_nvidia_version_menu() {
_run_cmd "CUDA Repo" \ local choice
"sudo extrepo enable nvidia-cuda" \ if [ "$DEBIAN_VERSION" = "12" ]; then
"Enabling official NVIDIA CUDA repository..." choice=$(_menu "Select NVIDIA Driver for Debian 12 (Bookworm):" "Choose the NVIDIA driver version:" 12 70 3 \
"535" "v535 — Debian Official (Recommended)" \
"470" "v470 — Debian Legacy (Kepler Support)")
elif [ "$DEBIAN_VERSION" = "13" ]; then
choice=$(_menu "Select NVIDIA Driver for Debian 13 (Trixie):" "Choose the NVIDIA driver version:" 14 70 5 \
"550" "v550 — Debian Official (Recommended)" \
"590" "v590 — NVIDIA CUDA Repo (Production Branch)" \
"595" "v595 — NVIDIA CUDA Repo (Newest Stable)")
else
NVIDIA_SELECTED_VERSION="auto"
return 0
fi fi
_run_cmd "APT Update" "sudo apt update" "Updating package lists..." [ -z "$choice" ] && return 1
NVIDIA_SELECTED_VERSION="$choice"
return 0
}
# -------------------------------------------------------------------
# NVIDIA Wayland/KMS base configuration (/etc/modprobe.d/nvidia-wayland.conf)
# Applies on Debian 12/13, any driver version (535/550/590/595).
# Arquitectura y detección híbrida son ORTOGONALES:
# - Arquitectura → afecta SOLO fbdev (kepler: el 470 no lo soporta)
# y el color/mensaje informativo.
# - Híbrida vs desktop → afecta NVreg (Preserve / kernel suspend
# notifier), INDEPENDIENTE de la arquitectura.
# 590/595 añaden el kernel suspend notifier (complementa, nunca
# reemplaza, NVreg_PreserveVideoMemoryAllocations).
# -------------------------------------------------------------------
_configure_nvidia_wayland() {
local ver="${1:-$NVIDIA_SELECTED_VERSION}"
local conf="/etc/modprobe.d/nvidia-wayland.conf"
local arch
local content=""
local color="${GREEN}"
local msg="Wayland config (desktop): KMS + video memory preservation enabled."
arch=$(_get_nvidia_arch_family)
# ── Arquitectura: solo fbdev y mensaje de color ──
case "$arch" in
kepler)
color="${RED}"
msg="WARNING: Wayland not supported on Kepler. Use X11 (Xorg)."
;;
maxwell | pascal)
color="${YELLOW}"
msg="Wayland support on ${arch} is experimental. X11 recommended."
;;
esac
# ── Híbrida vs desktop: NVreg independiente de la arquitectura ──
if _is_hybrid_laptop; then
content="options nvidia-drm modeset=1"$'\n'
[ "$arch" != "kepler" ] && content+="options nvidia-drm fbdev=1"$'\n'
color="${GREEN}"
msg="Wayland config (hybrid laptop): KMS enabled — NVreg omitted."
else
content="options nvidia NVreg_PreserveVideoMemoryAllocations=1"$'\n'
case "$ver" in
590 | 595) content+="options nvidia NVreg_UseKernelSuspendNotifiers=1"$'\n' ;;
esac
content+="options nvidia-drm modeset=1"$'\n'
[ "$arch" != "kepler" ] && content+="options nvidia-drm fbdev=1"$'\n'
fi
printf "%b" "$content" | sudo tee "$conf" >/dev/null || return 1
echo -e "${color}${msg}${NC}"
} }
# ------------------------------------------------------------------- # -------------------------------------------------------------------
# CASE A: Trixie + Backports Kernel → Official CUDA Repo (Pinned v590) # CASE A: Trixie + Backports Kernel → Official CUDA Repo (Pinned v590)
# ------------------------------------------------------------------- # -------------------------------------------------------------------
_install_nvidia_cuda_repo() { _install_nvidia_cuda_repo() {
local warn="WARNING: Official Debian NVIDIA driver (v550)\n" local ver="${1:-590}"
warn+="fails to compile on Trixie Backports Kernels.\n\n" local warn="WARNING: You are about to install NVIDIA v${ver} from\n"
warn+="The script will enable the official NVIDIA CUDA\n" warn+="the official NVIDIA CUDA repository.\n\n"
warn+="repository and install the production branch v590\n" warn+="Source: Official NVIDIA CUDA Repo\n"
warn+="using NVIDIA's unified driver pinning packages.\n\n" warn+="Driver: Production Branch v${ver} (unified metapackage)\n"
warn+="Source: Official NVIDIA CUDA Repo (Pinned v590.*)\n" warn+="[+] nvidia-driver-pinning-${ver} (version lock)\n"
warn+="Driver: Production Branch v590 (unified metapackage)\n" warn+="[+] nvidia-open (driver + open kernel modules)\n\n"
warn+="[+] nvidia-driver (full 64-bit compute + graphics)\n"
warn+="[+] firmware-nvidia-gsp\n"
warn+="[+] nvidia-driver-pinning-590 (branch locking)\n"
warn+="[+] APT Pinning (version 590.*)\n\n"
warn+="Do you want to proceed at your own risk?" warn+="Do you want to proceed at your own risk?"
if ! _confirm_custom "NVIDIA Driver — Trixie + Backports" "$warn" "Proceed" "Abort" 18 70; then if ! _confirm_custom "NVIDIA Driver — v${ver}" "$warn" "Proceed" "Abort" 18 70; then
echo -e "${YELLOW}NVIDIA installation aborted by user.${NC}" echo -e "${YELLOW}NVIDIA installation aborted by user.${NC}"
return 1 return 1
fi fi
# Step 1: Enable CUDA repo via extrepo # Step 1: Enable CUDA repo (cuda-keyring Trixie / extrepo Bookworm)
_enable_cuda_repo if ! _enable_cuda_repo; then
_msg "CUDA Repo — Error" "Failed to enable the official NVIDIA CUDA repository.\n\nNo NVIDIA driver was installed." 10 60
return 1
fi
# Step 2: Create APT pinning to lock v590 # Step 2: apt update explícito — sin índice actualizado el repo no
_run_cmd "APT Pinning" \ # se ve y apt resolvería el candidato Debian (v550) en vez de v${ver}.
'printf "%s\n" "Package: *nvidia*" "Package: *cuda*" "Package: libcuda1" "Package: firmware-nvidia-gsp" "Pin: version 590.*" "Pin-Priority: 1001" | sudo tee /etc/apt/preferences.d/block-nvidia > /dev/null' \ if ! _run_cmd "CUDA Repo" "sudo apt update" \
"Creating APT pinning to lock NVIDIA to v590 branch..." "Updating package lists after enabling CUDA repository..."; then
NVIDIA_DRIVER_MODE=""
_msg "CUDA Repo — Error" "Failed to update APT after enabling CUDA repo.\n\nNo NVIDIA driver was installed." 10 60
return 1
fi
# Step 3: Install NVIDIA unified metapackages (driver pinning) # Step 3: Pinning oficial — transacción APT INDEPENDIENTE y
_run_cmd "NVIDIA CUDA" \ # obligatoria. APT lee /etc/apt/preferences.d/ al inicio de su
"sudo apt install -y nvidia-driver-pinning-590 nvidia-driver firmware-nvidia-gsp" \ # ejecución, no durante la transacción: el pinning debe estar
"Installing NVIDIA v590 production driver via unified metapackages..." # instalado ANTES de instalar el driver. Si el repo no lo publica,
# es un problema del repo de NVIDIA: abortar limpiamente en vez de
# instalar una versión que el usuario no eligió.
if ! _run_cmd "NVIDIA Pinning" \
"sudo apt install -y nvidia-driver-pinning-${ver}" \
"Installing NVIDIA version pinning (${ver})..."; then
NVIDIA_DRIVER_MODE=""
_msg "NVIDIA — Error" "Failed to install NVIDIA driver pinning ${ver}.\n\nNo NVIDIA driver was installed." 10 60
return 1
fi
# Step 4: Instalar el metapaquete (pinning ya activo). Si falla,
# el pinning queda instalado (solo config, no es problema).
# firmware-nvidia-gsp llega como dependencia transitiva obligatoria
# (nvidia-open → nvidia-kernel-open-dkms → firmware-nvidia-gsp),
# alineado con la doc oficial: apt -V install nvidia-open.
if ! _run_cmd "NVIDIA CUDA" \
"sudo apt install -y nvidia-open" \
"Installing NVIDIA driver from CUDA repository..."; then
NVIDIA_DRIVER_MODE=""
_msg "NVIDIA — Error" "NVIDIA driver installation FAILED.\n\nNo NVIDIA driver was installed." 10 60
return 1
fi
# Post-install: el módulo DKMS instalado debe coincidir con la rama ${ver}
local dkms_ver
dkms_ver=$(dpkg -l nvidia-kernel-dkms nvidia-kernel-open-dkms 2>/dev/null | awk '$1=="ii" {print $3; exit}')
if [[ "$dkms_ver" == ${ver}.* ]]; then
echo -e "${GREEN}DKMS module ${dkms_ver} matches branch v${ver}.${NC}"
else
echo -e "${RED}WARNING: DKMS package (${dkms_ver:-none}) does not match v${ver}.*${NC}"
fi
NVIDIA_DRIVER_MODE="cuda-repo" NVIDIA_DRIVER_MODE="cuda-repo"
echo -e "${GREEN}NVIDIA Production Driver v590 installed from CUDA repo. Reboot required.${NC}" echo -e "${GREEN}NVIDIA Production Driver v${ver} installed from CUDA repo. Reboot required.${NC}"
echo "" _verify_nvidia_dkms_build nvidia-kernel-open-dkms nvidia-kernel-dkms || true
echo "──────────────────────────────────────────────"
echo "Verifying DKMS module compilation:"
if command -v dkms &>/dev/null; then
dkms status 2>/dev/null | grep nvidia || echo "(no nvidia DKMS module found)"
else
echo "(dkms not installed)"
fi
echo ""
echo "If the line ends with 'installed' → module is OK."
echo "Otherwise check: dmesg | grep nvidia"
echo "──────────────────────────────────────────────"
}
# -------------------------------------------------------------------
# CASE B: Bookworm + Backports Kernel → Debian backports
# -------------------------------------------------------------------
_install_nvidia_bookworm_bpo() {
local nv_pkg=""
local is_kepler
is_kepler=$(is_nvidia_kepler)
if [ "$is_kepler" = "true" ]; then
nv_pkg="nvidia-tesla-470-driver"
else
local nd_ver
nd_ver=$(apt-cache policy nvidia-detect 2>/dev/null | awk 'NR==3 {print $2; exit}')
if _confirm "NVIDIA Detect" "Install nvidia-detect to determine the correct driver?\n\n nvidia-detect ${nd_ver:-unknown}" 12 70; then
_run_cmd "NVIDIA" "sudo apt install -y nvidia-detect" "Installing nvidia-detect..."
else
echo "Skipping NVIDIA driver detection."
NVIDIA_DRIVER_MODE=""
return 0
fi
local recommended
recommended=$(nvidia-detect 2>/dev/null | grep -oP 'nvidia[\w-]+(?= package)')
if [ -z "$recommended" ]; then
echo -e "${RED}nvidia-detect could not determine a suitable driver.${NC}"
return 1
fi
if [[ "$recommended" =~ legacy-390|legacy-340 ]]; then
echo -e "${RED}Your GPU requires $recommended, which is not available.${NC}"
return 1
fi
nv_pkg="$recommended"
fi
local nv_ver
nv_ver=$(apt-cache policy "$nv_pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}')
local msg="Source: Debian Bookworm-Backports\n"
msg+="NVIDIA Driver: ${nv_pkg} ${nv_ver:-unknown}\n"
msg+=" (Compatible with Kernel v6.12+)\n"
msg+="[+] firmware-misc-nonfree\n"
msg+="[+] nvidia-vaapi-driver"
if ! _confirm "NVIDIA Driver — Backports" "$msg" 14 70; then
echo "Skipping NVIDIA driver installation."
return 0
fi
_run_cmd "NVIDIA" "sudo apt install -y -t bookworm-backports $nv_pkg firmware-misc-nonfree nvidia-vaapi-driver" \
"Installing NVIDIA driver from backports..."
NVIDIA_DRIVER_MODE="backports"
echo -e "${GREEN}NVIDIA driver installed from backports. Reboot required.${NC}"
echo ""
echo "──────────────────────────────────────────────"
echo "Verifying DKMS module compilation:"
if command -v dkms &>/dev/null; then
dkms status 2>/dev/null | grep nvidia || echo "(no nvidia DKMS module found)"
else
echo "(dkms not installed)"
fi
echo ""
echo "If the line ends with 'installed' → module is OK."
echo "Otherwise check: dmesg | grep nvidia"
echo "──────────────────────────────────────────────"
} }
# ------------------------------------------------------------------- # -------------------------------------------------------------------
# Bookworm Kepler intercepción — fuerza nvidia-legacy-470xx-driver # Bookworm Kepler intercepción — fuerza nvidia-legacy-470xx-driver
# sin pasar por nvidia-detect (evita falsa recomendación rama 535)
# ------------------------------------------------------------------- # -------------------------------------------------------------------
_install_nvidia_bookworm_kepler() { _install_nvidia_bookworm_kepler() {
local nv_pkg="nvidia-legacy-470xx-driver" local nv_pkg="nvidia-tesla-470-driver"
local nv_ver local nv_ver
nv_ver=$(apt-cache policy "$nv_pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}') nv_ver=$(apt-cache policy "$nv_pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}') || true
echo -e "${YELLOW}Kepler GPU detected — forcing ${nv_pkg}.${NC}" echo -e "${YELLOW}Kepler GPU detected — forcing ${nv_pkg}.${NC}"
@@ -209,8 +300,8 @@ _install_nvidia_bookworm_kepler() {
msg+="en lugar del moderno. Se usará el paquete:\n" msg+="en lugar del moderno. Se usará el paquete:\n"
msg+=" ${nv_pkg} ${nv_ver:-unknown}\n" msg+=" ${nv_pkg} ${nv_ver:-unknown}\n"
msg+="para evitar fallos de pantalla negra.\n\n" msg+="para evitar fallos de pantalla negra.\n\n"
msg+=" [SKIP] nvidia-detect (omitido — evita rama 535)\n"
msg+=" [USE] ${nv_pkg}\n" msg+=" [USE] ${nv_pkg}\n"
msg+=" [+] linux-headers-amd64\n"
msg+=" [+] firmware-misc-nonfree\n" msg+=" [+] firmware-misc-nonfree\n"
msg+=" [+] nvidia-settings\n\n" msg+=" [+] nvidia-settings\n\n"
msg+="Instalar driver legacy para Kepler?" msg+="Instalar driver legacy para Kepler?"
@@ -221,140 +312,72 @@ _install_nvidia_bookworm_kepler() {
return 0 return 0
fi fi
_run_cmd "NVIDIA Kepler" \ if ! _run_cmd "NVIDIA Kepler" \
"sudo apt install -y $nv_pkg firmware-misc-nonfree nvidia-settings" \ "sudo apt install -y linux-headers-amd64 $nv_pkg firmware-misc-nonfree nvidia-settings" \
"Instalando nvidia-legacy-470xx-driver..." "Instalando nvidia-legacy-470xx-driver..."; then
NVIDIA_DRIVER_MODE=""
# Si backports está habilitado, ofrecer actualización _msg "NVIDIA Kepler — Error" "Kepler driver installation FAILED.\n\nNo NVIDIA driver was installed." 10 60
if [ "$(is_backports_enabled)" == "true" ]; then return 1
local bpo_ver
bpo_ver=$(apt-cache madison "$nv_pkg" 2>/dev/null | \
grep "bookworm-backports" | awk '{print $3}' | head -1)
if [ -n "$bpo_ver" ]; then
local msg="Hay una versión en backports: ${bpo_ver}\n"
msg+="Instalar desde bookworm-backports?"
if _confirm "Kepler Backports" "$msg"; then
_run_cmd "NVIDIA Kepler" \
"sudo apt install -y -t bookworm-backports $nv_pkg" \
"Actualizando Kepler driver desde backports..."
NVIDIA_DRIVER_MODE="backports"
echo -e "${GREEN}Kepler driver actualizado desde backports.${NC}"
fi
fi
fi fi
NVIDIA_DRIVER_MODE="${NVIDIA_DRIVER_MODE:-stable}" NVIDIA_DRIVER_MODE="${NVIDIA_DRIVER_MODE:-stable}"
echo -e "${GREEN}Kepler driver (${nv_pkg}) installed. Reboot required.${NC}" echo -e "${GREEN}Kepler driver (${nv_pkg}) installed. Reboot required.${NC}"
echo "" _verify_nvidia_dkms_build nvidia-tesla-470-kernel-dkms || true
echo "──────────────────────────────────────────────"
echo "Verifying DKMS module compilation:"
if command -v dkms &>/dev/null; then
dkms status 2>/dev/null | grep nvidia || echo "(no nvidia DKMS module found)"
else
echo "(dkms not installed)"
fi
echo ""
echo "If the line ends with 'installed' → module is OK."
echo "Otherwise check: dmesg | grep nvidia"
echo "──────────────────────────────────────────────"
} }
# ------------------------------------------------------------------- # -------------------------------------------------------------------
# CASE C: Kernel stable (any distro) → Debian stable, optional backports # CASE B: Kernel stable (any distro) → Debian stable
# ------------------------------------------------------------------- # -------------------------------------------------------------------
_install_nvidia_standard() { _install_nvidia_standard() {
local nv_pkg="" # --- 1. ARQUITECTURA → MÓDULO KERNEL ---
local use_bpo=false # Solo Turing+ (conocido) usa el módulo abierto. Arquitectura
local is_kepler # unknown/vacía o antigua (Kepler/Fermi/Maxwell/Pascal/Volta) →
is_kepler=$(is_nvidia_kepler) # módulo cerrado como fallback seguro.
local fam
fam=$(_get_nvidia_arch_family)
local kernel_pkg="nvidia-kernel-dkms"
case "$fam" in
turing | ampere | ada | blackwell) kernel_pkg="nvidia-open-kernel-dkms" ;;
esac
if [ "$is_kepler" = "true" ]; then # --- 2. PAQUETES — UN SOLO apt install ---
if [ "$DEBIAN_CODENAME" = "trixie" ]; then local extra_pkgs="linux-headers-amd64 nvidia-driver firmware-nvidia-gsp nvidia-vaapi-driver"
_msg "NVIDIA Kepler" \ [ "$DEBIAN_VERSION" = "12" ] && extra_pkgs+=" mesa-vdpau-drivers"
"Your GPU is NVIDIA Kepler architecture.\n\nThe nvidia-tesla-470 driver is not available\nin Debian 13 (Trixie).\n\nOptions:\n 1. Use Debian 12 (Bookworm) with nvidia-tesla-470\n 2. Use open-source Nouveau driver (limited)\n\nNo NVIDIA driver will be installed." 14 65 local install_pkgs="$kernel_pkg $extra_pkgs"
return 1
fi
nv_pkg="nvidia-tesla-470-driver"
echo -e "${YELLOW}Kepler GPU detected. Will use ${nv_pkg}.${NC}"
else
local nd_ver
nd_ver=$(apt-cache policy nvidia-detect 2>/dev/null | awk 'NR==3 {print $2; exit}')
if _confirm "NVIDIA Detect" "Install nvidia-detect to determine the correct driver?\n\n nvidia-detect ${nd_ver:-unknown}" 12 70; then
_run_cmd "NVIDIA" "sudo apt install -y nvidia-detect" "Installing nvidia-detect..."
else
echo "Skipping NVIDIA driver detection."
return 0
fi
local recommended
recommended=$(nvidia-detect 2>/dev/null | grep -oP 'nvidia[\w-]+(?= package)')
if [ -z "$recommended" ]; then
echo -e "${RED}nvidia-detect could not determine a suitable driver.${NC}"
return 1
fi
if [[ "$recommended" =~ legacy-390|legacy-340 ]]; then
echo -e "${RED}Your GPU requires $recommended, which is not available.${NC}"
return 1
fi
nv_pkg="$recommended"
fi
# Check for backports (optional, if repo enabled) # --- 3. MENSAJE DE CONFIRMACIÓN ---
local stable_nv_ver local kernel_ver msg
stable_nv_ver=$(apt-cache policy "$nv_pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}') kernel_ver=$(apt-cache policy "$kernel_pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}') || true
if [ "$(is_backports_enabled)" == "true" ]; then
local bpo_nv_ver
bpo_nv_ver=$(apt-cache madison "$nv_pkg" 2>/dev/null | \
grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1)
if [ -n "$bpo_nv_ver" ]; then
local msg="Source: Debian ${DEBIAN_CODENAME^} (Backports available)\n"
msg+="NVIDIA Driver: ${nv_pkg}\n\n"
msg+=" Backports: ${bpo_nv_ver}\n"
msg+=" Stable: ${stable_nv_ver:-unknown}\n\n"
msg+="Choose version:"
if _confirm_custom "NVIDIA Driver" "$msg" "Backports" "Stable" 14 70; then
use_bpo=true
fi
fi
fi
local src_label="Debian ${DEBIAN_CODENAME^} Stable" msg="Source: Debian ${DEBIAN_CODENAME^} Stable\n"
$use_bpo && src_label="Debian ${DEBIAN_CODENAME^}-Backports" msg+="Kernel Module: ${kernel_pkg} ${kernel_ver:-unknown} (arch: ${fam:-unknown})\n"
msg+="[+] linux-headers-amd64\n"
local msg="Source: ${src_label}\n" msg+="[+] firmware-nvidia-gsp\n"
msg+="NVIDIA Driver: ${nv_pkg} ${stable_nv_ver:-unknown}\n" msg+="[+] nvidia-vaapi-driver"
msg+="[+] firmware-misc-nonfree\n" [ "$DEBIAN_VERSION" = "12" ] && msg+="\n[+] mesa-vdpau-drivers"
msg+="[+] nvidia-vaapi-driver\n"
msg+="[+] mesa-vdpau-drivers"
if ! _confirm "NVIDIA Driver" "$msg" 14 70; then if ! _confirm "NVIDIA Driver" "$msg" 14 70; then
echo "Skipping NVIDIA driver installation." echo "Skipping NVIDIA driver installation."
return 0 return 0
fi fi
local extra_pkgs="firmware-misc-nonfree nvidia-vaapi-driver mesa-vdpau-drivers" # --- 4. EJECUCIÓN ---
if $use_bpo; then if ! _run_cmd "NVIDIA" "sudo apt install -y $install_pkgs" \
_run_cmd "NVIDIA" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports $nv_pkg $extra_pkgs" \ "Installing NVIDIA driver from stable..."; then
"Installing NVIDIA driver from backports..." NVIDIA_DRIVER_MODE=""
NVIDIA_DRIVER_MODE="backports" _msg "NVIDIA — Error" "NVIDIA driver installation FAILED.\n\nNo NVIDIA driver was installed." 10 60
else return 1
_run_cmd "NVIDIA" "sudo apt install -y $nv_pkg $extra_pkgs" \ fi
"Installing NVIDIA driver from stable..." NVIDIA_DRIVER_MODE="stable"
NVIDIA_DRIVER_MODE="stable"
# Fix obligatorio para Debian 12 con módulo abierto
if [ "$DEBIAN_VERSION" = "12" ] && [[ "$kernel_pkg" == *"open"* ]]; then
echo "options nvidia NVreg_OpenRmEnableUnsupportedGpus=1" | sudo tee /etc/modprobe.d/nvidia-open.conf >/dev/null
echo "Applied required Open RM parameter for Debian 12."
fi fi
# --- 5. VERIFICACIÓN DKMS POST-INSTALL ---
echo -e "${GREEN}NVIDIA driver installed. Reboot required.${NC}" echo -e "${GREEN}NVIDIA driver installed. Reboot required.${NC}"
_verify_nvidia_dkms_build "$kernel_pkg" || true
echo ""
echo "──────────────────────────────────────────────"
echo "Verifying DKMS module compilation:"
if command -v dkms &>/dev/null; then
dkms status 2>/dev/null | grep nvidia || echo "(no nvidia DKMS module found)"
else
echo "(dkms not installed)"
fi
echo ""
echo "If the line ends with 'installed' → module is OK."
echo "Otherwise check: dmesg | grep nvidia"
echo "──────────────────────────────────────────────"
} }
+60
View File
@@ -0,0 +1,60 @@
#!/usr/bin/env bash
# nvidia_manage.sh — NVIDIA management menu: install/change or remove
_nvidia_driver_installed() {
dpkg -l 2>/dev/null | grep -qE "^ii (nvidia-driver|nvidia-tesla-470-driver|nvidia-open|nvidia-kernel-dkms|nvidia-kernel-open-dkms|nvidia-open-kernel-dkms)"
}
_nvidia_manage_menu() {
local choice
choice=$(_menu "NVIDIA Driver" "Manage NVIDIA Driver" 12 70 4 \
"1" "Install / Change NVIDIA Driver Version" \
"2" "Remove NVIDIA Driver and Restore Nouveau")
[ -z "$choice" ] && {
echo "Skipping NVIDIA installation."
return 1
}
case "$choice" in
2)
_nvidia_remove
return 1
;;
*) return 0 ;;
esac
}
_nvidia_remove() {
if ! _nvidia_driver_installed; then
echo -e "${YELLOW}NVIDIA driver is not installed on this system.${NC}"
return 0
fi
if ! _confirm "Remove NVIDIA" "This will:\n - Purge the NVIDIA driver packages\n - Remove script-generated configs\n - Remove the CUDA repo sources\n - Regenerate initramfs\n\nProceed?"; then
echo "NVIDIA removal cancelled."
return 0
fi
echo "Removing NVIDIA driver packages..."
sudo apt purge -y nvidia-driver nvidia-kernel-dkms nvidia-open-kernel-dkms nvidia-open nvidia-kernel-open-dkms nvidia-tesla-470-driver nvidia-settings nvidia-vaapi-driver firmware-nvidia-gsp mesa-vdpau-drivers nvidia-driver-pinning-* || true
echo "Cleaning up dependencies..."
sudo apt autoremove --purge -y || true
echo "Removing script-generated configuration..."
sudo rm -f /etc/modprobe.d/nvidia-wayland.conf || true
sudo rm -f /etc/modprobe.d/nvidia-open.conf || true
sudo rm -f /etc/apt/preferences.d/block-nvidia || true
sudo rm -f /etc/X11/xorg.conf.d/20-nvidia.conf || true
echo "Removing NVIDIA repository sources..."
sudo rm -f /etc/apt/sources.list.d/cuda-*.list || true
sudo rm -f /etc/apt/sources.list.d/extrepo_nvidia-cuda.sources || true
echo "Regenerating initramfs..."
sudo update-initramfs -u || true
echo -e "${GREEN}NVIDIA driver removed. Please reboot your system.${NC}"
return 0
}
+1 -1
View File
@@ -4,7 +4,7 @@
show_kernel_menu() { show_kernel_menu() {
while true; do while true; do
local items=("stable" "Install linux-image-amd64") local items=("stable" "Install linux-image-amd64")
[ "$DEBIAN_VERSION" != "11" ] && items+=("backports" "Install from backports") [ "$DEBIAN_VERSION" = "13" ] && items+=("backports" "Install from backports")
items+=("rt" "Install linux-image-rt-amd64 (Preempt-RT)") items+=("rt" "Install linux-image-rt-amd64 (Preempt-RT)")
items+=("cloud" "Install linux-image-cloud-amd64") items+=("cloud" "Install linux-image-cloud-amd64")
items+=("back" "Return to main menu") items+=("back" "Return to main menu")
+176 -52
View File
@@ -8,7 +8,7 @@ REPO_BACKUP_DIR=""
backup_current_repos() { backup_current_repos() {
REPO_BACKUP_DIR=$(mktemp -d) REPO_BACKUP_DIR=$(mktemp -d)
for f in /etc/apt/sources.list /etc/apt/sources.list.d/debian.sources \ for f in /etc/apt/sources.list /etc/apt/sources.list.d/debian.sources \
/etc/apt/sources.list.d/debian-backports.list /etc/apt/sources.list.d/debian-backports.sources; do /etc/apt/sources.list.d/debian-backports.list /etc/apt/sources.list.d/debian-backports.sources; do
if [ -f "$f" ]; then if [ -f "$f" ]; then
mkdir -p "$REPO_BACKUP_DIR/$(dirname "${f#/etc/apt/}")" mkdir -p "$REPO_BACKUP_DIR/$(dirname "${f#/etc/apt/}")"
cp "$f" "$REPO_BACKUP_DIR/$(dirname "${f#/etc/apt/}")/$(basename "$f")" cp "$f" "$REPO_BACKUP_DIR/$(dirname "${f#/etc/apt/}")/$(basename "$f")"
@@ -23,14 +23,14 @@ restore_previous_repos() {
echo -e "${RED}Restoring previous repository configuration...${NC}" echo -e "${RED}Restoring previous repository configuration...${NC}"
local found=false local found=false
for f in /etc/apt/sources.list /etc/apt/sources.list.d/debian.sources \ for f in /etc/apt/sources.list /etc/apt/sources.list.d/debian.sources \
/etc/apt/sources.list.d/debian-backports.list /etc/apt/sources.list.d/debian-backports.sources; do /etc/apt/sources.list.d/debian-backports.list /etc/apt/sources.list.d/debian-backports.sources; do
local rel="${f#/etc/apt/}" local rel="${f#/etc/apt/}"
local backup_file="$REPO_BACKUP_DIR/$rel" local backup_file="$REPO_BACKUP_DIR/$rel"
if [ -f "$backup_file" ]; then if [ -f "$backup_file" ]; then
sudo cp "$backup_file" "$f" sudo cp "$backup_file" "$f" || true
found=true found=true
elif [ -f "$f" ]; then elif [ -f "$f" ]; then
sudo rm -f "$f" sudo rm -f "$f" || true
found=true found=true
fi fi
done done
@@ -55,8 +55,8 @@ cleanup_repo_backup() {
_clean_embedded_backports_classic() { _clean_embedded_backports_classic() {
local codename="$1" local codename="$1"
local file="/etc/apt/sources.list" local file="/etc/apt/sources.list"
[ ! -f "$file" ] && return [ ! -f "$file" ] && return 0
grep -qE "^[^#]*${codename}-backports\b" "$file" 2>/dev/null || return grep -qE "^[^#]*${codename}-backports\b" "$file" 2>/dev/null || return 0
if _confirm "Clean Classic Sources" "Remove backports line from ${file}?"; then if _confirm "Clean Classic Sources" "Remove backports line from ${file}?"; then
sudo sed -i "/${codename}-backports/d" "$file" sudo sed -i "/${codename}-backports/d" "$file"
echo "Removed backports from ${file}" echo "Removed backports from ${file}"
@@ -66,10 +66,10 @@ _clean_embedded_backports_classic() {
_clean_embedded_backports_deb822() { _clean_embedded_backports_deb822() {
local codename="$1" local codename="$1"
local file="/etc/apt/sources.list.d/debian.sources" local file="/etc/apt/sources.list.d/debian.sources"
[ ! -f "$file" ] && return [ ! -f "$file" ] && return 0
# Only proceed if the Suites line contains the backports token # Only proceed if the Suites line contains the backports token
grep -qE "^Suites:.*${codename}-backports\b" "$file" 2>/dev/null || return grep -qE "^Suites:.*${codename}-backports\b" "$file" 2>/dev/null || return 0
if _confirm "Clean deb822 Sources" "Remove backports suite from ${file}?"; then if _confirm "Clean deb822 Sources" "Remove backports suite from ${file}?"; then
# Remove only the backports token, leaving other suites intact # Remove only the backports token, leaving other suites intact
@@ -103,7 +103,7 @@ _write_deb822() {
if content_differs "$main_file" "$main_content"; then if content_differs "$main_file" "$main_content"; then
if _confirm "Deb822 Sources" "Write main deb822 configuration to ${main_file}?"; then if _confirm "Deb822 Sources" "Write main deb822 configuration to ${main_file}?"; then
sudo mkdir -p /etc/apt/sources.list.d sudo mkdir -p /etc/apt/sources.list.d
echo -e "$main_content" | sudo tee "$main_file" > /dev/null echo -e "$main_content" | sudo tee "$main_file" >/dev/null || return 1
echo "Wrote ${main_file}" echo "Wrote ${main_file}"
else else
echo "Main repository configuration skipped." echo "Main repository configuration skipped."
@@ -113,9 +113,9 @@ _write_deb822() {
# Backports: always in separate file # Backports: always in separate file
if [ "$bp_enabled" = true ]; then if [ "$bp_enabled" = true ]; then
_write_deb822_backports "$codename" _write_deb822_backports "$codename" || true
else else
_remove_deb822_backports "$codename" _remove_deb822_backports "$codename" || true
fi fi
# On migration from classic, disable the old file # On migration from classic, disable the old file
@@ -146,14 +146,16 @@ _write_deb822_backports() {
if content_differs "$bp_file" "$bp_content"; then if content_differs "$bp_file" "$bp_content"; then
if _confirm "Deb822 Backports" "Write backports to ${bp_file}?"; then if _confirm "Deb822 Backports" "Write backports to ${bp_file}?"; then
sudo mkdir -p /etc/apt/sources.list.d sudo mkdir -p /etc/apt/sources.list.d
echo -e "$bp_content" | sudo tee "$bp_file" > /dev/null echo -e "$bp_content" | sudo tee "$bp_file" >/dev/null
echo "Wrote ${bp_file}" echo "Wrote ${bp_file}"
else
return 1
fi fi
fi fi
# If backports were formerly embedded in debian.sources, clean them # If backports were formerly embedded in debian.sources, clean them
grep -qE "^Suites:.*${codename}-backports\b" /etc/apt/sources.list.d/debian.sources 2>/dev/null && \ grep -qE "^Suites:.*${codename}-backports\b" /etc/apt/sources.list.d/debian.sources 2>/dev/null &&
_clean_embedded_backports_deb822 "$codename" _clean_embedded_backports_deb822 "$codename" || true
} }
_remove_deb822_backports() { _remove_deb822_backports() {
@@ -164,11 +166,13 @@ _remove_deb822_backports() {
if _confirm "Remove Backports" "Remove ${bp_file}?"; then if _confirm "Remove Backports" "Remove ${bp_file}?"; then
sudo rm -f "$bp_file" sudo rm -f "$bp_file"
echo "Removed ${bp_file}" echo "Removed ${bp_file}"
else
return 1
fi fi
fi fi
# Also clean any embedded backports in main debian.sources # Also clean any embedded backports in main debian.sources
grep -qE "^Suites:.*${codename}-backports\b" /etc/apt/sources.list.d/debian.sources 2>/dev/null && \ grep -qE "^Suites:.*${codename}-backports\b" /etc/apt/sources.list.d/debian.sources 2>/dev/null &&
_clean_embedded_backports_deb822 "$codename" _clean_embedded_backports_deb822 "$codename"
# Clean embedded backports from classic file too (safety net) # Clean embedded backports from classic file too (safety net)
@@ -195,7 +199,7 @@ _write_classic() {
if content_differs "$main_file" "$main_content"; then if content_differs "$main_file" "$main_content"; then
if _confirm "Classic Sources" "Write main classic configuration to ${main_file}?"; then if _confirm "Classic Sources" "Write main classic configuration to ${main_file}?"; then
echo -e "$main_content" | sudo tee "$main_file" > /dev/null echo -e "$main_content" | sudo tee "$main_file" >/dev/null || return 1
echo "Wrote ${main_file}" echo "Wrote ${main_file}"
else else
echo "Main repository configuration skipped." echo "Main repository configuration skipped."
@@ -205,9 +209,9 @@ _write_classic() {
# Backports: always in separate file # Backports: always in separate file
if [ "$bp_enabled" = true ]; then if [ "$bp_enabled" = true ]; then
_write_classic_backports "$codename" _write_classic_backports "$codename" || true
else else
_remove_classic_backports "$codename" _remove_classic_backports "$codename" || true
fi fi
# On migration from deb822, disable the old file # On migration from deb822, disable the old file
@@ -236,14 +240,16 @@ _write_classic_backports() {
if content_differs "$bp_file" "$bp_content"; then if content_differs "$bp_file" "$bp_content"; then
if _confirm "Classic Backports" "Write backports to ${bp_file}?"; then if _confirm "Classic Backports" "Write backports to ${bp_file}?"; then
sudo mkdir -p /etc/apt/sources.list.d sudo mkdir -p /etc/apt/sources.list.d
echo -e "$bp_content" | sudo tee "$bp_file" > /dev/null echo -e "$bp_content" | sudo tee "$bp_file" >/dev/null
echo "Wrote ${bp_file}" echo "Wrote ${bp_file}"
else
return 1
fi fi
fi fi
# If backports were formerly embedded in sources.list, clean them # If backports were formerly embedded in sources.list, clean them
grep -qE "^[^#]*${codename}-backports\b" /etc/apt/sources.list 2>/dev/null && \ grep -qE "^[^#]*${codename}-backports\b" /etc/apt/sources.list 2>/dev/null &&
_clean_embedded_backports_classic "$codename" _clean_embedded_backports_classic "$codename" || true
} }
_remove_classic_backports() { _remove_classic_backports() {
@@ -254,11 +260,13 @@ _remove_classic_backports() {
if _confirm "Remove Backports" "Remove ${bp_file}?"; then if _confirm "Remove Backports" "Remove ${bp_file}?"; then
sudo rm -f "$bp_file" sudo rm -f "$bp_file"
echo "Removed ${bp_file}" echo "Removed ${bp_file}"
else
return 1
fi fi
fi fi
# Also clean any embedded backports in main sources.list # Also clean any embedded backports in main sources.list
grep -qE "^[^#]*${codename}-backports\b" /etc/apt/sources.list 2>/dev/null && \ grep -qE "^[^#]*${codename}-backports\b" /etc/apt/sources.list 2>/dev/null &&
_clean_embedded_backports_classic "$codename" _clean_embedded_backports_classic "$codename"
# Clean embedded backports from deb822 file too (safety net) # Clean embedded backports from deb822 file too (safety net)
@@ -301,17 +309,17 @@ configure_repos() {
clear clear
case "$repo_choice" in case "$repo_choice" in
1) _repos_enable_components ;; 1) _repos_enable_components ;;
2) _repos_migrate_format ;; 2) _repos_migrate_format ;;
3) 3)
if [ "$DEBIAN_CODENAME" = "sid" ]; then if [ "$DEBIAN_CODENAME" = "sid" ]; then
break break
else else
_repos_setup_backports _repos_setup_backports
fi fi
;; ;;
4) _branch_migration || true ;; 4) _branch_migration || true ;;
5) break ;; 5) break ;;
esac esac
done done
} }
@@ -353,18 +361,98 @@ _repos_offer_upgrade() {
fi fi
} }
# Bootstrap a complete repository configuration from scratch when no active
# sources exist. Caller must run backup_current_repos() first so that a failed
# apt update can restore the previous state.
# Returns: 0 on success, 1 if skipped, declined or failed
bootstrap_repositories() {
local components="$1"
local bp_enabled="${2:-false}"
local bp_location="${3:-none}"
if [ -z "$DEBIAN_CODENAME" ]; then
_msg "Error" "Cannot bootstrap repositories: Debian codename unknown." 10 65
return 1
fi
# non-free-firmware does not exist on Bullseye
if [ "$DEBIAN_VERSION" = "11" ]; then
components=$(echo "$components" | sed 's/ non-free-firmware//g')
fi
if ! _confirm "Bootstrap Repositories" \
"No active APT sources were found (empty or missing sources.list).\n\n\
Configure repositories from scratch?" 10 65; then
echo "Repository configuration skipped."
cleanup_repo_backup
return 1
fi
if has_active_deb_sources; then
if ! _confirm "Custom Sources Found" \
"Active sources exist in other files (e.g. sources.list.d/*.sources).\n\n\
Adding deb.debian.org may duplicate your current mirror configuration. Continue?" 10 65; then
cleanup_repo_backup
return 1
fi
fi
# DEB822 is Trixie-only; Debian 11/12 always use classic
local use_deb822=false
if [ "$DEBIAN_VERSION" = "13" ]; then
local choice
choice=$(_menu "Repo Format" "Choose the repository format:" 12 60 3 \
"deb822" "Native DEB822 format (sources.list.d/debian.sources)" \
"classic" "Classic format (/etc/apt/sources.list)")
if [ "$choice" = "deb822" ]; then
use_deb822=true
fi
fi
if $use_deb822; then
_write_deb822 "$DEBIAN_CODENAME" "write" "$bp_enabled" "$bp_location" "$components" || {
cleanup_repo_backup
return 1
}
else
_write_classic "$DEBIAN_CODENAME" "write" "$bp_enabled" "$bp_location" "$components" || {
cleanup_repo_backup
return 1
}
fi
# Tidy: with deb822 chosen, an empty classic file is no longer needed
if $use_deb822 && [ -f /etc/apt/sources.list ] && ! grep -qE '^[^#]*\bdeb\b' /etc/apt/sources.list 2>/dev/null; then
if _confirm "Disable Classic" "An empty /etc/apt/sources.list is no longer needed. Move it aside (sources.list.disabled)?"; then
sudo mv /etc/apt/sources.list /etc/apt/sources.list.disabled
echo "Empty sources.list renamed to sources.list.disabled"
fi
fi
echo "Updating package lists..."
if sudo apt update; then
cleanup_repo_backup
echo -e "${GREEN}Repository components configured.${NC}"
return 0
else
restore_previous_repos
echo -e "${RED}apt update failed. Previous configuration restored.${NC}"
return 1
fi
}
_repos_enable_components() { _repos_enable_components() {
local current_format bp_enabled bp_location components local current_format bp_enabled bp_location components
current_format=$(detect_repo_format) current_format=$(detect_repo_format)
if _components_enabled; then if _components_enabled; then
if ! _confirm "Disable Components" \ if _confirm "Disable Components" \
"Contrib and non-free are already enabled. Disable them?"; then "Contrib and non-free are already enabled. Disable them?"; then
echo "No changes made." components="main"
_pause else
return components=$(detect_active_components)
echo "Keeping current components: $components"
fi fi
components="main"
else else
if ! _confirm "Enable Components" \ if ! _confirm "Enable Components" \
"Enable contrib and non-free components?\n\n\ "Enable contrib and non-free components?\n\n\
@@ -390,15 +478,47 @@ popular software (like gaming platforms and proprietary tools)." 12 60; then
backup_current_repos backup_current_repos
if [ "$current_format" = "deb822" ] || [ "$current_format" = "none" ]; then if [ "$current_format" = "none" ]; then
_write_deb822 "$DEBIAN_CODENAME" "write" "$bp_enabled" "$bp_location" "$components" if ! bootstrap_repositories "$components" "$bp_enabled" "$bp_location"; then
_pause
return
fi
_repos_offer_upgrade
echo -e "${GREEN}Cleaning old packages...${NC}"
sudo apt autoremove -y
sudo apt autoclean
echo -e "${GREEN}System packages cleaned.${NC}"
_pause
return
fi
echo "Verifying repository configuration (main, updates, security)..."
if [ "$current_format" = "deb822" ]; then
# Mixed-state guard: active classic lines alongside deb822 would duplicate sources
if [ -f /etc/apt/sources.list ] && grep -qE '^[^#]*\bdeb\b' /etc/apt/sources.list 2>/dev/null; then
if ! _confirm "Duplicate Config" \
"Active classic sources were also found in /etc/apt/sources.list.\n\n\
Writing debian.sources may duplicate your configuration. Continue?" 10 65; then
echo "No changes made."
_pause
return
fi
fi
if ! _write_deb822 "$DEBIAN_CODENAME" "write" "$bp_enabled" "$bp_location" "$components"; then
echo "No changes made."
_pause
return
fi
else else
_write_classic "$DEBIAN_CODENAME" "write" "$bp_enabled" "$bp_location" "$components" if ! _write_classic "$DEBIAN_CODENAME" "write" "$bp_enabled" "$bp_location" "$components"; then
echo "No changes made."
_pause
return
fi
fi fi
echo "Updating package lists..." echo "Updating package lists..."
if sudo apt update; then if sudo apt update; then
REPOS_CONFIGURED=true
cleanup_repo_backup cleanup_repo_backup
echo -e "${GREEN}Repository components configured.${NC}" echo -e "${GREEN}Repository components configured.${NC}"
_repos_offer_upgrade _repos_offer_upgrade
@@ -442,7 +562,6 @@ _repos_migrate_format() {
echo "Updating package lists..." echo "Updating package lists..."
if sudo apt update; then if sudo apt update; then
REPOS_CONFIGURED=true
cleanup_repo_backup cleanup_repo_backup
echo -e "${GREEN}Repository format migrated to DEB822.${NC}" echo -e "${GREEN}Repository format migrated to DEB822.${NC}"
else else
@@ -473,8 +592,8 @@ Answer NO to disable or remove backports if they are currently enabled." 16 70;
fi fi
# Nothing to do — already in desired state # Nothing to do — already in desired state
if { $enable_backports && [ "$bp_status" = "enabled" ]; } || \ if { $enable_backports && [ "$bp_status" = "enabled" ]; } ||
{ ! $enable_backports && [ "$bp_status" = "disabled" ]; }; then { ! $enable_backports && [ "$bp_status" = "disabled" ]; }; then
echo "Backports are already configured as requested." echo "Backports are already configured as requested."
_pause _pause
return return
@@ -482,18 +601,23 @@ Answer NO to disable or remove backports if they are currently enabled." 16 70;
backup_current_repos backup_current_repos
local write_ok=true
if $enable_backports; then if $enable_backports; then
if [ "$current_format" = "deb822" ]; then if [ "$current_format" = "deb822" ]; then
_write_deb822_backports "$DEBIAN_CODENAME" _write_deb822_backports "$DEBIAN_CODENAME" || write_ok=false
else else
_write_classic_backports "$DEBIAN_CODENAME" _write_classic_backports "$DEBIAN_CODENAME" || write_ok=false
fi fi
elif [ "$current_format" = "deb822" ]; then
_remove_deb822_backports "$DEBIAN_CODENAME" || write_ok=false
else else
if [ "$current_format" = "deb822" ]; then _remove_classic_backports "$DEBIAN_CODENAME" || write_ok=false
_remove_deb822_backports "$DEBIAN_CODENAME" fi
else
_remove_classic_backports "$DEBIAN_CODENAME" if ! $write_ok; then
fi echo "No changes made."
_pause
return
fi fi
echo "Updating package lists..." echo "Updating package lists..."
+50 -19
View File
@@ -27,27 +27,35 @@ _restore_backup() {
echo -e "${GREEN}Backup restored from $_MIGRATE_BACKUP${NC}" echo -e "${GREEN}Backup restored from $_MIGRATE_BACKUP${NC}"
} }
# Write the target branch repository configuration.
# DEB822 is only supported on Debian 13 (apt >= 2.3.14); Debian 11/12
# use the classic one-line format. SID has no security archive.
_write_branch_sources() {
local target="$1"
if [ "$DEBIAN_VERSION" = "13" ]; then
_write_deb822_branch "$target"
else
_write_classic_branch "$target"
fi
}
_write_deb822_branch() { _write_deb822_branch() {
local target="$1" local target="$1"
local main_file="/etc/apt/sources.list.d/debian.sources" local main_file="/etc/apt/sources.list.d/debian.sources"
local main_content="" local main_content=""
main_content+="Types: deb\n"
main_content+="URIs: https://deb.debian.org/debian\n"
if [ "$target" = "sid" ]; then if [ "$target" = "sid" ]; then
main_content+="Types: deb\n"
main_content+="URIs: https://deb.debian.org/debian\n"
main_content+="Suites: sid\n" main_content+="Suites: sid\n"
main_content+="Components: main contrib non-free non-free-firmware\n"
main_content+="\n"
main_content+="Types: deb\n"
main_content+="URIs: https://security.debian.org/debian-security\n"
main_content+="Suites: sid\n"
main_content+="Components: main contrib non-free non-free-firmware\n"
else else
# testing
main_content+="Types: deb\n"
main_content+="URIs: https://deb.debian.org/debian\n"
main_content+="Suites: testing testing-updates\n" main_content+="Suites: testing testing-updates\n"
main_content+="Components: main contrib non-free non-free-firmware\n" fi
main_content+="Components: main contrib non-free non-free-firmware\n"
# SID receives all updates via unstable itself; there is no sid-security suite
if [ "$target" != "sid" ]; then
main_content+="\n" main_content+="\n"
main_content+="Types: deb\n" main_content+="Types: deb\n"
main_content+="URIs: https://security.debian.org/debian-security\n" main_content+="URIs: https://security.debian.org/debian-security\n"
@@ -56,14 +64,30 @@ _write_deb822_branch() {
fi fi
sudo mkdir -p /etc/apt/sources.list.d sudo mkdir -p /etc/apt/sources.list.d
echo -e "$main_content" | sudo tee "$main_file" > /dev/null echo -e "$main_content" | sudo tee "$main_file" >/dev/null
echo "Wrote $main_file"
}
_write_classic_branch() {
local target="$1"
local main_file="/etc/apt/sources.list"
local main_content=""
main_content+="deb https://deb.debian.org/debian ${target} main contrib non-free non-free-firmware\n"
# SID receives all updates via unstable itself; there is no sid-security suite
if [ "$target" != "sid" ]; then
main_content+="deb https://security.debian.org/debian-security ${target}-security main contrib non-free non-free-firmware\n"
fi
echo -e "$main_content" | sudo tee "$main_file" >/dev/null
echo "Wrote $main_file" echo "Wrote $main_file"
} }
_branch_migration() { _branch_migration() {
# ── Screen 1: Risk warning ── # ── Screen 1: Risk warning ──
_msg_red "WARNING: Branch Migration" \ _msg_red "WARNING: Branch Migration" \
"Migrating from Debian Stable to Testing or SID is a\n\ "Migrating from Debian Stable to Testing or SID is a\n\
MAJOR change and CAN make your system UNBOOTABLE.\n\n\ MAJOR change and CAN make your system UNBOOTABLE.\n\n\
Risks include:\n\ Risks include:\n\
• NVIDIA / DKMS drivers may break\n\ • NVIDIA / DKMS drivers may break\n\
@@ -82,7 +106,7 @@ so you can restore if things go wrong." 16 70
local plan="This operation will:\n\n" local plan="This operation will:\n\n"
plan+=" 1. Backup current APT sources to /var/backups/\n" plan+=" 1. Backup current APT sources to /var/backups/\n"
plan+=" 2. Remove any backports configuration\n" plan+=" 2. Remove any backports configuration\n"
plan+=" 3. Write new DEB822 sources for the target branch\n" plan+=" 3. Write new sources for the target branch\n"
plan+=" 4. Run: apt update\n" plan+=" 4. Run: apt update\n"
plan+=" 5. Run: apt upgrade -y\n" plan+=" 5. Run: apt upgrade -y\n"
plan+=" 6. Run: apt full-upgrade -y\n" plan+=" 6. Run: apt full-upgrade -y\n"
@@ -101,7 +125,10 @@ so you can restore if things go wrong." 16 70
branch=$(_inputbox "Target Branch" \ branch=$(_inputbox "Target Branch" \
"Type exactly TESTING or SID (case-sensitive):" 10 60 "") "Type exactly TESTING or SID (case-sensitive):" 10 60 "")
[ -z "$branch" ] && { echo "Migration cancelled."; return; } [ -z "$branch" ] && {
echo "Migration cancelled."
return
}
if [ "$branch" != "TESTING" ] && [ "$branch" != "SID" ]; then if [ "$branch" != "TESTING" ] && [ "$branch" != "SID" ]; then
_msg "Invalid Branch" "You typed: $branch\n\nExpected: TESTING or SID (exact, case-sensitive).\nAborting." 10 60 _msg "Invalid Branch" "You typed: $branch\n\nExpected: TESTING or SID (exact, case-sensitive).\nAborting." 10 60
@@ -131,7 +158,11 @@ so you can restore if things go wrong." 16 70
[ -f /etc/apt/sources.list ] && sudo rm -f /etc/apt/sources.list [ -f /etc/apt/sources.list ] && sudo rm -f /etc/apt/sources.list
# 4d. Write new sources # 4d. Write new sources
_write_deb822_branch "$target" if ! _write_branch_sources "$target"; then
echo -e "${RED}[-]${NC} Failed to write new sources. Restoring backup..."
_restore_backup || true
return 1
fi
# 4e. SID guardrails: install bug alerts before upgrade # 4e. SID guardrails: install bug alerts before upgrade
if [ "$target" = "sid" ]; then if [ "$target" = "sid" ]; then
@@ -146,7 +177,7 @@ so you can restore if things go wrong." 16 70
echo -e "${RED}apt update failed. Restoring backup...${NC}" echo -e "${RED}apt update failed. Restoring backup...${NC}"
_restore_backup _restore_backup
_msg_red "Migration Failed" \ _msg_red "Migration Failed" \
"apt update failed. Backup has been restored from:\n\ "apt update failed. Backup has been restored from:\n\
$_MIGRATE_BACKUP\n\n\ $_MIGRATE_BACKUP\n\n\
Your system should be back to its previous state.\n\ Your system should be back to its previous state.\n\
Run 'sudo apt update' manually to verify." 12 70 Run 'sudo apt update' manually to verify." 12 70
@@ -169,7 +200,7 @@ Run 'sudo apt update' manually to verify." 12 70
# ── Screen 5: Reboot reminder ── # ── Screen 5: Reboot reminder ──
_msg "Migration Complete" \ _msg "Migration Complete" \
"System has been migrated to ${target}.\n\n\ "System has been migrated to ${target}.\n\n\
Backup saved at:\n $_MIGRATE_BACKUP\n\n\ Backup saved at:\n $_MIGRATE_BACKUP\n\n\
REBOOT your system.\nIf it fails to boot, restore the backup manually:\n\ REBOOT your system.\nIf it fails to boot, restore the backup manually:\n\
sudo tar xzf $_MIGRATE_BACKUP -C /\n sudo apt update\n sudo apt upgrade" 16 70 sudo tar xzf $_MIGRATE_BACKUP -C /\n sudo apt update\n sudo apt upgrade" 16 70
+62 -12
View File
@@ -2,34 +2,76 @@
# repo_detect.sh Detection-only helpers for idempotent repository configuration. # repo_detect.sh Detection-only helpers for idempotent repository configuration.
# Part A of the two-part architecture. No user dialogs, no writes. # Part A of the two-part architecture. No user dialogs, no writes.
# Detect the format of the main repo file # Any active (non-commented) source of any format, in any file?
# Returns: 0 if at least one active source exists, 1 otherwise
has_active_deb_sources() {
local f
for f in /etc/apt/sources.list /etc/apt/sources.list.d/*.list; do
[ -f "$f" ] || continue
grep -qE '^[^#]*\bdeb\b' "$f" 2>/dev/null && return 0
done
for f in /etc/apt/sources.list.d/*.sources; do
[ -f "$f" ] || continue
grep -qE '^Types:.*\bdeb\b' "$f" 2>/dev/null && \
grep -qE '^URIs:' "$f" 2>/dev/null && return 0
done
return 1
}
# Detect the format of the main repo file (content-aware).
# DEB822 is only valid on Debian 13 (Trixie); Debian 11/12 are classic-only.
# Returns: "deb822", "classic", or "none" # Returns: "deb822", "classic", or "none"
detect_repo_format() { detect_repo_format() {
if [ -f /etc/apt/sources.list.d/debian.sources ]; then if [ "$DEBIAN_VERSION" = "13" ] && [ -f /etc/apt/sources.list.d/debian.sources ] && \
grep -qE '^Types:.*\bdeb\b' /etc/apt/sources.list.d/debian.sources 2>/dev/null; then
echo "deb822" echo "deb822"
elif [ -f /etc/apt/sources.list ]; then elif [ -f /etc/apt/sources.list ] && grep -qE '^[^#]*\bdeb\b' /etc/apt/sources.list 2>/dev/null; then
echo "classic" echo "classic"
else else
echo "none" echo "none"
fi fi
} }
# Check whether backports are currently enabled (any format) # Detect the components currently active in the main repo file
# Returns: components list (e.g. "main contrib non-free non-free-firmware")
detect_active_components() {
if [ "$DEBIAN_VERSION" = "13" ] && [ -f /etc/apt/sources.list.d/debian.sources ]; then
local comps
comps=$(grep "^Components:" /etc/apt/sources.list.d/debian.sources 2>/dev/null | head -1 | cut -d: -f2- | sed 's/^[[:space:]]*//')
if [ -n "$comps" ]; then
echo "$comps"
return
fi
fi
if [ -f /etc/apt/sources.list ]; then
local comps
comps=$(grep "^[^#]*deb .* main" /etc/apt/sources.list 2>/dev/null | head -1 | sed 's/.*main\s*//')
if [ -n "$comps" ]; then
echo "main $comps"
return
fi
fi
if [ "$DEBIAN_VERSION" = "11" ]; then
echo "main contrib non-free"
else
echo "main contrib non-free non-free-firmware"
fi
}
# Check whether backports are currently enabled (any format, any file)
# Returns: 0 if enabled, 1 otherwise # Returns: 0 if enabled, 1 otherwise
detect_backports_status() { detect_backports_status() {
local codename="$1" local codename="$1"
if [ -f /etc/apt/sources.list.d/debian.sources ]; then if [ "$DEBIAN_VERSION" = "13" ] && [ -f /etc/apt/sources.list.d/debian.sources ]; then
grep -qE "^Suites:.*${codename}-backports" /etc/apt/sources.list.d/debian.sources 2>/dev/null && return 0 grep -qE "^Suites:.*${codename}-backports" /etc/apt/sources.list.d/debian.sources 2>/dev/null && return 0
fi fi
if [ -f /etc/apt/sources.list ]; then if [ -f /etc/apt/sources.list ]; then
grep -qE "^[^#]*${codename}-backports" /etc/apt/sources.list 2>/dev/null && return 0 grep -qE "^[^#]*${codename}-backports" /etc/apt/sources.list 2>/dev/null && return 0
fi fi
if [ -f /etc/apt/sources.list.d/debian-backports.sources ]; then if [ -d /etc/apt/sources.list.d ]; then
grep -qE "^Suites:.*${codename}-backports" /etc/apt/sources.list.d/debian-backports.sources 2>/dev/null && return 0 grep -qrE "^Suites:.*${codename}-backports" /etc/apt/sources.list.d/*.sources 2>/dev/null && return 0
fi grep -qrE "^[^#]*${codename}-backports" /etc/apt/sources.list.d/*.list 2>/dev/null && return 0
if [ -f /etc/apt/sources.list.d/debian-backports.list ]; then
grep -qE "^[^#]*${codename}-backports" /etc/apt/sources.list.d/debian-backports.list 2>/dev/null && return 0
fi fi
return 1 return 1
@@ -44,18 +86,26 @@ detect_backports_status() {
detect_backports_location() { detect_backports_location() {
local codename="$1" local codename="$1"
if [ -f /etc/apt/sources.list.d/debian-backports.sources ] && \ if [ "$DEBIAN_VERSION" = "13" ] && [ -f /etc/apt/sources.list.d/debian-backports.sources ] && \
grep -qE "^Suites:.*${codename}-backports" /etc/apt/sources.list.d/debian-backports.sources 2>/dev/null; then grep -qE "^Suites:.*${codename}-backports" /etc/apt/sources.list.d/debian-backports.sources 2>/dev/null; then
echo "standalone-deb822" echo "standalone-deb822"
elif [ -f /etc/apt/sources.list.d/debian-backports.list ] && \ elif [ -f /etc/apt/sources.list.d/debian-backports.list ] && \
grep -qE "^[^#]*${codename}-backports" /etc/apt/sources.list.d/debian-backports.list 2>/dev/null; then grep -qE "^[^#]*${codename}-backports" /etc/apt/sources.list.d/debian-backports.list 2>/dev/null; then
echo "standalone-classic" echo "standalone-classic"
elif [ -f /etc/apt/sources.list.d/debian.sources ] && \ elif [ "$DEBIAN_VERSION" = "13" ] && [ -f /etc/apt/sources.list.d/debian.sources ] && \
grep -qE "^Suites:.*${codename}-backports" /etc/apt/sources.list.d/debian.sources 2>/dev/null; then grep -qE "^Suites:.*${codename}-backports" /etc/apt/sources.list.d/debian.sources 2>/dev/null; then
echo "embedded-deb822" echo "embedded-deb822"
elif [ -f /etc/apt/sources.list ] && \ elif [ -f /etc/apt/sources.list ] && \
grep -qE "^[^#]*${codename}-backports" /etc/apt/sources.list 2>/dev/null; then grep -qE "^[^#]*${codename}-backports" /etc/apt/sources.list 2>/dev/null; then
echo "embedded-classic" echo "embedded-classic"
elif [ -d /etc/apt/sources.list.d ]; then
if grep -qrE "^Suites:.*${codename}-backports" /etc/apt/sources.list.d/*.sources 2>/dev/null; then
echo "embedded-deb822"
elif grep -qrE "^[^#]*${codename}-backports" /etc/apt/sources.list.d/*.list 2>/dev/null; then
echo "embedded-classic"
else
echo "none"
fi
else else
echo "none" echo "none"
fi fi
+25 -20
View File
@@ -19,11 +19,11 @@ config_sudo() {
clear clear
case "$choice" in case "$choice" in
1) _check_sudo_group ;; 1) _check_sudo_group ;;
2) _configure_nopasswd ;; 2) _configure_nopasswd ;;
3) _repair_home_ownership ;; 3) _repair_home_ownership ;;
4) _toggle_pwfeedback ;; 4) _toggle_pwfeedback ;;
5) return ;; 5) return ;;
esac esac
done done
} }
@@ -68,30 +68,35 @@ Useful for automation but reduces security." 14 70; then
local choices local choices
choices=$(_checklist "NOPASSWD Commands" \ choices=$(_checklist "NOPASSWD Commands" \
"Select commands to allow without password:" 12 60 3 \ "Select commands to allow without password:" 12 60 3 \
"apt" "APT package management" ON \ "apt" "APT package management" ON \
"systemctl" "Systemd service management" ON \ "systemctl" "Systemd service management" ON \
"power" "Shutdown, reboot, halt" ON) "power" "Shutdown, reboot, halt" ON)
clear clear
[ -z "$choices" ] && { echo "No commands selected."; return; } [ -z "$choices" ] && {
local cleaned; cleaned=$(echo "$choices" | tr -d '"') echo "No commands selected."
return
}
local cleaned
cleaned=$(echo "$choices" | tr -d '"')
local content="" local content=""
for cmd in $cleaned; do for cmd in $cleaned; do
case $cmd in case $cmd in
apt) apt)
content+="${USER} ALL=(root) NOPASSWD: /usr/bin/apt, /usr/bin/apt-get, /bin/apt, /bin/apt-get\n" content+="${USER} ALL=(root) NOPASSWD: /usr/bin/apt, /usr/bin/apt-get, /bin/apt, /bin/apt-get\n"
;; ;;
systemctl) systemctl)
content+="${USER} ALL=(root) NOPASSWD: /usr/bin/systemctl, /bin/systemctl\n" content+="${USER} ALL=(root) NOPASSWD: /usr/bin/systemctl, /bin/systemctl\n"
;; ;;
power) power)
content+="${USER} ALL=(root) NOPASSWD: /usr/sbin/shutdown, /sbin/shutdown, /usr/sbin/reboot, /sbin/reboot, /usr/sbin/halt, /sbin/halt\n" content+="${USER} ALL=(root) NOPASSWD: /usr/sbin/shutdown, /sbin/shutdown, /usr/sbin/reboot, /sbin/reboot, /usr/sbin/halt, /sbin/halt\n"
;; ;;
esac esac
done done
local content_str; content_str=$(echo -e "$content") local content_str
content_str=$(echo -e "$content")
if _validate_sudoers "$content_str" "$nopasswd_file"; then if _validate_sudoers "$content_str" "$nopasswd_file"; then
echo -e "${GREEN}Passwordless sudo configured for selected commands.${NC}" echo -e "${GREEN}Passwordless sudo configured for selected commands.${NC}"
else else
@@ -103,7 +108,7 @@ Useful for automation but reduces security." 14 70; then
# ── Option 3: Repair Home Directory Ownership ── # ── Option 3: Repair Home Directory Ownership ──
_repair_home_ownership() { _repair_home_ownership() {
local home local home
home=$(eval echo "~$USER") home=$(getent passwd "${SUDO_USER:-$USER}" | cut -d: -f6)
if [ ! -d "$home" ]; then if [ ! -d "$home" ]; then
_msg "Home Directory" "Home directory '$home' does not exist." 8 60 _msg "Home Directory" "Home directory '$home' does not exist." 8 60
+49 -42
View File
@@ -27,17 +27,17 @@ _show_sysinfo() {
if echo "$gpu_line" | grep -qi "nvidia"; then if echo "$gpu_line" | grep -qi "nvidia"; then
local nv_ver="" local nv_ver=""
nv_ver=$(nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -1) nv_ver=$(timeout 3 nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -1) || true
[ -z "$nv_ver" ] && nv_ver=$(dpkg -l nvidia-driver 2>/dev/null | awk '/^ii/ {print $3}' | sed 's/-.*//') [ -z "$nv_ver" ] && nv_ver=$(dpkg -l nvidia-driver 2>/dev/null | awk '/^ii/ {print $3}' | sed 's/-.*//') || true
msg+="GPU ${gpu_count}: ${desc}\n" msg+="GPU ${gpu_count}: ${desc}\n"
msg+=" Driver: ${nv_ver:+NVIDIA }${nv_ver:-not installed}\n" msg+=" Driver: ${nv_ver:+NVIDIA }${nv_ver:-not installed}\n"
else else
local mesa_ver="" local mesa_ver=""
mesa_ver=$(dpkg -l libgl1-mesa-dri 2>/dev/null | awk '/^ii/ {print $3; exit}' | sed 's/-.*//') mesa_ver=$(dpkg -l libgl1-mesa-dri 2>/dev/null | awk '/^ii/ {print $3; exit}' | sed 's/-.*//') || true
msg+="GPU ${gpu_count}: ${desc}\n" msg+="GPU ${gpu_count}: ${desc}\n"
msg+=" Driver: ${mesa_ver:+Mesa }${mesa_ver:-unknown}\n" msg+=" Driver: ${mesa_ver:+Mesa }${mesa_ver:-unknown}\n"
fi fi
done < <(lspci -nn | grep -E "VGA|3D" || true) done < <(echo "$LSPCI_OUTPUT" | grep -E "VGA|3D" || true)
fi fi
if ! $found_gpu; then if ! $found_gpu; then
@@ -52,13 +52,13 @@ _show_sysinfo() {
declare -a pci_eth_lines=() declare -a pci_eth_lines=()
while IFS= read -r line; do while IFS= read -r line; do
pci_eth_lines+=("$line") pci_eth_lines+=("$line")
done < <(lspci -d ::0200 2>/dev/null || true) done < <(echo "$LSPCI_OUTPUT" | grep -i 'ethernet controller' || true)
# ── 2. Detect ALL WiFi chipsets (class 0x0280 + vendor fallbacks) ── # ── 2. Detect ALL WiFi chipsets (class 0x0280 + vendor fallbacks) ──
declare -a pci_wifi_lines=() declare -a pci_wifi_lines=()
while IFS= read -r line; do while IFS= read -r line; do
pci_wifi_lines+=("$line") pci_wifi_lines+=("$line")
done < <(lspci -d ::0280 2>/dev/null || true) done < <(echo "$LSPCI_OUTPUT" | grep -i 'network controller' || true)
# Broadcom vendor-ID fallback (14e4) — include only if not already captured # Broadcom vendor-ID fallback (14e4) — include only if not already captured
while IFS= read -r line; do while IFS= read -r line; do
@@ -69,7 +69,7 @@ _show_sysinfo() {
done done
! $already && pci_wifi_lines+=("$line") ! $already && pci_wifi_lines+=("$line")
fi fi
done < <(lspci -nn 2>/dev/null || true) done < <(echo "$LSPCI_OUTPUT" || true)
# USB WiFi fallback # USB WiFi fallback
local usb_wifi_lines=() local usb_wifi_lines=()
@@ -99,6 +99,8 @@ _show_sysinfo() {
local -a shown_eth_descs=() local -a shown_eth_descs=()
local -a shown_wifi_descs=() local -a shown_wifi_descs=()
local has_eth=false has_wifi=false has_other=false local has_eth=false has_wifi=false has_other=false
local eth_idx=0
local wifi_idx=0
if ! command -v ip &>/dev/null; then if ! command -v ip &>/dev/null; then
msg+="(install iproute2 for interface details)\n" msg+="(install iproute2 for interface details)\n"
@@ -109,49 +111,53 @@ _show_sysinfo() {
state=$(echo "$line" | awk '{print $9}') state=$(echo "$line" | awk '{print $9}')
case "$iface" in case "$iface" in
lo|docker*|veth*|br-*|virbr*|tun*|tap*|bond*) continue ;; lo | docker* | veth* | br-* | virbr* | tun* | tap* | bond*) continue ;;
esac esac
ip4=$(ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}') ip4=$(timeout 2 ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}')
# Determine type by PCI class (most reliable) # Determine type by PCI class (most reliable)
local pci_class="" local pci_class=""
pci_class=$(cat "/sys/class/net/${iface}/device/class" 2>/dev/null || true) pci_class=$(cat "/sys/class/net/${iface}/device/class" 2>/dev/null || true)
case "$pci_class" in case "$pci_class" in
0x0200*) 0x0200*)
has_eth=true has_eth=true
desc="${eth_descs[0]:-Unknown Ethernet chipset}" desc="${eth_descs[$eth_idx]:-Unknown Ethernet chipset}"
shown_eth_descs+=("${eth_descs[0]}") shown_eth_descs+=("${eth_descs[$eth_idx]:-$desc}")
;; eth_idx=$((eth_idx + 1))
0x0280*) ;;
0x0280*)
has_wifi=true
desc="${wifi_descs[$wifi_idx]:-Unknown WiFi chipset}"
shown_wifi_descs+=("${wifi_descs[$wifi_idx]:-$desc}")
wifi_idx=$((wifi_idx + 1))
ssid=""
[ "$state" = "UP" ] && ssid=$(timeout 2 iwgetid -r "$iface" 2>/dev/null || true)
;;
*)
# Fallback: classify by interface name pattern
case "$iface" in
wl* | wlp* | wlo* | wlan*)
has_wifi=true has_wifi=true
desc="${wifi_descs[0]:-Unknown WiFi chipset}" desc="${wifi_descs[$wifi_idx]:-Unknown WiFi chipset}"
shown_wifi_descs+=("${wifi_descs[0]}") shown_wifi_descs+=("${wifi_descs[$wifi_idx]:-$desc}")
wifi_idx=$((wifi_idx + 1))
ssid="" ssid=""
[ "$state" = "UP" ] && ssid=$(iwgetid -r "$iface" 2>/dev/null || true) [ "$state" = "UP" ] && ssid=$(timeout 2 iwgetid -r "$iface" 2>/dev/null || true)
;;
eth* | enp* | ens* | enx* | eno*)
has_eth=true
desc="${eth_descs[$eth_idx]:-Unknown Ethernet chipset}"
shown_eth_descs+=("${eth_descs[$eth_idx]:-$desc}")
eth_idx=$((eth_idx + 1))
;; ;;
*) *)
# Fallback: classify by interface name pattern has_other=true
case "$iface" in desc="(network interface)"
wl*|wlp*|wlo*|wlan*)
has_wifi=true
desc="${wifi_descs[0]:-Unknown WiFi chipset}"
shown_wifi_descs+=("${wifi_descs[0]}")
ssid=""
[ "$state" = "UP" ] && ssid=$(iwgetid -r "$iface" 2>/dev/null || true)
;;
eth*|enp*|ens*|enx*|eno*)
has_eth=true
desc="${eth_descs[0]:-Unknown Ethernet chipset}"
shown_eth_descs+=("${eth_descs[0]}")
;;
*)
has_other=true
desc="(network interface)"
;;
esac
;; ;;
esac
;;
esac esac
if [ "$state" = "UP" ]; then if [ "$state" = "UP" ]; then
@@ -163,7 +169,7 @@ _show_sysinfo() {
else else
msg+="${iface}: ${desc}\n ↓\n" msg+="${iface}: ${desc}\n ↓\n"
fi fi
done < <(ip -o link show 2>/dev/null) done < <(timeout 2 ip -o link show 2>/dev/null)
fi fi
# ── 5. Show chipsets without an active interface ── # ── 5. Show chipsets without an active interface ──
@@ -208,7 +214,7 @@ _show_sysinfo() {
term_cols=$(tput cols 2>/dev/null || echo 80) term_cols=$(tput cols 2>/dev/null || echo 80)
[ "$term_cols" -lt 50 ] && term_cols=50 [ "$term_cols" -lt 50 ] && term_cols=50
local max_pct=$(( term_cols * 95 / 100 )) local max_pct=$((term_cols * 95 / 100))
[ "$max_pct" -lt 50 ] && max_pct=50 [ "$max_pct" -lt 50 ] && max_pct=50
local longest=0 local longest=0
@@ -217,7 +223,7 @@ _show_sysinfo() {
[ "$len" -gt "$longest" ] && longest=$len [ "$len" -gt "$longest" ] && longest=$len
done < <(echo -e "$msg") done < <(echo -e "$msg")
local width=$(( longest + 6 )) local width=$((longest + 6))
[ "$width" -lt 80 ] && width=80 [ "$width" -lt 80 ] && width=80
[ "$width" -gt "$max_pct" ] && width=$max_pct [ "$width" -gt "$max_pct" ] && width=$max_pct
@@ -232,8 +238,9 @@ _show_sysinfo() {
local lines local lines
lines=$(echo -e "$truncated" | wc -l) lines=$(echo -e "$truncated" | wc -l)
local height=$(( lines + 6 )) local height=$((lines + 6))
[ "$height" -gt 22 ] && height=22 local max_height=$((${LINES:-24} - 4 > 10 ? ${LINES:-24} - 4 : 10))
[ "$height" -gt "$max_height" ] && height=$max_height
[ "$height" -lt 10 ] && height=10 [ "$height" -lt 10 ] && height=10
_msg "System Information" "$truncated" "$height" "$width" _msg "System Information" "$truncated" "$height" "$width"
+189
View File
@@ -0,0 +1,189 @@
#!/usr/bin/env bash
# audio.sh — Audio & Sound (PipeWire, ALSA, PulseAudio tools)
_prefs_audio_menu() {
local headless=false
_is_headless && headless=true
local -a items=()
local pw_label="PipeWire Audio Stack (Bluetooth Hi-Res)"
# Bullseye ships the "pipewire" package; the pipewire-audio meta-package
# only exists from Bookworm onwards
local pw_pkg="pipewire-audio"
[ "$DEBIAN_VERSION" = "11" ] && pw_pkg="pipewire"
local pw_state; pw_state=$(_state "$pw_pkg")
items+=(
"pipewire-audio" "$pw_label" "$pw_state"
)
local alsa_state; alsa_state=$(_state "alsa-utils")
items+=(
"alsa-utils" "ALSA Utilities (alsa-utils, alsa-ucm-conf)" "$alsa_state"
)
if ! $headless; then
local pavu_state; pavu_state=$(_state "pavucontrol")
items+=(
"pavucontrol" "Volume Control GUI (pavucontrol)" "$pavu_state"
)
fi
local pulsemixer_state; pulsemixer_state=$(_state "pulsemixer")
local playerctl_state; playerctl_state=$(_state "playerctl")
items+=(
"pulsemixer" "Terminal audio mixer (pulsemixer)" "$pulsemixer_state"
"playerctl" "Multimedia key controller (playerctl)" "$playerctl_state"
)
local item_count=${#items[@]}
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
local choices
choices=$(_checklist "Audio & Sound" "Check [*] the packages you want installed.\n" \
$TUI_ALTO $TUI_ANCHO $lista_alto "${items[@]}")
clear
[ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
for pkg in $cleaned; do
case $pkg in
pipewire-audio) _install_pipewire_standard ;;
alsa-utils)
if ! is_installed "alsa-utils"; then
_run_install "alsa-utils alsa-ucm-conf"
else
echo "alsa-utils already installed."
fi
;;
pavucontrol)
if ! is_installed "pavucontrol"; then
_run_install "pavucontrol"
else
echo "pavucontrol already installed."
fi
;;
pulsemixer)
if ! is_installed "pulsemixer"; then
_run_install "pulsemixer"
else
echo "pulsemixer already installed."
fi
;;
playerctl)
if ! is_installed "playerctl"; then
_run_install "playerctl"
else
echo "playerctl already installed."
fi
;;
esac
done
echo -e "${GREEN}Audio & Sound setup complete.${NC}"
}
_install_pipewire_standard() {
local bt_pkgs="libldacbt-abr2 libldacbt-enc2 libopenaptx0 libspa-0.2-bluetooth"
if apt-cache show libfdk-aac2t64 &>/dev/null; then
bt_pkgs+=" libfdk-aac2t64"
elif apt-cache show libfdk-aac2 &>/dev/null; then
bt_pkgs+=" libfdk-aac2"
fi
# ── Resolve versions (needed for both installed and not-installed branches) ──
local stable_ver=""
stable_ver=$(apt-cache policy pipewire-audio 2>/dev/null | awk 'NR==3 {print $2; exit}') || true
local bpo_ver=""
if [ "$DEBIAN_VERSION" = "13" ] && [ "$(is_backports_enabled)" = "true" ]; then
bpo_ver=$(apt-cache madison pipewire-audio 2>/dev/null | \
grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1) || true
fi
local pkg_check="pipewire-audio"
[ "$DEBIAN_VERSION" = "11" ] && pkg_check="pipewire"
# ── Already installed branch ──
if is_installed "$pkg_check"; then
if [ -n "$bpo_ver" ]; then
local current_ver
current_ver=$(dpkg -l "$pkg_check" 2>/dev/null | awk '/^ii/{print $3}') || true
if _confirm "PipeWire" \
"PipeWire ${current_ver:+v${current_ver} }already installed.\n\nUpgrade to backports version v${bpo_ver}?"; then
echo "Upgrading PipeWire Audio Stack..."
echo "-> Target version: v${bpo_ver} (from ${DEBIAN_CODENAME}-backports)"
echo "-> Including Bluetooth Hi-Res codecs (LDAC, aptX, AAC)"
_run_cmd "PipeWire" \
"sudo apt install -y --reinstall -t ${DEBIAN_CODENAME}-backports pipewire-audio $bt_pkgs" \
"Upgrading PipeWire from backports..."
if [ "$DEBIAN_VERSION" != "11" ]; then
echo "Restarting PipeWire services..."
systemctl --user restart wireplumber pipewire pipewire-pulse 2>/dev/null || true
echo -e "${GREEN}PipeWire services restarted.${NC}"
fi
return
fi
fi
echo "$pkg_check already installed."
return
fi
# ── Confirm dialog ──
local apt_target="" pw_ver="" pw_src=""
if [ -n "$bpo_ver" ]; then
local msg="Backports repository is enabled.\n\n"
msg+="Available versions:\n"
msg+=" - Stable: v${stable_ver:-unknown}\n"
msg+=" - Backports: v${bpo_ver}\n\n"
msg+="Install from Backports (Recommended for newer hardware)\nor from Stable (more conservative)?"
if _confirm_custom "PipeWire Install" "$msg" "Backports" "Stable" 14 70; then
apt_target="-t ${DEBIAN_CODENAME}-backports"
pw_ver="$bpo_ver"
pw_src="from ${DEBIAN_CODENAME}-backports"
else
pw_ver="$stable_ver"
fi
else
local msg="PipeWire Audio Stack (v${stable_ver:-unknown})\n"
msg+="will be installed along with Bluetooth Hi-Res\n"
msg+="codecs (LDAC, aptX, AAC).\n\n"
msg+="Continue with installation?"
if ! _confirm "PipeWire Install" "$msg" 12 65; then
echo "PipeWire installation cancelled."
return
fi
pw_ver="$stable_ver"
fi
echo "Installing PipeWire Audio Stack..."
echo "-> Detected version: ${pw_ver:-unknown} ${pw_src:+($pw_src)}"
echo "-> Including Bluetooth Hi-Res codecs (LDAC, aptX, AAC)"
case "$DEBIAN_VERSION" in
11)
_run_cmd "PipeWire" \
"sudo apt install -y pipewire libspa-0.2-bluetooth pipewire-alsa libspa-0.2-jack $bt_pkgs" \
"Installing PipeWire (Bullseye basic mode)..."
echo -e "${GREEN}PipeWire installed (Bullseye basic mode).${NC}"
;;
12)
_run_cmd "PipeWire" \
"sudo apt install -y pipewire-audio $bt_pkgs" \
"Installing pipewire-audio meta-package (Bookworm)..."
echo -e "${GREEN}PipeWire audio stack installed.${NC}"
;;
13)
_run_cmd "PipeWire" \
"sudo apt install -y $apt_target pipewire-audio $bt_pkgs" \
"Installing pipewire-audio meta-package (Trixie)..."
echo -e "${GREEN}PipeWire audio stack installed.${NC}"
;;
esac
if [ "$DEBIAN_VERSION" != "11" ]; then
echo "Restarting PipeWire services..."
systemctl --user restart wireplumber pipewire pipewire-pulse 2>/dev/null || true
echo -e "${GREEN}PipeWire services restarted.${NC}"
fi
}
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env bash
# system_prefs.sh — System Preferences: time, locale, keyboard, audio
_prefs_date_time() {
echo -e "${YELLOW}Current system date/time:${NC} $(date '+%Y-%m-%d %H:%M')"
echo -e "${YELLOW}Timezone:${NC} $(timedatectl show -p Timezone --value 2>/dev/null || echo unknown)"
if _confirm "Timezone" "Change the system timezone (dpkg-reconfigure tzdata)?"; then
sudo env LC_ALL=C LANGUAGE=C dpkg-reconfigure tzdata || true
echo -e "${GREEN}Timezone: $(timedatectl show -p Timezone --value 2>/dev/null)${NC}"
fi
_ensure_time_synced
}
_prefs_locale_keyboard() {
sudo env LC_ALL=C LANGUAGE=C dpkg-reconfigure locales || true
sudo env LC_ALL=C LANGUAGE=C dpkg-reconfigure keyboard-configuration || true
echo -e "${GREEN}Language, locales and keyboard configured.${NC}"
}
_prefs_audio() { _prefs_audio_menu; }
_system_preferences_menu() {
while true; do
local choice
choice=$(_menu "System Preferences" "Select a preference group:" \
$TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"1" "Date, Time & Timezone" \
"2" "Language, Locales & Keyboard" \
"3" "Audio & Sound Stack" \
"4" "Back to main menu")
[ -z "$choice" ] && return
clear
case "$choice" in
1) _prefs_date_time ;;
2) _prefs_locale_keyboard ;;
3) _prefs_audio ;;
4) return ;;
esac
done
}
+175 -76
View File
@@ -22,6 +22,12 @@ WIFI_CHIPSET=""
DESKTOP_ENV="" DESKTOP_ENV=""
AUDIO_SERVER="" AUDIO_SERVER=""
# APT update deduplication flag (set to 1 after the first successful apt-get update)
APT_UPDATED=0
# Cached output of `lspci -nn` for the whole session (populated once via _init_lspci_cache)
LSPCI_OUTPUT=""
# -------------------------- # --------------------------
# Pre-flight checks # Pre-flight checks
# -------------------------- # --------------------------
@@ -93,11 +99,50 @@ sync_system_time() {
fi fi
} }
# -------------------------------------------------------------------
# Robust time sync: NTP + timezone validation + service restart
# -------------------------------------------------------------------
_ensure_time_synced() {
command -v timedatectl &>/dev/null || return
# ── Paso 1: Forzar NTP activo ──
sudo timedatectl set-ntp true --no-ask-password 2>/dev/null || true
# ── Paso 2: Validar zona horaria ──
local tz
tz=$(timedatectl show -p Timezone --value 2>/dev/null || echo "")
if [ -z "$tz" ] || [ "$tz" = "n/a" ] || [ "$tz" = "Etc/UTC" ]; then
if [ -n "${DISPLAY:-}" ] || [ -n "${SSH_TTY:-}" ]; then
_msg "Timezone" \
"Your system timezone is not set or is set to UTC.\n\nThe script will now open the timezone\nconfiguration tool to set your local timezone." 12 60
sudo env LC_ALL=C LANGUAGE=C dpkg-reconfigure tzdata || true
echo -e "${GREEN}Timezone configured: $(timedatectl show -p Timezone --value 2>/dev/null)${NC}"
else
echo -e "${YELLOW}Timezone not set. Run 'sudo dpkg-reconfigure tzdata' later.${NC}"
fi
fi
# ── Paso 3: Instalar/asegurar systemd-timesyncd ──
if ! is_installed systemd-timesyncd; then
sudo DEBIAN_FRONTEND=noninteractive apt install -y systemd-timesyncd || true
fi
sudo systemctl enable systemd-timesyncd 2>/dev/null || true
sudo systemctl restart systemd-timesyncd 2>/dev/null || true
# ── Paso 4: Verificar resultado ──
sleep 2
if timedatectl show --property=NTPSynchronized --value 2>/dev/null | grep -q yes; then
echo -e "${GREEN}Time synchronized: $(date '+%Y-%m-%d %H:%M')${NC}"
else
echo -e "${YELLOW}NTP sync did not complete yet (may need a moment).${NC}"
fi
}
# -------------------------------- # --------------------------------
# Debian version detection # Debian version detection
# -------------------------------- # --------------------------------
detect_debian_version() { detect_debian_version() {
if ! command -v lsb_release &> /dev/null; then if ! command -v lsb_release &>/dev/null; then
if [ -f /etc/os-release ]; then if [ -f /etc/os-release ]; then
DEBIAN_CODENAME=$(grep -oP 'VERSION_CODENAME=\K\w+' /etc/os-release 2>/dev/null || echo "") DEBIAN_CODENAME=$(grep -oP 'VERSION_CODENAME=\K\w+' /etc/os-release 2>/dev/null || echo "")
fi fi
@@ -110,13 +155,13 @@ detect_debian_version() {
DEBIAN_CODENAME=$(lsb_release -cs 2>/dev/null || echo "") DEBIAN_CODENAME=$(lsb_release -cs 2>/dev/null || echo "")
fi fi
case "$DEBIAN_CODENAME" in case "$DEBIAN_CODENAME" in
bullseye) DEBIAN_VERSION="11" ;; bullseye) DEBIAN_VERSION="11" ;;
bookworm) DEBIAN_VERSION="12" ;; bookworm) DEBIAN_VERSION="12" ;;
trixie) DEBIAN_VERSION="13" ;; trixie) DEBIAN_VERSION="13" ;;
*) *)
echo -e "${RED}Unsupported Debian version: '$DEBIAN_CODENAME'. Only 11 (bullseye), 12 (bookworm) and 13 (trixie) are supported.${NC}" echo -e "${RED}Unsupported Debian version: '$DEBIAN_CODENAME'. Only 11 (bullseye), 12 (bookworm) and 13 (trixie) are supported.${NC}"
exit 1 exit 1
;; ;;
esac esac
} }
@@ -124,7 +169,7 @@ detect_debian_version() {
# CPU and RAM info (cosmetic) # CPU and RAM info (cosmetic)
# ---------------------------------- # ----------------------------------
detect_cpu_ram() { detect_cpu_ram() {
CPU_SUMMARY=$(grep -m1 'model name' /proc/cpuinfo | sed 's/.*: //') CPU_SUMMARY=$(grep -m1 'model name' /proc/cpuinfo | sed 's/.*: //' || true)
RAM_KB=$(grep MemTotal /proc/meminfo | awk '{print $2}') RAM_KB=$(grep MemTotal /proc/meminfo | awk '{print $2}')
RAM_GB=$(awk -v kb="$RAM_KB" 'BEGIN { printf "%.2f", kb / 1048576 }') RAM_GB=$(awk -v kb="$RAM_KB" 'BEGIN { printf "%.2f", kb / 1048576 }')
RAM_SUMMARY="${RAM_GB} GB" RAM_SUMMARY="${RAM_GB} GB"
@@ -186,12 +231,23 @@ detect_kernel() {
KERNEL_VERSION=$(uname -r) KERNEL_VERSION=$(uname -r)
} }
# ----------------------------------
# lspci output cache
# ----------------------------------
# Populates LSPCI_OUTPUT once per session. `lspci -nn` includes the textual PCI
# class (VGA/3D/Ethernet/Network/Bluetooth controller) and the device IDs
# (e.g. 14e4:), so a single capture covers every grep used across modules.
_init_lspci_cache() {
[ -n "${LSPCI_OUTPUT:-}" ] && return
LSPCI_OUTPUT=$(timeout 2 lspci -nn 2>/dev/null || true)
}
# ---------------------------------- # ----------------------------------
# GPU detection # GPU detection
# ---------------------------------- # ----------------------------------
detect_gpu() { detect_gpu() {
local gpu_lines local gpu_lines
gpu_lines=$(lspci -nn | grep -E "VGA|3D") || true gpu_lines=$(echo "$LSPCI_OUTPUT" | grep -E "VGA|3D") || true
if [ -z "$gpu_lines" ]; then if [ -z "$gpu_lines" ]; then
GPU_TYPE="unknown" GPU_TYPE="unknown"
GPU_DESC="No GPU detected" GPU_DESC="No GPU detected"
@@ -201,7 +257,8 @@ detect_gpu() {
local has_nvidia=false has_amd=false has_intel=false local has_nvidia=false has_amd=false has_intel=false
local desc_lines="" nvidia_dev_id="" intel_dev_id="" local desc_lines="" nvidia_dev_id="" intel_dev_id=""
while IFS= read -r line; do while IFS= read -r line || [[ -n "$line" ]]; do
[[ -z "$line" ]] && continue
local desc local desc
desc=$(echo "$line" | sed -E 's/.*: //; s/ *\(rev.*//') desc=$(echo "$line" | sed -E 's/.*: //; s/ *\(rev.*//')
[ -n "$desc_lines" ] && desc_lines+=" + " [ -n "$desc_lines" ] && desc_lines+=" + "
@@ -217,7 +274,7 @@ detect_gpu() {
has_intel=true has_intel=true
[ -z "$intel_dev_id" ] && intel_dev_id=$(echo "$line" | grep -oP '8086:\K[0-9a-fA-F]+' | head -n1) [ -z "$intel_dev_id" ] && intel_dev_id=$(echo "$line" | grep -oP '8086:\K[0-9a-fA-F]+' | head -n1)
fi fi
done <<< "$gpu_lines" done <<<"$gpu_lines"
GPU_DESC="$desc_lines" GPU_DESC="$desc_lines"
HAS_NVIDIA=$has_nvidia HAS_NVIDIA=$has_nvidia
@@ -240,9 +297,9 @@ detect_gpu() {
if [ "$GPU_TYPE" = "nvidia" ]; then if [ "$GPU_TYPE" = "nvidia" ]; then
local nv_ver local nv_ver
nv_ver=$(nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -1) nv_ver=$(timeout 3 nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -1) || true
if [ -z "$nv_ver" ]; then if [ -z "$nv_ver" ]; then
nv_ver=$(dpkg -l nvidia-driver 2>/dev/null | awk '/^ii/ {print $3}' | sed 's/-.*//') nv_ver=$(dpkg -l nvidia-driver 2>/dev/null | awk '/^ii/ {print $3}' | sed 's/-.*//') || true
fi fi
[ -n "$nv_ver" ] && GPU_VERSION="NVIDIA $nv_ver" [ -n "$nv_ver" ] && GPU_VERSION="NVIDIA $nv_ver"
fi fi
@@ -282,21 +339,21 @@ declare -a WIFI_SSIDS=()
detect_network() { detect_network() {
local eth_line local eth_line
eth_line=$(lspci -nn | grep -i 'Ethernet controller' | head -n1) || true eth_line=$(echo "$LSPCI_OUTPUT" | grep -i 'Ethernet controller' | head -n1) || true
if [ -n "$eth_line" ]; then if [ -n "$eth_line" ]; then
ETH_DESC=$(echo "$eth_line" | sed -E 's/^.*\]: //; s/ \[[0-9a-fA-F]{4}:[0-9a-fA-F]{4}\]//; s/ \(rev [0-9a-fA-F]+\)//') ETH_DESC=$(echo "$eth_line" | sed -E 's/^.*\]: //; s/ \[[0-9a-fA-F]{4}:[0-9a-fA-F]{4}\]//; s/ \(rev [0-9a-fA-F]+\)//')
fi fi
local wifi_line local wifi_line
# Layer 1: grep by PCI class description text # Layer 1: grep by PCI class description text
wifi_line=$(lspci -nn 2>/dev/null | grep -iE 'network controller|wireless|wi-fi|wlan|802\.11' | head -n1) || true wifi_line=$(echo "$LSPCI_OUTPUT" | grep -iE 'network controller|wireless|wi-fi|wlan|802\.11' | head -n1) || true
# Layer 2: grep by exact PCI class code 0x0280 (Network controller) # Layer 2: grep by exact PCI class code 0x0280 (Network controller)
if [ -z "$wifi_line" ]; then if [ -z "$wifi_line" ]; then
wifi_line=$(lspci -d ::0280 2>/dev/null | head -n1) || true wifi_line=$(echo "$LSPCI_OUTPUT" | grep -i 'network controller' | head -n1) || true
fi fi
# Layer 3: Broadcom vendor ID fallback (14e4) # Layer 3: Broadcom vendor ID fallback (14e4)
if [ -z "$wifi_line" ]; then if [ -z "$wifi_line" ]; then
wifi_line=$(lspci -nn 2>/dev/null | grep -i '14e4:' | head -n1) || true wifi_line=$(echo "$LSPCI_OUTPUT" | grep -i '14e4:' | head -n1) || true
fi fi
if [ -n "$wifi_line" ]; then if [ -n "$wifi_line" ]; then
WIFI_CHIPSET="$wifi_line" WIFI_CHIPSET="$wifi_line"
@@ -323,25 +380,25 @@ detect_network() {
iface=$(echo "$line" | awk -F': ' '{print $2}' | sed 's/@.*//') iface=$(echo "$line" | awk -F': ' '{print $2}' | sed 's/@.*//')
state=$(echo "$line" | awk '{print $9}') state=$(echo "$line" | awk '{print $9}')
case "$iface" in case "$iface" in
eth*|enp*|ens*|enx*|eno*) eth* | enp* | ens* | enx* | eno*)
ip4=$(ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}') ip4=$(timeout 2 ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}')
ETH_NAMES+=("$iface") ETH_NAMES+=("$iface")
ETH_STATES+=("$state") ETH_STATES+=("$state")
ETH_IPS+=("${ip4:-}") ETH_IPS+=("${ip4:-}")
ETH_DESCS+=("${ETH_DESC:-}") ETH_DESCS+=("${ETH_DESC:-}")
;; ;;
wl*|wlp*|wlo*|wlan*) wl* | wlp* | wlo* | wlan*)
ip4=$(ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}') ip4=$(timeout 2 ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}')
ssid="" ssid=""
[ "$state" = "UP" ] && ssid=$(iwgetid -r "$iface" 2>/dev/null || true) [ "$state" = "UP" ] && ssid=$(timeout 2 iwgetid -r "$iface" 2>/dev/null || true)
WIFI_NAMES+=("$iface") WIFI_NAMES+=("$iface")
WIFI_STATES+=("$state") WIFI_STATES+=("$state")
WIFI_IPS+=("${ip4:-}") WIFI_IPS+=("${ip4:-}")
WIFI_SSIDS+=("${ssid:-}") WIFI_SSIDS+=("${ssid:-}")
WIFI_DESCS+=("${WIFI_DESC:-}") WIFI_DESCS+=("${WIFI_DESC:-}")
;; ;;
esac esac
done < <(ip -o link show 2>/dev/null) done < <(timeout 2 ip -o link show 2>/dev/null)
} }
# --------------------------------------- # ---------------------------------------
@@ -350,18 +407,18 @@ detect_network() {
detect_displayserver() { detect_displayserver() {
local st="${XDG_SESSION_TYPE:-}" local st="${XDG_SESSION_TYPE:-}"
case "$st" in case "$st" in
wayland) DISPLAY_SERVER="Wayland" ;; wayland) DISPLAY_SERVER="Wayland" ;;
x11) DISPLAY_SERVER="X11" ;; x11) DISPLAY_SERVER="X11" ;;
tty) DISPLAY_SERVER="none (tty)" ;; tty) DISPLAY_SERVER="none (tty)" ;;
*) *)
if [ -n "${WAYLAND_DISPLAY:-}" ]; then if [ -n "${WAYLAND_DISPLAY:-}" ]; then
DISPLAY_SERVER="Wayland" DISPLAY_SERVER="Wayland"
elif [ -n "${DISPLAY:-}" ]; then elif [ -n "${DISPLAY:-}" ]; then
DISPLAY_SERVER="X11" DISPLAY_SERVER="X11"
else else
DISPLAY_SERVER="unknown" DISPLAY_SERVER="unknown"
fi fi
;; ;;
esac esac
} }
@@ -382,7 +439,7 @@ detect_storage() {
elif [ "$rota" = "1" ]; then elif [ "$rota" = "1" ]; then
type="HDD" type="HDD"
else else
rm=$(cat /sys/block/"$name"/removable 2>/dev/null || echo 0) rm=$(timeout 2 cat /sys/block/"$name"/removable 2>/dev/null || echo 0)
if [ "$rm" = "1" ]; then if [ "$rm" = "1" ]; then
type="USB/SD" type="USB/SD"
else else
@@ -390,7 +447,7 @@ detect_storage() {
fi fi
fi fi
parts+=("${size} ${type}") parts+=("${size} ${type}")
done < <(lsblk -d -o NAME,SIZE,ROTA,TYPE -e 7,11 2>/dev/null || true) done < <(timeout 2 lsblk -d -o NAME,SIZE,ROTA,TYPE -e 7,11 2>/dev/null || true)
if [ ${#parts[@]} -eq 0 ]; then if [ ${#parts[@]} -eq 0 ]; then
STORAGE_SUMMARY="No disks detected" STORAGE_SUMMARY="No disks detected"
@@ -411,10 +468,10 @@ detect_storage() {
# --------------------------------------- # ---------------------------------------
detect_desktop_environment() { detect_desktop_environment() {
case "${XDG_CURRENT_DESKTOP:-}" in case "${XDG_CURRENT_DESKTOP:-}" in
*GNOME*) DESKTOP_ENV="gnome" ;; *GNOME*) DESKTOP_ENV="gnome" ;;
*KDE*) DESKTOP_ENV="kde" ;; *KDE*) DESKTOP_ENV="kde" ;;
*XFCE*) DESKTOP_ENV="xfce" ;; *XFCE*) DESKTOP_ENV="xfce" ;;
*) DESKTOP_ENV="other" ;; *) DESKTOP_ENV="other" ;;
esac esac
} }
@@ -422,7 +479,7 @@ detect_desktop_environment() {
# Audio server detection (PipeWire / PulseAudio) # Audio server detection (PipeWire / PulseAudio)
# --------------------------------------- # ---------------------------------------
detect_audio_server() { detect_audio_server() {
if command -v pw-cli &>/dev/null && pw-cli info &>/dev/null 2>&1; then if command -v pw-cli &>/dev/null && timeout 2 pw-cli info &>/dev/null 2>&1; then
AUDIO_SERVER="pipewire" AUDIO_SERVER="pipewire"
elif command -v pactl &>/dev/null; then elif command -v pactl &>/dev/null; then
AUDIO_SERVER="pulseaudio" AUDIO_SERVER="pulseaudio"
@@ -443,7 +500,7 @@ get_intel_generation() {
fi fi
local dev_int local dev_int
dev_int=$(printf "%d" "$INTEL_GPU_DEVICE_ID") dev_int=$(printf "%d" "$INTEL_GPU_DEVICE_ID")
if [ "$dev_int" -lt 5632 ]; then # 0x1600 = 5632 if [ "$dev_int" -lt 5632 ]; then # 0x1600 = 5632
echo "gen7-" echo "gen7-"
else else
echo "gen8+" echo "gen8+"
@@ -452,41 +509,48 @@ get_intel_generation() {
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# Check if backports repository is enabled (active line without #) # Check if backports repository is enabled (active line without #)
# Nota: el flujo NVIDIA Debian 12 (Bookworm) ya NO usa esta función
# (backports EOL 2026-08-09). Sigue activa para kernels, desktop/greetd,
# gaming, audio, comunicación y Mesa (AMD/Intel).
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
is_backports_enabled() { is_backports_enabled() {
local codename="${DEBIAN_CODENAME:-}" local codename="${DEBIAN_CODENAME:-}"
[ -z "$codename" ] && { echo false; return; } [ -z "$codename" ] && {
echo false
return
}
local c_pattern="^[^#]*${codename}-backports[[:space:]]+" local c_pattern="^[^#]*${codename}-backports[[:space:]]+"
local d_pattern="Suites:.*${codename}-backports" local d_pattern="Suites:.*${codename}-backports"
# Classic embedded (sources.list) # Classic embedded (sources.list)
if [ -f /etc/apt/sources.list ] && grep -Eq "$c_pattern" /etc/apt/sources.list 2>/dev/null; then if [ -f /etc/apt/sources.list ] && grep -Eq "$c_pattern" /etc/apt/sources.list 2>/dev/null; then
echo true; return echo true
return
fi fi
# Classic standalone (new — debian-backports.list) # Classic standalone (any .list file in sources.list.d)
if [ -f /etc/apt/sources.list.d/debian-backports.list ] && \ if [ -d /etc/apt/sources.list.d ] && grep -qrE "$c_pattern" /etc/apt/sources.list.d/*.list 2>/dev/null; then
grep -Eq "$c_pattern" /etc/apt/sources.list.d/debian-backports.list 2>/dev/null; then echo true
echo true; return return
fi fi
# Deb822 any .sources file # Deb822 any .sources file
if grep -qr "$d_pattern" /etc/apt/sources.list.d/*.sources 2>/dev/null; then if [ -d /etc/apt/sources.list.d ] && grep -qr "$d_pattern" /etc/apt/sources.list.d/*.sources 2>/dev/null; then
echo true; return echo true
return
fi fi
echo false echo false
} }
install_backports_or_stable() { install_backports_or_stable() {
local pkg="$1" local pkg="$1"
local pkg_desc="${2:-$pkg}" local pkg_desc="${2:-$pkg}"
local bpo_ver="" local bpo_ver=""
if [ "$(is_backports_enabled)" == true ]; then if [ "$(is_backports_enabled)" == true ]; then
bpo_ver=$(apt-cache madison "$pkg" 2>/dev/null | \ bpo_ver=$(apt-cache madison "$pkg" 2>/dev/null |
grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1) grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1)
fi fi
@@ -552,15 +616,23 @@ _msg_red() {
} }
_menu() { _menu() {
local title="$1" text="$2" h="$3" w="$4" lh="$5"; shift 5 local title="$1" text="$2" h="$3" w="$4" lh="$5"
shift 5
whiptail --title "$title" --menu "$text" "$h" "$w" "$lh" "$@" 3>&1 1>&2 2>&3 || true whiptail --title "$title" --menu "$text" "$h" "$w" "$lh" "$@" 3>&1 1>&2 2>&3 || true
} }
_checklist() { _checklist() {
local title="$1" text="$2" h="$3" w="$4" lh="$5"; shift 5 local title="$1" text="$2" h="$3" w="$4" lh="$5"
shift 5
whiptail --title "$title" --ok-button "Apply" --checklist "$text" "$h" "$w" "$lh" "$@" 3>&1 1>&2 2>&3 || true whiptail --title "$title" --ok-button "Apply" --checklist "$text" "$h" "$w" "$lh" "$@" 3>&1 1>&2 2>&3 || true
} }
_radiolist() {
local title="$1" text="$2" h="$3" w="$4" lh="$5"
shift 5
whiptail --title "$title" --ok-button "Install" --radiolist "$text" "$h" "$w" "$lh" "$@" 3>&1 1>&2 2>&3 || true
}
_inputbox() { _inputbox() {
whiptail --title "$1" --ok-button "Apply" --inputbox "$2" "${3:-10}" "${4:-60}" "${5:-}" 3>&1 1>&2 2>&3 || true whiptail --title "$1" --ok-button "Apply" --inputbox "$2" "${3:-10}" "${4:-60}" "${5:-}" 3>&1 1>&2 2>&3 || true
} }
@@ -569,7 +641,7 @@ _validate_sudoers() {
local content="$1" dest="$2" local content="$1" dest="$2"
local tmpfile local tmpfile
tmpfile=$(mktemp) || return 1 tmpfile=$(mktemp) || return 1
echo "$content" > "$tmpfile" echo "$content" >"$tmpfile"
if ! /usr/sbin/visudo -cf "$tmpfile" &>/dev/null; then if ! /usr/sbin/visudo -cf "$tmpfile" &>/dev/null; then
local err local err
err=$(/usr/sbin/visudo -cf "$tmpfile" 2>&1 || true) err=$(/usr/sbin/visudo -cf "$tmpfile" 2>&1 || true)
@@ -589,12 +661,14 @@ _pause() {
} }
# Blocks 2-4: run → pause # Blocks 2-4: run → pause
# Returns the exit code of the executed command so callers can abort
# or adjust state (e.g. NVIDIA_DRIVER_MODE) when a step fails.
_run_cmd() { _run_cmd() {
local title="$1" command="$2" success_msg="${3:-Running...}" local title="$1" command="$2" success_msg="${3:-Running...}"
echo -e "${GREEN}[+]${NC} $success_msg" echo -e "${GREEN}[+]${NC} $success_msg"
echo "──────────────────────────────────────────────" echo "──────────────────────────────────────────────"
bash -c "$command" local rc=0
local rc=$? bash -c "$command" || rc=$?
echo "──────────────────────────────────────────────" echo "──────────────────────────────────────────────"
if [ $rc -eq 0 ]; then if [ $rc -eq 0 ]; then
echo -e "${GREEN}[+]${NC} Done." echo -e "${GREEN}[+]${NC} Done."
@@ -602,6 +676,7 @@ _run_cmd() {
echo -e "${RED}[-]${NC} Failed (exit code: $rc)." echo -e "${RED}[-]${NC} Failed (exit code: $rc)."
fi fi
_pause _pause
return "$rc"
} }
# Blocks 1-4: confirm → run → pause # Blocks 1-4: confirm → run → pause
@@ -651,8 +726,8 @@ _run_install_pkg() {
get_backports_kernel_version() { get_backports_kernel_version() {
local ver local ver
ver=$(apt-cache policy linux-image-amd64 2>/dev/null | \ ver=$(apt-cache policy linux-image-amd64 2>/dev/null |
grep -E '^[[:space:]]+[0-9]+\.[0-9]+\.[0-9]+.*~bpo' | head -n1 | awk '{print $1}') grep -E '^[[:space:]]+[0-9]+\.[0-9]+\.[0-9]+.*~bpo' | head -n1 | awk '{print $1}')
if [ -n "$ver" ]; then if [ -n "$ver" ]; then
echo "$ver" echo "$ver"
else else
@@ -709,16 +784,38 @@ _check_network() {
return 1 return 1
} }
# ----------------------------------
# APT update deduplication
# ----------------------------------
# Runs `apt-get update` at most once per session. Subsequent calls bypass the
# network refresh. Returns 0 on success, 1 if apt-get update fails.
_ensure_apt_updated() {
if [ "$APT_UPDATED" -eq 1 ]; then
echo -e "${GREEN}[+]${NC} APT package lists already refreshed this session."
return 0
fi
echo -e "${GREEN}[+]${NC} Refreshing APT package lists..."
if sudo apt-get update; then
APT_UPDATED=1
return 0
fi
echo -e "${RED}[-]${NC} apt-get update failed."
return 1
}
# ---------------------------------- # ----------------------------------
# LightDM configuration # LightDM configuration
# ---------------------------------- # ----------------------------------
_configure_lightdm() { _configure_lightdm() {
command -v lightdm &>/dev/null || return 0 command -v lightdm &>/dev/null || return 0
if _confirm "LightDM" "Configure LightDM to show the user list on the login screen?\n\nThis disables greeter-hide-users."; then if _confirm "LightDM" "Configure LightDM to show the user list on the login screen?\n\nThis disables greeter-hide-users."; then
if ! is_installed lightdm-gtk-greeter-settings; then if ! is_installed lightdm-gtk-greeter-settings; then
echo -e "${YELLOW}Installing lightdm-gtk-greeter-settings...${NC}" echo -e "${YELLOW}Installing lightdm-gtk-greeter-settings...${NC}"
sudo DEBIAN_FRONTEND=noninteractive apt install -y lightdm-gtk-greeter-settings if ! sudo DEBIAN_FRONTEND=noninteractive apt install -y lightdm-gtk-greeter-settings; then
echo -e "${YELLOW}lightdm-gtk-greeter-settings could not be installed — LightDM configuration skipped.${NC}"
return 0
fi
fi fi
local conf_dir="/etc/lightdm/lightdm.conf.d" local conf_dir="/etc/lightdm/lightdm.conf.d"
@@ -729,7 +826,7 @@ _check_network() {
fi fi
sudo mkdir -p "$conf_dir" sudo mkdir -p "$conf_dir"
printf '[Seat:*]\ngreeter-hide-users=false\n' | sudo tee "$conf_file" > /dev/null printf '[Seat:*]\ngreeter-hide-users=false\n' | sudo tee "$conf_file" >/dev/null
echo -e "${GREEN}LightDM configured to show user list.${NC}" echo -e "${GREEN}LightDM configured to show user list.${NC}"
fi fi
} }
@@ -739,4 +836,6 @@ refresh_system_state() {
detect_debian_version detect_debian_version
detect_gpu detect_gpu
detect_cpu_ram detect_cpu_ram
detect_network
detect_desktop_environment
} }
+21 -4
View File
@@ -85,7 +85,12 @@ _zram_create() {
fi fi
fi fi
local half_ram_mb=$(( ((RAM_KB / 1024 / 1024 + 1) / 2) * 1024 )) local ram_gb=$(( RAM_KB / 1024 / 1024 ))
if [ "$ram_gb" -gt 8 ]; then
recommended_mb=4096
else
recommended_mb=$(( ((RAM_KB / 1024 / 1024 + 1) / 2) * 1024 ))
fi
local algo local algo
algo=$(_menu "ZRAM Configuration" \ algo=$(_menu "ZRAM Configuration" \
@@ -100,10 +105,10 @@ _zram_create() {
fi fi
local zram_size local zram_size
if _confirm "ZRAM Size" "Use recommended size for ZRAM? (${half_ram_mb} MB out of ${RAM_SUMMARY})"; then if _confirm "ZRAM Size" "Use recommended size for ZRAM? (${recommended_mb} MB out of ${RAM_SUMMARY})"; then
zram_size=$half_ram_mb zram_size=$recommended_mb
else else
zram_size=$(_inputbox "ZRAM Size" "Enter ZRAM size in MB:" 8 60 "$half_ram_mb") zram_size=$(_inputbox "ZRAM Size" "Enter ZRAM size in MB:" 8 60 "$recommended_mb")
if [ -z "$zram_size" ] || ! [[ "$zram_size" =~ ^[0-9]+$ ]] || [ "$zram_size" -eq 0 ]; then if [ -z "$zram_size" ] || ! [[ "$zram_size" =~ ^[0-9]+$ ]] || [ "$zram_size" -eq 0 ]; then
echo "ZRAM configuration cancelled." echo "ZRAM configuration cancelled."
return return
@@ -117,6 +122,10 @@ _zram_create() {
_run_cmd "ZRAM" "sudo apt install -y zram-tools" "Installing zram-tools..." _run_cmd "ZRAM" "sudo apt install -y zram-tools" "Installing zram-tools..."
echo "Resetting existing ZRAM device..."
sudo swapoff /dev/zram0 2>/dev/null || true
sudo modprobe -r zram 2>/dev/null || true
echo "Writing configuration..." echo "Writing configuration..."
sudo tee /etc/default/zramswap > /dev/null <<EOF sudo tee /etc/default/zramswap > /dev/null <<EOF
ALGO=$algo ALGO=$algo
@@ -127,6 +136,10 @@ EOF
echo "Restarting zramswap service..." echo "Restarting zramswap service..."
sudo systemctl restart zramswap sudo systemctl restart zramswap
if ! grep -q "\[${algo}\]" /sys/block/zram0/comp_algorithm 2>/dev/null; then
echo -e "${YELLOW}Warning: ZRAM algorithm not applied yet. Reboot to finalize.${NC}"
fi
echo "" echo ""
echo -e "${GREEN}ZRAM configured successfully.${NC}" echo -e "${GREEN}ZRAM configured successfully.${NC}"
echo "" echo ""
@@ -151,6 +164,10 @@ _zram_remove() {
echo "Stopping zramswap service..." echo "Stopping zramswap service..."
sudo systemctl stop zramswap || true sudo systemctl stop zramswap || true
echo "Releasing ZRAM device..."
sudo swapoff /dev/zram0 2>/dev/null || true
sudo modprobe -r zram 2>/dev/null || true
_run_cmd "ZRAM" "sudo apt purge -y zram-tools" "Purging zram-tools..." _run_cmd "ZRAM" "sudo apt purge -y zram-tools" "Purging zram-tools..."
echo "Removing configuration..." echo "Removing configuration..."