mirror of
https://github.com/stornic56/debianito-post-install.git
synced 2026-07-16 13:59:50 +00:00
Compare commits
23 Commits
3d1738ddc0
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| d8878b67e1 | |||
| ba72fd9f87 | |||
| f043c130a8 | |||
| 2ebb33460c | |||
| a91b0caa25 | |||
| 4ef48eac3b | |||
| 110d89baf8 | |||
| 8d1a05e3e0 | |||
| ad0b39e159 | |||
| 3972cc4811 | |||
| 2272306313 | |||
| bfd3144c7e | |||
| 2708d6dcb5 | |||
| 3e96906d6e | |||
| 002a888b46 | |||
| 3a652c28e6 | |||
| 63ef2e7343 | |||
| 23301f98b3 | |||
| 872f92d6b4 | |||
| 656f045163 | |||
| ba72875960 | |||
| 72032f2916 | |||
| af8fac4ac4 |
@@ -1,10 +1,11 @@
|
|||||||
# Debianito - Post-Installation Automation for Debian
|
<h1 align="center">Debianito - Post-Installation Automation for Debian</h1>
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
Debianito is a user-friendly post-installation automation script for Debian 12 (Bookworm) and Debian 13 (Trixie). It streamlines system configuration, driver installation, repository setup, gaming tools integration, and more with an interactive menu-driven interface.
|
Debianito is a user-friendly post-installation automation script for Debian 11 (Bullseye), Debian 12 (Bookworm) and Debian 13 (Trixie). It streamlines system configuration, driver installation (including NVIDIA drivers), repository setup with backports support, gaming tools integration, and more with an interactive menu-driven interface.
|
||||||
|
|
||||||
[](https://github.com/stornic56/debianito-post-install/blob/main/LICENSE)
|
[](https://github.com/stornic56/debianito-post-install/blob/main/LICENSE)
|
||||||
|

|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -14,16 +15,16 @@ Debianito is a user-friendly post-installation automation script for Debian 12 (
|
|||||||
|
|
||||||
| Requirement | Specification |
|
| Requirement | Specification |
|
||||||
|-------------|---------------|
|
|-------------|---------------|
|
||||||
| **OS** | Debian 12 (Bookworm), Debian 13 (Trixie) |
|
| **OS** | Debian 11 (Bullseye), Debian 12 (Bookworm), Debian 13 (Trixie) |
|
||||||
| **Privileges** | Script must be run with `sudo` privileges by a normal user |
|
| **Privileges** | Normal user with `sudo` access, script validates root/sudo in utils.sh |
|
||||||
| **Terminal** | Any modern terminal emulator that supports ANSI colors and UTF-8 box-drawing characters |
|
| **Terminal** | Any modern terminal emulator supporting ANSI colors and UTF-8 box-drawing characters |
|
||||||
| **Dependencies** | Standard Debian packages; script will install missing dependencies (e.g., `whiptail`, `lsb-release`) where necessary. |
|
| **Dependencies** | Standard Debian packages (`whiptail`, `lsb-release`); auto-installed if missing |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Installation Instructions
|
## Installation Instructions
|
||||||
|
|
||||||
### Step 1: Clone or Download the Repository
|
Clone the repository, make the script executable, and run it:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/stornic56/debianito-post-install
|
git clone https://github.com/stornic56/debianito-post-install
|
||||||
@@ -31,17 +32,7 @@ cd debianito-post-install
|
|||||||
chmod +x debianito.sh && ./debianito.sh
|
chmod +x debianito.sh && ./debianito.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
If you downloaded manually, ensure all `.sh` files are in their respective directories.
|
> ⚠️ **Do not run as root.** The script checks for non-root execution and requires sudo privileges.
|
||||||
|
|
||||||
### Step 2: Run the Script with Sudo Privileges
|
|
||||||
|
|
||||||
> **Do not run this script as root.** Use a normal user account and authorize via `sudo`.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./debianito.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
The script will perform initial checks, detect your system information (CPU, RAM, GPU), then present an interactive menu.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -49,39 +40,48 @@ The script will perform initial checks, detect your system information (CPU, RAM
|
|||||||
|
|
||||||
After running the script:
|
After running the script:
|
||||||
|
|
||||||
1. **Select Option:** Use arrow keys or type `1-9`.
|
1. **Select Option:** Use arrow keys or type 1-10.
|
||||||
2. **Confirm Actions:** For installation steps, you'll see a confirmation prompt (`whiptail`/`dialog`).
|
2. **Navigation:** Use Arrow Keys (Up↑/Down↓) to move between list options and ENTER key to confirm selection.
|
||||||
3. **Review System Info:** The header displays your detected Debian version and hardware summary before each action.
|
3. **Confirm Actions:** Installation prompts use whiptail for TUI confirmations.
|
||||||
4. **Repeat as Needed:** Return to the main menu at any time or exit when done.
|
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.
|
||||||
|
|
||||||
| Option | Description | What it does |
|
| Option | Description | What it does |
|
||||||
|--------|-------------|--------------|
|
|--------|-------------|--------------|
|
||||||
| **1** | System Info | Show detected hardware and OS details |
|
| **1** | [System Info](/docs/system_info.md) | Show detected OS, CPU, RAM, GPU and hardware details |
|
||||||
| **2** | User Privileges & Feedback | Add user to sudo group, enable password feedback (`pwfeedback`) |
|
| **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 | Setup official repos with/without backports (deb822 or classic format) |
|
| **3** | [Configure Repositories](/docs/repos_config.md) | Setup official repos with non-free/contrib options, optional Backports support and Deb822/classic format injection.|
|
||||||
| **4** | Setup Wireless & Firmware | Install WiFi firmware for Broadcom, Intel, and other chipsets |
|
| **4** | [Firmware, Wireless & Bluetooth](/docs/firmware.md) | Install essential firmware for GPUs and wireless|
|
||||||
| **5** | Configure Graphics Stack | AMD/Intel/NVIDIA drivers + monitoring tools (`nvtop`, `radeontop`) |
|
| **5** | [Graphics Drivers & Mesa Stack](/docs/gpu.md) | Configure AMD/Intel/NVIDIA drivers and Mesa graphics stack + monitoring tools |
|
||||||
| **6** | Update Kernel to Backports | Install latest stable kernel from Debian backports (7.0+) |
|
| **6** | [Backports Kernel](/docs/kernel.md) | Install latest kernel from Debian backports|
|
||||||
| **7** | Gaming Setup and Performance | Steam, GameMode, MangoHud, Heroic Games Launcher |
|
| **7** | [Gaming Setup ](/docs/gaming.md)| Steam, Heroic Games Launcher, [RetroArch](/docs/retroarch.md) GameMode, MangoHud, OpenRGB, Java JRE (Temurin 8/17/21) |
|
||||||
| **8** | Install ZRAM (compressed swap) | Configure compressed RAM for memory optimization |
|
| **8** | [ZRAM](/docs/zram.md)| Configure compressed RAM for memory optimization|
|
||||||
| **9** | Install Programs and Software | 10 categories: Essential, System, Dev, Players, Internet, Customization, Fetch, Download, Design |
|
| **9** | [Swap Management](/docs/swap.md)| Manage swap file or partition size and enable/disable swap space for system stability|
|
||||||
| **10** | Exit | Return to terminal |
|
| **10** | Install Programs and Software | Browse and install packages by category (Development, Themes, System Tools, etc.) using APT |
|
||||||
|
| **11** | [Boot Rescue + GRUB](/docs/boot.md))| Config and fix GRUB bootloader issues, chroot repair, or restore system boot configuration|
|
||||||
|
| **12** | [Desktop & Display](/docs/desktops_display.md)| Install and configure desktops and display managers|
|
||||||
|
| **13** | Exit | Return to terminal |
|
||||||
|
|
||||||
### Extra Applications Categories (Option 9)
|
### Install Programs and Software (Option 10)
|
||||||
|
|
||||||
- **Essential Pack:** Quick install of common tools (compression, system info, VLC, MS fonts)
|
The submenu offers the next categories:
|
||||||
- **System Tools:** htop, btop, ncdu, timeshift, tmux, flatpak, extrepo, virtualization tools
|
|
||||||
- **Development & Servers:** Docker, Nginx/Apache, PostgreSQL/MariaDB, SSH server, fail2ban, Python
|
| Option | Category Title | Description |
|
||||||
- **Media Players:** VLC, MPV
|
|--------|-------------------------------|-------------|
|
||||||
- **Internet:** Firefox (Mozilla), LibreWolf, Floorp, Chromium, Thunderbird, Riseup VPN, Tor Browser
|
| **0** | Essential Pack | Quick install of common tools (compression, system info, VLC, MS fonts)|
|
||||||
- **Customization → Desktop Themes (GTK/KDE):** Arc, Numix, Breeze GTK, Bluebird, Blackbird, Greybird, Orchis
|
| **1** | Customization System | Desktop themes, icon themes, cursor themes, and fonts |
|
||||||
- **Customization → Icon Themes:** Papirus, Numix, Elementary, Deepin, Suru, Obsidian, Breeze, Moka
|
| **2** | Download & Network | Downloaders (aria2, ytdlp, FileZilla) + Torrent clients (qBittorrent, Deluge, Transmission) |
|
||||||
- **Customization → Cursor Themes:** Bibata, Breeze, Chameleon, DMZ, XCursor, Oxygen
|
| **3** | Internet (Browsers, Email Clients, VPN) | Web browsers (Firefox/Mozilla, LibreWolf, Floorp, Chromium, Brave, Tor), email client (Thunderbird), and VPN tools (RiseUp, Proton, Mullvad)|
|
||||||
- **Customization → Fonts:** Bebas Neue, Anonymous Pro, ADF Verana, 3270, Liberation, MS Core, Ubuntu, Recommended
|
| **4** | Media Players | Multimedia playback with VLC media player and MPV for advanced video/audio support |
|
||||||
- **Fetch Tools:** Neofetch/Fastfetch, hyfetch, Linux logo, Screenfetch
|
| **5** | Multimedia & Design | image editing (GIMP), video editing (Kdenlive, HandBrake), 3D modeling (Blender), audio recording (Audacity), and graphics design (Inkscape) |
|
||||||
- **Downloaders:** aria2, ytdlp, FileZilla
|
| **6** | Code Editors & IDEs | vim, vim-gtk3, Neovim, Helix, nano, Emacs, Kate, Mousepad, Gedit, Geany, GNOME Text Editor, and VSCodium (VS Code open-source) |
|
||||||
- **Torrent Clients:** qBittorrent, Deluge, Transmission, mktorrent
|
| **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 |
|
||||||
- **Multimedia & Design:** GIMP, Kdenlive, Blender, OBS Studio, Audacity, Inkscape, HandBrake
|
| **8** | Security & Networking | Wireshark, tcpdump, Zenmap, ClamAV, UFW, fail2ban |
|
||||||
|
| **9** | Software Centers | Choose a software store to install. |
|
||||||
|
| **10** | Office & Productivity | Choose a software store to install. |
|
||||||
|
| **12** | System Tools | htop/btop, ncdu, Timeshift, tmux/screen, nvme-cli, Flatpak support, extension repository manager and qemu/virtmanager |
|
||||||
|
| **12** | Fetch / System Info | fastfetch/neofetch, hyfetch, Linux logo and screenfetch |
|
||||||
|
| **13** | Back to Main Menu | Return directly to the main Debianito menu (exit submenu) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -89,38 +89,101 @@ After running the script:
|
|||||||
|
|
||||||
| 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. |
|
||||||
| `/modules/` | Modular scripts for specific tasks: `sudo_config`, `repos`, `firmware`, `gpu`, etc. |
|
| `docs/` | Documentation directory containing Markdown files for each module. |
|
||||||
| `/modules/extras/` | Split-by-category sub-modules for the "Install Programs and Software" menu. |
|
| `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/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/gpu/` | GPU driver installation scripts for AMD and NVIDIA with architecture detection. |
|
||||||
|
| `modules/repos/` | Repository management scripts: migration tool (`migrate.sh`) and format detection (`repo_detect.sh`). |
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
├── debianito.sh # Main entry point; menu + system detection
|
├── debianito.sh
|
||||||
└── modules/
|
├── docs
|
||||||
├── utils.sh # System info helpers (CPU/RAM/GPU/WiFi detection)
|
│ ├── firmware.md
|
||||||
├── sudo_config.sh # User group + pwfeedback setup
|
│ ├── gaming.md
|
||||||
├── repos.sh # Repository configuration (classic/deb822 format)
|
│ ├── gpu.md
|
||||||
├── firmware.sh # WiFi microcode and chipset-specific support
|
│ ├── kernel.md
|
||||||
├── gpu.sh # AMD, Intel, NVIDIA driver/firmware handling
|
│ ├── repos_config.md
|
||||||
├── kernel.sh # Update Kernel to Backports with NVIDIA warnings
|
│ ├── retroarch.md
|
||||||
├── gaming.sh # Steam installation & performance tools
|
│ ├── system_info.md
|
||||||
├── extras.sh # Dispatcher for the "Extras" submenu
|
│ ├── user_priv_feed.md
|
||||||
├── extras/ # Category modules (one folder per category)
|
│ └── zram.md
|
||||||
│ ├── _helpers.sh # _inst() / _state() shared helpers
|
├── media
|
||||||
│ ├── essential/essential.sh # One-click essentials pack
|
│ └── gift
|
||||||
│ ├── system/system.sh # System Tools (25 items)
|
│ └── script.gif
|
||||||
│ ├── dev/dev.sh # Development & Servers (15 items)
|
├── modules
|
||||||
│ ├── players/players.sh # Media Players (mpv, vlc)
|
│ ├── bluetooth.sh
|
||||||
│ ├── internet/internet.sh # Browsers, Email, VPN (incl. Mozilla/Floorp/LibreWolf)
|
│ ├── bullseye
|
||||||
│ ├── themes/ # Customization submenu (4 options)
|
│ │ ├── extras.sh
|
||||||
│ │ ├── themes.sh # Submenu dispatcher
|
│ │ ├── legacy.sh
|
||||||
│ │ ├── desktop-themes/desktop-themes.sh # GTK/KDE themes (7)
|
│ │ └── repos.sh
|
||||||
│ │ ├── icons/icons.sh # Icon themes (11-12)
|
│ ├── desktop_display.sh
|
||||||
│ │ ├── cursors/cursors.sh # Cursor themes (6)
|
│ ├── extras
|
||||||
│ │ └── fonts/fonts.sh # Fonts (8)
|
│ │ ├── design
|
||||||
│ ├── fetch/fetch.sh # System info tools (neofetch/fastfetch/hyfetch)
|
│ │ │ └── design.sh
|
||||||
│ ├── download/download.sh # Downloaders + Torrent clients
|
│ │ ├── dev
|
||||||
│ └── design/design.sh # Multimedia & Design (12+ items)
|
│ │ │ ├── dev.sh
|
||||||
└── zram.sh # ZRAM compressed swap configuration
|
│ │ │ └── jellyfin.sh
|
||||||
|
│ │ ├── download
|
||||||
|
│ │ │ └── download.sh
|
||||||
|
│ │ ├── essential
|
||||||
|
│ │ │ └── essential.sh
|
||||||
|
│ │ ├── fetch
|
||||||
|
│ │ │ └── fetch.sh
|
||||||
|
│ │ ├── _helpers.sh
|
||||||
|
│ │ ├── internet
|
||||||
|
│ │ │ └── internet.sh
|
||||||
|
│ │ ├── java.sh
|
||||||
|
│ │ ├── office
|
||||||
|
│ │ │ └── office.sh
|
||||||
|
│ │ ├── players
|
||||||
|
│ │ │ └── players.sh
|
||||||
|
│ │ ├── programming
|
||||||
|
│ │ │ └── programming.sh
|
||||||
|
│ │ ├── security
|
||||||
|
│ │ │ └── security.sh
|
||||||
|
│ │ ├── system
|
||||||
|
│ │ │ ├── software_centers.sh
|
||||||
|
│ │ │ └── system.sh
|
||||||
|
│ │ └── themes
|
||||||
|
│ │ ├── cursors
|
||||||
|
│ │ │ └── cursors.sh
|
||||||
|
│ │ ├── desktop-themes
|
||||||
|
│ │ │ └── desktop-themes.sh
|
||||||
|
│ │ ├── fonts
|
||||||
|
│ │ │ └── fonts.sh
|
||||||
|
│ │ ├── icons
|
||||||
|
│ │ │ └── icons.sh
|
||||||
|
│ │ └── themes.sh
|
||||||
|
│ ├── extras.sh
|
||||||
|
│ ├── firmware.sh
|
||||||
|
│ ├── gaming
|
||||||
|
│ │ ├── _helpers.sh
|
||||||
|
│ │ ├── heroic.sh
|
||||||
|
│ │ ├── steam.sh
|
||||||
|
│ │ └── tools.sh
|
||||||
|
│ ├── gaming.sh
|
||||||
|
│ ├── gpu
|
||||||
|
│ │ ├── amd_intel.sh
|
||||||
|
│ │ ├── _helpers.sh
|
||||||
|
│ │ └── nvidia.sh
|
||||||
|
│ ├── gpu.sh
|
||||||
|
│ ├── kernel.sh
|
||||||
|
│ ├── repos
|
||||||
|
│ │ ├── migrate.sh
|
||||||
|
│ │ └── repo_detect.sh
|
||||||
|
│ ├── repos.sh
|
||||||
|
│ ├── rescue.sh
|
||||||
|
│ ├── sudo_config.sh
|
||||||
|
│ ├── swap.sh
|
||||||
|
│ ├── sysinfo.sh
|
||||||
|
│ ├── utils.sh
|
||||||
|
│ └── zram.sh
|
||||||
|
└── README.md
|
||||||
```
|
```
|
||||||
> 🤖 AI-Assisted Development Note
|
---
|
||||||
This project was developed with assistance from large language models for code generation, documentation and testing suggestions. The author takes full responsibility for the accuracy of all scripts included in this repository. All modifications have been reviewed manually before inclusion to ensure compatibility with Debian systems.
|
|
||||||
|
> 🤖 **AI-Assisted Development Note**
|
||||||
|
> This project was developed with assistance from large language models for code generation, documentation and testing suggestions. The author takes full responsibility for the accuracy of all scripts included in this repository. All modifications have been reviewed manually before inclusion to ensure compatibility with Debian systems.
|
||||||
|
|||||||
+97
-42
@@ -16,14 +16,28 @@ 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"
|
||||||
source "${MODULES_DIR}/sudo_config.sh"
|
source "${MODULES_DIR}/sudo_config.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}/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}/rescue.sh" ] && source "${MODULES_DIR}/rescue.sh"
|
||||||
|
[ -f "${MODULES_DIR}/swap.sh" ] && source "${MODULES_DIR}/swap.sh"
|
||||||
|
[ -f "${MODULES_DIR}/desktop_display.sh" ] && source "${MODULES_DIR}/desktop_display.sh"
|
||||||
|
|
||||||
|
# ── Bullseye-specific modules (loaded only on Debian 11) ──
|
||||||
|
if [ -d "${MODULES_DIR}/bullseye" ]; then
|
||||||
|
[ -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/extras.sh" ] && source "${MODULES_DIR}/bullseye/extras.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
REPOS_CONFIGURED=false
|
REPOS_CONFIGURED=false
|
||||||
DEBIAN_VERSION=""
|
DEBIAN_VERSION=""
|
||||||
@@ -31,76 +45,117 @@ DEBIAN_CODENAME=""
|
|||||||
|
|
||||||
main_menu() {
|
main_menu() {
|
||||||
# Auto-adjust TUI dimensions for small terminals
|
# Auto-adjust TUI dimensions for small terminals
|
||||||
if [ "$LINES" -lt $((TUI_ALTO + 6)) ] || [ "$COLUMNS" -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 - 4 > 8 ? LINES - 4 : 8))
|
||||||
TUI_ANCHO=$((COLUMNS - 4 > 50 ? COLUMNS - 4 : 50))
|
TUI_ANCHO=$((COLUMNS - 4 > 50 ? COLUMNS - 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
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
|
sudo -v >/dev/null 2>&1 || true
|
||||||
|
local STATE_REFRESHED=false
|
||||||
local choice
|
local choice
|
||||||
choice=$(whiptail --title "DEBIANITO — simple configurator script" --menu "" \
|
choice=$(_menu "DEBIANITO — Simple Configurator Script" "" \
|
||||||
$TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
$TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
||||||
"1" "System Info" \
|
"1" "System Information" \
|
||||||
"2" "User Privileges & Feedback" \
|
"2" "User Privileges & Feedback" \
|
||||||
"3" "Configure repositories" \
|
"3" "Configure Repositories" \
|
||||||
"4" "Wireless & Firmware" \
|
"4" "Firmware, Wireless & Bluetooth" \
|
||||||
"5" "Graphics Stack" \
|
"5" "Graphics Drivers & Mesa Stack" \
|
||||||
"6" "Backports Kernel" \
|
"6" "Backports Kernel" \
|
||||||
"7" "Gaming Setup" \
|
"7" "Gaming Setup" \
|
||||||
"8" "ZRAM (Swap)" \
|
"8" "ZRAM" \
|
||||||
"9" "Install Programs and Software" \
|
"9" "Swap Management" \
|
||||||
"10" "Exit" \
|
"10" "Install Programs and Software" \
|
||||||
3>&1 1>&2 2>&3)
|
"11" "Boot Rescue + GRUB" \
|
||||||
|
"12" "Desktop & Display" \
|
||||||
|
"13" "Exit")
|
||||||
|
|
||||||
clear
|
clear
|
||||||
|
|
||||||
case "$choice" in
|
case "$choice" in
|
||||||
1) _show_sysinfo ;;
|
1) _show_sysinfo ;;
|
||||||
2) config_sudo || true ;;
|
2) config_sudo || true ;;
|
||||||
3) configure_repos || true ;;
|
3)
|
||||||
4) install_firmware || true ;;
|
if [ "$DEBIAN_VERSION" = "11" ] && type configure_repos_bullseye &>/dev/null; then
|
||||||
5) install_gpu_drivers || true ;;
|
configure_repos_bullseye || true
|
||||||
6) install_kernel_backports || true ;;
|
|
||||||
7) install_gaming || true ;;
|
|
||||||
8) install_zram || true ;;
|
|
||||||
9) install_extras || true ;;
|
|
||||||
10) echo "Exiting."; exit 0 ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
_show_sysinfo() {
|
|
||||||
local gpu_info="${GPU_DESC}"
|
|
||||||
[ -n "$GPU_VERSION" ] && gpu_info+=" (${GPU_VERSION})"
|
|
||||||
|
|
||||||
local network_info
|
|
||||||
if [ -n "$ETH_DESC" ] && [ -n "$WIFI_DESC" ]; then
|
|
||||||
network_info="Ethernet: ${ETH_DESC}\nWiFi: ${WIFI_DESC}"
|
|
||||||
elif [ -n "$ETH_DESC" ]; then
|
|
||||||
network_info="${ETH_DESC}"
|
|
||||||
elif [ -n "$WIFI_DESC" ]; then
|
|
||||||
network_info="${WIFI_DESC}"
|
|
||||||
else
|
else
|
||||||
network_info="No adapters detected"
|
configure_repos || true
|
||||||
fi
|
fi
|
||||||
|
STATE_REFRESHED=true
|
||||||
_msg "System Information" \
|
;;
|
||||||
"Debian: ${DEBIAN_VERSION} (${DEBIAN_CODENAME})
|
4)
|
||||||
Kernel: ${KERNEL_VERSION}
|
if [ "$DEBIAN_VERSION" = "11" ] && type install_firmware_bullseye &>/dev/null; then
|
||||||
CPU: $(get_cpu_summary)
|
install_firmware_bullseye || true
|
||||||
RAM: $(get_ram_summary)
|
else
|
||||||
GPU: ${gpu_info}
|
install_firmware || true
|
||||||
Network: ${network_info}" 13 65
|
fi
|
||||||
|
;;
|
||||||
|
5) install_gpu_drivers || true; STATE_REFRESHED=true ;;
|
||||||
|
6)
|
||||||
|
if [ "$DEBIAN_VERSION" = "11" ]; then
|
||||||
|
_msg "Not Available" \
|
||||||
|
"Backports Kernel is not available on Debian 11 Bullseye.\n\n\
|
||||||
|
Ultra Minimalist Rescue Mode does not include third-party\n\
|
||||||
|
kernels. Use the stable kernel provided by Bullseye." 10 60
|
||||||
|
else
|
||||||
|
install_kernel_backports || true
|
||||||
|
fi
|
||||||
|
STATE_REFRESHED=true
|
||||||
|
;;
|
||||||
|
7)
|
||||||
|
if [ "$DEBIAN_VERSION" = "11" ] && type install_gaming_bullseye &>/dev/null; then
|
||||||
|
install_gaming_bullseye || true
|
||||||
|
else
|
||||||
|
install_gaming || true
|
||||||
|
fi
|
||||||
|
STATE_REFRESHED=true
|
||||||
|
;;
|
||||||
|
8) install_zram || true ;;
|
||||||
|
9) manage_swap || true; STATE_REFRESHED=true ;;
|
||||||
|
10)
|
||||||
|
if [ "$DEBIAN_VERSION" = "11" ] && type install_extras_bullseye &>/dev/null; then
|
||||||
|
install_extras_bullseye || true
|
||||||
|
else
|
||||||
|
install_extras || true
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
11) rescue_boot || true ;;
|
||||||
|
12) manage_desktop_display || true ;;
|
||||||
|
13) echo "Exiting."; exit 0 ;;
|
||||||
|
esac
|
||||||
|
if $STATE_REFRESHED; then
|
||||||
|
refresh_system_state
|
||||||
|
fi
|
||||||
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
check_root
|
check_root
|
||||||
check_sudo
|
check_sudo
|
||||||
|
if ! _check_network; then
|
||||||
|
echo -e "${YELLOW}──────────────────────────────────────────${NC}"
|
||||||
|
echo -e "${YELLOW} No internet connectivity detected.${NC}"
|
||||||
|
echo -e "${YELLOW} Package installation will fail without network.${NC}"
|
||||||
|
echo -e "${YELLOW} You can use: System Info, User Privileges, and${NC}"
|
||||||
|
echo -e "${YELLOW} other offline features.${NC}"
|
||||||
|
echo -e "${YELLOW}──────────────────────────────────────────${NC}"
|
||||||
|
fi
|
||||||
|
check_system_time
|
||||||
|
|
||||||
detect_debian_version
|
detect_debian_version
|
||||||
detect_cpu_ram
|
detect_cpu_ram
|
||||||
detect_kernel
|
detect_kernel
|
||||||
detect_gpu
|
detect_gpu
|
||||||
detect_network
|
detect_network
|
||||||
|
detect_displayserver
|
||||||
|
detect_storage
|
||||||
|
detect_desktop_environment
|
||||||
|
_configure_lightdm
|
||||||
|
detect_audio_server
|
||||||
|
|
||||||
|
# ── Bullseye-specific init (archive phase) ──
|
||||||
|
if [ "$DEBIAN_VERSION" = "11" ] && type check_bullseye_archive_phase &>/dev/null; then
|
||||||
|
check_bullseye_archive_phase
|
||||||
|
fi
|
||||||
|
|
||||||
main_menu
|
main_menu
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
## Option 11: Boot Rescue & Repair
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
|
### 2. Logical Execution Flow
|
||||||
|
|
||||||
|
**Block 1 — GRUB Boot Menu Settings**
|
||||||
|
- **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).
|
||||||
|
2. Show 3-second countdown (Faster boot).
|
||||||
|
3. Show menu for 5 seconds (Default behavior).
|
||||||
|
4. Custom timeout (User inputs specific seconds; -1 allows indefinite wait).
|
||||||
|
- **Variable Application:** Each selection updates three core variables: `GRUB_TIMEOUT`, `GRUB_TIMEOUT_STYLE`, and `GRUB_RECORDFAIL_TIMEOUT`. The custom option also allows setting `GRUB_DISABLE_OS_PROBER` to prevent extra entries.
|
||||||
|
- **Backup & Safety:** Before applying changes, the script creates a timestamped backup of `/etc/default/grub`. It writes an override configuration file at `/etc/default/grub.d/99_script_override.cfg` to ensure settings persist across updates.
|
||||||
|
- **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**
|
||||||
|
- **Pre-checks:** Before proceeding, the script verifies two conditions:
|
||||||
|
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).
|
||||||
|
- **Skip Logic:** If either check fails, the process stops immediately with a message indicating no repair is needed or applicable.
|
||||||
|
- **Repair Steps:** Upon user confirmation:
|
||||||
|
1. Reinstalls signed boot packages (`shim-signed`, `grub-efi-amd64-signed`, `linux-image-amd64`).
|
||||||
|
2. Reinstalls GRUB to the EFI partition using `grub-install` with the appropriate target and directory detection (preferring `/boot/efi` over `/boot`).
|
||||||
|
3. Regenerates the GRUB configuration via `update-grub`.
|
||||||
|
|
||||||
|
**Block 3 — Initramfs Regeneration**
|
||||||
|
- **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.
|
||||||
|
- **Purpose:** This fixes boot issues caused by missing drivers or corrupted initrd images that prevent the system from loading properly.
|
||||||
|
|
||||||
|
### 3. Intelligent Automation
|
||||||
|
|
||||||
|
- **EFI Directory Detection:** The script intelligently detects the EFI partition, checking `/boot/efi` first and falling back to `/boot` if necessary.
|
||||||
|
- **Secure Boot State Verification:** Instead of assuming Secure Boot is active, it uses `mokutil --sb-state` to verify the actual state before attempting repairs on non-UEFI or disabled systems.
|
||||||
|
- **GRUB Backup Strategy:** A timestamped backup file (e.g., `/etc/default/grub.backup.YYYYMMDD_HHMMSS`) is created prior to any modification, ensuring a safe point for rollback.
|
||||||
|
- **Rollback Mechanism:** If `update-grub` fails during the GRUB settings or Secure Boot repair process, the script automatically restores the backup and cleans up temporary override files.
|
||||||
|
- **Override Persistence:** Configuration values are written to `/etc/default/grub.d/99_script_override.cfg`, ensuring that changes survive package updates which might otherwise reset `/etc/default/grub`.
|
||||||
|
- **Input Validation:** Custom timeout inputs are validated using regex matching for integers (e.g., `^-?[0-9]+$`), allowing negative numbers like -1 while rejecting invalid text.
|
||||||
|
- **Variable Handling Logic:** The `_set_grub_var()` function handles three distinct cases: updating an existing variable, uncommenting a commented variable, or appending a new variable if it does not exist in the configuration file.
|
||||||
|
|
||||||
|
### 4. Paquetes y Recursos Gestionados
|
||||||
|
|
||||||
|
**Boot Packages Reinstalled (Secure Boot Repair):**
|
||||||
|
| Package | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| shim-signed | UEFI Secure Boot shim (first-stage bootloader) |
|
||||||
|
| grub-efi-amd64-signed | Signed GRUB for UEFI |
|
||||||
|
| linux-image-amd64 | Kernel image (re-signed) |
|
||||||
|
|
||||||
|
**GRUB Settings Modified:**
|
||||||
|
| Variable | Option 1 | Option 2 | Option 3 | Custom |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| GRUB_TIMEOUT | 0 | 3 | 5 | User value |
|
||||||
|
| GRUB_TIMEOUT_STYLE | hidden | menu | menu | menu |
|
||||||
|
| GRUB_RECORDFAIL_TIMEOUT | 0 | 3 | 5 | User value |
|
||||||
|
| GRUB_DISABLE_OS_PROBER | true | — | — | — |
|
||||||
|
|
||||||
|
**System Files Modified:**
|
||||||
|
| Package | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| /etc/default/grub | Main GRUB configuration |
|
||||||
|
| /etc/default/grub.d/99_script_override.cfg | Persistent override (survives grub updates) |
|
||||||
|
| /etc/default/grub.backup.* | Timestamped backup (auto-created) |
|
||||||
|
|
||||||
|
>**Note UEFI:** The Secure Boot repair ONLY works on UEFI systems. The script checks for `/sys/firmware/efi` and `mokutil --sb-state` before attempting anything. Legacy BIOS systems are automatically skipped.
|
||||||
|
|
||||||
|
>**Note GRUB:** After hiding the GRUB menu (Option 1), you must hold ESC immediately after powering on to access the menu. There is no other way to reach it during boot.
|
||||||
|
|
||||||
|
> **Technical data:** The override file at `/etc/default/grub.d/99_script_override.cfg` persists across kernel updates because GRUB reads drop-in configs from that directory. This is more reliable than editing `/etc/default/grub` directly for values that should survive updates.
|
||||||
|
|
||||||
|
> **Technical data:** `GRUB_DISABLE_OS_PROBER=true` is set when hiding the menu to prevent OS prober from adding extra entries that would require the menu to appear. For multi-boot systems, use Option 3 or Custom instead.
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
## Option 12: Desktop & Display
|
||||||
|
|
||||||
|
### 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".
|
||||||
|
|
||||||
|
### 2. Logical Flow of Execution
|
||||||
|
The execution logic is divided into five functional blocks:
|
||||||
|
|
||||||
|
**Block 1 — Display Manager Selection**
|
||||||
|
- 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.
|
||||||
|
- **Available Managers:**
|
||||||
|
- LightDM (available on all Debian versions).
|
||||||
|
- GDM3 (available on all Debian versions).
|
||||||
|
- SDDM (available on all Debian versions).
|
||||||
|
- greetd (available only on Debian 12 and 13).
|
||||||
|
- Each selected manager opens its own dedicated configuration submenu.
|
||||||
|
|
||||||
|
**Block 2 — LightDM Configuration**
|
||||||
|
- A checklist menu presents three options:
|
||||||
|
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`).
|
||||||
|
3. Enable autologin for current user (uncomments `autologin-user` and sets timeout to 0 in the main config).
|
||||||
|
- **Idempotency:** The script checks if `lightdm` and `lightdm-gtk-greeter-settings` are already installed before attempting installation, skipping redundant steps.
|
||||||
|
|
||||||
|
**Block 3 — GDM3 Configuration**
|
||||||
|
- A checklist menu presents up to four options:
|
||||||
|
1. Install/Reinstall gdm3 (auto-selects via debconf).
|
||||||
|
2. Toggle user list visibility (toggles `disable-user-list` in greeter.dconf-defaults).
|
||||||
|
3. Configure autologin (prompts for a username via whiptail inputbox to set in daemon.conf).
|
||||||
|
4. Force Enable Wayland on NVIDIA (Bookworm/Trixie + NVIDIA only).
|
||||||
|
- **Mechanism:** Creates or removes a symlink: `/etc/udev/rules.d/61-gdm.rules` → `/dev/null`.
|
||||||
|
- **Purpose:** This disables the udev rule that blocks GDM from using Wayland on NVIDIA GPUs.
|
||||||
|
- **Risk Warning:** Displays a warning that this may break graphics or cause instability.
|
||||||
|
- **Toggle Behavior:** If the symlink exists, removing it reverts to default behavior; if not present, creating it enables the override.
|
||||||
|
|
||||||
|
**Block 4 — SDDM Configuration**
|
||||||
|
- A submenu offers two options:
|
||||||
|
1. Install SDDM (auto-selects via debconf).
|
||||||
|
2. Enable Autologin:
|
||||||
|
- **Session Detection:** Auto-detects the installed session by checking `.desktop` files in priority order: `plasmawayland` → `lxqt-wayland` → `plasma` → `lxqt`.
|
||||||
|
- **Configuration:** Writes autologin settings to `/etc/sddm.conf.d/autologin.conf`.
|
||||||
|
- **Fallback:** If no session is found, it enables autologin but warns that SDDM will use the default session.
|
||||||
|
|
||||||
|
**Block 5 — greetd Configuration**
|
||||||
|
- greetd is a minimal, modern display manager designed for Wayland environments.
|
||||||
|
- Submenu options vary by Debian version:
|
||||||
|
- **All Versions:** Install base `greetd`, Install `greetd` + `tuigreet` (recommended TUI greeter).
|
||||||
|
- **Debian 13 only:** Additional options to install `gtk-greet`, `nwg-hello`, or `wlgreet`.
|
||||||
|
- **Backports Handling:** On Bookworm, `tuigreet` is installed from backports if not enabled.
|
||||||
|
- **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
|
||||||
|
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.
|
||||||
|
- **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.
|
||||||
|
- **greetd Backports:** On Bookworm, `tuigreet` is installed from backports (newer version) if not already enabled in the system.
|
||||||
|
- **Manual Config Warning:** The script explicitly informs users that greetd requires manual configuration and points to man pages for further details.
|
||||||
|
- **User Detection:** Uses `SUDO_USER` (the real user who ran sudo) instead of `$USER` (which is root during script execution). This ensures the correct user is set for automatic login across all display managers.
|
||||||
|
|
||||||
|
### 4. Packages and Resources Managed
|
||||||
|
|
||||||
|
**Display Manager Packages:**
|
||||||
|
| DM | Packages | Debian Versions |
|
||||||
|
|---|---|---|
|
||||||
|
| LightDM | lightdm, lightdm-gtk-greeter, lightdm-gtk-greeter-settings | All |
|
||||||
|
| GDM3 | gdm3 | All |
|
||||||
|
| SDDM | sddm | All |
|
||||||
|
| greetd (base) | greetd | 12, 13 |
|
||||||
|
| greetd + tuigreet | greetd, tuigreet | 12 (backports), 13 |
|
||||||
|
| greetd + gtk-greet | greetd, gtk-greet | 13 only |
|
||||||
|
| greetd + nwg-hello | greetd, nwg-hello | 13 only |
|
||||||
|
| greetd + wlgreet | greetd, wlgreet | 13 only |
|
||||||
|
|
||||||
|
**Configuration Files Modified:**
|
||||||
|
| DM | File Path | Configuration Purpose |
|
||||||
|
|---|---|---|
|
||||||
|
| LightDM | /etc/lightdm/lightdm.conf.d/50-debianito-userlist.conf | User list visibility toggle |
|
||||||
|
| LightDM | /etc/lightdm/lightdm.conf | Autologin user + timeout settings |
|
||||||
|
| GDM3 | /etc/gdm3/greeter.dconf-defaults | User list toggle (disable-user-list) |
|
||||||
|
| GDM3 | /etc/gdm3/daemon.conf | Autologin user and enable flag |
|
||||||
|
| GDM3 | /etc/udev/rules.d/61-gdm.rules | Wayland override (symlink to /dev/null) |
|
||||||
|
| SDDM | /etc/sddm.conf.d/autologin.conf | Autologin user + session type |
|
||||||
|
|
||||||
|
**Session Detection Priority (SDDM Autologin):**
|
||||||
|
| Priority | Session File | Session Type |
|
||||||
|
|---|---|---|
|
||||||
|
| 1 | /usr/share/wayland-sessions/plasmawayland.desktop | KDE Wayland |
|
||||||
|
| 2 | /usr/share/wayland-sessions/lxqt-wayland.desktop | LXQt Wayland |
|
||||||
|
| 3 | /usr/share/xsessions/plasma.desktop | KDE X11 |
|
||||||
|
| 4 | /usr/share/xsessions/lxqt.desktop | LXQt X11 |
|
||||||
|
|
||||||
|
> ⚠️ **Warning: Wayland on NVIDIA:** The "Force Enable Wayland on NVIDIA" option creates a symlink that disables the GDM udev rule. This is a known workaround but MAY cause graphics instability or breakage. To revert, remove `/etc/udev/rules.d/61-gdm.rules`.
|
||||||
|
|
||||||
|
> ⚠️ **Warning: greetd:** Unlike other display managers, greetd is installed but NOT configured by this script. You MUST manually create `/etc/greetd/config.toml` before you can log in. See `man greetd` and `man 5 greetd-sessions` for configuration details.
|
||||||
|
|
||||||
|
> ⚠️ **Warning: Autologin:** All autologin configurations use `SUDO_USER` (the user who ran sudo) instead of `$USER` (which is root during script execution). This ensures the correct user is set for automatic login.
|
||||||
|
|
||||||
|
> 💡 **Technical Note:** `debconf-set-selections` pre-selects the display manager before apt install, preventing the interactive "Configuring shared/default-x-display-manager" dialog that would otherwise pause the script.
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# Option 4: Advanced Firmware & Wireless Architecture
|
||||||
|
|
||||||
|
## 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).
|
||||||
|
|
||||||
|
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)
|
||||||
|
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.
|
||||||
|
* **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.
|
||||||
|
|
||||||
|
## 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:
|
||||||
|
|
||||||
|
* **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:**
|
||||||
|
* **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).
|
||||||
|
* **Realtek Hardware** ➔ `firmware-realtek`.
|
||||||
|
* **MediaTek / Ralink Hardware** ➔ `firmware-mediatek`.
|
||||||
|
* **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.
|
||||||
|
|
||||||
|
## 4. Installation Execution Flow (Atomic Pipeline)
|
||||||
|
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.
|
||||||
|
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):**
|
||||||
|
* 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).
|
||||||
|
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)
|
||||||
|
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.
|
||||||
|
* **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.
|
||||||
|
|
||||||
|
## 6. Bluetooth Stack Integration
|
||||||
|
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.
|
||||||
|
* **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:
|
||||||
|
* **KDE:** Installs `bluedevil` and optionally `pipewire-pulse` + `wireplumber` for Pipewire audio server integration.
|
||||||
|
* **GNOME:** Uses built-in GNOME Bluetooth support in `gnome-control-center`.
|
||||||
|
* **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.
|
||||||
|
|
||||||
|
This modular approach keeps Bluetooth handling separate from network firmware while maintaining tight integration through shared device detection arrays and coordinated installation flow.
|
||||||
+150
@@ -0,0 +1,150 @@
|
|||||||
|
## Option 7: Gaming Ecosystem, Performance Tweaks & Runtimes
|
||||||
|
|
||||||
|
### 1. Philosophy of the Gaming Environment in Debian
|
||||||
|
|
||||||
|
The Debianito gaming module transforms a server-grade Debian installation into a dedicated gaming station by carefully isolating dependencies and configuring compatibility layers without compromising system stability. The core philosophy follows three principles:
|
||||||
|
|
||||||
|
**Dependency Isolation:** All gaming-specific packages (Steam, Heroic, Mesa 32-bit libraries) are installed in user-space where possible, preventing conflicts with base system packages. The `steam-installer` package from Debian's contrib section is used as the bootstrap mechanism rather than Valve's official repository for stability reasons—this ensures compatibility with Debian's package management and reduces update complexity.
|
||||||
|
|
||||||
|
**Compatibility Layer Configuration:** Proton/Wine support is enabled through automatic installation of required 32-bit libraries (`libgl1-mesa-dri:i386`, `mesa-vulkan-drivers:i386`) that are mandatory for running Windows-only games on Linux. The module detects GPU architecture and installs appropriate drivers (NVIDIA proprietary, AMD open-source, Intel built-in) before attempting any launcher installation.
|
||||||
|
|
||||||
|
**Stability Over Features:** Unlike gaming-focused distributions that prioritize bleeding-edge kernels or unstable repositories, Debianito maintains the stability of Debian Stable while providing necessary backports for Mesa 32-bit support when available. This ensures long-term compatibility with games and launchers without risking system breakage from aggressive updates.
|
||||||
|
|
||||||
|
The module architecture separates concerns into distinct scripts (`steam.sh`, `heroic.sh`, `tools.sh`) that can be sourced independently, allowing users to enable only the components they need while maintaining a clean, auditable installation history.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Launchers and Compatibility Layers (Steam & Heroic)
|
||||||
|
|
||||||
|
**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:
|
||||||
|
```bash
|
||||||
|
apt install mesa-vulkan-drivers libglx-mesa0:i386 mesa-vulkan-drivers:i386 \
|
||||||
|
libgl1-mesa-dri:i386 libegl-mesa0:i386 mesa-va-drivers:i386
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Runtime Dependency Chain:** The `steam-installer` package depends on several critical components:
|
||||||
|
- `debconf` and `cdebconf` for configuration management
|
||||||
|
- `default-dbus-session-bus` for inter-process communication
|
||||||
|
- `lsof` for file listing utilities
|
||||||
|
- `zenity` or `yad` for graphical dialogs
|
||||||
|
- `steam-libs` and `steam-libs-i386` metapackages
|
||||||
|
|
||||||
|
3. **Self-Update Mechanism:** The installed Steam launcher includes a minimal version capable of downloading full updates automatically, reducing manual intervention requirements.
|
||||||
|
|
||||||
|
**Heroic Games Launcher Management:** Unlike Steam's Debian package approach, Heroic requires direct download from GitHub releases due to its rapid iteration cycle. The `install_heroic()` function in `heroic.sh` implements:
|
||||||
|
|
||||||
|
1. **Release Detection:** Uses GitHub API to identify the latest amd64 `.deb` release dynamically
|
||||||
|
2. **Dependency Pre-installation:** Ensures `curl` and `wget` are available before attempting download
|
||||||
|
3. **Temporary File Handling:** Downloads to `/tmp/heroic.deb`, validates file integrity, then installs via apt
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gh_url=$(curl -s --connect-timeout 10 https://api.github.com/repos/Heroic-Games-Launcher/\
|
||||||
|
HeroicGamesLauncher/releases/latest | \
|
||||||
|
grep -oP 'https://[^"]+amd64\.deb' | head -1)
|
||||||
|
```
|
||||||
|
|
||||||
|
This approach ensures users always get the latest stable release while maintaining compatibility with Debian's package verification mechanisms. The script also supports Flatpak alternatives for users who prefer sandboxed installations through Flathub.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Optimization Engine and Telemetry (GameMode & MangoHud)
|
||||||
|
|
||||||
|
**Feral GameMode Daemon:** When a game launches with `gamemoderun`, the Feral GameMode daemon performs several critical optimizations at the kernel level:
|
||||||
|
|
||||||
|
1. **CPU Scheduler Priority:** Adjusts scheduling policies to prioritize gaming processes over background tasks, reducing latency spikes during gameplay
|
||||||
|
2. **I/O Priority Management:** Increases I/O priority for game processes while deprioritizing non-essential system operations (updates, backups)
|
||||||
|
3. **Kernel Governor Tuning:** Forces CPU governor to Performance mode when games are detected, eliminating frequency scaling delays
|
||||||
|
4. **Screensaver Inhibition:** Prevents screensavers from activating during gaming sessions
|
||||||
|
|
||||||
|
The `install_gamemode()` function in `tools.sh` ensures the daemon is available system-wide:
|
||||||
|
```bash
|
||||||
|
_run_install gamemode
|
||||||
|
```
|
||||||
|
|
||||||
|
This allows users to wrap game launch commands with `gamemoderun %command%` for automatic optimization without manual configuration.
|
||||||
|
|
||||||
|
**MangoHud + goverlay Integration:** MangoHud provides real-time performance telemetry through Vulkan/OpenGL overlays that render directly into the game window:
|
||||||
|
|
||||||
|
1. **FPS Counter:** Displays current and average frames per second
|
||||||
|
2. **Temperature Monitoring:** Tracks CPU/GPU temperatures in real-time
|
||||||
|
3. **Memory Usage:** Shows VRAM, RAM, and swap utilization metrics
|
||||||
|
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:
|
||||||
|
```bash
|
||||||
|
if dpkg --print-foreign-architectures | grep -q i386; then
|
||||||
|
echo "Installing 32-bit MangoHud..."
|
||||||
|
_run_cmd "MangoHud" "sudo apt install -y mangohud:i386"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
The `goverlay` component extends this functionality by integrating with Wayland compositors for smoother overlay behavior on modern desktop environments. Both tools work together to provide comprehensive performance visibility without requiring game-specific configuration.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Peripheral Control and RGB Lighting (OpenRGB)
|
||||||
|
|
||||||
|
**Secure Hardware Access:** OpenRGB requires direct communication with hardware peripherals through the I2C bus, which traditionally required root privileges. The `install_openrgb()` function implements several security measures:
|
||||||
|
|
||||||
|
1. **udev Rule Configuration:** Reloads udev rules to properly identify and manage I2C devices without requiring elevated permissions during runtime
|
||||||
|
2. **Module Loading:** Ensures `i2c-dev` module is loaded and added to `/etc/modules` for persistence across reboots
|
||||||
|
3. **Group Membership:** Adds the user to the `i2c` group via `usermod -aG i2c "$USER"` so OpenRGB can access hardware without root
|
||||||
|
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:
|
||||||
|
```bash
|
||||||
|
if [ "$DEBIAN_VERSION" = "12" ]; then
|
||||||
|
url="https://codeberg.org/OpenRGB/OpenRGB/releases/download/release_candidate_1.0rc2/openrgb_1.0rc2_amd64_bookworm_0fca93e.deb"
|
||||||
|
elif [ "$DEBIAN_VERSION" = "13" ]; then
|
||||||
|
url="https://codeberg.org/OpenRGB/OpenRGB/releases/download/release_candidate_1.0rc2/openrgb_1.0rc2_amd64_trixie_0fca93e.deb"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
This approach eliminates the security risk of running OpenRGB as root while maintaining full hardware control for RGB peripherals, RAM modules, and motherboard lighting systems. Users must log out/in or reboot after installation to apply group membership changes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. Java Runtimes (Eclipse Temurin 8 / 17 / 21)
|
||||||
|
|
||||||
|
**Multi-Version Support:** The gaming module provides three specific Eclipse Temurin versions to accommodate different game requirements:
|
||||||
|
|
||||||
|
| Version | Use Case | Justification |
|
||||||
|
|---------|----------|---------------|
|
||||||
|
| **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 21** | Latest game engines, cutting-edge mods | Provides best performance for modern 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:
|
||||||
|
|
||||||
|
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.
|
||||||
|
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:
|
||||||
|
|
||||||
|
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
|
||||||
|
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`).
|
||||||
|
|
||||||
|
|
||||||
|
### References:
|
||||||
|
|
||||||
|
- [https://wiki.debian.org/Steam](https://wiki.debian.org/Steam)
|
||||||
|
- [wiki.archlinux.org/title/Steam](wiki.archlinux.org/title/Steam)
|
||||||
|
- [https://repo.steampowered.com/steam/](https://repo.steampowered.com/steam/)
|
||||||
|
- [https://www.protondb.com/](https://www.protondb.com/)
|
||||||
|
- [https://github.com/lutris/lutris](https://github.com/lutris/lutris)
|
||||||
|
- [https://github.com/lutris/docs/blob/master/InstallingDrivers.md](https://github.com/lutris/docs/blob/master/InstallingDrivers.md)
|
||||||
|
- [https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher](https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher)
|
||||||
|
- [https://github.com/flightlessmango/Mangohud](https://github.com/flightlessmango/Mangohud)
|
||||||
|
- [https://github.com/feralinteractive/gamemode](https://github.com/feralinteractive/gamemode)
|
||||||
|
- [https://gitlab.com/CalcProgrammer1/OpenRGB](https://gitlab.com/CalcProgrammer1/OpenRGB)
|
||||||
|
- [https://adoptium.net/es/installation/linux](https://adoptium.net/es/installation/linux)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+251
@@ -0,0 +1,251 @@
|
|||||||
|
## Option 5: Graphics Drivers, Mesa Stack & Display Architecture
|
||||||
|
|
||||||
|
### 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:
|
||||||
|
|
||||||
|
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.
|
||||||
|
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.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. The Automatic GPU Detection Pipeline
|
||||||
|
|
||||||
|
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:**
|
||||||
|
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:
|
||||||
|
* `GPU_TYPE`: Set to `"intel"`, `"amd"`, or `"nvidia"`. If no GPU is found, it defaults to `"unknown"` (common in VMs or headless servers).
|
||||||
|
* `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
|
||||||
|
if [ "$GPU_TYPE" = "unknown" ]; then
|
||||||
|
# Install generic Mesa stack (Safe fallback)
|
||||||
|
install_mesa_generic_stack
|
||||||
|
elif $HAS_INTEL; then
|
||||||
|
# Route to Intel-specific logic (i915/Xe, VAAPI selection)
|
||||||
|
install_intel_firmware && offer_intel_tools
|
||||||
|
elif $HAS_AMD; then
|
||||||
|
# Route to AMD-specific logic (amdgpu/radeonsi)
|
||||||
|
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.
|
||||||
|
* 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.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. **Intel Graphics Hardware**
|
||||||
|
|
||||||
|
| Architecture / Gen | Process Node | iGPU / dGPU | Kernel Driver (KMD) | OpenGL Driver | Vulkan Driver | Notes |
|
||||||
|
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
||||||
|
| **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. |
|
||||||
|
| **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** (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). |
|
||||||
|
| **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.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. |
|
||||||
|
| **Gen11** (Ice Lake) | 10nm | UHD Graphics G1, Iris Plus G4/G7 | `i915` | `iris` | `anv` | First architecture at 10nm. Vulkan 1.3+ support. |
|
||||||
|
| **Gen12** (Xe-LP) (Tiger Lake, Alder Lake, Raptor Lake) | Intel 7 (10nm ESF) | Iris Xe G7, UHD Graphics 770/730 | `i915/xe` | `iris` | `anv` | Renamed to "Iris Xe". Vulkan 1.3 support. The xe module has technical support but i915 remains the standard and more stable for this generation. |
|
||||||
|
| **Xe-LPG** (Meteor Lake) | TSMC N5 | Arc Graphics (8 Xe-Cores) | `i915/xe` | `iris` | `anv` | First tile-based architecture iGPU. |
|
||||||
|
| **Xe2-LPG** (Lunar Lake) | TSMC N3B | Arc Graphics (Xe2-LPG - 8 Xe-Cores) | `i915?/xe` | `iris` | `anv` | First iGPU with Xe2 architecture (Battlemage). |
|
||||||
|
| **Xe3-LPG** (Panther Lake) | Intel 18A | Arc Graphics (Xe3 iGPU) | `i915?/xe` | `iris` | `anv` | High-power iGPU. Requires Kernel 6.19 and Mesa 26 as base. |
|
||||||
|
| **Xe-HPG** (Alchemist) | TSMC N6 | **Arc A380, A580, A750, A770** (dGPU) | `i915/xe` | `iris` | `anv` | First modern dGPU (Arc). Support since Kernel 6 and Mesa 22. |
|
||||||
|
| **Xe2-HPG** (Battlemage) | TSMC N5 | **Arc B570, B580** (dGPU) | [`i915/xe`](https://www.phoronix.com/review/intel-xe-i915-linux-619) | `iris` | `anv` | Second generation dGPU. Very solid day-one Linux support since Kernel 6.12 and Mesa 24.2 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 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.
|
||||||
|
2. **Mesa Drivers (User Space)**:
|
||||||
|
* **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.
|
||||||
|
* **Modern Hardware (Gen9 and Xe)**: **`iris`** is the standard driver. It works excellently on both iGPUs and Arc dGPUs (Alchemist/Battlemage).
|
||||||
|
* **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).
|
||||||
|
* **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*.
|
||||||
|
* **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`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. AMD Radeon Architecture Reference
|
||||||
|
|
||||||
|
AMD's open-source support is divided by architecture families, each mapped to a specific Gallium3D driver within Mesa.
|
||||||
|
|
||||||
|
| Architecture | Representative GPU Families | Kernel Driver (KMD) | OpenGL Driver (Mesa) | Vulkan Driver (Mesa) | Technical Notes & Particularities |
|
||||||
|
| :--- | :--- | :--- | :--- | :--- | :--- |
|
||||||
|
| **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 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 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 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 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.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
|
||||||
|
|
||||||
|
#### 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.
|
||||||
|
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 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.
|
||||||
|
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.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. **NVIDIA Hardware & Driver Support**
|
||||||
|
|
||||||
|
#### 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.
|
||||||
|
|
||||||
|
| Architecture | Last Driver with Support | Kernel Module (KMD) | Proprietary Vulkan Support | NVK (Mesa) Support | Max CUDA Version | Notes and Particularities |
|
||||||
|
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
||||||
|
| **Fermi**<br>*(GF100/110)* | **390.xx** (Legacy) | `nvidia` (Closed) | **Vulkan 1.0** | No | **CUDA 8.0** | Last driver to support this architecture. Has not received security fixes for years. Only viable for completely offline systems. |
|
||||||
|
| **Kepler**<br>*(GK100/110)* | **470.xx** (Legacy) | `nvidia` (Closed) | **Vulkan 1.2** | No | **CUDA 11.8** | Last generation to receive "Legacy" status. Good compatibility with OpenGL 4.6, but Vulkan support stalled at 1.2. |
|
||||||
|
| **Maxwell**<br>*(GM100/200)* | **580.xx** (Old Standard) | `nvidia` (Closed) | **Vulkan 1.3** | No | **CUDA 12.0** | Removed from official support in driver 580 (CUDA 12.1). |
|
||||||
|
| **Pascal**<br>*(GP100/102/104)* | **580.xx** (Old Standard) | `nvidia` (Closed) | **Vulkan 1.3** | No | **CUDA 12.0** | Shares same fate as Maxwell. Still very popular (GTX 1060/1080), but requires blocking packages (e.g., in Debian) to prevent updates that break graphics support. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 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.
|
||||||
|
|
||||||
|
| Architecture | Compatible Active Drivers | Kernel Module (KMD) | Proprietary Vulkan Support | NVK (Mesa) Support | Max CUDA Version | Notes and Particularities |
|
||||||
|
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
||||||
|
| **Turing**<br>*(TU100/102/116)* | 525.xx to 610+ | `nvidia` (**Open Module**) | **Vulkan 1.3** | **Yes** (Vulkan 1.3) | **CUDA 12.8+** | First generation to use Open Kernel Module (introduced in 515, default in 525). *Note:* Security processor firmware (GSP) remains a closed blob. Excellent NVK support. |
|
||||||
|
| **Ampere**<br>*(GA100/102/104/107)* | 525.xx to 610+ | `nvidia` (**Open Module**) | **Vulkan 1.3** | **Yes** (Vulkan 1.3) | **CUDA 12.8+** | Mature support in both proprietary driver and NVK. For RTX 3060/3080/3090, NVK offers extremely competitive performance versus proprietary in many scenarios. |
|
||||||
|
| **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`. |
|
||||||
|
|
||||||
|
#### 💡 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).
|
||||||
|
* **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.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6. **Mesa Stack Optimization (AMD & Intel)**
|
||||||
|
|
||||||
|
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:**
|
||||||
|
* **`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.
|
||||||
|
* **`va-driver-all` / `vdpau-va-driver`**: Ensures video decoding acceleration is available for media players like VLC or MPV.
|
||||||
|
|
||||||
|
**Vendor-Specific Logic:**
|
||||||
|
|
||||||
|
| 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` | `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. |
|
||||||
|
|
||||||
|
**Critical Consistency Check:**
|
||||||
|
The script enforces the installation of 32-bit Mesa libraries (`libgl1-mesa-dri:i386`) alongside the 64-bit packages. This is a mandatory requirement for running Proton (Steam) and Wine applications, which often rely on 32-bit OpenGL contexts even when running on a 64-bit OS.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
|
#### **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**
|
||||||
|
- **Detection**: `_helpers.sh` function `is_nvidia_blackwell()` identifies GPUs via PCI IDs `10de:24xx`, `0x2900–0x29BF`, and `0x2B80–0x31FF`.
|
||||||
|
- **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`.
|
||||||
|
|
||||||
|
#### **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
|
||||||
|
offer_nvidia_enterprise_repo
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _confirm "NVIDIA Driver"; then
|
||||||
|
install_nvidia_driver # Installs latest stable (535/550) or v590 for Blackwell
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
### 8.**NVIDIA Driver Management & Kernel Compatibility**
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
| Driver NVIDIA | Debian Version | Supported Architectures (Generations) | Notes |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **[390.157](https://us.download.nvidia.com/XFree86/Linux-x86_64/390.157/README/supportedchips.html)** | **Debian 11** (Bullseye) | Fermi, Kepler, Maxwell, Pascal, Volta | Last driver with Fermi support. Stable for legacy hardware. |
|
||||||
|
| **[470.256.02](https://us.download.nvidia.com/XFree86/Linux-x86_64/470.256.02/README/supportedchips.html)** | Debian 11 / **Bookworm** | Kepler, Maxwell, Pascal, Volta, Turing *(Limited Ampere)* | Last driver supporting Kepler (GeForce). Quadro K-series often use Maxwell chips here. |
|
||||||
|
| **[535.247.01](https://us.download.nvidia.com/XFree86/Linux-x86_64/535.247.01/README/supportedchips.html)** | **Debian 12** (Bookworm) | Maxwell to Ada Lovelace | Kepler support dropped completely. Standard for RTX 3000/4000 series. |
|
||||||
|
| **[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:**
|
||||||
|
* **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.
|
||||||
|
* **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:**
|
||||||
|
When Kepler is detected on Bookworm, `nvidia.sh` bypasses `nvidia-detect` (which might recommend v535) and forces installation of `nvidia-tesla-470-driver`:
|
||||||
|
```bash
|
||||||
|
if [ "$is_kepler" = "true" ] && [ "$DEBIAN_CODENAME" = "bookworm" ]; then
|
||||||
|
nv_pkg="nvidia-tesla-470-driver"
|
||||||
|
# Avoids black screen issues by forcing legacy 470 branch
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 9. 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.
|
||||||
|
|
||||||
|
* **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`).
|
||||||
|
* **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))**:
|
||||||
|
* 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))**:
|
||||||
|
* 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))**:
|
||||||
|
* 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:**
|
||||||
|
```bash
|
||||||
|
if _confirm "Install Telemetry Tools"; then
|
||||||
|
case "$GPU_TYPE" in
|
||||||
|
nvidia) install_pkg nvtop ;;
|
||||||
|
amd) install_pkg radeontop ;;
|
||||||
|
intel) install_pkg intel-gpu-tools ;;
|
||||||
|
*) echo "Skipping telemetry for unknown GPU." ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
This modular approach ensures that users can verify their installation immediately after running `debianito`, providing confidence in the performance of their graphics stack.
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
## Option 6: Debian Backports Kernel Integration
|
||||||
|
|
||||||
|
### 1. Why a Backports Kernel?
|
||||||
|
|
||||||
|
The decision to integrate the Debian Backports kernel into `debianito.sh` is driven by the fundamental architectural conflict between **Stability** and **Hardware Enablement**.
|
||||||
|
|
||||||
|
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+).
|
||||||
|
|
||||||
|
For users with modern hardware released between 2025 and 2026, this freeze creates a compatibility gap:
|
||||||
|
* **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.
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
|
**The Installation Command Logic:**
|
||||||
|
The script utilizes `apt` with a specific target release flag to pull packages from the backports suite:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install -y -t ${DEBIAN_CODENAME}-backports linux-image-amd64
|
||||||
|
```
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
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.
|
||||||
|
2. **Image Package:** `linux-image-amd64` contains the bootable kernel binary and associated modules.
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### 3. Safety Mechanisms and Atomic Operation
|
||||||
|
|
||||||
|
To prevent boot loops or system instability, `kernel.sh` implements several safety checks before executing any installation commands:
|
||||||
|
|
||||||
|
* **Pre-flight Repository Validation:**
|
||||||
|
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.
|
||||||
|
|
||||||
|
* **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):**
|
||||||
|
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:**
|
||||||
|
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.
|
||||||
|
|
||||||
|
### 4. Critical Interconnection with Other Modules (Script Ecosystem)
|
||||||
|
|
||||||
|
The Backports Kernel module does not operate in isolation; it relies on a tightly coupled ecosystem within `debianito.sh` to ensure full functionality:
|
||||||
|
|
||||||
|
* **Option 4: Firmware & Wireless Drivers:**
|
||||||
|
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.
|
||||||
|
|
||||||
|
* **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:**
|
||||||
|
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:**
|
||||||
|
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.
|
||||||
@@ -0,0 +1,284 @@
|
|||||||
|
## Option 3: Advanced Repository Configuration
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
|
At its core, this component:
|
||||||
|
- Detects your current repository format (Classic `.list` vs modern DEB822 `.sources`)
|
||||||
|
- Backs up existing configurations before any modifications
|
||||||
|
- Enables critical non-free components required for hardware drivers and proprietary software
|
||||||
|
- Integrates Debian Backports to access newer kernels and firmware packages
|
||||||
|
- Validates changes through `apt update` with automatic restoration on failure
|
||||||
|
|
||||||
|
This is not just about "adding repositories"—it's about **system integrity assurance** that enables all other configuration options (GPU drivers, kernel upgrades, gaming setup) to function correctly.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Supported Injection Formats
|
||||||
|
|
||||||
|
The script intelligently adapts to your Debian version and existing repository structure:
|
||||||
|
|
||||||
|
#### Classic Format (`/etc/apt/sources.list`)
|
||||||
|
- **Structure**: Human-readable text with `deb` lines
|
||||||
|
- **Use Case**: Debian 11 (Bullseye) through Debian 12 (Bookworm) default
|
||||||
|
- **Characteristics**: Linear, comment-friendly, widely understood by all APT tools
|
||||||
|
- **Example**:
|
||||||
|
```bash
|
||||||
|
deb https://deb.debian.org/debian bookworm main contrib non-free non-free-firmware
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Modern DEB822 Format (`/etc/apt/sources.list.d/debian.sources`)
|
||||||
|
- **Structure**: Declarative YAML-like format with `Types`, `URIs`, and `Suites` blocks
|
||||||
|
- **Use Case**: Debian 13 (Trixie) default, future-proofing for newer releases
|
||||||
|
- **Characteristics**: Machine-parseable, structured, supports complex repository hierarchies
|
||||||
|
- **Example**:
|
||||||
|
```yaml
|
||||||
|
Types: deb
|
||||||
|
URIs: https://deb.debian.org/debian
|
||||||
|
Suites: trixie trixie-updates
|
||||||
|
Components: main contrib non-free non-free-firmware
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Migration Logic
|
||||||
|
The script automatically detects your current format and offers migration options:
|
||||||
|
- On Debian 13 (Trixie): Prompts to migrate TO DEB822 or stay with Classic
|
||||||
|
- Format changes are atomic—backup is created before any modification
|
||||||
|
- Old files are renamed with `.disabled` extension rather than deleted
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Logical Decision Tree (Step-by-Step Execution Flow)
|
||||||
|
|
||||||
|
The `configure_repos()` function in `repos.sh` executes the following sequence:
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ INITIAL DETECTION PHASE │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ 1. Detect Debian Codename (DEBIAN_CODENAME) │
|
||||||
|
│ └── If empty → Abort with error │
|
||||||
|
│ │
|
||||||
|
│ 2. Detect Current Format │
|
||||||
|
│ ├── detect_repo_format() → "deb822" | "classic" | "none" │
|
||||||
|
│ └── Display: "Current format: [format]" │
|
||||||
|
│ │
|
||||||
|
│ 3. Detect Backports Status │
|
||||||
|
│ ├── detect_backports_status() → enabled/disabled │
|
||||||
|
│ └── Detect Location: embedded vs standalone │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ USER INTERACTION PHASE │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ 4. Repository Menu Loop (while true) │
|
||||||
|
│ └── _menu: Select action from multiple options │
|
||||||
|
│ │
|
||||||
|
│ Options Available: │
|
||||||
|
│ ├── Debian 13+ (Trixie): │
|
||||||
|
│ │ ├── 1. Enable Contrib & Non-Free Components │
|
||||||
|
│ │ ├── 2. Migrate traditional sources.list to DEB822 │
|
||||||
|
│ │ ├── 3. Setup/Update Backports repositories │
|
||||||
|
│ │ ├── 4. [ADVANCED] Upgrade system branch (Testing/SID)│
|
||||||
|
│ │ └── 5. Back to main menu │
|
||||||
|
│ │
|
||||||
|
│ └── Other Versions: │
|
||||||
|
│ ├── 1-3 same as above │
|
||||||
|
│ └── No option 4 (branch upgrade not available) │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ DECISION MATRIX PHASE │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ 5. Determine Action Type (per menu selection) │
|
||||||
|
│ ├── If format changed → "migrate" │
|
||||||
|
│ ├── If nothing changed → "skip" (idempotent) │
|
||||||
|
│ └── Otherwise → "write" │
|
||||||
|
│ │
|
||||||
|
│ 6. Idempotency Check │
|
||||||
|
│ └── content_differs() compares generated vs existing │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ EXECUTION PHASE │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ 7. Backup Current Repositories │
|
||||||
|
│ └── backup_current_repos() → temp directory │
|
||||||
|
│ │
|
||||||
|
│ 8. Write Configuration │
|
||||||
|
│ ├── _write_deb822() OR _write_classic() │
|
||||||
|
│ ├── Creates appropriate file(s) │
|
||||||
|
│ └── Includes main + backports if enabled │
|
||||||
|
│ │
|
||||||
|
│ 9. Update Package Lists │
|
||||||
|
│ └── sudo apt update │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ POST-EXECUTION PHASE │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ 10. Success Path │
|
||||||
|
│ ├── REPOS_CONFIGURED=true │
|
||||||
|
│ ├── Cleanup disabled files │
|
||||||
|
│ └── Optional: Upgrade system if packages available │
|
||||||
|
│ │
|
||||||
|
│ 11. Failure Path (apt update failed) │
|
||||||
|
│ └── restore_previous_repos() → rollback to backup │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Safety Mechanisms:**
|
||||||
|
- **Atomic Operations**: Backup created before any write operation
|
||||||
|
- **Idempotency Check**: `content_differs()` prevents unnecessary modifications
|
||||||
|
- **Rollback on Failure**: If `apt update` fails, original configuration is restored
|
||||||
|
- **Disabled File Extension**: Old formats renamed with `.disabled` rather than deleted
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Software Components Activated
|
||||||
|
|
||||||
|
The script enables specific APT component branches that are essential for hardware functionality and software availability:
|
||||||
|
|
||||||
|
| Component | Purpose | Critical For | Debian Version Notes |
|
||||||
|
|-----------|---------|--------------|---------------------|
|
||||||
|
| **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 |
|
||||||
|
| **non-free** | Non-free firmware and proprietary software | NVIDIA GPU drivers, Wi-Fi firmware | Required for hardware support |
|
||||||
|
| **non-free-firmware** | Firmware blobs (Wi-Fi, Bluetooth, etc.) | Wireless adapters, embedded chips | **Critical from Debian 12+** |
|
||||||
|
|
||||||
|
#### Why `non-free-firmware` is Vital (Debian 12+)
|
||||||
|
|
||||||
|
Starting with Debian Bookworm (12.0), the `non-free-firmware` component was separated into its own repository branch:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Before Debian 12 (Bookworm)
|
||||||
|
deb https://deb.debian.org/debian bullseye main contrib non-free
|
||||||
|
|
||||||
|
# After Debian 12 (Bookworm+) - SEPARATE COMPONENTS
|
||||||
|
deb https://deb.debian.org/debian bookworm main contrib non-free non-free-firmware
|
||||||
|
```
|
||||||
|
|
||||||
|
**Impact of Missing `non-free-firmware`:**
|
||||||
|
- ❌ Wi-Fi adapters won't work without firmware blobs
|
||||||
|
- ❌ Bluetooth devices may fail to initialize
|
||||||
|
- ❌ Some GPU drivers require proprietary microcode
|
||||||
|
- ❌ Embedded hardware (Raspberry Pi, etc.) becomes unusable
|
||||||
|
|
||||||
|
The script ensures all four components are present because:
|
||||||
|
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
|
||||||
|
3. **Future-Proofing**: Newer hardware releases firmware in this component exclusively
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. Support for Debian Backports
|
||||||
|
|
||||||
|
The backports integration is a sophisticated feature that enables access to newer, tested packages without compromising system stability:
|
||||||
|
|
||||||
|
#### Detection Logic (`detect_backports_status` & `detect_backports_location`)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Checks ALL possible locations for backports configuration
|
||||||
|
├── /etc/apt/sources.list.d/debian-backports.sources (DEB822 standalone)
|
||||||
|
├── /etc/apt/sources.list.d/debian-backports.list (Classic standalone)
|
||||||
|
├── /etc/apt/sources.list.d/debian.sources (Embedded in DEB822)
|
||||||
|
└── /etc/apt/sources.list (Embedded in Classic)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Return Values:**
|
||||||
|
- `"standalone-deb822"` → Separate `.sources` file (recommended)
|
||||||
|
- `"standalone-classic"` → Separate `.list` file
|
||||||
|
- `"embedded-deb822"` → Inside `debian.sources`
|
||||||
|
- `"embedded-classic"` → Inside `sources.list`
|
||||||
|
- `"none"` → Not configured
|
||||||
|
|
||||||
|
#### Backports Injection Process
|
||||||
|
|
||||||
|
```bash
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ 1. User Selects: Enable Backports? │
|
||||||
|
│ └── whiptail confirm with explanation │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ 2. Determine Format │
|
||||||
|
│ ├── If DEB822 → _write_deb822_backports() │
|
||||||
|
│ └── If Classic → _write_classic_backports() │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ 3. Create Backports File │
|
||||||
|
│ ├── Location: /etc/apt/sources.list.d/ │
|
||||||
|
│ └── Name: debian-backports.sources or .list │
|
||||||
|
│ │
|
||||||
|
│ Content Example (DEB822): │
|
||||||
|
│ Types: deb │
|
||||||
|
│ URIs: https://deb.debian.org/debian │
|
||||||
|
│ Suites: bookworm-backports │
|
||||||
|
│ Components: main contrib non-free non-free-firmware │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ 4. Cleanup Embedded Backports (Safety Net) │
|
||||||
|
│ └── If backports existed in main file, remove them │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Why Enable Backports?
|
||||||
|
|
||||||
|
The script includes a detailed explanation because backports enable critical features:
|
||||||
|
|
||||||
|
| 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) |
|
||||||
|
| **GPU "Drivers"** | Latest Mesa from stable | Latest Mesa from testing |
|
||||||
|
| **Wi-Fi Firmware** | Older firmware versions | Newest firmware for modern cards |
|
||||||
|
| **System Stability** | Maximum stability | Tested-but-newer packages |
|
||||||
|
|
||||||
|
#### Backports Warning System
|
||||||
|
|
||||||
|
The script includes safeguards:
|
||||||
|
- Only enabled if user explicitly confirms
|
||||||
|
- Warns about potential compatibility issues
|
||||||
|
- Can be disabled anytime via Option 3 again
|
||||||
|
- Automatically detected in other modules (kernel, GPU)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Technical Implementation Notes
|
||||||
|
|
||||||
|
**Idempotency Guarantee:**
|
||||||
|
```bash
|
||||||
|
# content_differs() ensures no duplicate writes
|
||||||
|
if [ "$current" = "$generated" ]; then
|
||||||
|
return 1 # No changes needed
|
||||||
|
fi
|
||||||
|
return 0 # Changes required
|
||||||
|
```
|
||||||
|
|
||||||
|
**Atomic Backup Mechanism:**
|
||||||
|
```bash
|
||||||
|
backup_current_repos() {
|
||||||
|
REPO_BACKUP_DIR=$(mktemp -d)
|
||||||
|
for f in /etc/apt/sources.list /etc/apt/sources.list.d/*.sources; do
|
||||||
|
cp "$f" "$REPO_BACKUP_DIR/" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Rollback on failure:
|
||||||
|
restore_previous_repos() {
|
||||||
|
sudo cp "$backup_file" "$original_path" # Restore from temp backup
|
||||||
|
rm -rf "$REPO_BACKUP_DIR" # Clean up after success/failure
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Component Activation Pattern:**
|
||||||
|
All four components are written in a single operation to prevent partial configurations:
|
||||||
|
```bash
|
||||||
|
Components: main contrib non-free non-free-firmware # Atomic write
|
||||||
|
# Not written as separate lines to avoid merge conflicts
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
# Installing New Cores in RetroArch on Debian
|
||||||
|
|
||||||
|
RetroArch installed via the official Debian repositories (`apt`) has a few key restrictions: the internal core downloader and updater are **disabled** by default, and cores are stored in system‑wide, read‑only directories. This guide explains two reliable ways to add new emulation cores (e.g., PPSSPP, Dolphin, MAME) to your Debian system, along with the necessary supporting files and configuration tweaks.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Understanding RetroArch’s Directory Structure on Debian
|
||||||
|
|
||||||
|
When installed via `apt`, RetroArch uses these locations:
|
||||||
|
|
||||||
|
| **Component** | **Default Path** (system‑wide) |
|
||||||
|
|-----------------------------|---------------------------------------------------------|
|
||||||
|
| Cores (`.so` files) | `/usr/lib/x86_64-linux-gnu/libretro/` |
|
||||||
|
| Core info (`.info` files) | `/usr/share/libretro/info/` |
|
||||||
|
| System/BIOS/Assets | `~/.config/retroarch/system/` (user‑writable) |
|
||||||
|
| Saves, States, Config | `~/.config/retroarch/` (user‑writable) |
|
||||||
|
|
||||||
|
Because the core and info directories are owned by root, you cannot write to them without `sudo`.
|
||||||
|
You have two options:
|
||||||
|
|
||||||
|
1. **Manual installation** – download cores and info files yourself and copy them with `sudo`.
|
||||||
|
2. **Reconfigure RetroArch** to use user‑writable folders, then use the built‑in **Core Downloader**.
|
||||||
|
|
||||||
|
Both methods work; choose the one that suits you best.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Method 1 – Manual Core Installation (Recommended for Reliability)
|
||||||
|
|
||||||
|
This method guarantees that you can add any core, even if the online updater is blocked.
|
||||||
|
|
||||||
|
### 1. Download and Install the Core (`.so`)
|
||||||
|
|
||||||
|
The core is a shared library. For 64‑bit Linux, get it from the official Libretro buildbot:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Example: PPSSPP core
|
||||||
|
wget https://buildbot.libretro.com/nightly/linux/x86_64/latest/ppsspp_libretro.so.zip
|
||||||
|
unzip ppsspp_libretro.so.zip
|
||||||
|
sudo mv ppsspp_libretro.so /usr/lib/x86_64-linux-gnu/libretro/
|
||||||
|
rm ppsspp_libretro.so.zip
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Replace `ppsspp` with any core name** – e.g., `mame_libretro`, `dolphin_libretro`, etc.
|
||||||
|
> Browse all available cores at:
|
||||||
|
> [https://buildbot.libretro.com/nightly/linux/x86_64/latest/](https://buildbot.libretro.com/nightly/linux/x86_64/latest/)
|
||||||
|
|
||||||
|
### 2. Download and Install the Core Info (`.info`)
|
||||||
|
|
||||||
|
RetroArch will not recognise the core without its corresponding `.info` file.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget https://raw.githubusercontent.com/libretro/libretro-core-info/master/ppsspp_libretro.info
|
||||||
|
sudo mkdir -p /usr/share/libretro/info/
|
||||||
|
sudo mv ppsspp_libretro.info /usr/share/libretro/info/
|
||||||
|
```
|
||||||
|
|
||||||
|
> The `.info` files for all cores are maintained at:
|
||||||
|
> [https://github.com/libretro/libretro-core-info](https://github.com/libretro/libretro-core-info)
|
||||||
|
> You can also download directly: `https://raw.githubusercontent.com/libretro/libretro-core-info/master/<core_name>.info`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Method 2 – Enable the Built‑in Core Downloader
|
||||||
|
|
||||||
|
If you prefer using RetroArch’s graphical interface to download cores, you can change the core directories to writable locations.
|
||||||
|
|
||||||
|
### Step 1 – Edit RetroArch Configuration
|
||||||
|
|
||||||
|
Create or edit `~/.config/retroarch/retroarch.cfg` and add these lines:
|
||||||
|
|
||||||
|
```
|
||||||
|
libretro_directory = "~/.config/retroarch/libretro/"
|
||||||
|
libretro_info_path = "~/.config/retroarch/libretro-info/"
|
||||||
|
menu_show_core_updater = "true"
|
||||||
|
```
|
||||||
|
|
||||||
|
Now create the directories:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p ~/.config/retroarch/libretro
|
||||||
|
mkdir -p ~/.config/retroarch/libretro-info
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2 – Update Core Info Files
|
||||||
|
|
||||||
|
- Launch RetroArch.
|
||||||
|
- Go to **Online Updater** → **Update Core Info Files**.
|
||||||
|
- Wait for the update to complete.
|
||||||
|
|
||||||
|
### Step 3 – Download Cores
|
||||||
|
|
||||||
|
- Go to **Online Updater** → **Core Downloader**.
|
||||||
|
- Select the core you want (e.g., PPSSPP).
|
||||||
|
- The core will be downloaded to your user directory and will appear in the core list.
|
||||||
|
|
||||||
|
> ⚠️ **Note:** Some cores may require additional system files (BIOS/assets). These are still placed in `~/.config/retroarch/system/` – you’ll need to obtain them separately (see below).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Essential Configuration for Graphics
|
||||||
|
|
||||||
|
The default video driver (`gl`) often causes black screens or crashes with many cores (especially PPSSPP). **Change the driver** to `vulkan` (preferred) or `glcore`.
|
||||||
|
|
||||||
|
1. In RetroArch, go to **Settings** → **Drivers** → **Video**.
|
||||||
|
2. Select **vulkan** (or **glcore** if Vulkan is not available).
|
||||||
|
3. Return to the main menu, go to **Configuration File** → **Save Current Configuration**.
|
||||||
|
4. **Restart RetroArch** for the change to take effect.
|
||||||
|
|
||||||
|
> If you’re on older hardware, you may need to install Vulkan drivers:
|
||||||
|
> `sudo apt install mesa-vulkan-drivers`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installing Additional System Files (Assets / BIOS)
|
||||||
|
|
||||||
|
Some emulators require extra files (fonts, sound banks, BIOS images) to work correctly. These always go into your **user** system directory:
|
||||||
|
|
||||||
|
```
|
||||||
|
~/.config/retroarch/system/
|
||||||
|
```
|
||||||
|
|
||||||
|
For **PPSSPP**, you need its asset bundle:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p ~/.config/retroarch/system/PPSSPP
|
||||||
|
wget https://buildbot.libretro.com/assets/system/PPSSPP.zip
|
||||||
|
unzip PPSSPP.zip -d ~/.config/retroarch/system/
|
||||||
|
```
|
||||||
|
|
||||||
|
After extraction, you should see subfolders like `flash0/`, `lang/`, `themes/`, etc.
|
||||||
|
|
||||||
|
For other systems (e.g., **Dolphin**, **PCSX2**), check the official Libretro documentation for required BIOS files and place them in the appropriate subdirectory under `system/`.
|
||||||
|
You can find many asset packs at:
|
||||||
|
[https://buildbot.libretro.com/assets/system/](https://buildbot.libretro.com/assets/system/)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ROM / Game File Formats
|
||||||
|
|
||||||
|
- **Supported formats** for PPSSPP: `.iso`, `.cso`, `.chd`, `.pbp`.
|
||||||
|
- **Always decompress your ROMs** – do not leave them in `.zip`, `.rar`, or `.7z` archives; the cores cannot read compressed archives directly.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Useful References
|
||||||
|
|
||||||
|
| Resource | URL |
|
||||||
|
|----------|-----|
|
||||||
|
| Core builds (nightly, Linux x86_64) | [https://buildbot.libretro.com/nightly/linux/x86_64/latest/](https://buildbot.libretro.com/nightly/linux/x86_64/latest/) |
|
||||||
|
| Core info files (GitHub) | [https://github.com/libretro/libretro-core-info](https://github.com/libretro/libretro-core-info) |
|
||||||
|
| System assets (BIOS, firmware, etc.) | [https://buildbot.libretro.com/assets/system/](https://buildbot.libretro.com/assets/system/) |
|
||||||
|
| Official RetroArch documentation | [https://docs.libretro.com/](https://docs.libretro.com/) |
|
||||||
|
| Debian Wiki – RetroArch | [https://wiki.debian.org/RetroArch](https://wiki.debian.org/RetroArch) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Final Notes
|
||||||
|
|
||||||
|
- The Debian package disables auto‑updates and the core downloader **by default** – this is intentional for stability.
|
||||||
|
- Manual installation (Method 1) is the most straightforward and works for **any** core, regardless of distribution restrictions.
|
||||||
|
- If you choose Method 2, remember that you may still need to manually place BIOS/asset files in `~/.config/retroarch/system/`.
|
||||||
|
- Always test your video driver setting; `vulkan` is recommended for PPSSPP and other 3D‑heavy cores.
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
## Option 9: Swap
|
||||||
|
|
||||||
|
### 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**.
|
||||||
|
|
||||||
|
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.
|
||||||
|
* **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?
|
||||||
|
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.
|
||||||
|
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.
|
||||||
|
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).
|
||||||
|
|
||||||
|
### 3. The Logical Decision Tree (Step by Step)
|
||||||
|
The execution flow follows a strict logical tree designed for safety and idempotency:
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
2. **Menu Selection Loop:**
|
||||||
|
* Enters a continuous loop presenting options (Status, Create, Remove, Swappiness).
|
||||||
|
* Breaks only when the user selects "Back to main menu".
|
||||||
|
|
||||||
|
3. **Action Execution Paths:**
|
||||||
|
* **Path A: Status Check (`_swap_current_status`)**
|
||||||
|
* Reads active swap entries via `swapon --show`.
|
||||||
|
* Reads current swappiness from `/proc/sys/vm/swappiness`.
|
||||||
|
* Parses `/etc/fstab` for managed tags.
|
||||||
|
* **Path B: Create/Resize (`_swap_create_file`)**
|
||||||
|
* **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.
|
||||||
|
* **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`).
|
||||||
|
* **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`)**
|
||||||
|
* Checks for the unique `SWAP_FSTAB_TAG` in fstab.
|
||||||
|
* Confirms user intent to delete.
|
||||||
|
* Executes `swapoff`, removes the fstab line, and deletes the physical file.
|
||||||
|
* **Path D: Swappiness (`_swap_set_swappiness`)**
|
||||||
|
* Validates input (0-100 integer).
|
||||||
|
* Writes a temporary sysctl config file.
|
||||||
|
* Applies changes immediately via `sysctl -w`.
|
||||||
|
|
||||||
|
### 4. What does each menu item do and what does it mean?
|
||||||
|
Each option in the swap management submenu serves a specific technical purpose:
|
||||||
|
|
||||||
|
* **Option 1: Show current swap & swappiness**
|
||||||
|
* **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.
|
||||||
|
|
||||||
|
* **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.
|
||||||
|
* **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**
|
||||||
|
* **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.
|
||||||
|
|
||||||
|
* **Option 4: Change 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.
|
||||||
|
|
||||||
|
* **Option 5: Back to main menu**
|
||||||
|
* **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.
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
## Option 1: Hardware Detection & System Information
|
||||||
|
|
||||||
|
### 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).
|
||||||
|
|
||||||
|
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)
|
||||||
|
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 |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| **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`. |
|
||||||
|
| **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. |
|
||||||
|
| **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. |
|
||||||
|
| **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. |
|
||||||
|
|
||||||
|
### 3. Strategic Importance for the Script
|
||||||
|
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.
|
||||||
|
* **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.
|
||||||
|
* **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
|
||||||
|
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.
|
||||||
|
* **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.
|
||||||
|
* **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.
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
## Option 2: User Privileges & Feedback
|
||||||
|
|
||||||
|
### 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).
|
||||||
|
|
||||||
|
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.
|
||||||
|
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
|
||||||
|
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):**
|
||||||
|
* **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.
|
||||||
|
|
||||||
|
* **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.
|
||||||
|
* **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):**
|
||||||
|
* **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.
|
||||||
|
|
||||||
|
* **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.
|
||||||
|
* **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)
|
||||||
|
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:**
|
||||||
|
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 1–5.
|
||||||
|
|
||||||
|
**Option 1: Sudo Group Membership (`_check_sudo_group`)**
|
||||||
|
* **Step A:** Execute `groups "$USER"` via pipe to grep for `\bsudo\b`.
|
||||||
|
* **Decision:**
|
||||||
|
* *If Match:* Display success message ("User is already in sudo group"). Exit function.
|
||||||
|
* *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`)**
|
||||||
|
* **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.
|
||||||
|
* *If Not Exists:* Prompt user to configure NOPASSWD for maintenance commands.
|
||||||
|
* *On Confirm:* Display a checklist menu allowing selection of `apt`, `systemctl`, or `power` commands.
|
||||||
|
* **Step B:** Process selected 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 C:** Write configuration:
|
||||||
|
* Pipe content to `sudo tee /etc/sudoers.d/${USER}-nopasswd`.
|
||||||
|
* Set file permissions to `0440` (readable only by root and owner).
|
||||||
|
* Notify success or failure.
|
||||||
|
|
||||||
|
**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 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`)**
|
||||||
|
* **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.
|
||||||
|
* *If Not Exists:* Prompt user to enable visual feedback.
|
||||||
|
* *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
|
||||||
|
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.
|
||||||
|
* **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.
|
||||||
|
* **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.
|
||||||
|
* **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.
|
||||||
+251
@@ -0,0 +1,251 @@
|
|||||||
|
# Option 8: ZRAM Configuration & Memory Optimization
|
||||||
|
|
||||||
|
## 1. The Science of ZRAM vs. Traditional Swap
|
||||||
|
|
||||||
|
### Core Concept: CPU Cycles vs. Disk I/O
|
||||||
|
|
||||||
|
Traditional swap storage operates on a fundamental latency gap that becomes critical under memory pressure:
|
||||||
|
|
||||||
|
| Storage Medium | Latency Range | Write Amplification | SSD Wear Impact |
|
||||||
|
|---------------|---------------|---------------------|-----------------|
|
||||||
|
| **DRAM (RAM)** | ~10–50 nanoseconds | None | Zero |
|
||||||
|
| **NVMe SSD** | ~20–70 microseconds | 1.2x–3.0x | Moderate to High |
|
||||||
|
| **SATA SSD** | ~100–200 microseconds | 1.5x–4.0x | High |
|
||||||
|
| **HDD** | ~5–10 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:
|
||||||
|
|
||||||
|
- **Time Cost**: Each 4 KiB page write takes microseconds (NVMe) to milliseconds (HDD)
|
||||||
|
- **Wear Cost**: Every write consumes P/E (Program/Erase) cycles from NAND flash cells, reducing TBW (Terabytes Written) lifespan
|
||||||
|
- **System Impact**: High latency causes "thrashing" where the system spends more time waiting for disk I/O than executing actual work
|
||||||
|
|
||||||
|
### ZRAM's Solution: Compression in RAM
|
||||||
|
|
||||||
|
ZRAM creates a compressed block device entirely within physical memory. When pages need to be swapped, they are:
|
||||||
|
|
||||||
|
1. **Compressed on-the-fly** using CPU algorithms (LZ4 or ZSTD)
|
||||||
|
2. **Stored in RAM pool** at compressed size (typically 2:1 to 3:1 ratio)
|
||||||
|
3. **Decompressed instantly** when needed (microseconds vs milliseconds)
|
||||||
|
|
||||||
|
The trade-off is explicit: **CPU cycles for reduced I/O latency**. Modern CPUs can compress/decompress pages in microseconds, making this far cheaper than any disk operation.
|
||||||
|
|
||||||
|
### Why Only LZ4 and ZSTD?
|
||||||
|
|
||||||
|
The script offers only two algorithms because they represent the optimal balance points:
|
||||||
|
|
||||||
|
| Algorithm | Compression Ratio | Speed | CPU Overhead | Best Use Case |
|
||||||
|
|-----------|------------------|-------|--------------|---------------|
|
||||||
|
| **LZ4** | ~2:1–3:1 | Fastest | Lowest | Gaming, real-time workloads |
|
||||||
|
| **ZSTD** | ~3:1–5:1 | Medium | Moderate | General use, better memory savings |
|
||||||
|
|
||||||
|
- **LZ4**: Prioritizes speed over compression ratio. Ideal for systems where CPU availability is limited or latency-sensitive (gaming servers).
|
||||||
|
- **ZSTD**: Offers superior compression ratios with acceptable overhead. Best for systems prioritizing maximum effective RAM capacity.
|
||||||
|
|
||||||
|
The kernel supports additional algorithms (lzo-rle, deflate, lz4hc), but these are either deprecated, slower, or offer diminishing returns compared to LZ4/ZSTD in modern hardware.
|
||||||
|
|
||||||
|
### Extending SSD Lifespan Through Reduced Writes
|
||||||
|
|
||||||
|
By intercepting swap writes before they reach physical storage:
|
||||||
|
|
||||||
|
- **Write Reduction**: Pages that would write to disk now compress in RAM
|
||||||
|
- **TBW Conservation**: Each avoided write preserves P/E cycles on NAND flash cells
|
||||||
|
- **System Longevity**: Critical for systems with limited SSD endurance ratings (e.g., 100 TBW consumer drives)
|
||||||
|
|
||||||
|
As the Linux kernel documentation states: *"Users with SSDs as swap devices can extend device lifespan by drastically reducing writes that shorten its life."*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Injection Flow and Configuration Logic (`zram-tools`)
|
||||||
|
|
||||||
|
### Pipeline Execution Sequence
|
||||||
|
|
||||||
|
The script follows a deterministic flow to ensure safe, reproducible configuration:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ install_zram() Function │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ 1. Validate RAM Detection │
|
||||||
|
│ └─ Check if RAM_KB is available and non-zero │
|
||||||
|
│ │
|
||||||
|
│ 2. Compression Algorithm Selection │
|
||||||
|
│ ├─ Present menu: LZ4 (fast) vs ZSTD (better ratio) │
|
||||||
|
│ └─ User choice stored in $algo variable │
|
||||||
|
│ │
|
||||||
|
│ 3. Size Calculation Logic │
|
||||||
|
│ ┌──────────────────────────────────────────────┐ │
|
||||||
|
│ │ half_ram_mb = ((RAM_KB / 1024 / 1024 + 1) │ │
|
||||||
|
│ │ / 2) * 1024 │ │
|
||||||
|
│ └──────────────────────────────────────────────┘ │
|
||||||
|
│ └─ Result: ~50% of total physical RAM in MB │
|
||||||
|
│ │
|
||||||
|
│ 4. Configuration Confirmation │
|
||||||
|
│ ├─ Display summary with algorithm, size, priority=100 │
|
||||||
|
│ └─ User must confirm before applying │
|
||||||
|
│ │
|
||||||
|
│ 5. Package Installation │
|
||||||
|
│ sudo apt install -y zram-tools │
|
||||||
|
│ │
|
||||||
|
│ 6. Configuration File Write │
|
||||||
|
│ /etc/default/zramswap │
|
||||||
|
│ ALGO=$algo │
|
||||||
|
│ SIZE=$zram_size │
|
||||||
|
│ PRIORITY=100 │
|
||||||
|
│ │
|
||||||
|
│ 7. Service Restart │
|
||||||
|
│ sudo systemctl restart zramswap │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mathematical Size Calculation
|
||||||
|
|
||||||
|
The script uses this formula to determine ZRAM size:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
half_ram_mb=$(( ((RAM_KB / 1024 / 1024 + 1) / 2) * 1024 ))
|
||||||
|
```
|
||||||
|
|
||||||
|
**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:**
|
||||||
|
```
|
||||||
|
System with 8 GB (8388608 KB) RAM:
|
||||||
|
half_ram_mb = ((8388608 / 1024 / 1024 + 1) / 2) * 1024
|
||||||
|
= ((8 + 1) / 2) * 1024
|
||||||
|
= (9 / 2) * 1024
|
||||||
|
= 4.5 * 1024
|
||||||
|
= 4608 MB (~4.5 GB)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Priority Configuration (`PRIORITY=100`)
|
||||||
|
|
||||||
|
The `swapon` priority determines which swap device the kernel prefers when multiple devices exist:
|
||||||
|
|
||||||
|
- **Higher number** = Higher preference (used first by kernel)
|
||||||
|
- **Default system swap**: Typically 0–60
|
||||||
|
- **ZRAM with PRIORITY=100**: Ensures ZRAM is used before physical disk swap
|
||||||
|
|
||||||
|
This prevents thrashing where pages bounce between slow disk swap and fast RAM-based ZRAM.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Kernel Parameter Tuning (`sysctl`)
|
||||||
|
|
||||||
|
### Essential VM Parameters for Aggressive ZRAM Usage
|
||||||
|
|
||||||
|
While the current script focuses on `zram-tools` configuration, optimal performance requires complementary kernel parameter tuning:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Recommended sysctl configuration for ZRAM systems
|
||||||
|
vm.swappiness = 180
|
||||||
|
vm.watermark_boost_factor = 0
|
||||||
|
vm.watermark_scale_factor = 125
|
||||||
|
vm.page-cluster = 0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameter Explanations
|
||||||
|
|
||||||
|
| Parameter | Value | Purpose |
|
||||||
|
|-----------|-------|---------|
|
||||||
|
| **`vm.swappiness`** | `180–200` | 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 (20–40) 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 2–3x 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
|
||||||
|
|
||||||
|
### Safe Service Initialization
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo systemctl restart zramswap
|
||||||
|
```
|
||||||
|
|
||||||
|
**Why `restart` instead of `start`:**
|
||||||
|
- Ensures previous configuration is cleanly terminated
|
||||||
|
- Prevents orphaned processes from conflicting with new settings
|
||||||
|
- Reloads systemd unit files if they were modified during installation
|
||||||
|
|
||||||
|
### User Verification Commands
|
||||||
|
|
||||||
|
#### Primary: `zramctl` (util-linux)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo zramctl
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output Interpretation:**
|
||||||
|
```
|
||||||
|
NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT
|
||||||
|
/dev/zram0 lz4 4G 2.1G 318.6M 424.9M [SWAP]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Column | Meaning |
|
||||||
|
|--------|---------|
|
||||||
|
| **NAME** | Device identifier (/dev/zram0) |
|
||||||
|
| **ALGORITHM** | Active compression algorithm (lz4, zstd, etc.) |
|
||||||
|
| **DISKSIZE** | Maximum uncompressed data capacity configured |
|
||||||
|
| **DATA** | Currently stored uncompressed pages in ZRAM |
|
||||||
|
| **COMPR** | Actual compressed size using physical RAM |
|
||||||
|
| **TOTAL** | Total memory used including metadata overhead |
|
||||||
|
| **STREAMS** | Number of active swap streams (typically 4) |
|
||||||
|
|
||||||
|
#### Secondary: `swapon --show`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo swapon --show
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows all active swap devices with priority levels. ZRAM should appear with priority matching the configured value (100 in this script).
|
||||||
|
|
||||||
|
### Real-Time Monitoring
|
||||||
|
|
||||||
|
For continuous monitoring of compression effectiveness:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Watch compression ratio changes over time
|
||||||
|
watch -n 5 'zramctl | grep /dev/zram'
|
||||||
|
|
||||||
|
# Monitor memory pressure and swap usage
|
||||||
|
watch -n 5 'free -h && zramctl'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Troubleshooting Indicators
|
||||||
|
|
||||||
|
| 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 |
|
||||||
|
| 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` |
|
||||||
|
|
||||||
|
### Permanent Configuration
|
||||||
|
|
||||||
|
To ensure ZRAM persists across reboots, the script writes configuration to `/etc/default/zramswap`. This file is read by systemd's `zramswap.service` unit at boot time. Additionally, adding the following ensures the kernel module loads:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo "zram" | sudo tee /etc/modules-load.d/zram.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### References:
|
||||||
|
|
||||||
|
- [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.archlinux.org/title/Zram](https://wiki.archlinux.org/title/Zram)
|
||||||
|
- [https://wiki.gentoo.org/wiki/Zram](https://wiki.gentoo.org/wiki/Zram)
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 852 KiB |
@@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# modules/bluetooth.sh
|
||||||
|
# Requires: modules/utils.sh (globals + helpers), modules/firmware.sh (PCI_BT_DEVS, USB_BT_DEVS, USB_WIFI_DEVS)
|
||||||
|
|
||||||
|
_install_bluetooth_stack() {
|
||||||
|
local has_bt=false
|
||||||
|
[ ${#PCI_BT_DEVS[@]} -gt 0 ] && has_bt=true
|
||||||
|
[ ${#USB_BT_DEVS[@]} -gt 0 ] && has_bt=true
|
||||||
|
if ! $has_bt; then
|
||||||
|
for dev in "${USB_WIFI_DEVS[@]}"; do
|
||||||
|
if echo "$dev" | grep -qi 'bluetooth'; then
|
||||||
|
has_bt=true; break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
if ! $has_bt; then
|
||||||
|
echo " → No Bluetooth hardware detected, skipping."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if is_installed bluez; then
|
||||||
|
echo " → Bluetooth stack already installed."
|
||||||
|
service_enable_only=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! ${service_enable_only:-false} = true ]; then
|
||||||
|
local bt_pkgs=()
|
||||||
|
! is_installed bluez && bt_pkgs+=(bluez)
|
||||||
|
! is_installed bluez-tools && bt_pkgs+=(bluez-tools)
|
||||||
|
! is_installed bluez-obexd && bt_pkgs+=(bluez-obexd)
|
||||||
|
if [ ${#bt_pkgs[@]} -gt 0 ]; then
|
||||||
|
_run_cmd "Bluetooth" "sudo DEBIAN_FRONTEND=noninteractive apt install -y ${bt_pkgs[*]}" "Installing Bluetooth stack..."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v rfkill &>/dev/null; then
|
||||||
|
if rfkill list bluetooth 2>/dev/null | grep -q "Soft blocked: yes"; then
|
||||||
|
echo " → Unblocking Bluetooth (rfkill)..."
|
||||||
|
sudo rfkill unblock bluetooth
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${DESKTOP_ENV:-other}" in
|
||||||
|
kde)
|
||||||
|
if ! is_installed bluedevil; then
|
||||||
|
_run_cmd "Bluetooth" "sudo DEBIAN_FRONTEND=noninteractive apt install -y bluedevil" "Installing bluedevil..."
|
||||||
|
fi
|
||||||
|
if [ "${AUDIO_SERVER:-}" = "pipewire" ]; then
|
||||||
|
! is_installed pipewire-pulse && _run_cmd "Bluetooth" "sudo DEBIAN_FRONTEND=noninteractive apt install -y pipewire-pulse" "Installing pipewire-pulse..."
|
||||||
|
! is_installed wireplumber && _run_cmd "Bluetooth" "sudo DEBIAN_FRONTEND=noninteractive apt install -y wireplumber" "Installing wireplumber..."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
gnome)
|
||||||
|
echo " → GNOME Bluetooth support already in gnome-control-center."
|
||||||
|
;;
|
||||||
|
xfce|other)
|
||||||
|
if ! is_installed blueman; then
|
||||||
|
_run_cmd "Bluetooth" "sudo DEBIAN_FRONTEND=noninteractive apt install -y blueman" "Installing blueman..."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if ! systemctl is-enabled bluetooth &>/dev/null 2>&1; then
|
||||||
|
sudo systemctl enable bluetooth 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
if ! systemctl is-active bluetooth &>/dev/null 2>&1; then
|
||||||
|
sudo systemctl start bluetooth 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
_msg "Bluetooth Setup" "Bluetooth stack installed.\n\nA session restart or reboot is\nrecommended to load the desktop\napplets and tray icons." 10 60
|
||||||
|
}
|
||||||
@@ -0,0 +1,623 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# extras.sh — Bullseye: software purgado / solo repos oficiales
|
||||||
|
# License GPL v3
|
||||||
|
|
||||||
|
# ── Essential Pack (Bullseye) ──
|
||||||
|
_quick_install_bullseye() {
|
||||||
|
_msg "Essential Pack — Bullseye" \
|
||||||
|
"Install basic programs:\n\n\
|
||||||
|
- Compression (zip, unrar, p7zip-full)\n\
|
||||||
|
- System tools (htop, inxi, neofetch, bpytop)\n\
|
||||||
|
- VLC media player\n\
|
||||||
|
- Microsoft fonts" 13 60
|
||||||
|
|
||||||
|
local quick_pkgs=(
|
||||||
|
zip unzip rar unrar p7zip-full p7zip-rar
|
||||||
|
neofetch bpytop htop inxi vlc
|
||||||
|
ttf-mscorefonts-installer
|
||||||
|
)
|
||||||
|
_run_install_batch "${quick_pkgs[@]}"
|
||||||
|
echo -e "${GREEN}Essential Pack installed.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Firmware (Bullseye) ──
|
||||||
|
install_firmware_bullseye() {
|
||||||
|
echo -e "${YELLOW}Installing firmware-linux-nonfree (Bullseye)...${NC}"
|
||||||
|
|
||||||
|
# ── Safeguard: non-free repos must be enabled ──
|
||||||
|
if ! grep -qr "non-free" /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null; then
|
||||||
|
_msg "Error" "Error: No 'non-free' repositories were detected.\n\
|
||||||
|
Please first run the 'Configure repositories' option in the\n\
|
||||||
|
main menu to install proprietary firmwares." 10 65
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if is_installed "firmware-linux-nonfree"; then
|
||||||
|
echo "firmware-linux-nonfree already installed."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local fw_ver
|
||||||
|
fw_ver=$(apt-cache policy firmware-linux-nonfree 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
|
|
||||||
|
if _confirm "Firmware" \
|
||||||
|
"firmware-linux-nonfree proporciona drivers para:\n\
|
||||||
|
WiFi, Bluetooth, GPU, audio, webcams, etc.\n\n\
|
||||||
|
Version: ${fw_ver:-unknown}\n\n\
|
||||||
|
Instalar?"; then
|
||||||
|
_run_cmd "Firmware" "sudo apt install -y firmware-linux-nonfree" \
|
||||||
|
"Installing firmware-linux-nonfree..."
|
||||||
|
echo -e "${GREEN}Firmware installed.${NC}"
|
||||||
|
fi
|
||||||
|
type _handle_wireless &>/dev/null && _handle_wireless
|
||||||
|
}
|
||||||
|
|
||||||
|
# ======================================================================
|
||||||
|
# EXTRA SOFTWARE CATEGORIES — Bullseye versions (purged/whitelisted)
|
||||||
|
# Only packages available in Debian 11 official repos.
|
||||||
|
# ======================================================================
|
||||||
|
|
||||||
|
_cat_customization_bullseye() {
|
||||||
|
local sub
|
||||||
|
sub=$(_menu "Customization (Bullseye)" "Select type:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
||||||
|
"1" "Desktop Themes (GTK/KDE)" \
|
||||||
|
"2" "Icon Themes" \
|
||||||
|
"3" "Cursor Themes" \
|
||||||
|
"4" "Fonts" \
|
||||||
|
)
|
||||||
|
[ -z "$sub" ] && return
|
||||||
|
case $sub in
|
||||||
|
1) _cat_themes_bullseye ;;
|
||||||
|
2) _cat_icons_bullseye ;;
|
||||||
|
3) _cat_cursors_bullseye ;;
|
||||||
|
4) _cat_fonts_bullseye ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_cat_themes_bullseye() {
|
||||||
|
local item_count=6
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "Desktop Themes (Bullseye)" "Select desktop themes${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
|
"arc-theme" "Arc GTK theme" "$(_state arc-theme)" \
|
||||||
|
"blackbird-gtk-theme" "Blackbird GTK theme" "$(_state blackbird-gtk-theme)" \
|
||||||
|
"bluebird-gtk-theme" "Bluebird GTK theme" "$(_state bluebird-gtk-theme)" \
|
||||||
|
"breeze-gtk-theme" "Breeze GTK theme (KDE port)" "$(_state breeze-gtk-theme)" \
|
||||||
|
"greybird-gtk-theme" "Greybird GTK theme" "$(_state greybird-gtk-theme)" \
|
||||||
|
"numix-gtk-theme" "Numix GTK theme" "$(_state numix-gtk-theme)" \
|
||||||
|
)
|
||||||
|
clear
|
||||||
|
[ -z "$choices" ] && return
|
||||||
|
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
for pkg in $cleaned; do
|
||||||
|
! is_installed "$pkg" && _run_install "$pkg" || echo "$pkg already installed."
|
||||||
|
done
|
||||||
|
echo -e "${GREEN}Desktop themes installed.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_cat_icons_bullseye() {
|
||||||
|
local items=(
|
||||||
|
"breeze-icon-theme" "Breeze icon theme" "$(_state breeze-icon-theme)"
|
||||||
|
"deepin-icon-theme" "Deepin icon theme" "$(_state deepin-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-circle" "Numix Circle icon theme" "$(_state numix-icon-theme-circle)"
|
||||||
|
"obsidian-icon-theme" "Obsidian icon theme" "$(_state obsidian-icon-theme)"
|
||||||
|
"papirus-icon-theme" "Papirus icon theme" "$(_state papirus-icon-theme)"
|
||||||
|
"paper-icon-theme" "Paper icon theme" "$(_state paper-icon-theme)"
|
||||||
|
"suru-icon-theme" "Suru icon theme" "$(_state suru-icon-theme)"
|
||||||
|
)
|
||||||
|
local item_count=${#items[@]}
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "Icon Themes (Bullseye)" "Select icon themes${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
|
"${items[@]}" )
|
||||||
|
clear
|
||||||
|
[ -z "$choices" ] && return
|
||||||
|
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
for pkg in $cleaned; do
|
||||||
|
! is_installed "$pkg" && _run_install "$pkg" || echo "$pkg already installed."
|
||||||
|
done
|
||||||
|
echo -e "${GREEN}Icon themes installed.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_cat_cursors_bullseye() {
|
||||||
|
local item_count=5
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "Cursor Themes (Bullseye)" "Select cursor themes${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
|
"breeze-cursor-theme" "Breeze cursors (KDE)" "$(_state breeze-cursor-theme)" \
|
||||||
|
"chameleon-cursor-theme" "Chameleon cursors" "$(_state chameleon-cursor-theme)" \
|
||||||
|
"dmz-cursor-theme" "DMZ cursors" "$(_state dmz-cursor-theme)" \
|
||||||
|
"oxygencursors" "Oxygen cursors (KDE legacy)" "$(_state oxygencursors)" \
|
||||||
|
"xcursor-themes" "X11 base cursors" "$(_state xcursor-themes)" \
|
||||||
|
)
|
||||||
|
clear
|
||||||
|
[ -z "$choices" ] && return
|
||||||
|
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
for pkg in $cleaned; do
|
||||||
|
! is_installed "$pkg" && _run_install "$pkg" || echo "$pkg already installed."
|
||||||
|
done
|
||||||
|
echo -e "${GREEN}Cursor themes installed.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_cat_fonts_bullseye() {
|
||||||
|
local item_count=4
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "Fonts (Bullseye)" "Available fonts${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
|
"fonts-firacode" "Fira Code monospace font" "$(_state fonts-firacode)" \
|
||||||
|
"fonts-noto" "Noto fonts (Google)" "$(_state fonts-noto)" \
|
||||||
|
"fonts-dejavu-core" "DejaVu core fonts" "$(_state fonts-dejavu-core)" \
|
||||||
|
"ttf-mscorefonts-installer" "Microsoft Core Fonts" "$(_state ttf-mscorefonts-installer)" \
|
||||||
|
)
|
||||||
|
clear
|
||||||
|
[ -z "$choices" ] && return
|
||||||
|
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
for pkg in $cleaned; do
|
||||||
|
! is_installed "$pkg" && _run_install "$pkg" || echo "$pkg already installed."
|
||||||
|
done
|
||||||
|
echo -e "${GREEN}Fonts installed.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_cat_download_bullseye() {
|
||||||
|
local choices1 choices2=""
|
||||||
|
|
||||||
|
local item_count1=2
|
||||||
|
local lista_alto1=$((item_count1 > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count1))
|
||||||
|
choices1=$(_checklist "Downloaders" "Select download tools:" $TUI_ALTO $TUI_ANCHO $lista_alto1 \
|
||||||
|
"aria2" "Multiprotocol downloader (CLI)" "$(_state aria2)" \
|
||||||
|
"filezilla" "FTP/SFTP client (GUI)" "$(_state filezilla)" \
|
||||||
|
)
|
||||||
|
clear
|
||||||
|
|
||||||
|
local item_count2=8
|
||||||
|
local lista_alto2=$((item_count2 > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count2))
|
||||||
|
choices2=$(_checklist "Torrent Clients" "Select torrent clients${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto2 \
|
||||||
|
"deluge" "BitTorrent client (GTK)" "$(_state deluge)" \
|
||||||
|
"deluged" "BitTorrent daemon/server" "$(_state deluged)" \
|
||||||
|
"mktorrent" "Torrent metainfo creator (CLI)" "$(_state mktorrent)" \
|
||||||
|
"qbittorrent" "BitTorrent client (Qt)" "$(_state qbittorrent)" \
|
||||||
|
"qbittorrent-nox" "BitTorrent WebUI/CLI" "$(_state qbittorrent-nox)" \
|
||||||
|
"transmission-cli" "BitTorrent client (CLI)" "$(_state transmission-cli)" \
|
||||||
|
"transmission-gtk" "BitTorrent client (GTK)" "$(_state transmission-gtk)" \
|
||||||
|
"transmission-qt" "BitTorrent client (Qt)" "$(_state transmission-qt)" \
|
||||||
|
)
|
||||||
|
clear
|
||||||
|
|
||||||
|
local cleaned
|
||||||
|
cleaned=$(echo "$choices1 $choices2" | tr -d '"')
|
||||||
|
[ -z "$cleaned" ] && { echo "No download tools selected."; return; }
|
||||||
|
|
||||||
|
for pkg in $cleaned; do
|
||||||
|
if ! is_installed "$pkg"; then
|
||||||
|
_run_install "$pkg"
|
||||||
|
else
|
||||||
|
echo "$pkg already installed."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo -e "${GREEN}Download & network tools installed.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_cat_internet_bullseye() {
|
||||||
|
local item_count=11
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "Internet (Bullseye)" "Select browsers, email${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
|
"chromium" "Chromium web browser" "$(_state chromium)" \
|
||||||
|
"dillo" "Lightweight graphical browser" "$(_state dillo)" \
|
||||||
|
"elinks" "Text-mode web browser" "$(_state elinks)" \
|
||||||
|
"epiphany-browser" "GNOME web browser" "$(_state epiphany-browser)" \
|
||||||
|
"falkon" "KDE web browser (QtWebEngine)" "$(_state falkon)" \
|
||||||
|
"firefox-esr" "Firefox ESR (official Debian)" "$(_state firefox-esr)" \
|
||||||
|
"konqueror" "KDE file manager / web browser" "$(_state konqueror)" \
|
||||||
|
"qutebrowser" "Keyboard-driven browser (Qt)" "$(_state qutebrowser)" \
|
||||||
|
"thunderbird" "Email client" "$(_state thunderbird)" \
|
||||||
|
"torbrowser-launcher" "Tor Browser launcher" "$(_state torbrowser-launcher)" \
|
||||||
|
"w3m" "Text-mode browser + deps" "$(_state w3m)" \
|
||||||
|
)
|
||||||
|
clear
|
||||||
|
[ -z "$choices" ] && return
|
||||||
|
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
for pkg in $cleaned; do
|
||||||
|
case $pkg in
|
||||||
|
w3m)
|
||||||
|
local need=()
|
||||||
|
! is_installed "w3m" && need+=("w3m")
|
||||||
|
! is_installed "w3m-img" && need+=("w3m-img")
|
||||||
|
! is_installed "ca-certificates" && need+=("ca-certificates")
|
||||||
|
! is_installed "xsel" && need+=("xsel")
|
||||||
|
[ ${#need[@]} -gt 0 ] && _run_install_batch "${need[@]}" || echo "Already installed."
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if ! is_installed "$pkg"; then
|
||||||
|
_run_install "$pkg"
|
||||||
|
else
|
||||||
|
echo "$pkg already installed."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
echo -e "${GREEN}Internet tools installed.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_cat_players_bullseye() {
|
||||||
|
local item_count=2
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "Media Players (Bullseye)" "Select media players${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
|
"mpv" "Lightweight media player" "$(_state mpv)" \
|
||||||
|
"vlc" "VLC media player" "$(_state vlc)" \
|
||||||
|
)
|
||||||
|
clear
|
||||||
|
[ -z "$choices" ] && return
|
||||||
|
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
for pkg in $cleaned; do
|
||||||
|
if ! is_installed "$pkg"; then
|
||||||
|
_run_install "$pkg"
|
||||||
|
else
|
||||||
|
echo "$pkg already installed."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo -e "${GREEN}Media players installed.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_cat_design_bullseye() {
|
||||||
|
local item_count=13
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "Multimedia & Design (Bullseye)" "Select multimedia and design tools${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
|
"ardour" "Digital audio workstation" "$(_state ardour)" \
|
||||||
|
"audacity" "Audio editor/recorder" "$(_state audacity)" \
|
||||||
|
"blender" "3D modeling/animation suite" "$(_state blender)" \
|
||||||
|
"ffmpeg" "Multimedia framework (CLI)" "$(_state ffmpeg)" \
|
||||||
|
"gimp" "Image editor" "$(_state gimp)" \
|
||||||
|
"handbrake" "Video transcoder (DVD ripper)" "$(_state handbrake)" \
|
||||||
|
"inkscape" "Vector graphics editor" "$(_state inkscape)" \
|
||||||
|
"kdenlive" "Video editor (KDE)" "$(_state kdenlive)" \
|
||||||
|
"krita" "Digital painting/illustration" "$(_state krita)" \
|
||||||
|
"obs-studio" "Screen recording/streaming" "$(_state obs-studio)" \
|
||||||
|
"openshot-qt" "Video editor (simple)" "$(_state openshot-qt)" \
|
||||||
|
"scribus" "Desktop publishing (DTP)" "$(_state scribus)" \
|
||||||
|
"shotcut" "Video editor (cross-platform)" "$(_state shotcut)" \
|
||||||
|
)
|
||||||
|
clear
|
||||||
|
[ -z "$choices" ] && return
|
||||||
|
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
for pkg in $cleaned; do
|
||||||
|
if ! is_installed "$pkg"; then
|
||||||
|
_run_install "$pkg"
|
||||||
|
else
|
||||||
|
echo "$pkg already installed."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo -e "${GREEN}Multimedia & design tools installed.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_cat_programming_bullseye() {
|
||||||
|
local item_count=9
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "Code Editors & IDEs (Bullseye)" "Select editors and IDEs${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
|
"vim" "Classic terminal editor" "$(_state vim)" \
|
||||||
|
"vim-gtk3" "Vim with GTK3 GUI" "$(_state vim-gtk3)" \
|
||||||
|
"neovim" "Modern vim fork" "$(_state neovim)" \
|
||||||
|
"nano" "Simple terminal editor" "$(_state nano)" \
|
||||||
|
"emacs" "Extensible editor / IDE" "$(_state emacs)" \
|
||||||
|
"kate" "KDE advanced text editor" "$(_state kate)" \
|
||||||
|
"mousepad" "Xfce text editor" "$(_state mousepad)" \
|
||||||
|
"gedit" "GNOME text editor" "$(_state gedit)" \
|
||||||
|
"geany" "Lightweight IDE" "$(_state geany)" \
|
||||||
|
)
|
||||||
|
clear
|
||||||
|
[ -z "$choices" ] && return
|
||||||
|
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
for pkg in $cleaned; do
|
||||||
|
if ! is_installed "$pkg"; then
|
||||||
|
_run_install "$pkg"
|
||||||
|
else
|
||||||
|
echo "$pkg already installed."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo -e "${GREEN}Code editors & IDEs installed.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_cat_dev_bullseye() {
|
||||||
|
local item_count=14
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "Servers & Dev Tools (Bullseye)" "Select development tools and servers${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
|
"apache2" "Apache web server" "$(_state apache2)" \
|
||||||
|
"build-essential" "C/C++ build tools (gcc, make)" "$(_state build-essential)" \
|
||||||
|
"docker" "Docker container runtime" "$(_state docker.io)" \
|
||||||
|
"mariadb-server" "MariaDB database server" "$(_state mariadb-server)" \
|
||||||
|
"netcat-openbsd" "TCP/IP networking utility" "$(_state netcat-openbsd)" \
|
||||||
|
"nginx" "Nginx web server" "$(_state nginx)" \
|
||||||
|
"openssh-server" "SSH server" "$(_state openssh-server)" \
|
||||||
|
"openssl" "OpenSSL cryptography toolkit" "$(_state openssl)" \
|
||||||
|
"postgresql" "PostgreSQL database server" "$(_state postgresql)" \
|
||||||
|
"python3-pip" "Python 3 pip + venv + dev" "$(_state python3-pip)" \
|
||||||
|
"redis-server" "Redis key-value store" "$(_state redis-server)" \
|
||||||
|
"sqlite3" "SQLite database engine" "$(_state sqlite3)" \
|
||||||
|
"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
|
||||||
|
[ -z "$choices" ] && return
|
||||||
|
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
for pkg in $cleaned; do
|
||||||
|
case $pkg in
|
||||||
|
docker)
|
||||||
|
local need=()
|
||||||
|
! is_installed "docker.io" && need+=("docker.io")
|
||||||
|
! is_installed "docker-compose" && need+=("docker-compose")
|
||||||
|
if [ ${#need[@]} -gt 0 ]; then
|
||||||
|
_run_install_batch "${need[@]}"
|
||||||
|
else
|
||||||
|
echo "Docker already installed."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
python3-pip)
|
||||||
|
local need=()
|
||||||
|
! is_installed "python3-pip" && need+=("python3-pip")
|
||||||
|
! is_installed "python3-venv" && need+=("python3-venv")
|
||||||
|
! is_installed "python3-dev" && need+=("python3-dev")
|
||||||
|
if [ ${#need[@]} -gt 0 ]; then
|
||||||
|
_run_install_batch "${need[@]}"
|
||||||
|
else
|
||||||
|
echo "Python 3 tools already installed."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
jellyfin)
|
||||||
|
install_jellyfin
|
||||||
|
;;
|
||||||
|
openjdk-dev-env)
|
||||||
|
_install_dev_java
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
if ! is_installed "$pkg"; then
|
||||||
|
_run_install "$pkg"
|
||||||
|
else
|
||||||
|
echo "$pkg already installed."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
echo -e "${GREEN}Servers & dev tools installed.${NC}"
|
||||||
|
}
|
||||||
|
_cat_security_bullseye() {
|
||||||
|
local item_count=5
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "Security & Networking (Bullseye)" "Select security and networking tools${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
|
"wireshark" "Network protocol analyzer (GUI)" "$(_state wireshark)" \
|
||||||
|
"tcpdump" "Command-line packet analyzer" "$(_state tcpdump)" \
|
||||||
|
"fail2ban" "Brute-force protection daemon" "$(_state fail2ban)" \
|
||||||
|
"ufw" "Uncomplicated firewall" "$(_state ufw)" \
|
||||||
|
"clamav" "Antivirus engine (ClamAV)" "$(_state clamav)" \
|
||||||
|
)
|
||||||
|
clear
|
||||||
|
[ -z "$choices" ] && return
|
||||||
|
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
for pkg in $cleaned; do
|
||||||
|
case $pkg in
|
||||||
|
clamav)
|
||||||
|
_install_clamav
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if ! is_installed "$pkg"; then
|
||||||
|
_run_install "$pkg"
|
||||||
|
else
|
||||||
|
echo "$pkg already installed."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
echo -e "${GREEN}Security & networking tools installed.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_cat_general_bullseye() {
|
||||||
|
local item_count=18
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "System Tools (Bullseye)" "Select system utilities${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
|
"compress" "Compression tools (zip, unrar, p7zip)" "$(_state zip)" \
|
||||||
|
"conky" "System monitor for desktop" "$(_state conky)" \
|
||||||
|
"cpu-x" "CPU-X (alternative to CPU-Z)" "$(_state cpu-x)" \
|
||||||
|
"curl-wget" "HTTP transfer tools (curl, wget)" "$(_state curl)" \
|
||||||
|
"flatpak" "Flatpak sandbox (Bullseye native)" "$(_state flatpak)" \
|
||||||
|
"fwupd" "Firmware update daemon" "$(_state fwupd)" \
|
||||||
|
"gnome-disk-utility" "Disk management GUI" "$(_state gnome-disk-utility)" \
|
||||||
|
"gparted" "Partition editor" "$(_state gparted)" \
|
||||||
|
"htop" "Interactive process viewer" "$(_state htop)" \
|
||||||
|
"inxi" "System information tool" "$(_state inxi)" \
|
||||||
|
"kvm" "QEMU/KVM virtualization" "$(_state virt-manager)" \
|
||||||
|
"lshw" "List hardware details" "$(_state lshw)" \
|
||||||
|
"mc" "Midnight Commander" "$(_state mc)" \
|
||||||
|
"nvme-cli" "NVMe SSD health monitoring" "$(_state nvme-cli)" \
|
||||||
|
"ncdu" "Disk usage analyzer" "$(_state ncdu)" \
|
||||||
|
"psensor" "Temperature monitor" "$(_state psensor)" \
|
||||||
|
"timeshift" "System restore snapshots" "$(_state timeshift)" \
|
||||||
|
"tmux" "Terminal multiplexer" "$(_state tmux)" \
|
||||||
|
"wine" "Windows compatibility layer" "$(_state wine)" \
|
||||||
|
)
|
||||||
|
clear
|
||||||
|
[ -z "$choices" ] && return
|
||||||
|
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
for pkg in $cleaned; do
|
||||||
|
case $pkg in
|
||||||
|
compress)
|
||||||
|
local need=()
|
||||||
|
! is_installed "zip" && need+=("zip")
|
||||||
|
! is_installed "unzip" && need+=("unzip")
|
||||||
|
! is_installed "rar" && need+=("rar")
|
||||||
|
! is_installed "unrar" && need+=("unrar")
|
||||||
|
! is_installed "p7zip-full" && need+=("p7zip-full")
|
||||||
|
! is_installed "p7zip-rar" && need+=("p7zip-rar")
|
||||||
|
[ ${#need[@]} -gt 0 ] && _run_install_batch "${need[@]}"
|
||||||
|
;;
|
||||||
|
curl-wget)
|
||||||
|
local need=()
|
||||||
|
! is_installed "curl" && need+=("curl")
|
||||||
|
! is_installed "wget" && need+=("wget")
|
||||||
|
[ ${#need[@]} -gt 0 ] && _run_install_batch "${need[@]}" || echo "Already installed."
|
||||||
|
;;
|
||||||
|
kvm)
|
||||||
|
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..."
|
||||||
|
sudo adduser "$USER" libvirt 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
|
||||||
|
echo -e "${YELLOW}Wine installed but version check failed.${NC}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Wine64 already installed."
|
||||||
|
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
|
||||||
|
done
|
||||||
|
echo -e "${GREEN}System tools installed.${NC}"
|
||||||
|
_pause
|
||||||
|
}
|
||||||
|
|
||||||
|
_cat_fetch_bullseye() {
|
||||||
|
local items=(
|
||||||
|
"neofetch" "System info fetcher" "$(_state neofetch)"
|
||||||
|
"screenfetch" "System info (BSD/Linux)" "$(_state screenfetch)"
|
||||||
|
"linuxlogo" "Linux logo + system info" "$(_state linuxlogo)"
|
||||||
|
)
|
||||||
|
local item_count=${#items[@]}
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "Fetch Tools (Bullseye)" "Select system info tools:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
|
"${items[@]}" )
|
||||||
|
clear
|
||||||
|
[ -z "$choices" ] && return
|
||||||
|
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
for pkg in $cleaned; do
|
||||||
|
if ! is_installed "$pkg"; then
|
||||||
|
_run_install "$pkg"
|
||||||
|
else
|
||||||
|
echo "$pkg already installed."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo -e "${GREEN}Fetch tools installed.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ======================================================================
|
||||||
|
# master installer — replaces install_extras() on Bullseye
|
||||||
|
# ======================================================================
|
||||||
|
install_extras_bullseye() {
|
||||||
|
echo -e "${YELLOW}Extra software — Bullseye mode (official repos only).${NC}"
|
||||||
|
_load_extras
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
local cat_choice
|
||||||
|
cat_choice=$(_menu "Extra Software — Bullseye" "Select a category${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
||||||
|
"0" "Essential Pack" \
|
||||||
|
"1" "Customization System" \
|
||||||
|
"2" "Download & Network" \
|
||||||
|
"3" "Internet (Browsers, Email)" \
|
||||||
|
"4" "Media Players" \
|
||||||
|
"5" "Multimedia & Design" \
|
||||||
|
"6" "Code Editors & IDEs" \
|
||||||
|
"7" "Servers & Dev Tools" \
|
||||||
|
"8" "Security & Networking" \
|
||||||
|
"9" "Software Centers" \
|
||||||
|
"10" "System Tools" \
|
||||||
|
"11" "Fetch / System Info" \
|
||||||
|
"12" "Back to main menu" \
|
||||||
|
)
|
||||||
|
|
||||||
|
[ -z "$cat_choice" ] && return
|
||||||
|
clear
|
||||||
|
|
||||||
|
case "$cat_choice" in
|
||||||
|
0) _quick_install_bullseye ;;
|
||||||
|
1) _cat_customization_bullseye ;;
|
||||||
|
2) _cat_download_bullseye ;;
|
||||||
|
3) _cat_internet_bullseye ;;
|
||||||
|
4) _cat_players_bullseye ;;
|
||||||
|
5) _cat_design_bullseye ;;
|
||||||
|
6) _cat_programming_bullseye ;;
|
||||||
|
7) _cat_dev_bullseye ;;
|
||||||
|
8) _cat_security_bullseye ;;
|
||||||
|
9) _cat_software_centers_bullseye ;;
|
||||||
|
10) _cat_general_bullseye ;;
|
||||||
|
11) _cat_fetch_bullseye ;;
|
||||||
|
12) return ;;
|
||||||
|
esac
|
||||||
|
clear
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
_cat_software_centers_bullseye() {
|
||||||
|
local sc_choice
|
||||||
|
sc_choice=$(_menu "Software Centers" "Choose a software store to install:" 12 65 2 \
|
||||||
|
"gnome-software" "Software Center for GNOME" \
|
||||||
|
"plasma-discover" "Software manager for Plasma" \
|
||||||
|
)
|
||||||
|
[ -z "$sc_choice" ] && return
|
||||||
|
|
||||||
|
_run_cmd "Install" "sudo apt install -y $sc_choice" "Installing ${sc_choice}..."
|
||||||
|
|
||||||
|
if _confirm "Flatpak Support" "Do you want to enable Flatpak support for this software center?"; then
|
||||||
|
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}"
|
||||||
|
}
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# legacy.sh — Bullseye: hardware detection, NVIDIA legacy drivers, lightweight gaming
|
||||||
|
# License GPL v3
|
||||||
|
|
||||||
|
BULLSEYE_USE_ARCHIVE=false
|
||||||
|
BULLSEYE_USE_ARCHIVE_CHECKED=false
|
||||||
|
|
||||||
|
check_bullseye_archive_phase() {
|
||||||
|
$BULLSEYE_USE_ARCHIVE_CHECKED && return
|
||||||
|
BULLSEYE_USE_ARCHIVE_CHECKED=true
|
||||||
|
|
||||||
|
local current_year
|
||||||
|
local current_month
|
||||||
|
current_year=$(date +%Y)
|
||||||
|
current_month=$(date +%-m)
|
||||||
|
|
||||||
|
if [ "$current_year" -gt 2026 ] || \
|
||||||
|
{ [ "$current_year" -eq 2026 ] && [ "$current_month" -ge 9 ]; }; then
|
||||||
|
BULLSEYE_USE_ARCHIVE=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $BULLSEYE_USE_ARCHIVE; then
|
||||||
|
_msg "Debian 11 — Archive Phase" \
|
||||||
|
"Bullseye LTS support ended on 31 Aug 2026.\n\n\
|
||||||
|
The script will use archive.debian.org mirrors.\n\
|
||||||
|
No security updates will be available." 12 60
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# NVIDIA driver installer for Bullseye (Kepler → 470, Fermi → 390)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
install_nvidia_bullseye() {
|
||||||
|
echo -e "${YELLOW}NVIDIA GPU detected (Bullseye mode).${NC}"
|
||||||
|
|
||||||
|
local is_fermi; is_fermi=$(is_nvidia_fermi)
|
||||||
|
|
||||||
|
local nv_pkg=""
|
||||||
|
local gpu_gen=""
|
||||||
|
|
||||||
|
if [ "$is_fermi" = "true" ]; then
|
||||||
|
nv_pkg="nvidia-legacy-390xx-driver"
|
||||||
|
gpu_gen="Fermi"
|
||||||
|
else
|
||||||
|
# Bullseye: cualquier otra NVIDIA (Kepler incl.) → nvidia-driver (470)
|
||||||
|
nv_pkg="nvidia-driver"
|
||||||
|
gpu_gen="NVIDIA"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local nv_ver
|
||||||
|
nv_ver=$(apt-cache policy "$nv_pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
|
|
||||||
|
local msg="Source: Debian Bullseye Stable\n"
|
||||||
|
msg+="Driver: ${gpu_gen} — ${nv_pkg} ${nv_ver:-unknown}\n"
|
||||||
|
msg+="[+] firmware-misc-nonfree\n"
|
||||||
|
msg+="[+] nvidia-settings\n\n"
|
||||||
|
msg+="Instalar driver NVIDIA?"
|
||||||
|
|
||||||
|
if ! _confirm "NVIDIA — Bullseye" "$msg" 14 70; then
|
||||||
|
echo "Omitiendo driver NVIDIA."
|
||||||
|
NVIDIA_DRIVER_MODE=""
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
_run_cmd "NVIDIA" \
|
||||||
|
"sudo apt install -y $nv_pkg firmware-misc-nonfree nvidia-settings" \
|
||||||
|
"Instalando driver NVIDIA ${gpu_gen}..."
|
||||||
|
|
||||||
|
local i386_active=false
|
||||||
|
dpkg --print-foreign-architectures | grep -q i386 && i386_active=true
|
||||||
|
if $i386_active; then
|
||||||
|
local nv32_pkg="${nv_pkg}:i386"
|
||||||
|
local nv32_ver
|
||||||
|
nv32_ver=$(apt-cache policy "$nv32_pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
|
if [ -n "$nv32_ver" ] && [ "$nv32_ver" != "(none)" ]; then
|
||||||
|
echo "Installing 32-bit compatibility for ${nv_pkg}..."
|
||||||
|
_run_cmd "NVIDIA 32-bit" "sudo apt install -y $nv32_pkg" \
|
||||||
|
"Installing NVIDIA 32-bit libraries..."
|
||||||
|
else
|
||||||
|
echo "No 32-bit compatibility package available for ${nv_pkg} on Bullseye."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
NVIDIA_DRIVER_MODE="stable"
|
||||||
|
echo -e "${GREEN}Driver NVIDIA ${nv_pkg} instalado. Requiere reinicio.${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 "──────────────────────────────────────────────"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Lightweight Gaming for Bullseye — sin Steam, sin Heroic
|
||||||
|
# 32-bit Mesa/NVIDIA + gamemode + mangohud + goverlay + lutris
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
install_gaming_bullseye() {
|
||||||
|
echo -e "${YELLOW}Lightweight Gaming (Bullseye mode).${NC}"
|
||||||
|
|
||||||
|
local enable_32bit=false
|
||||||
|
if _confirm "32-bit Support" \
|
||||||
|
"Enable i386 architecture for 32-bit games?\n\n\
|
||||||
|
Required by Steam/Proton for 32-bit games.\n\
|
||||||
|
Installs matching 32-bit graphics drivers."; then
|
||||||
|
enable_32bit=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $enable_32bit; then
|
||||||
|
echo "Enabling i386 multi-architecture support..."
|
||||||
|
if ! dpkg --print-foreign-architectures | grep -q i386; then
|
||||||
|
sudo dpkg --add-architecture i386
|
||||||
|
fi
|
||||||
|
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
||||||
|
|
||||||
|
if [ "$GPU_TYPE" = "nvidia" ]; then
|
||||||
|
local nv32_pkg="nvidia-driver-libs:i386"
|
||||||
|
local nv32_ver
|
||||||
|
nv32_ver=$(apt-cache policy "$nv32_pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
|
if [ -n "$nv32_ver" ] && [ "$nv32_ver" != "(none)" ]; then
|
||||||
|
local msg="Source: Debian Bullseye Stable\n"
|
||||||
|
msg+="NVIDIA 32-bit Libraries ${nv32_ver}\n\n"
|
||||||
|
msg+="[+] nvidia-driver-libs:i386"
|
||||||
|
if _confirm "NVIDIA 32-bit" "$msg" 12 70; then
|
||||||
|
_run_cmd "32-bit NVIDIA" "sudo apt install -y ${nv32_pkg}" \
|
||||||
|
"Installing NVIDIA 32-bit libraries..."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "nvidia-driver-libs:i386 not available on Bullseye."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Mesa 32-bit
|
||||||
|
local mesa_32=(
|
||||||
|
"mesa-vulkan-drivers:i386"
|
||||||
|
"libgl1-mesa-dri:i386"
|
||||||
|
"libglx-mesa0:i386"
|
||||||
|
"libegl-mesa0:i386"
|
||||||
|
"mesa-va-drivers:i386"
|
||||||
|
)
|
||||||
|
local ref_ver
|
||||||
|
ref_ver=$(apt-cache policy "mesa-vulkan-drivers:i386" 2>/dev/null | \
|
||||||
|
awk 'NR==3 {print $2; exit}')
|
||||||
|
local comp_line="Components: Vulkan:i386, OpenGL:i386, GLX:i386, EGL:i386, VA-API:i386"
|
||||||
|
|
||||||
|
local msg="Mesa 32-bit drivers for gaming.\n\n"
|
||||||
|
msg+="Source: Debian Bullseye Stable\n"
|
||||||
|
msg+="Mesa ${ref_ver}\n"
|
||||||
|
msg+="${comp_line}\n\n"
|
||||||
|
msg+="Install 32-bit drivers?"
|
||||||
|
|
||||||
|
if _confirm "Mesa 32-bit" "$msg" 14 70; then
|
||||||
|
_run_cmd "Mesa 32-bit" "sudo apt install -y ${mesa_32[*]}" \
|
||||||
|
"Installing Mesa 32-bit..."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Gaming tools checklist (no Steam, no Heroic)
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "Gaming Tools — Bullseye" \
|
||||||
|
"Select gaming optimization tools:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
||||||
|
"gamemode" "Game performance optimization" ON \
|
||||||
|
"mangohud" "Performance overlay (Vulkan/OpenGL)" ON \
|
||||||
|
"goverlay" "MangoHud config GUI" ON \
|
||||||
|
"lutris" "Game launcher/manager" OFF \
|
||||||
|
"java" "Java Runtimes (8, 17, 21)" OFF)
|
||||||
|
|
||||||
|
if [ -z "$choices" ]; then
|
||||||
|
echo "No gaming tools selected."
|
||||||
|
_pause
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local cleaned
|
||||||
|
cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
|
||||||
|
for pkg in $cleaned; do
|
||||||
|
case $pkg in
|
||||||
|
mangohud)
|
||||||
|
local mh_pkgs="mangohud"
|
||||||
|
if $enable_32bit; then
|
||||||
|
local mh32_ver
|
||||||
|
mh32_ver=$(apt-cache policy mangohud:i386 2>/dev/null | \
|
||||||
|
awk 'NR==3 {print $2; exit}')
|
||||||
|
if [ -n "$mh32_ver" ] && [ "$mh32_ver" != "(none)" ]; then
|
||||||
|
mh_pkgs+=" mangohud:i386"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
_run_cmd "MangoHud" "sudo apt install -y $mh_pkgs" "Installing MangoHud (64 + 32-bit)..."
|
||||||
|
;;
|
||||||
|
gamemode) _run_cmd "GameMode" "sudo apt install -y gamemode" "Installing GameMode..." ;;
|
||||||
|
goverlay) _run_cmd "GOverlay" "sudo apt install -y goverlay" "Installing GOverlay..." ;;
|
||||||
|
lutris)
|
||||||
|
local pkgs="lutris wine64"
|
||||||
|
if dpkg --print-foreign-architectures 2>/dev/null | grep -q i386; then
|
||||||
|
pkgs+=" wine32"
|
||||||
|
fi
|
||||||
|
_run_cmd "Lutris" "sudo apt install -y $pkgs" "Installing Lutris + Wine..."
|
||||||
|
;;
|
||||||
|
java) _install_gaming_java ;;
|
||||||
|
*) _run_install "$pkg" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "${GREEN}Lightweight gaming setup complete.${NC}"
|
||||||
|
_pause
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# repos.sh — Bullseye: repos clásicos con archive phase
|
||||||
|
# License GPL v3
|
||||||
|
|
||||||
|
configure_repos_bullseye() {
|
||||||
|
echo -e "${YELLOW}Repository configuration — Debian 11 Bullseye${NC}"
|
||||||
|
|
||||||
|
local info="Repository configuration for Debian 11 Bullseye.\n\n"
|
||||||
|
info+="Official repositories will be used with components\n"
|
||||||
|
info+="main, contrib and non-free (non-free-firmware excluded).\n"
|
||||||
|
info+="DEB822 format is not used.\n"
|
||||||
|
if $BULLSEYE_USE_ARCHIVE; then
|
||||||
|
info+="\nArchive Mode: URLs will point to archive.debian.org\n"
|
||||||
|
info+="(Bullseye LTS ended on 31 Aug 2026)."
|
||||||
|
fi
|
||||||
|
_msg "Repositories — Bullseye" "$info" 12 65
|
||||||
|
|
||||||
|
if [ -f /etc/apt/sources.list ]; then
|
||||||
|
if ! _confirm "Repositories" "/etc/apt/sources.list already exists.\n\nOverwrite with Bullseye configuration?"; then
|
||||||
|
echo "Keeping current configuration."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
local base_uri="https://deb.debian.org/debian"
|
||||||
|
local security_uri="https://security.debian.org/debian-security"
|
||||||
|
if $BULLSEYE_USE_ARCHIVE; then
|
||||||
|
base_uri="https://archive.debian.org/debian"
|
||||||
|
security_uri="https://archive.debian.org/debian-security"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local content=""
|
||||||
|
content="# Oficial Repo\n"
|
||||||
|
content+="deb ${base_uri} bullseye main contrib non-free\n"
|
||||||
|
content+="#deb-src ${base_uri} bullseye main contrib non-free\n\n"
|
||||||
|
|
||||||
|
content+="# Security\n"
|
||||||
|
content+="deb ${security_uri} bullseye-security main contrib non-free\n"
|
||||||
|
content+="#deb-src ${security_uri} bullseye-security main contrib non-free\n"
|
||||||
|
|
||||||
|
echo -e "$content" | sudo tee /etc/apt/sources.list > /dev/null
|
||||||
|
|
||||||
|
echo "Updating package lists..."
|
||||||
|
if sudo apt update; then
|
||||||
|
echo -e "${GREEN}Debian 11 Bullseye repositories configured.${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}apt update failed. Check your network connection.${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
@@ -0,0 +1,281 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
manage_desktop_display() {
|
||||||
|
while true; do
|
||||||
|
local choice
|
||||||
|
choice=$(_menu "Desktop & Display" \
|
||||||
|
"Select an option:" $TUI_ALTO $TUI_ANCHO 6 \
|
||||||
|
"1" "Desktop Environment" \
|
||||||
|
"2" "Display Manager" \
|
||||||
|
"3" "Back to main menu")
|
||||||
|
[ -z "$choice" ] && break
|
||||||
|
clear
|
||||||
|
case "$choice" in
|
||||||
|
1) _msg "Coming Soon" "Desktop Environment management will be available in a future update." 10 60 ;;
|
||||||
|
2) display_manager_menu ;;
|
||||||
|
3) break ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
display_manager_menu() {
|
||||||
|
while true; do
|
||||||
|
local -a dm_items=()
|
||||||
|
dm_items+=("1" "LightDM")
|
||||||
|
dm_items+=("2" "GDM3")
|
||||||
|
dm_items+=("3" "SDDM")
|
||||||
|
if [ "$DEBIAN_VERSION" = "12" ] || [ "$DEBIAN_VERSION" = "13" ]; then
|
||||||
|
dm_items+=("4" "greetd")
|
||||||
|
dm_items+=("5" "Back")
|
||||||
|
else
|
||||||
|
dm_items+=("4" "Back")
|
||||||
|
fi
|
||||||
|
local choice
|
||||||
|
choice=$(_menu "Display Manager" \
|
||||||
|
"Select an option:" $TUI_ALTO $TUI_ANCHO 6 \
|
||||||
|
"${dm_items[@]}")
|
||||||
|
[ -z "$choice" ] && break
|
||||||
|
clear
|
||||||
|
case "$choice" in
|
||||||
|
1) lightdm_config_menu ;;
|
||||||
|
2) configure_gdm3 ;;
|
||||||
|
3) configure_sddm ;;
|
||||||
|
4) configure_greetd ;;
|
||||||
|
5) break ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
lightdm_config_menu() {
|
||||||
|
local -a items=()
|
||||||
|
items+=("install_lightdm" "Install LightDM & GTK Greeter" "$(_state lightdm)")
|
||||||
|
items+=("enable_userlist" "Enable user list at login screen" "OFF")
|
||||||
|
items+=("enable_autologin" "Enable autologin for current user" "OFF")
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "LightDM Configuration" \
|
||||||
|
"Select options to apply:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
||||||
|
"${items[@]}")
|
||||||
|
if [ -z "$choices" ]; then
|
||||||
|
echo "No changes."
|
||||||
|
_pause
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
local cleaned
|
||||||
|
cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
for item in $cleaned; do
|
||||||
|
case $item in
|
||||||
|
install_lightdm)
|
||||||
|
if ! is_installed lightdm || ! is_installed lightdm-gtk-greeter-settings; then
|
||||||
|
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..."
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}[LightDM] LightDM and GTK Greeter settings are already installed, skipping...${NC}"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
enable_userlist)
|
||||||
|
local conf="/etc/lightdm/lightdm.conf.d/50-debianito-userlist.conf"
|
||||||
|
sudo mkdir -p "$(dirname "$conf")"
|
||||||
|
if echo "[Seat:*]
|
||||||
|
greeter-hide-users=false" | sudo tee "$conf" > /dev/null; then
|
||||||
|
echo -e "${GREEN}User list enabled in LightDM.${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}Failed to write configuration.${NC}"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
enable_autologin)
|
||||||
|
local dm_conf="/etc/lightdm/lightdm.conf"
|
||||||
|
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-timeout[[:space:]=].*/autologin-user-timeout=0/' "$dm_conf"
|
||||||
|
echo -e "${GREEN}Autologin enabled for user: ${lightdm_user}${NC}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
_pause
|
||||||
|
}
|
||||||
|
|
||||||
|
configure_greetd() {
|
||||||
|
while true; do
|
||||||
|
local -a gd_items=()
|
||||||
|
gd_items+=("1" "Install base greetd")
|
||||||
|
gd_items+=("2" "Install greetd + tuigreet (Recommended TUI greeter)")
|
||||||
|
if [ "$DEBIAN_VERSION" = "13" ]; then
|
||||||
|
gd_items+=("3" "Install gtkgreet (Requires manual setup)")
|
||||||
|
gd_items+=("4" "Install nwg-hello (Requires manual setup)")
|
||||||
|
gd_items+=("5" "Install wlgreet (Requires manual setup)")
|
||||||
|
gd_items+=("6" "Back")
|
||||||
|
else
|
||||||
|
gd_items+=("3" "Back")
|
||||||
|
fi
|
||||||
|
local choice
|
||||||
|
choice=$(_menu "greetd Configuration" \
|
||||||
|
"Select an option${SCROLL_HINT}:" \
|
||||||
|
$TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
||||||
|
"${gd_items[@]}")
|
||||||
|
[ -z "$choice" ] && return
|
||||||
|
clear
|
||||||
|
case "$choice" in
|
||||||
|
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"
|
||||||
|
sudo apt update -qq
|
||||||
|
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
|
||||||
|
_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'."
|
||||||
|
else
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
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
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
configure_gdm3() {
|
||||||
|
while true; do
|
||||||
|
local items_enabled=()
|
||||||
|
items_enabled+=("install" "Install/Reinstall gdm3 (Set as default)" "$(_state gdm3)")
|
||||||
|
items_enabled+=("userlist" "Hide user list (disable-user-list)" "OFF")
|
||||||
|
items_enabled+=("autologin" "Configure Autologin" "OFF")
|
||||||
|
if [ "$DEBIAN_VERSION" = "12" ] || [ "$DEBIAN_VERSION" = "13" ]; then
|
||||||
|
if [ "$HAS_NVIDIA" = true ]; then
|
||||||
|
items_enabled+=("wayland" "Force Enable Wayland on NVIDIA (Risk!)" "OFF")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
local choice
|
||||||
|
choice=$(_checklist "GDM3 Configuration" \
|
||||||
|
"Select options to apply${SCROLL_HINT}:" \
|
||||||
|
$TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
||||||
|
"${items_enabled[@]}")
|
||||||
|
[ -z "$choice" ] && return
|
||||||
|
clear
|
||||||
|
|
||||||
|
local cleaned
|
||||||
|
cleaned=$(echo "$choice" | tr -d '"')
|
||||||
|
for item in $cleaned; do
|
||||||
|
case $item in
|
||||||
|
install)
|
||||||
|
echo "gdm3 shared/default-x-display-manager select gdm3" | sudo debconf-set-selections
|
||||||
|
_run_cmd "GDM3" "sudo apt install -y gdm3" "Installing gdm3..."
|
||||||
|
;;
|
||||||
|
userlist)
|
||||||
|
local greeter_conf="/etc/gdm3/greeter.dconf-defaults"
|
||||||
|
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"
|
||||||
|
echo -e "${GREEN}User list is now VISIBLE.${NC}"
|
||||||
|
else
|
||||||
|
sudo sed -i 's/^#[[:space:]]*disable-user-list=true/disable-user-list=true/' "$greeter_conf"
|
||||||
|
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
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
_pause
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
configure_sddm() {
|
||||||
|
while true; do
|
||||||
|
local choice
|
||||||
|
choice=$(_menu "SDDM Configuration" \
|
||||||
|
"Select an option${SCROLL_HINT}:" \
|
||||||
|
$TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
||||||
|
"1" "Install SDDM (Set as default)" \
|
||||||
|
"2" "Enable Autologin" \
|
||||||
|
"3" "Back")
|
||||||
|
[ -z "$choice" ] && return
|
||||||
|
clear
|
||||||
|
case "$choice" in
|
||||||
|
1)
|
||||||
|
echo "sddm shared/default-x-display-manager select sddm" | sudo debconf-set-selections
|
||||||
|
_run_cmd "SDDM" "sudo apt install -y sddm" "Installing SDDM..."
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
local sddm_session=""
|
||||||
|
local sddm_user="${SUDO_USER:-$USER}"
|
||||||
|
if [ -f /usr/share/wayland-sessions/plasmawayland.desktop ]; then
|
||||||
|
sddm_session="plasmawayland"
|
||||||
|
elif [ -f /usr/share/wayland-sessions/lxqt-wayland.desktop ]; then
|
||||||
|
sddm_session="lxqt-wayland"
|
||||||
|
elif [ -f /usr/share/xsessions/plasma.desktop ]; then
|
||||||
|
sddm_session="plasma"
|
||||||
|
elif [ -f /usr/share/xsessions/lxqt.desktop ]; then
|
||||||
|
sddm_session="lxqt"
|
||||||
|
fi
|
||||||
|
sudo mkdir -p /etc/sddm.conf.d
|
||||||
|
cat << EOF | sudo tee /etc/sddm.conf.d/autologin.conf > /dev/null
|
||||||
|
[Autologin]
|
||||||
|
User=${sddm_user}
|
||||||
|
Session=${sddm_session}
|
||||||
|
Relogin=false
|
||||||
|
EOF
|
||||||
|
if [ -n "$sddm_session" ]; then
|
||||||
|
echo -e "${GREEN}Autologin enabled for user ${sddm_user}, session: ${sddm_session}.${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Autologin enabled for user ${sddm_user}. No session set (SDDM will use default).${NC}"
|
||||||
|
fi
|
||||||
|
_pause
|
||||||
|
;;
|
||||||
|
3) return ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
+17
-12
@@ -27,20 +27,22 @@ install_extras() {
|
|||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
local cat_choice
|
local cat_choice
|
||||||
cat_choice=$(whiptail --title "Extra Software" --menu \
|
cat_choice=$(_menu "Install Programs and Software" \
|
||||||
"Select a category:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
"Select a category${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
||||||
"0" "Essential Pack" \
|
"0" "Essential Pack" \
|
||||||
"1" "Customization System" \
|
"1" "Customization System" \
|
||||||
"2" "Download & Network" \
|
"2" "Download & Network" \
|
||||||
"3" "Internet (Browsers, Email, VPN)" \
|
"3" "Internet (Browsers, Email, VPN)" \
|
||||||
"4" "Media Players" \
|
"4" "Media Players" \
|
||||||
"5" "Multimedia & Design" \
|
"5" "Multimedia & Design" \
|
||||||
"6" "Programming Applications" \
|
"6" "Code Editors & IDEs" \
|
||||||
"7" "Security & Networking" \
|
"7" "Servers & Dev Tools" \
|
||||||
"8" "System Tools" \
|
"8" "Security & Networking" \
|
||||||
"9" "Fetch / System Info" \
|
"9" "Software Centers" \
|
||||||
"10" "Back to main menu" \
|
"10" "Office & Productivity" \
|
||||||
3>&1 1>&2 2>&3)
|
"11" "System Tools" \
|
||||||
|
"12" "Fetch / System Info" \
|
||||||
|
"13" "Back to main menu")
|
||||||
|
|
||||||
[ -z "$cat_choice" ] && return
|
[ -z "$cat_choice" ] && return
|
||||||
clear
|
clear
|
||||||
@@ -53,10 +55,13 @@ install_extras() {
|
|||||||
4) _cat_players ;;
|
4) _cat_players ;;
|
||||||
5) _cat_design ;;
|
5) _cat_design ;;
|
||||||
6) _cat_programming ;;
|
6) _cat_programming ;;
|
||||||
7) _cat_security ;;
|
7) _cat_dev ;;
|
||||||
8) _cat_general ;;
|
8) _cat_security ;;
|
||||||
9) _cat_fetch ;;
|
9) _cat_software_centers ;;
|
||||||
10) return ;;
|
10) _cat_office ;;
|
||||||
|
11) _cat_general ;;
|
||||||
|
12) _cat_fetch ;;
|
||||||
|
13) return ;;
|
||||||
esac
|
esac
|
||||||
clear
|
clear
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -1,10 +1,24 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Shared helpers for extras categories
|
# Shared helpers for extras categories
|
||||||
|
|
||||||
_inst() {
|
_install_clamav() {
|
||||||
if is_installed "$1"; then echo " (installed)"; else echo ""; fi
|
if is_installed "clamav"; then
|
||||||
}
|
echo "ClamAV already installed."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
_run_install "clamav"
|
||||||
|
echo -e "${GREEN}ClamAV installed.${NC}"
|
||||||
|
|
||||||
_state() {
|
if _confirm "ClamAV" "Update virus signatures now (freshclam)?"; then
|
||||||
is_installed "$1" && echo "ON" || echo "OFF"
|
sudo systemctl stop clamav-freshclam 2>/dev/null || true
|
||||||
|
sudo freshclam || true
|
||||||
|
sudo systemctl start clamav-freshclam 2>/dev/null || true
|
||||||
|
_pause
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _confirm "ClamAV" "Run quick scan on /bin to verify engine works?"; then
|
||||||
|
echo "Running background scan on /bin..."
|
||||||
|
sudo clamscan --recursive --infected /bin &
|
||||||
|
echo "Scan running in background (PID $!). Check results later."
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,11 @@
|
|||||||
_cat_design() {
|
_cat_design() {
|
||||||
local headless=false
|
local headless=false
|
||||||
_is_headless && headless=true
|
_is_headless && headless=true
|
||||||
|
local -a items=()
|
||||||
|
if ! $headless; then
|
||||||
local audacity_state; audacity_state=$(_state "audacity")
|
local audacity_state; audacity_state=$(_state "audacity")
|
||||||
local ardour_state; ardour_state=$(_state "ardour")
|
local ardour_state; ardour_state=$(_state "ardour")
|
||||||
local blender_state; blender_state=$(_state "blender")
|
local blender_state; blender_state=$(_state "blender")
|
||||||
local ffmpeg_state; ffmpeg_state=$(_state "ffmpeg")
|
|
||||||
local gimp_state; gimp_state=$(_state "gimp")
|
local gimp_state; gimp_state=$(_state "gimp")
|
||||||
local handbrake_state; handbrake_state=$(_state "handbrake")
|
local handbrake_state; handbrake_state=$(_state "handbrake")
|
||||||
local inkscape_state; inkscape_state=$(_state "inkscape")
|
local inkscape_state; inkscape_state=$(_state "inkscape")
|
||||||
@@ -17,35 +18,34 @@ _cat_design() {
|
|||||||
local openshot_state; openshot_state=$(_state "openshot-qt")
|
local openshot_state; openshot_state=$(_state "openshot-qt")
|
||||||
local scribus_state; scribus_state=$(_state "scribus")
|
local scribus_state; scribus_state=$(_state "scribus")
|
||||||
local shotcut_state; shotcut_state=$(_state "shotcut")
|
local shotcut_state; shotcut_state=$(_state "shotcut")
|
||||||
|
items+=(
|
||||||
|
"audacity" "Audio editor/recorder" "$audacity_state"
|
||||||
|
"ardour" "Digital audio workstation" "$ardour_state"
|
||||||
|
"blender" "3D modeling/animation" "$blender_state"
|
||||||
|
"gimp" "Image editor" "$gimp_state"
|
||||||
|
"handbrake" "Video transcoder" "$handbrake_state"
|
||||||
|
"inkscape" "Vector graphics editor" "$inkscape_state"
|
||||||
|
"kdenlive" "Video editor (KDE)" "$kdenlive_state"
|
||||||
|
"krita" "Digital painting" "$krita_state"
|
||||||
|
"obs-studio" "Screen recording" "$obs_state"
|
||||||
|
"openshot-qt" "Simple video editor" "$openshot_state"
|
||||||
|
"scribus" "Desktop publishing" "$scribus_state"
|
||||||
|
"shotcut" "Cross-platform video editor" "$shotcut_state"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
local ffmpeg_state; ffmpeg_state=$(_state "ffmpeg")
|
||||||
|
items+=("ffmpeg" "Multimedia framework (CLI)" "$ffmpeg_state")
|
||||||
|
|
||||||
|
local item_count=${#items[@]}
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
local choices
|
local choices
|
||||||
choices=$(whiptail --title "Multimedia & Design" --checklist \
|
choices=$(_checklist "Multimedia & Design" "Select multimedia and design tools${SCROLL_HINT}:" \
|
||||||
"Select multimedia and design tools:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
$TUI_ALTO $TUI_ANCHO $lista_alto "${items[@]}")
|
||||||
"audacity" "Audio editor/recorder$(_inst audacity)" "$audacity_state" \
|
|
||||||
"ardour" "Digital audio workstation$(_inst ardour)" "$ardour_state" \
|
|
||||||
"blender" "3D modeling/animation suite$(_inst blender)" "$blender_state" \
|
|
||||||
"ffmpeg" "Multimedia framework (CLI)$(_inst ffmpeg)" "$ffmpeg_state" \
|
|
||||||
"gimp" "Image editor (Photoshop alternative)$(_inst gimp)" "$gimp_state" \
|
|
||||||
"handbrake" "Video transcoder (DVD ripper)$(_inst handbrake)" "$handbrake_state" \
|
|
||||||
"inkscape" "Vector graphics editor$(_inst inkscape)" "$inkscape_state" \
|
|
||||||
"kdenlive" "Video editor (KDE)$(_inst kdenlive)" "$kdenlive_state" \
|
|
||||||
"krita" "Digital painting/illustration$(_inst krita)" "$krita_state" \
|
|
||||||
"obs-studio" "Screen recording/streaming$(_inst obs-studio)" "$obs_state" \
|
|
||||||
"openshot-qt" "Video editor (simple)$(_inst openshot-qt)" "$openshot_state" \
|
|
||||||
"scribus" "Desktop publishing (DTP)$(_inst scribus)" "$scribus_state" \
|
|
||||||
"shotcut" "Video editor (cross-platform)$(_inst shotcut)" "$shotcut_state" \
|
|
||||||
3>&1 1>&2 2>&3)
|
|
||||||
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 $headless; then
|
|
||||||
echo "Skipping $pkg (headless mode)"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if ! is_installed "$pkg"; then
|
if ! is_installed "$pkg"; then
|
||||||
_run_install "$pkg"
|
_run_install "$pkg"
|
||||||
else
|
else
|
||||||
|
|||||||
+31
-17
@@ -4,6 +4,7 @@
|
|||||||
_cat_dev() {
|
_cat_dev() {
|
||||||
local headless=false
|
local headless=false
|
||||||
_is_headless && headless=true
|
_is_headless && headless=true
|
||||||
|
local -a items=()
|
||||||
local apache_state; apache_state=$(_state "apache2")
|
local apache_state; apache_state=$(_state "apache2")
|
||||||
local build_state; build_state=$(_state "build-essential")
|
local build_state; build_state=$(_state "build-essential")
|
||||||
local certbot_state; certbot_state=$(_state "certbot")
|
local certbot_state; certbot_state=$(_state "certbot")
|
||||||
@@ -17,25 +18,32 @@ _cat_dev() {
|
|||||||
local pip_state; pip_state=$(_state "python3-pip")
|
local pip_state; pip_state=$(_state "python3-pip")
|
||||||
local redis_state; redis_state=$(_state "redis-server")
|
local redis_state; redis_state=$(_state "redis-server")
|
||||||
local sqlite_state; sqlite_state=$(_state "sqlite3")
|
local sqlite_state; sqlite_state=$(_state "sqlite3")
|
||||||
|
local jdk_desc; jdk_desc=$(_any_jdk_installed_desc)
|
||||||
|
local jdk_state; jdk_state=$(_any_jdk_state)
|
||||||
|
items+=(
|
||||||
|
"apache2" "Apache web server" "$apache_state"
|
||||||
|
"build-essential" "C/C++ build tools (gcc, make)" "$build_state"
|
||||||
|
"certbot" "Let's Encrypt TLS certificates" "$certbot_state"
|
||||||
|
"docker" "Docker + docker-compose" "$docker_state"
|
||||||
|
"mariadb-server" "MariaDB database server" "$mariadb_state"
|
||||||
|
"netcat-openbsd" "TCP/IP networking utility" "$netcat_state"
|
||||||
|
"nginx" "Nginx web server" "$nginx_state"
|
||||||
|
"openssh-server" "SSH server" "$ssh_state"
|
||||||
|
"openssl" "OpenSSL cryptography toolkit" "$openssl_state"
|
||||||
|
"postgresql" "PostgreSQL database server" "$pg_state"
|
||||||
|
"python3-pip" "Python 3 pip + venv + dev" "$pip_state"
|
||||||
|
"redis-server" "Redis key-value store" "$redis_state"
|
||||||
|
"sqlite3" "SQLite database engine" "$sqlite_state"
|
||||||
|
"jellyfin" "Jellyfin Media Server (Web GUI on port 8096)" OFF
|
||||||
|
"openjdk-dev-env" "Adoptium Temurin JDK (17, 21, 25 LTS)${jdk_desc}" "${jdk_state}"
|
||||||
|
)
|
||||||
|
|
||||||
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
|
local item_count=${#items[@]}
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
local choices
|
local choices
|
||||||
choices=$(whiptail --title "Development & Servers" --checklist \
|
choices=$(_checklist "Development & Servers" "Select development tools and servers${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
"Select development tools and servers (12 items, ↑↓ scroll):" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
|
"${items[@]}" \
|
||||||
"apache2" "Apache web server$(_inst apache2)" "$apache_state" \
|
)
|
||||||
"build-essential" "C/C++ build tools (gcc, make)$(_inst build-essential)" "$build_state" \
|
|
||||||
"certbot" "Let's Encrypt TLS certificates$(_inst certbot)" "$certbot_state" \
|
|
||||||
"docker" "Docker + docker-compose$(_inst docker.io)" "$docker_state" \
|
|
||||||
"mariadb-server" "MariaDB database server$(_inst mariadb-server)" "$mariadb_state" \
|
|
||||||
"netcat-openbsd" "TCP/IP networking utility$(_inst netcat-openbsd)" "$netcat_state" \
|
|
||||||
"nginx" "Nginx web server$(_inst nginx)" "$nginx_state" \
|
|
||||||
"openssh-server" "SSH server$(_inst openssh-server)" "$ssh_state" \
|
|
||||||
"openssl" "OpenSSL cryptography toolkit$(_inst openssl)" "$openssl_state" \
|
|
||||||
"postgresql" "PostgreSQL database server$(_inst postgresql)" "$pg_state" \
|
|
||||||
"python3-pip" "Python 3 pip + venv + dev$(_inst python3-pip)" "$pip_state" \
|
|
||||||
"redis-server" "Redis key-value store$(_inst redis-server)" "$redis_state" \
|
|
||||||
"sqlite3" "SQLite database engine$(_inst sqlite3)" "$sqlite_state" \
|
|
||||||
3>&1 1>&2 2>&3)
|
|
||||||
clear
|
clear
|
||||||
|
|
||||||
[ -z "$choices" ] && return
|
[ -z "$choices" ] && return
|
||||||
@@ -65,6 +73,12 @@ _cat_dev() {
|
|||||||
echo "Docker already installed."
|
echo "Docker already installed."
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
jellyfin)
|
||||||
|
install_jellyfin
|
||||||
|
;;
|
||||||
|
openjdk-dev-env)
|
||||||
|
_install_dev_java
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
if ! is_installed "$pkg"; then
|
if ! is_installed "$pkg"; then
|
||||||
_run_install "$pkg"
|
_run_install "$pkg"
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# jellyfin.sh — Jellyfin Media Server installation (extrepo)
|
||||||
|
|
||||||
|
_enable_jellyfin_repo() {
|
||||||
|
if [ ! -f /etc/apt/sources.list.d/extrepo_jellyfin.sources ]; then
|
||||||
|
if ! command -v extrepo &>/dev/null; then
|
||||||
|
_run_cmd "extrepo" "sudo apt install -y extrepo" "Installing extrepo..."
|
||||||
|
fi
|
||||||
|
_run_cmd "Jellyfin" "sudo extrepo enable jellyfin" "Enabling Jellyfin repository..."
|
||||||
|
fi
|
||||||
|
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
||||||
|
}
|
||||||
|
|
||||||
|
install_jellyfin() {
|
||||||
|
local ver
|
||||||
|
ver=$(apt-cache policy jellyfin 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
|
|
||||||
|
if _confirm "Install: Jellyfin" "Install Jellyfin Media Server
|
||||||
|
Repository: repo.jellyfin.org/debian
|
||||||
|
Version: ${ver:-unknown}"; then
|
||||||
|
|
||||||
|
_enable_jellyfin_repo
|
||||||
|
_run_cmd "Jellyfin" "sudo DEBIAN_FRONTEND=noninteractive apt install -y jellyfin" "Installing Jellyfin..."
|
||||||
|
|
||||||
|
echo -e "${GREEN}Jellyfin Server installed. Web interface available at http://localhost:8096${NC}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
@@ -4,43 +4,57 @@
|
|||||||
_cat_download() {
|
_cat_download() {
|
||||||
local headless=false
|
local headless=false
|
||||||
_is_headless && headless=true
|
_is_headless && headless=true
|
||||||
|
local -a items1=()
|
||||||
|
local -a items2=()
|
||||||
local aria2_state; aria2_state=$(_state "aria2")
|
local aria2_state; aria2_state=$(_state "aria2")
|
||||||
local filezilla_state; filezilla_state=$(_state "filezilla")
|
|
||||||
local ytdlp_state; ytdlp_state=$(_state "yt-dlp")
|
local ytdlp_state; ytdlp_state=$(_state "yt-dlp")
|
||||||
local ytdlp_gui_state; ytdlp_gui_state=$(_state "youtubedl-gui")
|
|
||||||
|
|
||||||
local deluge_state; deluge_state=$(_state "deluge")
|
|
||||||
local deluged_state; deluged_state=$(_state "deluged")
|
local deluged_state; deluged_state=$(_state "deluged")
|
||||||
local mktorrent_state; mktorrent_state=$(_state "mktorrent")
|
local mktorrent_state; mktorrent_state=$(_state "mktorrent")
|
||||||
local qbit_state; qbit_state=$(_state "qbittorrent")
|
|
||||||
local qbitnox_state; qbitnox_state=$(_state "qbittorrent-nox")
|
local qbitnox_state; qbitnox_state=$(_state "qbittorrent-nox")
|
||||||
local tr_cli_state; tr_cli_state=$(_state "transmission-cli")
|
local tr_cli_state; tr_cli_state=$(_state "transmission-cli")
|
||||||
|
items1+=(
|
||||||
|
"aria2" "Multiprotocol downloader (CLI)" "$aria2_state"
|
||||||
|
"yt-dlp" "Video downloader CLI" "$ytdlp_state"
|
||||||
|
)
|
||||||
|
items2+=(
|
||||||
|
"deluged" "BitTorrent daemon/server" "$deluged_state"
|
||||||
|
"mktorrent" "Torrent metainfo creator (CLI)" "$mktorrent_state"
|
||||||
|
"qbittorrent-nox" "BitTorrent WebUI/CLI" "$qbitnox_state"
|
||||||
|
"transmission-cli" "BitTorrent client (CLI)" "$tr_cli_state"
|
||||||
|
)
|
||||||
|
if ! $headless; then
|
||||||
|
local filezilla_state; filezilla_state=$(_state "filezilla")
|
||||||
|
local ytdlp_gui_state; ytdlp_gui_state=$(_state "youtubedl-gui")
|
||||||
|
local deluge_state; deluge_state=$(_state "deluge")
|
||||||
|
local qbit_state; qbit_state=$(_state "qbittorrent")
|
||||||
local tr_gtk_state; tr_gtk_state=$(_state "transmission-gtk")
|
local tr_gtk_state; tr_gtk_state=$(_state "transmission-gtk")
|
||||||
local tr_qt_state; tr_qt_state=$(_state "transmission-qt")
|
local tr_qt_state; tr_qt_state=$(_state "transmission-qt")
|
||||||
|
items1+=(
|
||||||
|
"filezilla" "FTP/SFTP client (GUI)" "$filezilla_state"
|
||||||
|
"youtubedl-gui" "GUI for yt-dlp" "$ytdlp_gui_state"
|
||||||
|
)
|
||||||
|
items2+=(
|
||||||
|
"deluge" "BitTorrent client (GTK)" "$deluge_state"
|
||||||
|
"qbittorrent" "BitTorrent client (Qt)" "$qbit_state"
|
||||||
|
"transmission-gtk" "BitTorrent client (GTK)" "$tr_gtk_state"
|
||||||
|
"transmission-qt" "BitTorrent client (Qt)" "$tr_qt_state"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
|
local item_count1=${#items1[@]}
|
||||||
|
local lista_alto1=$((item_count1 > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count1))
|
||||||
local choices1 choices2=""
|
local choices1 choices2=""
|
||||||
|
|
||||||
choices1=$(whiptail --title "Downloaders" --checklist \
|
choices1=$(_checklist "Downloaders" "Select download tools:" $TUI_ALTO $TUI_ANCHO $lista_alto1 \
|
||||||
"Select download tools:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
|
"${items1[@]}" \
|
||||||
"aria2" "Multiprotocol downloader (CLI)$(_inst aria2)" "$aria2_state" \
|
)
|
||||||
"filezilla" "FTP/SFTP client (GUI)$(_inst filezilla)" "$filezilla_state" \
|
|
||||||
"yt-dlp" "Video downloader CLI$(_inst yt-dlp)" "$ytdlp_state" \
|
|
||||||
"youtubedl-gui" "GUI for yt-dlp$(_inst youtubedl-gui)" "$ytdlp_gui_state" \
|
|
||||||
3>&1 1>&2 2>&3)
|
|
||||||
clear
|
clear
|
||||||
|
|
||||||
choices2=$(whiptail --title "Torrent Clients" --checklist \
|
local item_count2=${#items2[@]}
|
||||||
"Select torrent clients:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
local lista_alto2=$((item_count2 > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count2))
|
||||||
"deluge" "BitTorrent client (GTK)$(_inst deluge)" "$deluge_state" \
|
choices2=$(_checklist "Torrent Clients" "Select torrent clients:" $TUI_ALTO $TUI_ANCHO $lista_alto2 \
|
||||||
"deluged" "BitTorrent daemon/server$(_inst deluged)" "$deluged_state" \
|
"${items2[@]}" \
|
||||||
"mktorrent" "Torrent metainfo creator (CLI)$(_inst mktorrent)" "$mktorrent_state" \
|
)
|
||||||
"qbittorrent" "BitTorrent client (Qt)$(_inst qbittorrent)" "$qbit_state" \
|
|
||||||
"qbittorrent-nox" "BitTorrent WebUI/CLI$(_inst qbittorrent-nox)" "$qbitnox_state" \
|
|
||||||
"transmission-cli" "BitTorrent client (CLI)$(_inst transmission-cli)" "$tr_cli_state" \
|
|
||||||
"transmission-gtk" "BitTorrent client (GTK)$(_inst transmission-gtk)" "$tr_gtk_state" \
|
|
||||||
"transmission-qt" "BitTorrent client (Qt)$(_inst transmission-qt)" "$tr_qt_state" \
|
|
||||||
3>&1 1>&2 2>&3)
|
|
||||||
clear
|
clear
|
||||||
|
|
||||||
local cleaned
|
local cleaned
|
||||||
@@ -60,10 +74,6 @@ _cat_download() {
|
|||||||
install_backports_or_stable qbittorrent-nox
|
install_backports_or_stable qbittorrent-nox
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
if $headless; then
|
|
||||||
echo "Skipping $pkg (headless mode)"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if ! is_installed "$pkg"; then
|
if ! is_installed "$pkg"; then
|
||||||
_run_install "$pkg"
|
_run_install "$pkg"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -10,12 +10,13 @@ _quick_install() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
_msg "Essential Pack" \
|
_msg "Essential Pack" \
|
||||||
"Install basic programs:\n\n - Compression (zip, unrar, 7z)\n - System tools (htop, inxi, ${fetch_pkg})\n - VLC media player\n - Microsoft fonts" 13 60
|
"Install basic programs:\n\n - Compression (zip, unrar, 7z)\n - System tools (htop, inxi, ${fetch_pkg}, $(_is_headless || echo "VLC"))\n - Microsoft fonts" 13 60
|
||||||
|
|
||||||
local quick_pkgs=(
|
local quick_pkgs=(
|
||||||
zip unzip rar unrar p7zip-full p7zip-rar
|
zip unzip rar unrar p7zip-full p7zip-rar
|
||||||
"$fetch_pkg" htop vlc inxi ttf-mscorefonts-installer
|
"$fetch_pkg" htop inxi ttf-mscorefonts-installer
|
||||||
)
|
)
|
||||||
|
_is_headless || quick_pkgs+=(vlc)
|
||||||
_run_install_batch "${quick_pkgs[@]}"
|
_run_install_batch "${quick_pkgs[@]}"
|
||||||
echo -e "${GREEN}Essential Pack installed.${NC}"
|
echo -e "${GREEN}Essential Pack installed.${NC}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,29 +18,29 @@ _cat_fetch() {
|
|||||||
hyfetch_state=$(_state "hyfetch")
|
hyfetch_state=$(_state "hyfetch")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local items=()
|
local -a items=()
|
||||||
|
|
||||||
if [ "$fetch_pkg" = "fastfetch" ]; then
|
if [ "$fetch_pkg" = "fastfetch" ]; then
|
||||||
items+=("fastfetch" "System info fetcher$(_inst fastfetch)" "$fetch_state")
|
items+=("fastfetch" "System info fetcher" "$fetch_state")
|
||||||
if [ "$DEBIAN_CODENAME" = "trixie" ]; then
|
if [ "$DEBIAN_CODENAME" = "trixie" ]; then
|
||||||
items+=("hyfetch" "Neofetch with pride flags$(_inst hyfetch)" "$hyfetch_state")
|
items+=("hyfetch" "Neofetch with pride flags" "$hyfetch_state")
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
items+=("linuxlogo" "Linux logo + system info$(_inst linuxlogo)" "$linuxlogo_state")
|
items+=("linuxlogo" "Linux logo + system info" "$linuxlogo_state")
|
||||||
if [ "$fetch_pkg" = "neofetch" ]; then
|
if [ "$fetch_pkg" = "neofetch" ]; then
|
||||||
items+=("neofetch" "System info fetcher$(_inst neofetch)" "$fetch_state")
|
items+=("neofetch" "System info fetcher" "$fetch_state")
|
||||||
if [ "$DEBIAN_CODENAME" = "trixie" ]; then
|
if [ "$DEBIAN_CODENAME" = "trixie" ]; then
|
||||||
items+=("hyfetch" "Neofetch with pride flags$(_inst hyfetch)" "$hyfetch_state")
|
items+=("hyfetch" "Neofetch with pride flags" "$hyfetch_state")
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
items+=("screenfetch" "System info (BSD/Linux)$(_inst screenfetch)" "$screenfetch_state")
|
items+=("screenfetch" "System info (BSD/Linux)" "$screenfetch_state")
|
||||||
|
|
||||||
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
|
local item_count=${#items[@]}
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
local choices
|
local choices
|
||||||
choices=$(whiptail --title "Fetch Tools" --checklist \
|
choices=$(_checklist "Fetch Tools" "Select system info tools:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
"Select system info tools:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
|
|
||||||
"${items[@]}" \
|
"${items[@]}" \
|
||||||
3>&1 1>&2 2>&3)
|
)
|
||||||
clear
|
clear
|
||||||
|
|
||||||
[ -z "$choices" ] && return
|
[ -z "$choices" ] && return
|
||||||
|
|||||||
@@ -1,91 +1,231 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# internet.sh — Browsers, email, VPN (was _cat_browsers, now includes riseup-vpn)
|
# internet.sh — Browsers, email, VPN
|
||||||
|
# extrepo-powered: mozilla, floorp, palemoon, librewolf, tailscale, mullvad, protonvpn
|
||||||
|
# firefox-esr from Debian repos (with locale auto-detect)
|
||||||
|
|
||||||
|
# ── Helpers extrepo ──
|
||||||
|
_ensure_extrepo() {
|
||||||
|
if ! command -v extrepo &>/dev/null; then
|
||||||
|
_run_cmd "extrepo" "sudo apt install -y extrepo" "Installing extrepo..."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_enable_mozilla_repo() {
|
||||||
|
if [ ! -f /etc/apt/sources.list.d/extrepo_mozilla.sources ]; then
|
||||||
|
_ensure_extrepo
|
||||||
|
_run_cmd "Mozilla" "sudo extrepo enable mozilla" "Enabling Mozilla repository..."
|
||||||
|
fi
|
||||||
|
if [ ! -f /etc/apt/preferences.d/mozilla ]; then
|
||||||
|
sudo tee /etc/apt/preferences.d/mozilla > /dev/null << 'EOF'
|
||||||
|
Package: *
|
||||||
|
Pin: origin packages.mozilla.org
|
||||||
|
Pin-Priority: 1000
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
||||||
|
}
|
||||||
|
|
||||||
|
_enable_floorp_repo() {
|
||||||
|
if [ ! -f /etc/apt/sources.list.d/extrepo_floorp.sources ]; then
|
||||||
|
_ensure_extrepo
|
||||||
|
_run_cmd "Floorp" "sudo extrepo enable floorp" "Enabling Floorp repository..."
|
||||||
|
fi
|
||||||
|
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
||||||
|
}
|
||||||
|
|
||||||
|
install_palemoon() {
|
||||||
|
if [ "$DEBIAN_VERSION" -lt 12 ] 2>/dev/null; then
|
||||||
|
_msg "Pale Moon" "Pale Moon is only available on\nDebian 12 (Bookworm) and 13 (Trixie).\n\nSkipping installation." 10 60
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local cpu_flags cpu_label REPO_PALEMOON
|
||||||
|
cpu_flags=$(grep -m1 '^flags' /proc/cpuinfo 2>/dev/null)
|
||||||
|
|
||||||
|
if echo "$cpu_flags" | grep -q 'avx2'; then
|
||||||
|
REPO_PALEMOON="palemoon_avx2_gtk3"
|
||||||
|
cpu_label="AVX2"
|
||||||
|
elif echo "$cpu_flags" | grep -q 'avx'; then
|
||||||
|
REPO_PALEMOON="palemoon_avx_gtk3"
|
||||||
|
cpu_label="AVX"
|
||||||
|
else
|
||||||
|
REPO_PALEMOON="palemoon_sse2_gtk3"
|
||||||
|
cpu_label="SSE2"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_msg "Pale Moon" "CPU detected: ${cpu_label} support.\n\nEnabling optimized repository:\n ${REPO_PALEMOON}" 10 60
|
||||||
|
|
||||||
|
if ls /etc/apt/sources.list.d/extrepo_palemoon_*.sources &>/dev/null; then
|
||||||
|
echo "Pale Moon repository already enabled."
|
||||||
|
else
|
||||||
|
_ensure_extrepo
|
||||||
|
_run_cmd "Pale Moon" "sudo extrepo enable ${REPO_PALEMOON}" "Enabling ${REPO_PALEMOON}..."
|
||||||
|
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! is_installed "palemoon"; then
|
||||||
|
_run_cmd "Pale Moon" "sudo apt install -y palemoon" "Installing Pale Moon..."
|
||||||
|
echo -e "${GREEN}Pale Moon installed.${NC}"
|
||||||
|
else
|
||||||
|
echo "Pale Moon already installed."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_enable_librewolf_repo() {
|
||||||
|
if [ ! -f /etc/apt/sources.list.d/extrepo_librewolf.sources ]; then
|
||||||
|
_ensure_extrepo
|
||||||
|
_run_cmd "LibreWolf" "sudo extrepo enable librewolf" "Enabling LibreWolf repository..."
|
||||||
|
fi
|
||||||
|
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
||||||
|
}
|
||||||
|
|
||||||
|
_enable_tailscale_repo() {
|
||||||
|
if [ ! -f /etc/apt/sources.list.d/extrepo_tailscale.sources ]; then
|
||||||
|
_ensure_extrepo
|
||||||
|
_run_cmd "Tailscale" "sudo extrepo enable tailscale" "Enabling Tailscale repository..."
|
||||||
|
fi
|
||||||
|
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
||||||
|
}
|
||||||
|
|
||||||
|
_enable_mullvad_repo() {
|
||||||
|
if [ ! -f /etc/apt/sources.list.d/extrepo_mullvad.sources ]; then
|
||||||
|
_ensure_extrepo
|
||||||
|
_run_cmd "Mullvad" "sudo extrepo enable mullvad" "Enabling Mullvad repository..."
|
||||||
|
fi
|
||||||
|
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
||||||
|
}
|
||||||
|
|
||||||
|
install_protonvpn() {
|
||||||
|
if [ ! -f /etc/apt/sources.list.d/extrepo_protonvpn.sources ]; then
|
||||||
|
_ensure_extrepo
|
||||||
|
_run_cmd "ProtonVPN" "sudo extrepo enable protonvpn stable" "Enabling ProtonVPN repository (stable suite)..."
|
||||||
|
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
||||||
|
else
|
||||||
|
echo "ProtonVPN repository already enabled."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! is_installed "proton-vpn-gtk-app"; then
|
||||||
|
_msg "ProtonVPN" "Installing Proton VPN GTK client\nfrom the official Proton repository." 10 60
|
||||||
|
_run_cmd "ProtonVPN" "sudo apt install -y proton-vpn-gtk-app" "Installing Proton VPN GTK app..."
|
||||||
|
echo -e "${GREEN}ProtonVPN installed.${NC}"
|
||||||
|
else
|
||||||
|
echo "Proton VPN GTK app already installed."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Categories ──
|
||||||
_cat_internet() {
|
_cat_internet() {
|
||||||
local headless=false
|
local headless=false
|
||||||
_is_headless && headless=true
|
_is_headless && headless=true
|
||||||
|
local -a items=()
|
||||||
|
if ! $headless; then
|
||||||
local chromium_state; chromium_state=$(_state "chromium")
|
local chromium_state; chromium_state=$(_state "chromium")
|
||||||
local dillo_state; dillo_state=$(_state "dillo")
|
local dillo_state; dillo_state=$(_state "dillo")
|
||||||
local elinks_state; elinks_state=$(_state "elinks")
|
|
||||||
local epiphany_state; epiphany_state=$(_state "epiphany-browser")
|
local epiphany_state; epiphany_state=$(_state "epiphany-browser")
|
||||||
local falkon_state; falkon_state=$(_state "falkon")
|
local falkon_state; falkon_state=$(_state "falkon")
|
||||||
local firefox_state="OFF"
|
local firefox_state="OFF"
|
||||||
if command -v firefox &>/dev/null && ! command -v firefox-esr &>/dev/null; then
|
if command -v firefox &>/dev/null && ! is_installed "firefox-esr"; then
|
||||||
firefox_state="ON"
|
firefox_state="ON"
|
||||||
fi
|
fi
|
||||||
|
local firefox_esr_state
|
||||||
|
firefox_esr_state=$(_state "firefox-esr")
|
||||||
local floorp_state; floorp_state=$(_state "floorp")
|
local floorp_state; floorp_state=$(_state "floorp")
|
||||||
local konqueror_state; konqueror_state=$(_state "konqueror")
|
local konqueror_state; konqueror_state=$(_state "konqueror")
|
||||||
local librewolf_state; librewolf_state=$(_state "librewolf")
|
local librewolf_state; librewolf_state=$(_state "librewolf")
|
||||||
|
local palemoon_state; palemoon_state=$(_state "palemoon")
|
||||||
local privacybrowser_state; privacybrowser_state=$(_state "privacybrowser")
|
local privacybrowser_state; privacybrowser_state=$(_state "privacybrowser")
|
||||||
local qutebrowser_state; qutebrowser_state=$(_state "qutebrowser")
|
local qutebrowser_state; qutebrowser_state=$(_state "qutebrowser")
|
||||||
local riseupvpn_state; riseupvpn_state=$(_state "riseup-vpn")
|
|
||||||
local thunderbird_state; thunderbird_state=$(_state "thunderbird")
|
local thunderbird_state; thunderbird_state=$(_state "thunderbird")
|
||||||
local torbrowser_state; torbrowser_state=$(_state "torbrowser-launcher")
|
local torbrowser_state; torbrowser_state=$(_state "torbrowser-launcher")
|
||||||
|
local mullvadbrowser_state; mullvadbrowser_state=$(_state "mullvad-browser")
|
||||||
|
local protonvpn_state; protonvpn_state=$(_state "protonvpn")
|
||||||
|
items+=(
|
||||||
|
"chromium" "Chromium web browser" "$chromium_state"
|
||||||
|
"dillo" "Lightweight graphical browser" "$dillo_state"
|
||||||
|
"epiphany-browser" "GNOME web browser" "$epiphany_state"
|
||||||
|
"falkon" "KDE web browser (QtWebEngine)" "$falkon_state"
|
||||||
|
"firefox" "Firefox from Mozilla (replaces ESR)" "$firefox_state"
|
||||||
|
"firefox-esr" "Firefox ESR (official Debian + locale auto)" "$firefox_esr_state"
|
||||||
|
"floorp" "Firefox-based browser (extrepo)" "$floorp_state"
|
||||||
|
"konqueror" "KDE file manager / web browser" "$konqueror_state"
|
||||||
|
"librewolf" "Privacy-focused Firefox fork (extrepo)" "$librewolf_state"
|
||||||
|
"palemoon" "Classic Firefox-derived browser (extrepo)" "$palemoon_state"
|
||||||
|
"privacybrowser" "Privacy-focused web browser" "$privacybrowser_state"
|
||||||
|
"qutebrowser" "Keyboard-driven browser (Qt)" "$qutebrowser_state"
|
||||||
|
"thunderbird" "Email client" "$thunderbird_state"
|
||||||
|
"torbrowser-launcher" "Tor Browser launcher" "$torbrowser_state"
|
||||||
|
"mullvad-browser" "Mullvad privacy browser" "$mullvadbrowser_state"
|
||||||
|
"protonvpn" "ProtonVPN client" "$protonvpn_state"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
local elinks_state; elinks_state=$(_state "elinks")
|
||||||
|
local riseupvpn_state; riseupvpn_state=$(_state "riseup-vpn")
|
||||||
local w3m_state; w3m_state=$(_state "w3m")
|
local w3m_state; w3m_state=$(_state "w3m")
|
||||||
|
local tailscale_state; tailscale_state=$(_state "tailscale")
|
||||||
|
local mullvad_state; mullvad_state=$(_state "mullvad-vpn")
|
||||||
|
items+=(
|
||||||
|
"elinks" "Text-mode web browser" "$elinks_state"
|
||||||
|
"riseup-vpn" "Riseup VPN client" "$riseupvpn_state"
|
||||||
|
"w3m" "Text-mode browser + deps (w3m-img)" "$w3m_state"
|
||||||
|
"tailscale" "Zero-config VPN & mesh networking" "$tailscale_state"
|
||||||
|
"mullvad-vpn" "Mullvad VPN client (WireGuard)" "$mullvad_state"
|
||||||
|
)
|
||||||
|
|
||||||
|
local item_count=${#items[@]}
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
local choices
|
local choices
|
||||||
choices=$(whiptail --title "Internet" --checklist \
|
choices=$(_checklist "Internet" "Select browsers, email, and VPN tools${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
"Select browsers, email, and VPN tools:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
"${items[@]}" \
|
||||||
"chromium" "Chromium web browser$(_inst chromium)" "$chromium_state" \
|
)
|
||||||
"dillo" "Lightweight graphical browser$(_inst dillo)" "$dillo_state" \
|
|
||||||
"elinks" "Text-mode web browser$(_inst elinks)" "$elinks_state" \
|
|
||||||
"epiphany-browser" "GNOME web browser$(_inst epiphany-browser)" "$epiphany_state" \
|
|
||||||
"falkon" "KDE web browser (QtWebEngine)$(_inst falkon)" "$falkon_state" \
|
|
||||||
"firefox" "Firefox from Mozilla (replaces ESR)" "$firefox_state" \
|
|
||||||
"floorp" "Firefox-based browser (external repo)" "$floorp_state" \
|
|
||||||
"konqueror" "KDE file manager / web browser$(_inst konqueror)" "$konqueror_state" \
|
|
||||||
"librewolf" "Privacy-focused Firefox fork$(_inst librewolf)" "$librewolf_state" \
|
|
||||||
"privacybrowser" "Privacy-focused web browser$(_inst privacybrowser)" "$privacybrowser_state" \
|
|
||||||
"qutebrowser" "Keyboard-driven browser (Qt)$(_inst qutebrowser)" "$qutebrowser_state" \
|
|
||||||
"riseup-vpn" "Riseup VPN client$(_inst riseup-vpn)" "$riseupvpn_state" \
|
|
||||||
"thunderbird" "Email client$(_inst thunderbird)" "$thunderbird_state" \
|
|
||||||
"torbrowser-launcher" "Tor Browser launcher$(_inst torbrowser-launcher)" "$torbrowser_state" \
|
|
||||||
"w3m" "Text-mode browser + deps (w3m-img)$(_inst w3m)" "$w3m_state" \
|
|
||||||
3>&1 1>&2 2>&3)
|
|
||||||
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
|
||||||
|
_msg "Firefox" "You selected both Firefox (Mozilla) and Firefox ESR.\nPlease choose only one Firefox variant." 10 60
|
||||||
|
return
|
||||||
|
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
|
||||||
;;
|
;;
|
||||||
|
firefox-esr)
|
||||||
|
install_firefox_esr
|
||||||
|
;;
|
||||||
floorp)
|
floorp)
|
||||||
if ! is_installed "floorp"; then
|
_enable_floorp_repo
|
||||||
echo "Setting up Floorp repository..."
|
|
||||||
! is_installed "curl" && _run_install curl
|
|
||||||
! is_installed "gpg" && _run_install gpg
|
|
||||||
sudo install -d -m 0755 /etc/apt/keyrings
|
|
||||||
curl -fsSL https://ppa.floorp.app/KEY.gpg | \
|
|
||||||
sudo gpg --dearmor -o /usr/share/keyrings/Floorp.gpg
|
|
||||||
sudo curl -sS --compressed -o /etc/apt/sources.list.d/Floorp.list \
|
|
||||||
'https://ppa.floorp.app/Floorp.list'
|
|
||||||
sudo tee /etc/apt/preferences.d/floorp > /dev/null << EOF
|
|
||||||
Package: *
|
|
||||||
Pin: origin ppa.floorp.app
|
|
||||||
Pin-Priority: 1000
|
|
||||||
EOF
|
|
||||||
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
|
||||||
_run_install floorp
|
_run_install floorp
|
||||||
echo -e "${GREEN}Floorp installed.${NC}"
|
echo -e "${GREEN}Floorp installed.${NC}"
|
||||||
else
|
|
||||||
echo "Floorp already installed."
|
|
||||||
fi
|
|
||||||
;;
|
;;
|
||||||
librewolf)
|
librewolf)
|
||||||
if ! is_installed "librewolf"; then
|
_enable_librewolf_repo
|
||||||
echo "Installing LibreWolf..."
|
|
||||||
install_backports_or_stable extrepo
|
|
||||||
sudo extrepo enable librewolf 2>/dev/null || true
|
|
||||||
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
|
||||||
_run_install librewolf
|
_run_install librewolf
|
||||||
echo -e "${GREEN}LibreWolf installed.${NC}"
|
echo -e "${GREEN}LibreWolf installed.${NC}"
|
||||||
else
|
;;
|
||||||
echo "LibreWolf already installed."
|
palemoon)
|
||||||
fi
|
install_palemoon
|
||||||
|
;;
|
||||||
|
tailscale)
|
||||||
|
_enable_tailscale_repo
|
||||||
|
_run_install tailscale
|
||||||
|
echo -e "${GREEN}Tailscale installed.${NC}"
|
||||||
|
;;
|
||||||
|
mullvad-vpn)
|
||||||
|
_enable_mullvad_repo
|
||||||
|
_run_install mullvad-vpn
|
||||||
|
echo -e "${GREEN}Mullvad VPN installed.${NC}"
|
||||||
|
;;
|
||||||
|
mullvad-browser)
|
||||||
|
_enable_mullvad_repo
|
||||||
|
_run_install mullvad-browser
|
||||||
|
echo -e "${GREEN}Mullvad Browser installed.${NC}"
|
||||||
|
;;
|
||||||
|
protonvpn)
|
||||||
|
install_protonvpn
|
||||||
;;
|
;;
|
||||||
riseup-vpn)
|
riseup-vpn)
|
||||||
install_backports_or_stable riseup-vpn
|
install_backports_or_stable riseup-vpn
|
||||||
@@ -103,10 +243,6 @@ EOF
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
if $headless; then
|
|
||||||
echo "Skipping $pkg (headless mode)"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if ! is_installed "$pkg"; then
|
if ! is_installed "$pkg"; then
|
||||||
_run_install "$pkg"
|
_run_install "$pkg"
|
||||||
else
|
else
|
||||||
@@ -120,62 +256,57 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
install_firefox_mozilla() {
|
install_firefox_mozilla() {
|
||||||
if command -v firefox &>/dev/null && ! command -v firefox-esr &>/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
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v firefox &>/dev/null && ! is_installed "firefox-esr"; then
|
||||||
echo "Firefox (Mozilla) is already installed."
|
echo "Firefox (Mozilla) is already installed."
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Setting up Mozilla APT repository for Firefox..."
|
|
||||||
|
|
||||||
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
|
if _confirm "Firefox ESR" "Firefox ESR is installed.\nRemove it before installing Mozilla Firefox?"; then
|
||||||
echo "Removing Firefox ESR..."
|
echo "Removing Firefox ESR..."
|
||||||
sudo apt remove -y firefox-esr
|
sudo apt remove -y firefox-esr
|
||||||
else
|
else
|
||||||
echo "Keeping Firefox ESR."
|
echo "Keeping Firefox ESR."
|
||||||
|
return
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
! is_installed "wget" && _run_install wget
|
_enable_mozilla_repo
|
||||||
! is_installed "gpg" && _run_install gpg
|
_run_cmd "Firefox" "sudo apt install -y firefox" "Installing Firefox (Mozilla)..."
|
||||||
|
|
||||||
sudo install -d -m 0755 /etc/apt/keyrings
|
|
||||||
|
|
||||||
wget -q https://packages.mozilla.org/apt/repo-signing-key.gpg -O- | \
|
|
||||||
sudo tee /etc/apt/keyrings/packages.mozilla.org.asc > /dev/null
|
|
||||||
|
|
||||||
local fp
|
|
||||||
fp=$(gpg -n -q --import --import-options import-show \
|
|
||||||
/etc/apt/keyrings/packages.mozilla.org.asc 2>/dev/null | \
|
|
||||||
awk '/pub/{getline; gsub(/^ +| +$/,""); print}')
|
|
||||||
if [ "$fp" != "35BAA0B33E9EB396F59CA838C0BA5CE6DC6315A3" ]; then
|
|
||||||
echo -e "${YELLOW}Warning: Mozilla key fingerprint does not match expected value.${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
local use_deb822=false
|
|
||||||
[ -f /etc/apt/sources.list.d/debian.sources ] && use_deb822=true
|
|
||||||
|
|
||||||
if $use_deb822; then
|
|
||||||
sudo tee /etc/apt/sources.list.d/mozilla.sources > /dev/null << EOF
|
|
||||||
Types: deb
|
|
||||||
URIs: https://packages.mozilla.org/apt
|
|
||||||
Suites: mozilla
|
|
||||||
Components: main
|
|
||||||
Signed-By: /etc/apt/keyrings/packages.mozilla.org.asc
|
|
||||||
EOF
|
|
||||||
else
|
|
||||||
echo "deb [signed-by=/etc/apt/keyrings/packages.mozilla.org.asc] https://packages.mozilla.org/apt mozilla main" | \
|
|
||||||
sudo tee /etc/apt/sources.list.d/mozilla.list > /dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
sudo tee /etc/apt/preferences.d/mozilla > /dev/null << EOF
|
|
||||||
Package: *
|
|
||||||
Pin: origin packages.mozilla.org
|
|
||||||
Pin-Priority: 1000
|
|
||||||
EOF
|
|
||||||
|
|
||||||
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
|
||||||
_run_install firefox
|
|
||||||
|
|
||||||
echo -e "${GREEN}Firefox (Mozilla) installed.${NC}"
|
echo -e "${GREEN}Firefox (Mozilla) installed.${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
install_firefox_esr() {
|
||||||
|
if is_installed "firefox-esr"; then
|
||||||
|
echo "Firefox ESR is already installed."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v firefox &>/dev/null; then
|
||||||
|
if _confirm "Firefox" "Mozilla Firefox is installed.\nRemove it before installing Firefox ESR?"; then
|
||||||
|
echo "Removing Mozilla Firefox..."
|
||||||
|
sudo apt remove -y firefox
|
||||||
|
else
|
||||||
|
echo "Keeping Mozilla Firefox."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
_run_cmd "Firefox ESR" "sudo apt install -y firefox-esr" "Installing Firefox ESR..."
|
||||||
|
|
||||||
|
local lang_pkg
|
||||||
|
lang_pkg=$(_detect_lang_pkg "firefox-esr-l10n")
|
||||||
|
if [ -n "$lang_pkg" ]; then
|
||||||
|
_run_cmd "Firefox ESR Locale" "sudo apt install -y ${lang_pkg}" \
|
||||||
|
"Installing locale: ${lang_pkg}..."
|
||||||
|
else
|
||||||
|
echo "No matching locale package found for your language."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}Firefox ESR installed.${NC}"
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# java.sh — Adoptium Temurin repository setup (extrepo) and Java version selectors
|
||||||
|
# License GPL v3
|
||||||
|
|
||||||
|
_enable_temurin_repo() {
|
||||||
|
if [ -f /etc/apt/sources.list.d/extrepo_temurin.sources ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if ! command -v extrepo &>/dev/null; then
|
||||||
|
_run_cmd "extrepo" "sudo apt install -y extrepo" "Installing extrepo..."
|
||||||
|
fi
|
||||||
|
_run_cmd "Temurin" "sudo extrepo enable temurin" "Enabling Adoptium Temurin repository..."
|
||||||
|
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
||||||
|
}
|
||||||
|
|
||||||
|
install_minecraft_java() {
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "Java Runtimes for Minecraft" \
|
||||||
|
"Select Java version(s) to install:" 14 65 3 \
|
||||||
|
"8" "Java 8 — Classic mods & Minecraft <= 1.16.5" OFF \
|
||||||
|
"17" "Java 17 — Minecraft 1.17 to 1.20.4" ON \
|
||||||
|
"21" "Java 21 — Modern Minecraft >= 1.20.5 & 1.21+" OFF)
|
||||||
|
[ -z "$choices" ] && { echo "No Java version selected."; return; }
|
||||||
|
_enable_temurin_repo
|
||||||
|
local cleaned
|
||||||
|
cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
for ver in $cleaned; do
|
||||||
|
_run_cmd "Java" "sudo apt install -y temurin-${ver}-jre" \
|
||||||
|
"Installing Temurin JRE ${ver}..."
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
_install_dev_java() {
|
||||||
|
local ver
|
||||||
|
ver=$(_menu "Java Development Kits (JDK)" \
|
||||||
|
"Select JDK version:" 12 60 3 \
|
||||||
|
"17" "Java 17 LTS Development Kit" \
|
||||||
|
"21" "Java 21 LTS Development Kit" \
|
||||||
|
"25" "Java 25 LTS Development Kit")
|
||||||
|
[ -z "$ver" ] && { echo "No JDK version selected."; return; }
|
||||||
|
_enable_temurin_repo
|
||||||
|
_run_install "temurin-${ver}-jdk"
|
||||||
|
}
|
||||||
|
|
||||||
|
_any_jdk_installed_desc() {
|
||||||
|
local inst
|
||||||
|
inst=$(dpkg -l 'temurin-*-jdk' 2>/dev/null | awk '/^ii/ {print $2; exit}')
|
||||||
|
[ -n "$inst" ] && echo " ($inst installed)" || echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
_any_jdk_state() {
|
||||||
|
dpkg -l 'temurin-*-jdk' 2>/dev/null | grep -q '^ii' && echo "ON" || echo "OFF"
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# office.sh — Office & Productivity (OnlyOffice via extrepo, LibreOffice backports)
|
||||||
|
# License GPL v3
|
||||||
|
|
||||||
|
# ── OnlyOffice ──
|
||||||
|
_enable_onlyoffice_repo() {
|
||||||
|
if [ ! -f /etc/apt/sources.list.d/extrepo_onlyoffice-desktopeditors.sources ]; then
|
||||||
|
if ! command -v extrepo &>/dev/null; then
|
||||||
|
_run_cmd "extrepo" "sudo apt install -y extrepo" "Installing extrepo..."
|
||||||
|
fi
|
||||||
|
_run_cmd "OnlyOffice" "sudo extrepo enable onlyoffice-desktopeditors" "Enabling OnlyOffice repository..."
|
||||||
|
fi
|
||||||
|
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
||||||
|
}
|
||||||
|
|
||||||
|
install_onlyoffice() {
|
||||||
|
local ver
|
||||||
|
ver=$(apt-cache policy onlyoffice-desktopeditors 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
|
|
||||||
|
if _confirm "Install: OnlyOffice" "Install OnlyOffice Desktop Editors
|
||||||
|
Repository: download.onlyoffice.com
|
||||||
|
Version: ${ver:-unknown}"; then
|
||||||
|
_enable_onlyoffice_repo
|
||||||
|
_run_cmd "OnlyOffice" "sudo DEBIAN_FRONTEND=noninteractive apt install -y onlyoffice-desktopeditors" "Installing OnlyOffice..." || echo -e "${RED}OnlyOffice servers are currently slow or down. Please try again later.${NC}"
|
||||||
|
echo -e "${GREEN}OnlyOffice installed.${NC}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── LibreOffice (backports) ──
|
||||||
|
install_libreoffice_bpo() {
|
||||||
|
if [ "$DEBIAN_VERSION" != "12" ] && [ "$DEBIAN_VERSION" != "13" ]; then
|
||||||
|
_msg "LibreOffice" "LibreOffice backports only available on Debian 12+."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local lang_pkg
|
||||||
|
lang_pkg=$(_detect_lang_pkg "libreoffice-l10n")
|
||||||
|
|
||||||
|
local ver
|
||||||
|
ver=$(apt-cache policy libreoffice 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
|
local bpo_ver
|
||||||
|
bpo_ver=$(apt-cache madison libreoffice 2>/dev/null | grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1)
|
||||||
|
|
||||||
|
local msg="Install LibreOffice?\n\n"
|
||||||
|
msg+=" Stable: ${ver:-unknown}\n"
|
||||||
|
msg+=" Backports: ${bpo_ver:-unavailable}\n"
|
||||||
|
[ -n "$lang_pkg" ] && msg+=" Language: ${lang_pkg}\n"
|
||||||
|
|
||||||
|
if _confirm "LibreOffice" "$msg"; then
|
||||||
|
local pkgs="libreoffice${lang_pkg:+ $lang_pkg}"
|
||||||
|
if [ -n "$bpo_ver" ]; then
|
||||||
|
_run_cmd "LibreOffice" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports $pkgs" \
|
||||||
|
"Installing LibreOffice from backports..."
|
||||||
|
else
|
||||||
|
_run_cmd "LibreOffice" "sudo apt install -y $pkgs" \
|
||||||
|
"Installing LibreOffice from stable..."
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}LibreOffice installed.${NC}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_cat_office() {
|
||||||
|
local headless=false
|
||||||
|
_is_headless && headless=true
|
||||||
|
local -a items=()
|
||||||
|
if ! $headless; then
|
||||||
|
items+=(
|
||||||
|
"onlyoffice" "OnlyOffice Desktop Editors (extrepo)" OFF
|
||||||
|
"libreoffice" "LibreOffice (backports on Bookworm/Trixie)" OFF
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
local item_count=${#items[@]}
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "Office & Productivity" "Select office applications${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
|
"${items[@]}" \
|
||||||
|
)
|
||||||
|
|
||||||
|
[ -z "$choices" ] && return
|
||||||
|
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
|
||||||
|
for pkg in $cleaned; do
|
||||||
|
case $pkg in
|
||||||
|
onlyoffice) install_onlyoffice ;;
|
||||||
|
libreoffice) install_libreoffice_bpo ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
@@ -4,16 +4,22 @@
|
|||||||
_cat_players() {
|
_cat_players() {
|
||||||
local headless=false
|
local headless=false
|
||||||
_is_headless && headless=true
|
_is_headless && headless=true
|
||||||
|
local -a items=()
|
||||||
|
if ! $headless; then
|
||||||
local mpv_state; mpv_state=$(_state "mpv")
|
local mpv_state; mpv_state=$(_state "mpv")
|
||||||
local vlc_state; vlc_state=$(_state "vlc")
|
local vlc_state; vlc_state=$(_state "vlc")
|
||||||
|
items+=(
|
||||||
|
"mpv" "Lightweight media player" "$mpv_state"
|
||||||
|
"vlc" "VLC media player" "$vlc_state"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
|
local item_count=${#items[@]}
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
local choices
|
local choices
|
||||||
choices=$(whiptail --title "Media Players" --checklist \
|
choices=$(_checklist "Media Players" "Select media players:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
"Select media players:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
|
"${items[@]}" \
|
||||||
"mpv" "Lightweight media player$(_inst mpv)" "$mpv_state" \
|
)
|
||||||
"vlc" "VLC media player$(_inst vlc)" "$vlc_state" \
|
|
||||||
3>&1 1>&2 2>&3)
|
|
||||||
clear
|
clear
|
||||||
|
|
||||||
[ -z "$choices" ] && return
|
[ -z "$choices" ] && return
|
||||||
@@ -21,10 +27,6 @@ _cat_players() {
|
|||||||
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 $headless; then
|
|
||||||
echo "Skipping $pkg (headless mode)"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if ! is_installed "$pkg"; then
|
if ! is_installed "$pkg"; then
|
||||||
_run_install "$pkg"
|
_run_install "$pkg"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -4,12 +4,21 @@
|
|||||||
_cat_programming() {
|
_cat_programming() {
|
||||||
local headless=false
|
local headless=false
|
||||||
_is_headless && headless=true
|
_is_headless && headless=true
|
||||||
|
local -a items=()
|
||||||
local vim_state; vim_state=$(_state "vim")
|
local vim_state; vim_state=$(_state "vim")
|
||||||
local vimgtk_state; vimgtk_state=$(_state "vim-gtk3")
|
|
||||||
local neovim_state; neovim_state=$(_state "neovim")
|
local neovim_state; neovim_state=$(_state "neovim")
|
||||||
local hx_state; hx_state=$(_state "hx")
|
local hx_state; hx_state=$(_state "hx")
|
||||||
local nano_state; nano_state=$(_state "nano")
|
local nano_state; nano_state=$(_state "nano")
|
||||||
local emacs_state; emacs_state=$(_state "emacs")
|
local emacs_state; emacs_state=$(_state "emacs")
|
||||||
|
items+=(
|
||||||
|
"vim" "Classic terminal editor" "$vim_state"
|
||||||
|
"neovim" "Modern vim fork" "$neovim_state"
|
||||||
|
"hx" "Helix modal editor (Rust)" "$hx_state"
|
||||||
|
"nano" "Simple terminal editor" "$nano_state"
|
||||||
|
"emacs" "Extensible editor / IDE" "$emacs_state"
|
||||||
|
)
|
||||||
|
if ! $headless; then
|
||||||
|
local vimgtk_state; vimgtk_state=$(_state "vim-gtk3")
|
||||||
local kate_state; kate_state=$(_state "kate")
|
local kate_state; kate_state=$(_state "kate")
|
||||||
local mousepad_state; mousepad_state=$(_state "mousepad")
|
local mousepad_state; mousepad_state=$(_state "mousepad")
|
||||||
local gedit_state; gedit_state=$(_state "gedit")
|
local gedit_state; gedit_state=$(_state "gedit")
|
||||||
@@ -19,24 +28,23 @@ _cat_programming() {
|
|||||||
if command -v codium &>/dev/null; then
|
if command -v codium &>/dev/null; then
|
||||||
codium_state="ON"
|
codium_state="ON"
|
||||||
fi
|
fi
|
||||||
|
items+=(
|
||||||
|
"vim-gtk3" "Vim with GTK3 GUI" "$vimgtk_state"
|
||||||
|
"kate" "KDE advanced text editor" "$kate_state"
|
||||||
|
"mousepad" "Xfce text editor" "$mousepad_state"
|
||||||
|
"gedit" "GNOME text editor" "$gedit_state"
|
||||||
|
"geany" "Lightweight IDE" "$geany_state"
|
||||||
|
"gnome-text-editor" "GNOME modern text editor" "$gte_state"
|
||||||
|
"vscodium" "VS Code open-source (extrepo)" "$codium_state"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
|
local item_count=${#items[@]}
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
local choices
|
local choices
|
||||||
choices=$(whiptail --title "Programming Applications" --checklist \
|
choices=$(_checklist "Programming Applications" "Select editors and IDEs${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
"Select editors and IDEs (12 items, ↑↓ scroll):" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
|
"${items[@]}" \
|
||||||
"vim" "Classic terminal editor$(_inst vim)" "$vim_state" \
|
)
|
||||||
"vim-gtk3" "Vim with GTK3 GUI$(_inst vim-gtk3)" "$vimgtk_state" \
|
|
||||||
"neovim" "Modern vim fork$(_inst neovim)" "$neovim_state" \
|
|
||||||
"hx" "Helix modal editor (Rust)$(_inst hx)" "$hx_state" \
|
|
||||||
"nano" "Simple terminal editor$(_inst nano)" "$nano_state" \
|
|
||||||
"emacs" "Extensible editor / IDE$(_inst emacs)" "$emacs_state" \
|
|
||||||
"kate" "KDE advanced text editor$(_inst kate)" "$kate_state" \
|
|
||||||
"mousepad" "Xfce text editor$(_inst mousepad)" "$mousepad_state" \
|
|
||||||
"gedit" "GNOME text editor$(_inst gedit)" "$gedit_state" \
|
|
||||||
"geany" "Lightweight IDE$(_inst geany)" "$geany_state" \
|
|
||||||
"gnome-text-editor" "GNOME modern text editor$(_inst gnome-text-editor)" "$gte_state" \
|
|
||||||
"vscodium" "VS Code open-source (external repo)$(_inst codium)" "$codium_state" \
|
|
||||||
3>&1 1>&2 2>&3)
|
|
||||||
clear
|
clear
|
||||||
|
|
||||||
[ -z "$choices" ] && return
|
[ -z "$choices" ] && return
|
||||||
@@ -49,10 +57,6 @@ _cat_programming() {
|
|||||||
install_vscodium
|
install_vscodium
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
if $headless; then
|
|
||||||
echo "Skipping $pkg (headless mode)"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if ! is_installed "$pkg"; then
|
if ! is_installed "$pkg"; then
|
||||||
_run_install "$pkg"
|
_run_install "$pkg"
|
||||||
else
|
else
|
||||||
@@ -65,41 +69,23 @@ _cat_programming() {
|
|||||||
echo -e "${GREEN}Programming applications installed.${NC}"
|
echo -e "${GREEN}Programming applications installed.${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_enable_vscodium_repo() {
|
||||||
|
if [ ! -f /etc/apt/sources.list.d/extrepo_vscodium.sources ]; then
|
||||||
|
if ! command -v extrepo &>/dev/null; then
|
||||||
|
_run_cmd "extrepo" "sudo apt install -y extrepo" "Installing extrepo..."
|
||||||
|
fi
|
||||||
|
_run_cmd "VSCodium" "sudo extrepo enable vscodium" "Enabling VSCodium repository..."
|
||||||
|
fi
|
||||||
|
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
||||||
|
}
|
||||||
|
|
||||||
install_vscodium() {
|
install_vscodium() {
|
||||||
if command -v codium &>/dev/null; then
|
if command -v codium &>/dev/null; then
|
||||||
echo "VSCodium is already installed."
|
echo "VSCodium is already installed."
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Setting up VSCodium repository..."
|
_enable_vscodium_repo
|
||||||
|
|
||||||
! is_installed "wget" && _run_install wget
|
|
||||||
! is_installed "gpg" && _run_install gpg
|
|
||||||
|
|
||||||
sudo install -d -m 0755 /usr/share/keyrings
|
|
||||||
|
|
||||||
wget -qO - https://gitlab.com/paulcarroty/vscodium-deb-rpm-repo/raw/master/pub.gpg \
|
|
||||||
| gpg --dearmor \
|
|
||||||
| sudo dd of=/usr/share/keyrings/vscodium-archive-keyring.gpg 2>/dev/null
|
|
||||||
|
|
||||||
local use_deb822=false
|
|
||||||
[ -f /etc/apt/sources.list.d/debian.sources ] && use_deb822=true
|
|
||||||
|
|
||||||
if $use_deb822; then
|
|
||||||
sudo tee /etc/apt/sources.list.d/vscodium.sources > /dev/null << 'EOF'
|
|
||||||
Types: deb
|
|
||||||
URIs: https://download.vscodium.com/debs
|
|
||||||
Suites: vscodium
|
|
||||||
Components: main
|
|
||||||
Architectures: amd64 arm64
|
|
||||||
Signed-by: /usr/share/keyrings/vscodium-archive-keyring.gpg
|
|
||||||
EOF
|
|
||||||
else
|
|
||||||
echo "deb [arch=amd64,arm64 signed-by=/usr/share/keyrings/vscodium-archive-keyring.gpg] https://download.vscodium.com/debs vscodium main" \
|
|
||||||
| sudo tee /etc/apt/sources.list.d/vscodium.list > /dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
|
||||||
_run_install codium
|
_run_install codium
|
||||||
|
|
||||||
echo -e "${GREEN}VSCodium installed.${NC}"
|
echo -e "${GREEN}VSCodium installed.${NC}"
|
||||||
|
|||||||
@@ -4,22 +4,32 @@
|
|||||||
_cat_security() {
|
_cat_security() {
|
||||||
local headless=false
|
local headless=false
|
||||||
_is_headless && headless=true
|
_is_headless && headless=true
|
||||||
|
local -a items=()
|
||||||
|
if ! $headless; then
|
||||||
local wireshark_state; wireshark_state=$(_state "wireshark")
|
local wireshark_state; wireshark_state=$(_state "wireshark")
|
||||||
local tcpdump_state; tcpdump_state=$(_state "tcpdump")
|
|
||||||
local zenmap_state; zenmap_state=$(_state "zenmap")
|
local zenmap_state; zenmap_state=$(_state "zenmap")
|
||||||
|
items+=(
|
||||||
|
"wireshark" "Network protocol analyzer (GUI)" "$wireshark_state"
|
||||||
|
"zenmap" "Network scanner GUI (Nmap frontend)" "$zenmap_state"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
local tcpdump_state; tcpdump_state=$(_state "tcpdump")
|
||||||
local fail2ban_state; fail2ban_state=$(_state "fail2ban")
|
local fail2ban_state; fail2ban_state=$(_state "fail2ban")
|
||||||
local ufw_state; ufw_state=$(_state "ufw")
|
local ufw_state; ufw_state=$(_state "ufw")
|
||||||
|
local clamav_state; clamav_state=$(_state "clamav")
|
||||||
|
items+=(
|
||||||
|
"tcpdump" "Command-line packet analyzer" "$tcpdump_state"
|
||||||
|
"fail2ban" "Brute-force protection daemon" "$fail2ban_state"
|
||||||
|
"ufw" "Uncomplicated firewall" "$ufw_state"
|
||||||
|
"clamav" "Antivirus engine (ClamAV)" "$clamav_state"
|
||||||
|
)
|
||||||
|
|
||||||
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
|
local item_count=${#items[@]}
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
local choices
|
local choices
|
||||||
choices=$(whiptail --title "Security & Networking" --checklist \
|
choices=$(_checklist "Security & Networking" "Select security and networking tools${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
"Select security and networking tools (5 items):" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
|
"${items[@]}" \
|
||||||
"wireshark" "Network protocol analyzer (GUI)$(_inst wireshark)" "$wireshark_state" \
|
)
|
||||||
"tcpdump" "Command-line packet analyzer$(_inst tcpdump)" "$tcpdump_state" \
|
|
||||||
"zenmap" "Network scanner GUI (Nmap frontend)$(_inst zenmap)" "$zenmap_state" \
|
|
||||||
"fail2ban" "Brute-force protection daemon$(_inst fail2ban)" "$fail2ban_state" \
|
|
||||||
"ufw" "Uncomplicated firewall$(_inst ufw)" "$ufw_state" \
|
|
||||||
3>&1 1>&2 2>&3)
|
|
||||||
clear
|
clear
|
||||||
|
|
||||||
[ -z "$choices" ] && return
|
[ -z "$choices" ] && return
|
||||||
@@ -31,6 +41,9 @@ _cat_security() {
|
|||||||
zenmap)
|
zenmap)
|
||||||
install_backports_or_stable zenmap
|
install_backports_or_stable zenmap
|
||||||
;;
|
;;
|
||||||
|
clamav)
|
||||||
|
_install_clamav
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
if ! is_installed "$pkg"; then
|
if ! is_installed "$pkg"; then
|
||||||
_run_install "$pkg"
|
_run_install "$pkg"
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# software_centers.sh — Standalone Software Center installer
|
||||||
|
|
||||||
|
_cat_software_centers() {
|
||||||
|
local headless=false
|
||||||
|
_is_headless && headless=true
|
||||||
|
if $headless; then
|
||||||
|
echo "Software centers require a GUI — skipping."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
local de_type
|
||||||
|
de_type=$(_detect_desktop_type)
|
||||||
|
local sc_choice
|
||||||
|
sc_choice=$(_menu "Software Centers" "Choose a software store to install:" 12 65 2 \
|
||||||
|
"gnome-software" "Software Center for GNOME" \
|
||||||
|
"plasma-discover" "Software manager for Plasma" \
|
||||||
|
)
|
||||||
|
[ -z "$sc_choice" ] && return
|
||||||
|
|
||||||
|
if { [ "$de_type" = "qt" ] && [ "$sc_choice" = "gnome-software" ]; } || \
|
||||||
|
{ [ "$de_type" = "gtk" ] && [ "$sc_choice" = "plasma-discover" ]; }; then
|
||||||
|
_msg "Warning" "Warning: This store requires extra background libraries \
|
||||||
|
and may look visually inconsistent with your current desktop environment."
|
||||||
|
! _confirm "Continue?" "Install anyway?" && return
|
||||||
|
fi
|
||||||
|
|
||||||
|
_run_cmd "Install" "sudo apt install -y $sc_choice" "Installing ${sc_choice}..."
|
||||||
|
|
||||||
|
if _confirm "Flatpak Support" "Do you want to enable Flatpak support for this software center?"; then
|
||||||
|
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}"
|
||||||
|
}
|
||||||
+151
-64
@@ -1,10 +1,25 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# system.sh — System Tools (extrepo moved here from Dev & Servers)
|
# system.sh — System Tools (extrepo moved here from Dev & Servers)
|
||||||
|
|
||||||
|
_detect_desktop_type() {
|
||||||
|
local desktop
|
||||||
|
desktop="${XDG_CURRENT_DESKTOP:-${DESKTOP_SESSION:-}}"
|
||||||
|
desktop="${desktop,,}"
|
||||||
|
|
||||||
|
case "$desktop" in
|
||||||
|
*kde*|*lxqt*|*razor*|*plasma*)
|
||||||
|
echo "qt"; return ;;
|
||||||
|
*gnome*|*xfce*|*cinnamon*|*mate*|*lxde*|*budgie*|*sway*|*hyprland*|*i3*|*bspwm*|*openbox*|*fluxbox*)
|
||||||
|
echo "gtk"; return ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "gtk"
|
||||||
|
}
|
||||||
|
|
||||||
_cat_general() {
|
_cat_general() {
|
||||||
local headless=false
|
local headless=false
|
||||||
_is_headless && headless=true
|
_is_headless && headless=true
|
||||||
local alacritty_state; alacritty_state=$(_state "alacritty")
|
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
|
||||||
@@ -12,8 +27,6 @@ _cat_general() {
|
|||||||
else
|
else
|
||||||
compress_state="OFF"
|
compress_state="OFF"
|
||||||
fi
|
fi
|
||||||
local conky_state; conky_state=$(_state "conky")
|
|
||||||
local corectrl_state; corectrl_state=$(_state "corectrl")
|
|
||||||
local cpufetch_state; cpufetch_state=$(_state "cpufetch")
|
local cpufetch_state; cpufetch_state=$(_state "cpufetch")
|
||||||
local cpu_x_state; cpu_x_state=$(_state "cpu-x")
|
local cpu_x_state; cpu_x_state=$(_state "cpu-x")
|
||||||
local curl_wget_state
|
local curl_wget_state
|
||||||
@@ -22,60 +35,72 @@ _cat_general() {
|
|||||||
else
|
else
|
||||||
curl_wget_state="OFF"
|
curl_wget_state="OFF"
|
||||||
fi
|
fi
|
||||||
local dcgtk_state; dcgtk_state=$(_state "doublecmd-gtk")
|
|
||||||
local dcqt_state; dcqt_state=$(_state "doublecmd-qt")
|
|
||||||
local extrepo_state; extrepo_state=$(_state "extrepo")
|
local extrepo_state; extrepo_state=$(_state "extrepo")
|
||||||
local flatpak_state; flatpak_state=$(_state "flatpak")
|
local flatpak_state; flatpak_state=$(_state "flatpak")
|
||||||
local fwupd_state; fwupd_state=$(_state "fwupd")
|
local fwupd_state; fwupd_state=$(_state "fwupd")
|
||||||
local disks_state; disks_state=$(_state "gnome-disk-utility")
|
|
||||||
local gparted_state; gparted_state=$(_state "gparted")
|
|
||||||
local hardinfo_state; hardinfo_state=$(_state "hardinfo")
|
|
||||||
local htop_state; htop_state=$(_state "htop")
|
local htop_state; htop_state=$(_state "htop")
|
||||||
local inxi_state; inxi_state=$(_state "inxi")
|
local inxi_state; inxi_state=$(_state "inxi")
|
||||||
local kitty_state; kitty_state=$(_state "kitty")
|
|
||||||
local kvm_state; kvm_state=$(_state "virt-manager")
|
local kvm_state; kvm_state=$(_state "virt-manager")
|
||||||
local lshw_state; lshw_state=$(_state "lshw")
|
local lshw_state; lshw_state=$(_state "lshw")
|
||||||
local mc_state; mc_state=$(_state "mc")
|
local mc_state; mc_state=$(_state "mc")
|
||||||
local nala_state; nala_state=$(_state "nala")
|
local nala_state; nala_state=$(_state "nala")
|
||||||
local ncdu_state; ncdu_state=$(_state "ncdu")
|
local ncdu_state; ncdu_state=$(_state "ncdu")
|
||||||
local psensor_state; psensor_state=$(_state "psensor")
|
|
||||||
local timeshift_state; timeshift_state=$(_state "timeshift")
|
|
||||||
local tmux_state; tmux_state=$(_state "tmux")
|
local tmux_state; tmux_state=$(_state "tmux")
|
||||||
local wine_state; wine_state=$(_state "wine")
|
local wine_state; wine_state=$(_state "wine")
|
||||||
|
local nvme_state; nvme_state=$(_state "nvme-cli")
|
||||||
|
items+=(
|
||||||
|
"btop" "Resource monitor (fancy top)" "$btop_state"
|
||||||
|
"compress" "Compression tools (zip, unrar, 7z)" "$compress_state"
|
||||||
|
"cpufetch" "CPU info fetcher" "$cpufetch_state"
|
||||||
|
"cpu-x" "CPU-X (alternative to CPU-Z)" "$cpu_x_state"
|
||||||
|
"curl-wget" "HTTP transfer tools (curl, wget)" "$curl_wget_state"
|
||||||
|
"extrepo" "External repository manager" "$extrepo_state"
|
||||||
|
"flatpak" "Flatpak sandbox + Flathub" "$flatpak_state"
|
||||||
|
"fwupd" "Firmware update daemon" "$fwupd_state"
|
||||||
|
"htop" "Interactive process viewer" "$htop_state"
|
||||||
|
"inxi" "System information tool" "$inxi_state"
|
||||||
|
"kvm" "QEMU/KVM virtualization" "$kvm_state"
|
||||||
|
"lshw" "List hardware details" "$lshw_state"
|
||||||
|
"mc" "Midnight Commander (file manager)" "$mc_state"
|
||||||
|
"nala" "APT frontend (parallel downloads)" "$nala_state"
|
||||||
|
"ncdu" "Disk usage analyzer (ncurses)" "$ncdu_state"
|
||||||
|
"nvme-cli" "NVMe SSD health monitoring" "$nvme_state"
|
||||||
|
"tmux" "Terminal multiplexer" "$tmux_state"
|
||||||
|
"wine" "Windows compatibility layer" "$wine_state"
|
||||||
|
)
|
||||||
|
if ! $headless; then
|
||||||
|
local alacritty_state; alacritty_state=$(_state "alacritty")
|
||||||
|
local conky_state; conky_state=$(_state "conky")
|
||||||
|
local corectrl_state; corectrl_state=$(_state "corectrl")
|
||||||
|
local dcgtk_state; dcgtk_state=$(_state "doublecmd-gtk")
|
||||||
|
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 kitty_state; kitty_state=$(_state "kitty")
|
||||||
|
local psensor_state; psensor_state=$(_state "psensor")
|
||||||
|
local timeshift_state; timeshift_state=$(_state "timeshift")
|
||||||
|
items+=(
|
||||||
|
"alacritty" "GPU-accelerated terminal" "$alacritty_state"
|
||||||
|
"conky" "System monitor for desktop" "$conky_state"
|
||||||
|
"corectrl" "AMD GPU control (CoreCtrl)" "$corectrl_state"
|
||||||
|
"doublecmd-gtk" "Dual-panel file manager (GTK)" "$dcgtk_state"
|
||||||
|
"doublecmd-qt" "Dual-panel file manager (Qt)" "$dcqt_state"
|
||||||
|
"gnome-disk-utility" "Disk management GUI" "$disks_state"
|
||||||
|
"gparted" "GNOME partition editor" "$gparted_state"
|
||||||
|
"hardinfo" "Graphical system profiler" "$hardinfo_state"
|
||||||
|
"kitty" "GPU-based terminal emulator" "$kitty_state"
|
||||||
|
"psensor" "Hardware temperature monitor" "$psensor_state"
|
||||||
|
"timeshift" "System restore snapshots" "$timeshift_state"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
|
local item_count=${#items[@]}
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
local choices
|
local choices
|
||||||
choices=$(whiptail --title "System Tools" --checklist \
|
choices=$(_checklist "System Tools" "Select system utilities to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
"Select system utilities to install (28 items, ↑↓ scroll):" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
|
"${items[@]}" \
|
||||||
"alacritty" "GPU-accelerated terminal$(_inst alacritty)" "$alacritty_state" \
|
)
|
||||||
"btop" "Resource monitor (fancy top)$(_inst btop)" "$btop_state" \
|
|
||||||
"compress" "Compression tools (zip, unrar, 7z)$(_inst zip)" "$compress_state" \
|
|
||||||
"conky" "System monitor for desktop$(_inst conky)" "$conky_state" \
|
|
||||||
"corectrl" "AMD GPU control (CoreCtrl)$(_inst corectrl)" "$corectrl_state" \
|
|
||||||
"cpufetch" "CPU info fetcher$(_inst cpufetch)" "$cpufetch_state" \
|
|
||||||
"cpu-x" "CPU-X (alternative to CPU-Z)$(_inst cpu-x)" "$cpu_x_state" \
|
|
||||||
"curl-wget" "HTTP transfer tools (curl, wget)$(_inst curl)" "$curl_wget_state" \
|
|
||||||
"doublecmd-gtk" "Dual-panel file manager (GTK)$(_inst doublecmd-gtk)" "$dcgtk_state" \
|
|
||||||
"doublecmd-qt" "Dual-panel file manager (Qt)$(_inst doublecmd-qt)" "$dcqt_state" \
|
|
||||||
"extrepo" "External repository manager$(_inst extrepo)" "$extrepo_state" \
|
|
||||||
"flatpak" "Flatpak sandbox + Flathub$(_inst flatpak)" "$flatpak_state" \
|
|
||||||
"fwupd" "Firmware update daemon$(_inst fwupd)" "$fwupd_state" \
|
|
||||||
"gnome-disk-utility" "Disk management GUI$(_inst gnome-disk-utility)" "$disks_state" \
|
|
||||||
"gparted" "GNOME partition editor$(_inst gparted)" "$gparted_state" \
|
|
||||||
"hardinfo" "Graphical system profiler$(_inst hardinfo)" "$hardinfo_state" \
|
|
||||||
"htop" "Interactive process viewer$(_inst htop)" "$htop_state" \
|
|
||||||
"inxi" "System information tool$(_inst inxi)" "$inxi_state" \
|
|
||||||
"kitty" "GPU-based terminal emulator$(_inst kitty)" "$kitty_state" \
|
|
||||||
"kvm" "QEMU/KVM virtualization$(_inst virt-manager)" "$kvm_state" \
|
|
||||||
"lshw" "List hardware details$(_inst lshw)" "$lshw_state" \
|
|
||||||
"mc" "Midnight Commander (file manager)$(_inst mc)" "$mc_state" \
|
|
||||||
"nala" "APT frontend (parallel downloads)$(_inst nala)" "$nala_state" \
|
|
||||||
"ncdu" "Disk usage analyzer (ncurses)$(_inst ncdu)" "$ncdu_state" \
|
|
||||||
"psensor" "Hardware temperature monitor$(_inst psensor)" "$psensor_state" \
|
|
||||||
"timeshift" "System restore snapshots$(_inst timeshift)" "$timeshift_state" \
|
|
||||||
"tmux" "Terminal multiplexer$(_inst tmux)" "$tmux_state" \
|
|
||||||
"wine" "Windows compatibility layer$(_inst wine)" "$wine_state" \
|
|
||||||
3>&1 1>&2 2>&3)
|
|
||||||
clear
|
clear
|
||||||
|
|
||||||
[ -z "$choices" ] && return
|
[ -z "$choices" ] && return
|
||||||
@@ -113,19 +138,38 @@ _cat_general() {
|
|||||||
flatpak)
|
flatpak)
|
||||||
if ! is_installed "flatpak"; then
|
if ! is_installed "flatpak"; then
|
||||||
_run_cmd "Flatpak" "sudo apt install -y flatpak" "Installing Flatpak..."
|
_run_cmd "Flatpak" "sudo apt install -y flatpak" "Installing Flatpak..."
|
||||||
if command -v plasma-discover &>/dev/null; then
|
|
||||||
_run_cmd "Flatpak" "sudo apt install -y plasma-discover-backend-flatpak" "Installing Flatpak backend..."
|
|
||||||
echo "Flatpak backend for Discover installed."
|
|
||||||
elif command -v gnome-software &>/dev/null; then
|
|
||||||
_run_cmd "Flatpak" "sudo apt install -y gnome-software-plugin-flatpak" "Installing Flatpak plugin..."
|
|
||||||
echo "Flatpak plugin for GNOME Software installed."
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
echo "Flatpak already installed."
|
echo "Flatpak already installed."
|
||||||
fi
|
fi
|
||||||
flatpak remote-add --if-not-exists flathub \
|
flatpak remote-add --if-not-exists flathub \
|
||||||
https://dl.flathub.org/repo/flathub.flatpakrepo
|
https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||||
echo "Flathub repository added."
|
echo "Flathub repository added."
|
||||||
|
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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}"
|
echo -e "${GREEN}A reboot is recommended.${NC}"
|
||||||
;;
|
;;
|
||||||
fwupd)
|
fwupd)
|
||||||
@@ -144,12 +188,15 @@ _cat_general() {
|
|||||||
_run_cmd "fwupd" "sudo fwupdmgr update -y" "Installing firmware updates..."
|
_run_cmd "fwupd" "sudo fwupdmgr update -y" "Installing firmware updates..."
|
||||||
else
|
else
|
||||||
echo "Skipping firmware update."
|
echo "Skipping firmware update."
|
||||||
|
_pause
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "No firmware updates available."
|
echo "No firmware updates available."
|
||||||
|
_pause
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
echo -e "${GREEN}fwupd setup complete.${NC}"
|
echo -e "${GREEN}fwupd setup complete.${NC}"
|
||||||
|
_pause
|
||||||
;;
|
;;
|
||||||
kvm)
|
kvm)
|
||||||
if ! is_installed "virt-manager"; then
|
if ! is_installed "virt-manager"; then
|
||||||
@@ -162,24 +209,62 @@ _cat_general() {
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
wine)
|
wine)
|
||||||
if ! is_installed "wine"; then
|
if ! is_installed "wine64"; then
|
||||||
echo "Checking for i386 architecture..."
|
_run_cmd "Wine" "sudo apt install -y --no-install-recommends wine64 fonts-wine" "Installing Wine (64-bit only)..."
|
||||||
if ! dpkg --print-foreign-architectures 2>/dev/null | grep -q i386; then
|
local wine_ver
|
||||||
echo "Enabling i386 architecture for Wine..."
|
wine_ver=$(wine --version 2>/dev/null)
|
||||||
sudo dpkg --add-architecture i386
|
if [ -n "$wine_ver" ]; then
|
||||||
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
echo -e "${GREEN}Wine (64-bit) installed: ${wine_ver}${NC}"
|
||||||
fi
|
|
||||||
_run_cmd "Wine" "sudo apt install -y wine wine32 wine64 libwine libwine:i386 fonts-wine" "Installing Wine..."
|
|
||||||
echo -e "${GREEN}Wine installed. Run 'winecfg' to configure.${NC}"
|
|
||||||
else
|
else
|
||||||
echo "Wine already installed."
|
echo -e "${YELLOW}Wine installed but version check failed.${NC}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Wine64 already installed."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
nvme-cli)
|
||||||
|
if ! lsblk -d -o TRAN 2>/dev/null | grep -q "^nvme$"; then
|
||||||
|
echo "No NVMe controller detected. Skipping."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if ! is_installed "nvme-cli"; then
|
||||||
|
_run_cmd "nvme-cli" "sudo apt install -y nvme-cli" "Installing nvme-cli..."
|
||||||
|
fi
|
||||||
|
local nvme_devs=()
|
||||||
|
while read -r dev; do
|
||||||
|
nvme_devs+=("$dev")
|
||||||
|
done < <(lsblk -d -o NAME,TRAN 2>/dev/null | awk '$2 == "nvme" {print $1}')
|
||||||
|
if [ ${#nvme_devs[@]} -eq 0 ]; then
|
||||||
|
echo "No NVMe block devices found for health check."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
local dev_list=""
|
||||||
|
local dev
|
||||||
|
for dev in "${nvme_devs[@]}"; do
|
||||||
|
[ -n "$dev_list" ] && dev_list+=", "
|
||||||
|
dev_list+="/dev/${dev}"
|
||||||
|
done
|
||||||
|
if _confirm "NVMe Health" "Run smart-log on ${#nvme_devs[@]} NVMe device(s): ${dev_list}?"; then
|
||||||
|
echo ""
|
||||||
|
for dev in "${nvme_devs[@]}"; do
|
||||||
|
local cw="" temp="" pu=""
|
||||||
|
while IFS= read -r line; do
|
||||||
|
case "$line" in
|
||||||
|
*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 ""
|
||||||
|
done
|
||||||
|
_pause
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
if $headless; then
|
|
||||||
echo "Skipping $pkg (headless mode)"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if ! is_installed "$pkg"; then
|
if ! is_installed "$pkg"; then
|
||||||
_run_install "$pkg"
|
_run_install "$pkg"
|
||||||
else
|
else
|
||||||
@@ -190,4 +275,6 @@ _cat_general() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
echo -e "${GREEN}System tools installed.${NC}"
|
echo -e "${GREEN}System tools installed.${NC}"
|
||||||
|
_pause
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,23 +2,32 @@
|
|||||||
# cursors.sh — Cursor themes
|
# cursors.sh — Cursor themes
|
||||||
|
|
||||||
_cat_cursors() {
|
_cat_cursors() {
|
||||||
|
local headless=false
|
||||||
|
_is_headless && headless=true
|
||||||
|
local -a items=()
|
||||||
|
if ! $headless; then
|
||||||
local bibata_state; bibata_state=$(_state "bibata-cursor-theme")
|
local bibata_state; bibata_state=$(_state "bibata-cursor-theme")
|
||||||
local breeze_state; breeze_state=$(_state "breeze-cursor-theme")
|
local breeze_state; breeze_state=$(_state "breeze-cursor-theme")
|
||||||
local chameleon_state; chameleon_state=$(_state "chameleon-cursor-theme")
|
local chameleon_state; chameleon_state=$(_state "chameleon-cursor-theme")
|
||||||
local dmz_state; dmz_state=$(_state "dmz-cursor-theme")
|
local dmz_state; dmz_state=$(_state "dmz-cursor-theme")
|
||||||
local xcursor_state; xcursor_state=$(_state "xcursor-themes")
|
local xcursor_state; xcursor_state=$(_state "xcursor-themes")
|
||||||
local oxygen_state; oxygen_state=$(_state "oxygencursors")
|
local oxygen_state; oxygen_state=$(_state "oxygencursors")
|
||||||
|
items+=(
|
||||||
|
"bibata-cursor-theme" "Bibata cursors" "$bibata_state"
|
||||||
|
"breeze-cursor-theme" "Breeze cursors (KDE)" "$breeze_state"
|
||||||
|
"chameleon-cursor-theme" "Chameleon cursors" "$chameleon_state"
|
||||||
|
"dmz-cursor-theme" "DMZ cursors" "$dmz_state"
|
||||||
|
"xcursor-themes" "X11 base cursors" "$xcursor_state"
|
||||||
|
"oxygencursors" "Oxygen cursors (KDE legacy)" "$oxygen_state"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
local item_count=${#items[@]}
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
local choices
|
local choices
|
||||||
choices=$(whiptail --title "Cursor Themes" --checklist \
|
choices=$(_checklist "Cursor Themes" "Select cursor themes to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
"Select cursor themes to install:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
"${items[@]}" \
|
||||||
"bibata-cursor-theme" "Bibata cursors$(_inst bibata-cursor-theme)" "$bibata_state" \
|
)
|
||||||
"breeze-cursor-theme" "Breeze cursors (KDE)$(_inst breeze-cursor-theme)" "$breeze_state" \
|
|
||||||
"chameleon-cursor-theme" "Chameleon cursors$(_inst chameleon-cursor-theme)" "$chameleon_state" \
|
|
||||||
"dmz-cursor-theme" "DMZ cursors$(_inst dmz-cursor-theme)" "$dmz_state" \
|
|
||||||
"xcursor-themes" "X11 base cursors$(_inst xcursor-themes)" "$xcursor_state" \
|
|
||||||
"oxygencursors" "Oxygen cursors (KDE legacy)$(_inst oxygencursors)" "$oxygen_state" \
|
|
||||||
3>&1 1>&2 2>&3)
|
|
||||||
clear
|
clear
|
||||||
|
|
||||||
[ -z "$choices" ] && return
|
[ -z "$choices" ] && return
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
_cat_themes() {
|
_cat_themes() {
|
||||||
local headless=false
|
local headless=false
|
||||||
_is_headless && headless=true
|
_is_headless && headless=true
|
||||||
|
local -a items=()
|
||||||
|
if ! $headless; then
|
||||||
local arc_state; arc_state=$(_state "arc-theme")
|
local arc_state; arc_state=$(_state "arc-theme")
|
||||||
local blackbird_state; blackbird_state=$(_state "blackbird-gtk-theme")
|
local blackbird_state; blackbird_state=$(_state "blackbird-gtk-theme")
|
||||||
local bluebird_state; bluebird_state=$(_state "bluebird-gtk-theme")
|
local bluebird_state; bluebird_state=$(_state "bluebird-gtk-theme")
|
||||||
@@ -11,18 +13,23 @@ _cat_themes() {
|
|||||||
local greybird_state; greybird_state=$(_state "greybird-gtk-theme")
|
local greybird_state; greybird_state=$(_state "greybird-gtk-theme")
|
||||||
local numix_gtk_state; numix_gtk_state=$(_state "numix-gtk-theme")
|
local numix_gtk_state; numix_gtk_state=$(_state "numix-gtk-theme")
|
||||||
local orchis_state; orchis_state=$(_state "orchis-gtk-theme")
|
local orchis_state; orchis_state=$(_state "orchis-gtk-theme")
|
||||||
|
items+=(
|
||||||
|
"arc-theme" "Arc GTK theme" "$arc_state"
|
||||||
|
"blackbird-gtk-theme" "Blackbird GTK theme" "$blackbird_state"
|
||||||
|
"bluebird-gtk-theme" "Bluebird GTK theme" "$bluebird_state"
|
||||||
|
"breeze-gtk-theme" "Breeze GTK theme (KDE port)" "$breeze_gtk_state"
|
||||||
|
"greybird-gtk-theme" "Greybird GTK theme" "$greybird_state"
|
||||||
|
"numix-gtk-theme" "Numix GTK theme" "$numix_gtk_state"
|
||||||
|
"orchis-gtk-theme" "Orchis GTK theme" "$orchis_state"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
local item_count=${#items[@]}
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
local choices
|
local choices
|
||||||
choices=$(whiptail --title "Desktop Themes (GTK/KDE)" --checklist \
|
choices=$(_checklist "Desktop Themes (GTK/KDE)" "Select desktop themes to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
"Select desktop themes to install:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
"${items[@]}" \
|
||||||
"arc-theme" "Arc GTK theme$(_inst arc-theme)" "$arc_state" \
|
)
|
||||||
"blackbird-gtk-theme" "Blackbird GTK theme$(_inst blackbird-gtk-theme)" "$blackbird_state" \
|
|
||||||
"bluebird-gtk-theme" "Bluebird GTK theme$(_inst bluebird-gtk-theme)" "$bluebird_state" \
|
|
||||||
"breeze-gtk-theme" "Breeze GTK theme (KDE port)$(_inst breeze-gtk-theme)" "$breeze_gtk_state" \
|
|
||||||
"greybird-gtk-theme" "Greybird GTK theme$(_inst greybird-gtk-theme)" "$greybird_state" \
|
|
||||||
"numix-gtk-theme" "Numix GTK theme$(_inst numix-gtk-theme)" "$numix_gtk_state" \
|
|
||||||
"orchis-gtk-theme" "Orchis GTK theme$(_inst orchis-gtk-theme)" "$orchis_state" \
|
|
||||||
3>&1 1>&2 2>&3)
|
|
||||||
clear
|
clear
|
||||||
|
|
||||||
[ -z "$choices" ] && return
|
[ -z "$choices" ] && return
|
||||||
@@ -30,10 +37,6 @@ _cat_themes() {
|
|||||||
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 $headless; then
|
|
||||||
echo "Skipping $pkg (headless mode)"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if ! is_installed "$pkg"; then
|
if ! is_installed "$pkg"; then
|
||||||
_run_install "$pkg"
|
_run_install "$pkg"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
# fonts.sh — Fonts
|
# fonts.sh — Fonts
|
||||||
|
|
||||||
_cat_fonts() {
|
_cat_fonts() {
|
||||||
|
local headless=false
|
||||||
|
_is_headless && headless=true
|
||||||
|
local -a items=()
|
||||||
|
if ! $headless; then
|
||||||
local bebas_state; bebas_state=$(_state "fonts-bebas-neue")
|
local bebas_state; bebas_state=$(_state "fonts-bebas-neue")
|
||||||
local anon_state; anon_state=$(_state "fonts-anonymous-pro")
|
local anon_state; anon_state=$(_state "fonts-anonymous-pro")
|
||||||
local verana_state; verana_state=$(_state "fonts-adf-verana")
|
local verana_state; verana_state=$(_state "fonts-adf-verana")
|
||||||
@@ -10,19 +14,24 @@ _cat_fonts() {
|
|||||||
local mscore_state; mscore_state=$(_state "ttf-mscorefonts-installer")
|
local mscore_state; mscore_state=$(_state "ttf-mscorefonts-installer")
|
||||||
local ubuntu_state; ubuntu_state=$(_state "fonts-ubuntu")
|
local ubuntu_state; ubuntu_state=$(_state "fonts-ubuntu")
|
||||||
local recommended_state; recommended_state=$(_state "fonts-recommended")
|
local recommended_state; recommended_state=$(_state "fonts-recommended")
|
||||||
|
items+=(
|
||||||
|
"fonts-bebas-neue" "Bebas Neue (display)" "$bebas_state"
|
||||||
|
"fonts-anonymous-pro" "Anonymous Pro (monospace)" "$anon_state"
|
||||||
|
"fonts-adf-verana" "ADF Verana (sans-serif)" "$verana_state"
|
||||||
|
"fonts-3270" "IBM 3270 terminal font" "$f3270_state"
|
||||||
|
"fonts-liberation" "Liberation (MS-compatible)" "$liberation_state"
|
||||||
|
"ttf-mscorefonts-installer" "Microsoft fonts (EULA required)" "$mscore_state"
|
||||||
|
"fonts-ubuntu" "Ubuntu font family" "$ubuntu_state"
|
||||||
|
"fonts-recommended" "Debian recommended fonts" "$recommended_state"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
local item_count=${#items[@]}
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
local choices
|
local choices
|
||||||
choices=$(whiptail --title "Fonts" --checklist \
|
choices=$(_checklist "Fonts" "Select fonts to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
"Select fonts to install:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
"${items[@]}" \
|
||||||
"fonts-bebas-neue" "Bebas Neue (display)$(_inst fonts-bebas-neue)" "$bebas_state" \
|
)
|
||||||
"fonts-anonymous-pro" "Anonymous Pro (monospace)$(_inst fonts-anonymous-pro)" "$anon_state" \
|
|
||||||
"fonts-adf-verana" "ADF Verana (sans-serif)$(_inst fonts-adf-verana)" "$verana_state" \
|
|
||||||
"fonts-3270" "IBM 3270 terminal font$(_inst fonts-3270)" "$f3270_state" \
|
|
||||||
"fonts-liberation" "Liberation (MS-compatible)$(_inst fonts-liberation)" "$liberation_state" \
|
|
||||||
"ttf-mscorefonts-installer" "Microsoft fonts (EULA required)$(_inst ttf-mscorefonts-installer)" "$mscore_state" \
|
|
||||||
"fonts-ubuntu" "Ubuntu font family$(_inst fonts-ubuntu)" "$ubuntu_state" \
|
|
||||||
"fonts-recommended" "Debian recommended fonts$(_inst fonts-recommended)" "$recommended_state" \
|
|
||||||
3>&1 1>&2 2>&3)
|
|
||||||
clear
|
clear
|
||||||
|
|
||||||
[ -z "$choices" ] && return
|
[ -z "$choices" ] && return
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
_cat_icons() {
|
_cat_icons() {
|
||||||
local headless=false
|
local headless=false
|
||||||
_is_headless && headless=true
|
_is_headless && headless=true
|
||||||
|
local -a items=()
|
||||||
|
if ! $headless; then
|
||||||
local breeze_state; breeze_state=$(_state "breeze-icon-theme")
|
local breeze_state; breeze_state=$(_state "breeze-icon-theme")
|
||||||
local deepin_state; deepin_state=$(_state "deepin-icon-theme")
|
local deepin_state; deepin_state=$(_state "deepin-icon-theme")
|
||||||
local ele_state; ele_state=$(_state "elementary-icon-theme")
|
local ele_state; ele_state=$(_state "elementary-icon-theme")
|
||||||
@@ -17,34 +19,34 @@ _cat_icons() {
|
|||||||
local suru_state; suru_state=$(_state "suru-icon-theme")
|
local suru_state; suru_state=$(_state "suru-icon-theme")
|
||||||
|
|
||||||
local kf6_state="OFF"
|
local kf6_state="OFF"
|
||||||
local has_kf6=false
|
|
||||||
if [ "$DEBIAN_CODENAME" = "trixie" ]; then
|
if [ "$DEBIAN_CODENAME" = "trixie" ]; then
|
||||||
kf6_state=$(_state "kf6-breeze-icon-theme")
|
kf6_state=$(_state "kf6-breeze-icon-theme")
|
||||||
has_kf6=true
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local items=(
|
items=(
|
||||||
"breeze-icon-theme" "Breeze icon theme$(_inst breeze-icon-theme)" "$breeze_state"
|
"breeze-icon-theme" "Breeze icon theme" "$breeze_state"
|
||||||
"deepin-icon-theme" "Deepin icon theme$(_inst deepin-icon-theme)" "$deepin_state"
|
"deepin-icon-theme" "Deepin icon theme" "$deepin_state"
|
||||||
"elementary-icon-theme" "Elementary icon theme$(_inst elementary-icon-theme)" "$ele_state"
|
"elementary-icon-theme" "Elementary icon theme" "$ele_state"
|
||||||
"elementary-xfce-icon-theme" "Elementary Xfce icons$(_inst elementary-xfce-icon-theme)" "$ele_xfce_state"
|
"elementary-xfce-icon-theme" "Elementary Xfce icons" "$ele_xfce_state"
|
||||||
"moka-icon-theme" "Moka icon theme$(_inst moka-icon-theme)" "$moka_state"
|
"moka-icon-theme" "Moka icon theme" "$moka_state"
|
||||||
"numix-icon-theme" "Numix icon theme$(_inst numix-icon-theme)" "$numix_state"
|
"numix-icon-theme" "Numix icon theme" "$numix_state"
|
||||||
"numix-icon-theme-circle" "Numix Circle icon theme$(_inst numix-icon-theme-circle)" "$numix_c_state"
|
"numix-icon-theme-circle" "Numix Circle icon theme" "$numix_c_state"
|
||||||
"obsidian-icon-theme" "Obsidian icon theme$(_inst obsidian-icon-theme)" "$obsidian_state"
|
"obsidian-icon-theme" "Obsidian icon theme" "$obsidian_state"
|
||||||
"papirus-icon-theme" "Papirus icon theme$(_inst papirus-icon-theme)" "$papirus_state"
|
"papirus-icon-theme" "Papirus icon theme" "$papirus_state"
|
||||||
"paper-icon-theme" "Paper icon theme$(_inst paper-icon-theme)" "$paper_state"
|
"paper-icon-theme" "Paper icon theme" "$paper_state"
|
||||||
"suru-icon-theme" "Suru icon theme$(_inst suru-icon-theme)" "$suru_state"
|
"suru-icon-theme" "Suru icon theme" "$suru_state"
|
||||||
)
|
)
|
||||||
if $has_kf6; then
|
if [ "$DEBIAN_CODENAME" = "trixie" ]; then
|
||||||
items+=("kf6-breeze-icon-theme" "KF6 Breeze icon theme$(_inst kf6-breeze-icon-theme)" "$kf6_state")
|
items+=("kf6-breeze-icon-theme" "KF6 Breeze icon theme" "$kf6_state")
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
local item_count=${#items[@]}
|
||||||
|
local lista_alto=$((item_count > TUI_ALTO_LISTA ? TUI_ALTO_LISTA : item_count))
|
||||||
local choices
|
local choices
|
||||||
choices=$(whiptail --title "Icon Themes" --checklist \
|
choices=$(_checklist "Icon Themes" "Select icon themes to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $lista_alto \
|
||||||
"Select icon themes to install:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
|
||||||
"${items[@]}" \
|
"${items[@]}" \
|
||||||
3>&1 1>&2 2>&3)
|
)
|
||||||
clear
|
clear
|
||||||
|
|
||||||
[ -z "$choices" ] && return
|
[ -z "$choices" ] && return
|
||||||
@@ -52,10 +54,6 @@ _cat_icons() {
|
|||||||
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 $headless; then
|
|
||||||
echo "Skipping $pkg (headless mode)"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if ! is_installed "$pkg"; then
|
if ! is_installed "$pkg"; then
|
||||||
_run_install "$pkg"
|
_run_install "$pkg"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -2,15 +2,13 @@
|
|||||||
# themes.sh — Customization submenu dispatcher
|
# themes.sh — Customization submenu dispatcher
|
||||||
|
|
||||||
_cat_customization() {
|
_cat_customization() {
|
||||||
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
|
|
||||||
local sub
|
local sub
|
||||||
sub=$(whiptail --title "Customization System" --menu \
|
sub=$(_menu "Customization System" "Select type:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
||||||
"Select type:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
|
|
||||||
"1" "Desktop Themes (GTK/KDE)" \
|
"1" "Desktop Themes (GTK/KDE)" \
|
||||||
"2" "Icon Themes" \
|
"2" "Icon Themes" \
|
||||||
"3" "Cursor Themes" \
|
"3" "Cursor Themes" \
|
||||||
"4" "Fonts" \
|
"4" "Fonts" \
|
||||||
3>&1 1>&2 2>&3)
|
)
|
||||||
[ -z "$sub" ] && return
|
[ -z "$sub" ] && return
|
||||||
case $sub in
|
case $sub in
|
||||||
1) _cat_themes ;;
|
1) _cat_themes ;;
|
||||||
|
|||||||
+426
-57
@@ -1,72 +1,441 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
install_firmware() {
|
# ── Global arrays ──
|
||||||
local fw_pkgs=""
|
PCI_NET_DEVS=()
|
||||||
local fw_bpo
|
USB_WIFI_DEVS=()
|
||||||
fw_bpo=$(apt-cache madison firmware-linux-nonfree 2>/dev/null | \
|
PCI_BT_DEVS=()
|
||||||
grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1)
|
USB_BT_DEVS=()
|
||||||
if [ -n "$fw_bpo" ]; then
|
_DETECTED_FW_PKGS=()
|
||||||
local fw_stable
|
_FW_PLAN_HW_LINES=()
|
||||||
fw_stable=$(apt-cache policy firmware-linux-nonfree 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
_FW_PLAN_PKG_LINES=()
|
||||||
fw_pkgs=" - firmware-linux-nonfree ${fw_bpo} (backports) / ${fw_stable} (stable)\n"
|
|
||||||
|
# ── Network device detection (PCI + USB) ──
|
||||||
|
_detect_all_network_devices() {
|
||||||
|
! is_installed pciutils && _run_install_pkg pciutils
|
||||||
|
! is_installed usbutils && _run_install_pkg usbutils
|
||||||
|
|
||||||
|
PCI_NET_DEVS=()
|
||||||
|
while IFS= read -r line; do
|
||||||
|
PCI_NET_DEVS+=("$line")
|
||||||
|
done < <(lspci -nn 2>/dev/null | grep -iE 'network controller|ethernet controller' || true)
|
||||||
|
|
||||||
|
USB_WIFI_DEVS=()
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if echo "$line" | grep -qiE 'wireless|wifi|802\.11|bluetooth|wlan'; then
|
||||||
|
USB_WIFI_DEVS+=("$line")
|
||||||
|
fi
|
||||||
|
done < <(lsusb 2>/dev/null || true)
|
||||||
|
|
||||||
|
PCI_BT_DEVS=()
|
||||||
|
while IFS= read -r line; do
|
||||||
|
PCI_BT_DEVS+=("$line")
|
||||||
|
done < <(lspci -nn 2>/dev/null | grep -i 'Bluetooth controller' || true)
|
||||||
|
|
||||||
|
USB_BT_DEVS=()
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if echo "$line" | grep -qi 'bluetooth'; then
|
||||||
|
if ! echo "$line" | grep -qiE 'wireless|wifi|802\.11|wlan'; then
|
||||||
|
USB_BT_DEVS+=("$line")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < <(lsusb 2>/dev/null || true)
|
||||||
|
|
||||||
|
_FW_PLAN_HW_LINES=()
|
||||||
|
for dev in "${PCI_NET_DEVS[@]}"; do
|
||||||
|
local desc dev_type
|
||||||
|
desc=$(echo "$dev" | sed -E 's/^[^ ]+ [^:]+: //; s/ \[[0-9a-fA-F]{4}:[0-9a-fA-F]{4}\]//; s/ \(rev.*\)//')
|
||||||
|
if echo "$dev" | grep -qiE 'network controller|wireless|wi-fi|wlan|802\.11'; then
|
||||||
|
dev_type="WiFi PCI"
|
||||||
else
|
else
|
||||||
local fw_ver
|
dev_type="Ethernet PCI"
|
||||||
fw_ver=$(apt-cache policy firmware-linux-nonfree 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
|
||||||
fw_pkgs=" - firmware-linux-nonfree ${fw_ver}\n"
|
|
||||||
fi
|
|
||||||
if ! _confirm "Base Firmware" "Install firmware?\n\n${fw_pkgs}"; then
|
|
||||||
echo "Skipping base firmware."
|
|
||||||
return
|
|
||||||
fi
|
fi
|
||||||
|
_FW_PLAN_HW_LINES+=(" \xe2\x97\x8f ${desc} (${dev_type})")
|
||||||
|
done
|
||||||
|
for dev in "${USB_WIFI_DEVS[@]}"; do
|
||||||
|
local desc
|
||||||
|
desc=$(echo "$dev" | sed 's/^.*ID //')
|
||||||
|
_FW_PLAN_HW_LINES+=(" \xe2\x97\x8f ${desc} (USB)")
|
||||||
|
done
|
||||||
|
|
||||||
echo -e "${YELLOW}Installing base firmware...${NC}"
|
for dev in "${PCI_BT_DEVS[@]}"; do
|
||||||
local pkg="firmware-linux-nonfree"
|
local desc
|
||||||
if [ "$(is_backports_enabled)" == true ] && [ -n "$fw_bpo" ]; then
|
desc=$(echo "$dev" | sed -E 's/^[^ ]+ [^:]+: //; s/ \[[0-9a-fA-F]{4}:[0-9a-fA-F]{4}\]//; s/ \(rev.*\)//')
|
||||||
_run_cmd "Firmware" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports $pkg" "Installing firmware from backports..."
|
_FW_PLAN_HW_LINES+=(" \xe2\x97\x8f ${desc} (Bluetooth PCI)")
|
||||||
else
|
done
|
||||||
_run_cmd "Firmware" "sudo apt install -y $pkg" "Installing firmware..."
|
for dev in "${USB_BT_DEVS[@]}"; do
|
||||||
fi
|
local desc
|
||||||
|
desc=$(echo "$dev" | sed 's/^.*ID //')
|
||||||
echo -e "${GREEN}Base firmware installed.${NC}"
|
_FW_PLAN_HW_LINES+=(" \xe2\x97\x8f ${desc} (Bluetooth USB)")
|
||||||
|
done
|
||||||
handle_wifi_firmware
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# ---------------------------
|
# ── Firmware package mapping ──
|
||||||
# Specific WiFi firmware
|
_detect_firmware_needs() {
|
||||||
# ---------------------------
|
local -A pkg_info
|
||||||
handle_wifi_firmware() {
|
_DETECTED_FW_PKGS=()
|
||||||
if [ -z "$WIFI_CHIPSET" ] || [ "$WIFI_CHIPSET" = "No WiFi adapter found" ]; then
|
_FW_PLAN_PKG_LINES=()
|
||||||
echo "No WiFi adapter to configure."
|
|
||||||
return
|
local dev_list
|
||||||
|
dev_list=("${PCI_NET_DEVS[@]}" "${USB_WIFI_DEVS[@]}")
|
||||||
|
|
||||||
|
for dev in "${dev_list[@]}"; do
|
||||||
|
local raw_desc vendor_lc pkg
|
||||||
|
raw_desc=$(echo "$dev" | sed -E 's/^[^ ]+ [^:]+: //; s/ \[[0-9a-fA-F]{4}:[0-9a-fA-F]{4}\]//; s/ \(rev.*\)//')
|
||||||
|
vendor_lc=$(echo "$dev" | sed -n 's/^.*]: //p' | awk '{print $1}' | tr '[:upper:]' '[:lower:]')
|
||||||
|
|
||||||
|
[[ "$vendor_lc" != *intel* && "$vendor_lc" != *realtek* && "$vendor_lc" != *atheros* && "$vendor_lc" != *qualcomm* && "$vendor_lc" != *mediatek* ]] && continue
|
||||||
|
|
||||||
|
case "$vendor_lc" in
|
||||||
|
*intel*)
|
||||||
|
if echo "$dev" | grep -qiE 'wireless|wi-fi|wlan|802\.11'; then
|
||||||
|
pkg="firmware-iwlwifi"
|
||||||
|
else
|
||||||
|
pkg="firmware-intel-misc"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*realtek*) pkg="firmware-realtek" ;;
|
||||||
|
*atheros*|*qualcomm*) pkg="firmware-atheros" ;;
|
||||||
|
*mediatek*) pkg="firmware-mediatek" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
local short_dev
|
||||||
|
short_dev=$(echo "$raw_desc" | sed 's/ *\[[^]]*\]//g; s/ */ /g')
|
||||||
|
if [ -z "${pkg_info[$pkg]-}" ]; then
|
||||||
|
pkg_info[$pkg]="$short_dev"
|
||||||
|
else
|
||||||
|
pkg_info[$pkg]+=", $short_dev"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for pkg in "${!pkg_info[@]}"; do
|
||||||
|
_DETECTED_FW_PKGS+=("$pkg")
|
||||||
|
_FW_PLAN_PKG_LINES+=(" [+] ${pkg} \xe2\x86\x90 ${pkg_info[$pkg]}")
|
||||||
|
done
|
||||||
|
|
||||||
|
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_firmware_plan() {
|
||||||
|
local plan=""
|
||||||
|
plan+="This section installs the essential non-free firmware stack\n"
|
||||||
|
plan+="for Debian (including CPU microcode, GPU, network, and core\n"
|
||||||
|
plan+="drivers). The script has scanned your hardware to prepare\n"
|
||||||
|
plan+="the setup:\n\n"
|
||||||
|
|
||||||
|
plan+="Detected controllers:\n"
|
||||||
|
if [ ${#_FW_PLAN_HW_LINES[@]} -eq 0 ]; then
|
||||||
|
plan+=" (none detected)\n"
|
||||||
|
else
|
||||||
|
for line in "${_FW_PLAN_HW_LINES[@]}"; do
|
||||||
|
plan+="${line}\n"
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Detected WiFi: $WIFI_CHIPSET"
|
plan+="\nPlanned firmware packages:\n"
|
||||||
|
local fw_line
|
||||||
# Broadcom IDs often start with 14e4:
|
if is_installed firmware-linux-nonfree; then
|
||||||
local broadcom_id
|
local cur_ver
|
||||||
broadcom_id=$(lspci -nn | grep -i network | grep -oP '14e4:[0-9a-fA-F]+' | head -n1)
|
cur_ver=$(dpkg -l firmware-linux-nonfree 2>/dev/null | awk '/^ii/{print $3}')
|
||||||
if [ -n "$broadcom_id" ]; then
|
fw_line=" [+] firmware-linux-nonfree ${cur_ver} (already installed)"
|
||||||
echo -e "${YELLOW}Broadcom wireless device found (ID: $broadcom_id)${NC}"
|
|
||||||
|
|
||||||
# List of device IDs supported by brcmsmac/brcmfmac
|
|
||||||
local supported_ids="4357 4358 4360 4727 43a0 43a1 43a2 43b1"
|
|
||||||
local device_id
|
|
||||||
device_id=$(echo "$broadcom_id" | cut -d: -f2)
|
|
||||||
|
|
||||||
if echo "$supported_ids" | grep -qw "$device_id"; then
|
|
||||||
echo "Chipset supported by firmware-brcm80211. Installing..."
|
|
||||||
_run_cmd "WiFi" "sudo apt install -y firmware-brcm80211" "Installing Broadcom firmware..."
|
|
||||||
else
|
else
|
||||||
# Offer to install broadcom-sta-dkms for older chips
|
fw_line=" [+] firmware-linux-nonfree (base meta-package)"
|
||||||
if _confirm "Broadcom WiFi" "Install broadcom-sta-dkms?\n\nRequired for this Broadcom chipset.\nCompiles a kernel module (needs linux-headers)."; then
|
fi
|
||||||
_run_cmd "Broadcom" "sudo apt install -y linux-headers-$(uname -r) broadcom-sta-dkms" "Installing Broadcom driver..."
|
plan+="${fw_line}\n"
|
||||||
|
|
||||||
|
for line in "${_FW_PLAN_PKG_LINES[@]}"; do
|
||||||
|
plan+="${line}\n"
|
||||||
|
done
|
||||||
|
|
||||||
|
local has_bt=false
|
||||||
|
[ ${#PCI_BT_DEVS[@]} -gt 0 ] && has_bt=true
|
||||||
|
[ ${#USB_BT_DEVS[@]} -gt 0 ] && has_bt=true
|
||||||
|
if ! $has_bt; then
|
||||||
|
for dev in "${USB_WIFI_DEVS[@]}"; do
|
||||||
|
if echo "$dev" | grep -qi 'bluetooth'; then
|
||||||
|
has_bt=true; break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
plan+="\nBluetooth:\n"
|
||||||
|
if $has_bt; then
|
||||||
|
if is_installed bluez; then
|
||||||
|
plan+=" [+] bluez (already installed)\n"
|
||||||
|
else
|
||||||
|
plan+=" [+] bluez + bluez-tools + bluez-obexd (base stack)\n"
|
||||||
|
fi
|
||||||
|
case "${DESKTOP_ENV:-other}" in
|
||||||
|
kde) plan+=" [+] bluedevil (KDE applet)\n"
|
||||||
|
if [ "${AUDIO_SERVER:-}" = "pipewire" ]; then
|
||||||
|
plan+=" → pipewire-pulse + wireplumber (if missing)\n"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
gnome) plan+=" (already in gnome-control-center)\n" ;;
|
||||||
|
*) plan+=" [+] blueman (GTK Bluetooth manager)\n" ;;
|
||||||
|
esac
|
||||||
|
plan+=" → Bluetooth service will be enabled\n"
|
||||||
|
else
|
||||||
|
plan+=" (no Bluetooth hardware detected)\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
plan+="\nInstallation order:\n"
|
||||||
|
plan+=" 1. Base firmware (firmware-linux-nonfree)\n"
|
||||||
|
plan+=" 2. Network firmware (realtek, iwlwifi, ...)\n"
|
||||||
|
plan+=" 3. Broadcom / Bluetooth firmware\n"
|
||||||
|
|
||||||
|
echo -e "$plan"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Install detected firmware packages ──
|
||||||
|
_install_detected_firmware() {
|
||||||
|
local to_install=()
|
||||||
|
for pkg in "${_DETECTED_FW_PKGS[@]}"; do
|
||||||
|
if is_installed "$pkg"; then
|
||||||
|
echo " --> $pkg already installed."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
local ver
|
||||||
|
ver=$(apt-cache policy "$pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
|
if [ -z "$ver" ] || [ "$ver" = "(none)" ]; then
|
||||||
|
echo " --> $pkg not available in repositories, skipping."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
to_install+=("$pkg")
|
||||||
|
done
|
||||||
|
if [ ${#to_install[@]} -gt 0 ]; then
|
||||||
|
_run_cmd "Firmware" "sudo DEBIAN_FRONTEND=noninteractive apt install -y ${to_install[*]}" \
|
||||||
|
"Installing network firmware packages..."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Wireless handler (Broadcom 3-tier) ──
|
||||||
|
_handle_wireless() {
|
||||||
|
local installed_any=false
|
||||||
|
if [ ${#PCI_NET_DEVS[@]} -eq 0 ] && [ ${#USB_WIFI_DEVS[@]} -eq 0 ]; then
|
||||||
|
_detect_all_network_devices
|
||||||
|
fi
|
||||||
|
|
||||||
|
for dev in "${PCI_NET_DEVS[@]}"; do
|
||||||
|
local bcm_id
|
||||||
|
bcm_id=$(echo "$dev" | grep -oP '14e4:[0-9a-fA-F]+' || true)
|
||||||
|
[ -z "$bcm_id" ] && continue
|
||||||
|
local dev_id
|
||||||
|
dev_id=$(echo "$bcm_id" | cut -d: -f2 | tr '[:upper:]' '[:lower:]')
|
||||||
|
|
||||||
|
if _is_broadcom_brcm "$dev_id"; then
|
||||||
|
if ! is_installed "firmware-brcm80211"; then
|
||||||
|
_run_cmd "Broadcom" "sudo DEBIAN_FRONTEND=noninteractive apt install -y firmware-brcm80211" \
|
||||||
|
"Installing firmware-brcm80211..."
|
||||||
|
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
|
||||||
|
continue
|
||||||
|
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
|
||||||
|
_run_cmd "Broadcom" "sudo DEBIAN_FRONTEND=noninteractive apt install -y linux-headers-$(uname -r) broadcom-sta-dkms" \
|
||||||
|
"Installing Broadcom driver..."
|
||||||
|
|
||||||
|
local has_broadcom_bt=false
|
||||||
|
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 combo card (WiFi + Bluetooth) detected.${NC}"
|
||||||
|
cat > /etc/modprobe.d/broadcom-combo.conf <<'EOF'
|
||||||
|
# Broadcom combo: ensure btusb loads after wl
|
||||||
|
softdep wl post: btusb
|
||||||
|
EOF
|
||||||
|
echo -e "${YELLOW}A reboot may be required for Bluetooth to work correctly.${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Broadcom proprietary driver installed. A reboot may be required."
|
echo "Broadcom proprietary driver installed. A reboot may be required."
|
||||||
else
|
_pause
|
||||||
echo "Skipping Broadcom driver installation."
|
installed_any=true
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
else
|
done
|
||||||
echo "No special WiFi firmware needed for this adapter."
|
|
||||||
|
for dev in "${USB_WIFI_DEVS[@]}"; do
|
||||||
|
if echo "$dev" | grep -qi '0a5c'; then
|
||||||
|
_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
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if ! $installed_any; then
|
||||||
|
echo "No special WiFi firmware needed -- base firmware-linux-nonfree covers this system."
|
||||||
|
_pause
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ── Ensure non-free repository is enabled ──
|
||||||
|
_ensure_nonfree_repo() {
|
||||||
|
local nonfree_found=false
|
||||||
|
if [ -f /etc/apt/sources.list ] && grep -Eq '^[^#]*\bnon-free\b' /etc/apt/sources.list 2>/dev/null; then
|
||||||
|
nonfree_found=true
|
||||||
|
fi
|
||||||
|
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
|
||||||
|
nonfree_found=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if $nonfree_found; then
|
||||||
|
return 0
|
||||||
|
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 [ -f /etc/apt/sources.list ]; then
|
||||||
|
sudo sed -i '/^deb / { /non-free/! s/\(main[^ ]*\)/\1 non-free non-free-firmware/ }' /etc/apt/sources.list
|
||||||
|
fi
|
||||||
|
if [ -d /etc/apt/sources.list.d ]; then
|
||||||
|
for f in /etc/apt/sources.list.d/*.sources; do
|
||||||
|
[ -f "$f" ] || continue
|
||||||
|
sudo sed -i '/^Components:/ { /non-free/! s/$/ non-free non-free-firmware/ }' "$f"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
sudo apt update
|
||||||
|
echo -e "${GREEN}non-free repository enabled.${NC}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Main entry point ──
|
||||||
|
install_firmware() {
|
||||||
|
echo -e "${YELLOW}Base firmware check...${NC}"
|
||||||
|
|
||||||
|
if ! _ensure_nonfree_repo; then
|
||||||
|
_msg "Error" "No 'non-free' repositories were enabled and the user declined to add them.\nPlease enable non-free manually or accept the prompt in the Firmware option." 10 65
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 1. Detect
|
||||||
|
_detect_all_network_devices
|
||||||
|
_detect_firmware_needs
|
||||||
|
|
||||||
|
# 2. Plan
|
||||||
|
local plan
|
||||||
|
plan=$(_build_firmware_plan)
|
||||||
|
_msg "Firmware, Wireless & Bluetooth Setup" "$plan" 22 72
|
||||||
|
|
||||||
|
# 3. Confirm
|
||||||
|
if ! _confirm "Firmware" "Apply the network & firmware plan?"; then
|
||||||
|
echo "Firmware installation skipped."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. Install base firmware meta-package (unchanged logic)
|
||||||
|
local fw_pkg="firmware-linux-nonfree"
|
||||||
|
local fw_bpo
|
||||||
|
fw_bpo=$(apt-cache madison "$fw_pkg" 2>/dev/null | \
|
||||||
|
grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1)
|
||||||
|
|
||||||
|
local fw_stable
|
||||||
|
fw_stable=$(apt-cache policy "$fw_pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
|
|
||||||
|
if is_installed "$fw_pkg"; then
|
||||||
|
if [ -n "$fw_bpo" ]; then
|
||||||
|
local current_ver
|
||||||
|
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
|
||||||
|
_run_cmd "Firmware" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports $fw_pkg" "Upgrading firmware..."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "$fw_pkg already installed."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
local msg="firmware-linux-nonfree provides hardware drivers for:\n"
|
||||||
|
msg+=" WiFi, Bluetooth, GPU, audio, webcams, and more.\n\n"
|
||||||
|
if [ -n "$fw_bpo" ]; then
|
||||||
|
msg+=" ● Stable: ${fw_stable}\n"
|
||||||
|
msg+=" Ultra tested, but may lack support for\n"
|
||||||
|
msg+=" very recent hardware.\n\n"
|
||||||
|
msg+=" ● Backports: ${fw_bpo} (Recommended)\n"
|
||||||
|
msg+=" Updated firmware for modern hardware from\n"
|
||||||
|
msg+=" 2025/2026: recent GPUs, processors, WiFi.\n\n"
|
||||||
|
msg+="Choose version:"
|
||||||
|
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..."
|
||||||
|
else
|
||||||
|
_run_cmd "Firmware" "sudo apt install -y $fw_pkg" "Installing firmware from stable..."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
msg+=" Version: ${fw_stable}\n\n"
|
||||||
|
msg+="Install it?"
|
||||||
|
if _confirm "Firmware" "$msg"; then
|
||||||
|
_run_cmd "Firmware" "sudo apt install -y $fw_pkg" "Installing firmware..."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}Base firmware installed.${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 5. Install specific network firmware packages
|
||||||
|
_install_detected_firmware
|
||||||
|
|
||||||
|
# 6. Broadcom wireless handler
|
||||||
|
_handle_wireless
|
||||||
|
|
||||||
|
# 7. Bluetooth stack
|
||||||
|
_install_bluetooth_stack
|
||||||
|
|
||||||
|
# 8. Summary
|
||||||
|
echo -e "${GREEN}Network & firmware setup complete.${NC}"
|
||||||
|
_pause
|
||||||
|
}
|
||||||
|
|||||||
+105
-63
@@ -1,93 +1,135 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Install gaming tools (Steam, gamemode, mangohud, etc.)
|
# Gaming dispatcher — sources submodules and provides install_gaming()
|
||||||
|
|
||||||
|
_GAMING_DIR="${MODULES_DIR}/gaming"
|
||||||
|
source "${_GAMING_DIR}/_helpers.sh"
|
||||||
|
source "${_GAMING_DIR}/steam.sh"
|
||||||
|
source "${_GAMING_DIR}/heroic.sh"
|
||||||
|
source "${_GAMING_DIR}/tools.sh"
|
||||||
|
|
||||||
|
# Check if 'contrib' component is enabled; offer to add if missing
|
||||||
|
ensure_contrib_repo() {
|
||||||
|
local contrib_found=false
|
||||||
|
|
||||||
|
if [ -f /etc/apt/sources.list ]; then
|
||||||
|
if grep -Eq '^[^#]*\bcontrib\b' /etc/apt/sources.list 2>/dev/null; then
|
||||||
|
contrib_found=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! $contrib_found && [ -d /etc/apt/sources.list.d ]; then
|
||||||
|
if grep -qr 'Components:.*\bcontrib\b' /etc/apt/sources.list.d/*.sources 2>/dev/null; then
|
||||||
|
contrib_found=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $contrib_found; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _confirm "contrib Repository" "Component 'contrib' is required for Steam.\n\nAdd 'contrib' to your APT repositories?"; then
|
||||||
|
if [ -f /etc/apt/sources.list ]; then
|
||||||
|
sudo sed -i '/^deb / { /contrib/! s/main/main contrib/ }' /etc/apt/sources.list
|
||||||
|
fi
|
||||||
|
if [ -d /etc/apt/sources.list.d ]; then
|
||||||
|
for f in /etc/apt/sources.list.d/*.sources; do
|
||||||
|
[ -f "$f" ] || continue
|
||||||
|
sudo sed -i '/^Components:/ { /contrib/! s/$/ contrib/ }' "$f"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
sudo apt update
|
||||||
|
echo -e "${GREEN}contrib repository enabled.${NC}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${YELLOW}contrib repository not enabled. Steam installation may fail.${NC}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
install_gaming() {
|
install_gaming() {
|
||||||
echo -e "${YELLOW}Gaming setup...${NC}"
|
echo -e "${YELLOW}Gaming setup...${NC}"
|
||||||
|
|
||||||
# 1. 32-bit support prompt FIRST
|
# 1. Single checklist with ALL options (including i386 toggle)
|
||||||
local enable_32bit=false
|
|
||||||
if _confirm "32-bit Support" "Enable i386 for 32-bit games?\n\nRequired by Steam/Proton.\nInstalls matching 32-bit graphics drivers."; then
|
|
||||||
enable_32bit=true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if $enable_32bit; then
|
|
||||||
echo "Enabling 32-bit architecture (i386)..."
|
|
||||||
if ! dpkg --print-foreign-architectures | grep -q i386; then
|
|
||||||
sudo dpkg --add-architecture i386
|
|
||||||
fi
|
|
||||||
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
|
||||||
|
|
||||||
echo "Installing 32-bit graphics drivers..."
|
|
||||||
if [ "$GPU_TYPE" = "nvidia" ]; then
|
|
||||||
_run_cmd "32-bit" "sudo apt install -y nvidia-driver-libs:i386" "Installing 32-bit NVIDIA drivers..."
|
|
||||||
else
|
|
||||||
_run_cmd "32-bit" "sudo apt install -y mesa-vulkan-drivers libglx-mesa0:i386 mesa-vulkan-drivers:i386 libgl1-mesa-dri:i386" "Installing 32-bit Mesa drivers..."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 2. Gaming packages checklist
|
|
||||||
local choices
|
local choices
|
||||||
choices=$(whiptail --title "Gaming Setup" --checklist \
|
choices=$(_checklist "Gaming Setup" \
|
||||||
"Select gaming packages to install:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
"Select gaming packages to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
||||||
"steam" "Steam (official .deb, needs 32-bit)" ON \
|
"steam" "Steam (requires 32-bit support)" ON \
|
||||||
"gamemode" "Game performance optimization" ON \
|
"gamemode" "Game performance optimization" ON \
|
||||||
"mangohud" "Performance overlay (Vulkan/GL)" ON \
|
"mangohud" "Performance overlay (Vulkan/OpenGL)" ON \
|
||||||
"heroic" "Heroic Launcher (Epic/GOG) .deb" OFF \
|
|
||||||
"goverlay" "MangoHud config GUI" ON \
|
"goverlay" "MangoHud config GUI" ON \
|
||||||
"lutris" "Game launcher/manager" OFF \
|
"heroic" "Heroic Launcher (Epic/GOG)" OFF \
|
||||||
3>&1 1>&2 2>&3)
|
"java" "Minecraft Java Runtime" OFF \
|
||||||
|
"openrgb" "OpenRGB (RGB lighting control)" OFF \
|
||||||
|
"lutris" "Lutris + Wine (requires 32-bit support)" OFF \
|
||||||
|
"retroarch" "RetroArch Emulator Frontend" OFF \
|
||||||
|
"i386" "Enable 32-bit (i386) architecture" ON)
|
||||||
|
|
||||||
if [ -z "$choices" ]; then
|
if [ -z "$choices" ]; then
|
||||||
echo "No gaming packages selected."
|
echo "No gaming packages selected."
|
||||||
|
_pause
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local cleaned
|
local cleaned
|
||||||
cleaned=$(echo "$choices" | tr -d '"')
|
cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
|
||||||
# 3. Warn if Steam selected without 32-bit
|
# 2. Determine if 32-bit is needed (steam, lutris, or explicit i386 toggle)
|
||||||
if echo "$cleaned" | grep -qw "steam" && ! $enable_32bit; then
|
local need_32bit=false
|
||||||
echo -e "${YELLOW}Warning: Steam requires 32-bit support.${NC}"
|
for p in $cleaned; do
|
||||||
echo "Installation may fail. Re-run this option and enable 32-bit support."
|
case $p in steam|lutris) need_32bit=true ;; esac
|
||||||
|
done
|
||||||
|
echo "$cleaned" | grep -qw i386 && need_32bit=true
|
||||||
|
|
||||||
|
# Strip pseudo-entry "i386" from the install list
|
||||||
|
local install_list
|
||||||
|
install_list=$(echo "$cleaned" | tr ' ' '\n' | grep -v '^i386$' | tr '\n' ' ')
|
||||||
|
install_list=${install_list% }
|
||||||
|
|
||||||
|
# 3. Enable i386 architecture if needed
|
||||||
|
if $need_32bit && ! dpkg --print-foreign-architectures 2>/dev/null | grep -q i386; then
|
||||||
|
echo -e "${YELLOW}Enabling i386 architecture (required by selection)...${NC}"
|
||||||
|
sudo dpkg --add-architecture i386
|
||||||
|
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 4. Install selected packages
|
# 4. Install 32-bit graphics drivers only if 32-bit is needed
|
||||||
for pkg in $cleaned; do
|
if $need_32bit; then
|
||||||
|
echo "Installing 32-bit graphics drivers..."
|
||||||
|
if [ "$GPU_TYPE" = "nvidia" ]; then
|
||||||
|
_install_nvidia_32bit
|
||||||
|
else
|
||||||
|
_install_mesa_32bit
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 5. Install selected packages
|
||||||
|
for pkg in $install_list; do
|
||||||
case $pkg in
|
case $pkg in
|
||||||
steam)
|
steam)
|
||||||
local steam_deb="/tmp/steam_latest.deb"
|
if ensure_contrib_repo; then
|
||||||
_run_cmd "Steam" "wget -O $steam_deb https://cdn.fastly.steamstatic.com/client/installer/steam.deb" "Downloading Steam..."
|
install_steam
|
||||||
_run_cmd "Steam" "sudo apt install -y $steam_deb" "Installing Steam..."
|
|
||||||
echo -e "${GREEN}Steam installed.${NC}"
|
|
||||||
;;
|
|
||||||
mangohud)
|
|
||||||
_run_cmd "MangoHud" "sudo apt install -y mangohud" "Installing MangoHud..."
|
|
||||||
if $enable_32bit; then
|
|
||||||
echo "Installing 32-bit MangoHud..."
|
|
||||||
_run_cmd "MangoHud" "sudo apt install -y mangohud:i386" "Installing 32-bit MangoHud..."
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
heroic)
|
|
||||||
local heroic_deb="/tmp/heroic.deb"
|
|
||||||
_run_cmd "Heroic" "sudo apt install -y curl wget" "Installing dependencies..."
|
|
||||||
local gh_url
|
|
||||||
gh_url=$(curl -s --connect-timeout 10 https://api.github.com/repos/Heroic-Games-Launcher/\
|
|
||||||
HeroicGamesLauncher/releases/latest | \
|
|
||||||
grep -oP 'https://[^"]+amd64\.deb' | head -1)
|
|
||||||
if [ -z "$gh_url" ]; then
|
|
||||||
echo -e "${RED}Could not determine latest Heroic release.${NC}"
|
|
||||||
else
|
else
|
||||||
_run_cmd "Heroic" "wget -O $heroic_deb $gh_url" "Downloading Heroic..."
|
echo -e "${YELLOW}Skipping Steam installation (contrib repository not enabled).${NC}"
|
||||||
_run_cmd "Heroic" "sudo apt install -y $heroic_deb" "Installing Heroic..."
|
|
||||||
rm -f "$heroic_deb"
|
|
||||||
echo -e "${GREEN}Heroic Games Launcher installed.${NC}"
|
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
heroic) install_heroic ;;
|
||||||
_run_install "$pkg"
|
java) install_minecraft_java ;;
|
||||||
|
mangohud) install_mangohud ;;
|
||||||
|
gamemode) install_gamemode ;;
|
||||||
|
goverlay) install_goverlay ;;
|
||||||
|
openrgb)
|
||||||
|
if [ "$DEBIAN_VERSION" = "11" ]; then
|
||||||
|
echo "OpenRGB requires Debian 12+."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
install_openrgb
|
||||||
;;
|
;;
|
||||||
|
lutris) install_lutris ;;
|
||||||
|
retroarch) install_retroarch ;;
|
||||||
|
*) _run_install "$pkg" ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
echo -e "${GREEN}Gaming setup complete.${NC}"
|
echo -e "${GREEN}Gaming setup complete.${NC}"
|
||||||
|
_pause
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Shared helpers for gaming submodules
|
||||||
|
|
||||||
|
_install_mesa_32bit() {
|
||||||
|
local base_pkgs=(
|
||||||
|
"mesa-vulkan-drivers"
|
||||||
|
"libgl1-mesa-dri"
|
||||||
|
"libglx-mesa0"
|
||||||
|
"libegl-mesa0"
|
||||||
|
"mesa-va-drivers"
|
||||||
|
"mesa-libgallium"
|
||||||
|
)
|
||||||
|
|
||||||
|
local i386_active=false
|
||||||
|
dpkg --print-foreign-architectures 2>/dev/null | grep -q i386 && i386_active=true
|
||||||
|
|
||||||
|
local install_list=()
|
||||||
|
|
||||||
|
for p in "${base_pkgs[@]}"; do
|
||||||
|
if apt-cache show "$p" >/dev/null 2>&1; then
|
||||||
|
install_list+=("$p")
|
||||||
|
fi
|
||||||
|
if $i386_active && apt-cache show "${p}:i386" >/dev/null 2>&1; then
|
||||||
|
install_list+=("${p}:i386")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ ${#install_list[@]} -eq 0 ]; then
|
||||||
|
echo "No Mesa 32-bit packages available for installation."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
_run_cmd "Mesa 32-bit" "sudo apt install -y ${install_list[*]}" \
|
||||||
|
"Installing Mesa drivers (${#install_list[@]} packages)..."
|
||||||
|
echo -e "${GREEN}Mesa 32-bit libraries installed.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
apt_cache_exists() {
|
||||||
|
apt-cache show "$1" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
_detect_installed_nvidia_driver() {
|
||||||
|
dpkg -l 2>/dev/null | awk '
|
||||||
|
/^ii/ && ($2=="nvidia-driver" || $2=="nvidia-open" ||
|
||||||
|
$2 ~ /^nvidia-legacy-[0-9]+xx-driver$/ ||
|
||||||
|
$2 ~ /^nvidia-tesla-[0-9]+-driver$/) {print $2; exit}'
|
||||||
|
}
|
||||||
|
|
||||||
|
_nvidia_libs_pkg() {
|
||||||
|
case "$1" in
|
||||||
|
nvidia-driver|nvidia-open) echo "nvidia-driver-libs" ;;
|
||||||
|
*) echo "${1}-libs" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_install_nvidia_32bit() {
|
||||||
|
local drv_pkg
|
||||||
|
drv_pkg=$(_detect_installed_nvidia_driver)
|
||||||
|
if [ -z "$drv_pkg" ]; then
|
||||||
|
_msg "NVIDIA 32-bit" \
|
||||||
|
"No NVIDIA driver detected.\n\nRun Graphics Drivers (option 5) first,\nthen return to add 32-bit libraries." 10 60
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local drv_ver
|
||||||
|
drv_ver=$(dpkg -s "$drv_pkg" 2>/dev/null | sed -n 's/^Version: //p')
|
||||||
|
local libs_pkg
|
||||||
|
libs_pkg=$(_nvidia_libs_pkg "$drv_pkg")
|
||||||
|
|
||||||
|
if ! apt_cache_exists "${libs_pkg}:i386"; then
|
||||||
|
_msg "NVIDIA 32-bit" \
|
||||||
|
"No ${libs_pkg}:i386 available for your driver (${drv_pkg}).\nSkipping 32-bit NVIDIA libraries." 10 60
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _confirm "NVIDIA 32-bit" \
|
||||||
|
"Driver: ${drv_pkg} ${drv_ver}\n\nInstall ${libs_pkg}:i386 (same version to prevent ABI mismatch)." 12 70; then
|
||||||
|
_run_cmd "NVIDIA 32-bit" "sudo apt install -y ${libs_pkg}:i386=${drv_ver}" \
|
||||||
|
"Installing 32-bit NVIDIA libraries (${drv_ver})..."
|
||||||
|
fi
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Heroic Games Launcher installation from GitHub releases
|
||||||
|
|
||||||
|
install_heroic() {
|
||||||
|
local heroic_deb="/tmp/heroic.deb"
|
||||||
|
local ua="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
||||||
|
|
||||||
|
_run_cmd "Heroic" "sudo apt install -y curl jq" "Installing dependencies..."
|
||||||
|
|
||||||
|
local json
|
||||||
|
json=$(curl -s --connect-timeout 10 -H "User-Agent: $ua" \
|
||||||
|
"https://api.github.com/repos/Heroic-Games-Launcher/HeroicGamesLauncher/releases/latest") || {
|
||||||
|
_msg "Heroic Error" "Could not fetch release data from GitHub API." 8 60
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
local deb_url
|
||||||
|
deb_url=$(echo "$json" | jq -r '
|
||||||
|
.assets[] | select(.name | endswith("amd64.deb")) | .browser_download_url
|
||||||
|
' 2>/dev/null || true)
|
||||||
|
|
||||||
|
if [ -z "$deb_url" ]; then
|
||||||
|
_msg "Heroic Error" "Could not find amd64.deb asset in latest release." 10 60
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_run_cmd "Heroic" "curl -sL -H 'User-Agent: $ua' -o '$heroic_deb' '$deb_url'" "Downloading Heroic..."
|
||||||
|
|
||||||
|
if ! dpkg-deb --info "$heroic_deb" >/dev/null 2>&1; then
|
||||||
|
_msg "Heroic Error" "Downloaded .deb is corrupted or truncated.\n\nRemoving file." 10 60
|
||||||
|
rm -f "$heroic_deb"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}Package integrity verified.${NC}"
|
||||||
|
_run_cmd "Heroic" "sudo apt install -y '$heroic_deb'" "Installing Heroic..."
|
||||||
|
rm -f "$heroic_deb"
|
||||||
|
echo -e "${GREEN}Heroic Games Launcher installed.${NC}"
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Steam installation from Debian repos
|
||||||
|
|
||||||
|
install_steam() {
|
||||||
|
_run_cmd "Steam" "sudo apt install -y steam-installer" "Installing Steam from Debian repos..."
|
||||||
|
echo -e "${GREEN}Steam installed.${NC}"
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Gaming performance tools installation
|
||||||
|
|
||||||
|
install_mangohud() {
|
||||||
|
local pkgs="mangohud"
|
||||||
|
if dpkg --print-foreign-architectures | grep -q i386; then
|
||||||
|
pkgs+=" mangohud:i386"
|
||||||
|
fi
|
||||||
|
_run_cmd "MangoHud" "sudo apt install -y $pkgs" "Installing MangoHud (64 + 32-bit)..."
|
||||||
|
}
|
||||||
|
|
||||||
|
install_gamemode() {
|
||||||
|
_run_install gamemode
|
||||||
|
}
|
||||||
|
|
||||||
|
install_goverlay() {
|
||||||
|
_run_install goverlay
|
||||||
|
}
|
||||||
|
|
||||||
|
install_lutris() {
|
||||||
|
local pkgs="lutris wine64"
|
||||||
|
if dpkg --print-foreign-architectures 2>/dev/null | grep -q i386; then
|
||||||
|
pkgs+=" wine32"
|
||||||
|
fi
|
||||||
|
_run_cmd "Lutris" "sudo apt install -y $pkgs" "Installing Lutris + Wine..."
|
||||||
|
}
|
||||||
|
|
||||||
|
install_openrgb() {
|
||||||
|
local deb_suffix
|
||||||
|
case "$DEBIAN_CODENAME" in
|
||||||
|
bookworm) deb_suffix="bookworm" ;;
|
||||||
|
trixie) deb_suffix="trixie" ;;
|
||||||
|
*)
|
||||||
|
echo "OpenRGB requires Debian 12 (Bookworm) or 13 (Trixie)."
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
local deb_path="/tmp/openrgb.deb"
|
||||||
|
local ua="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
||||||
|
|
||||||
|
_run_cmd "OpenRGB" "sudo apt install -y curl jq" "Installing dependencies..."
|
||||||
|
|
||||||
|
local json
|
||||||
|
json=$(curl -s --connect-timeout 10 \
|
||||||
|
"https://codeberg.org/api/v1/repos/OpenRGB/OpenRGB/releases?limit=1") || {
|
||||||
|
echo -e "${RED}Could not fetch OpenRGB releases from Codeberg API.${NC}"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
local deb_url sha256
|
||||||
|
while IFS=' ' read -r url hash; do
|
||||||
|
deb_url="$url"
|
||||||
|
sha256="$hash"
|
||||||
|
done < <(echo "$json" | jq -r '
|
||||||
|
.[0].assets[] | select(.name | contains("amd64_'"${deb_suffix}"'.deb")) |
|
||||||
|
"\(.browser_download_url) \(.sha256 // "")"
|
||||||
|
' 2>/dev/null)
|
||||||
|
|
||||||
|
if [ -z "$deb_url" ]; then
|
||||||
|
echo -e "${RED}Could not find OpenRGB .deb for ${DEBIAN_CODENAME^}.${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_run_cmd "OpenRGB" "curl -L -o '${deb_path}' -A '${ua}' '${deb_url}'" "Downloading OpenRGB..."
|
||||||
|
|
||||||
|
if [ -n "$sha256" ]; then
|
||||||
|
if ! echo "$sha256 $deb_path" | sha256sum -c --strict; then
|
||||||
|
echo -e "${RED}SHA256 mismatch! Downloaded file may be corrupted. Removing.${NC}"
|
||||||
|
rm -f "$deb_path"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}SHA256 verified.${NC}"
|
||||||
|
else
|
||||||
|
if ! dpkg-deb --info "$deb_path" >/dev/null 2>&1; then
|
||||||
|
echo -e "${RED}Downloaded .deb is corrupted. Removing.${NC}"
|
||||||
|
rm -f "$deb_path"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo -e "${YELLOW}No SHA256 in API, validated via dpkg-deb.${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo apt install -y "$deb_path"
|
||||||
|
rm -f "$deb_path"
|
||||||
|
|
||||||
|
sudo modprobe i2c-dev
|
||||||
|
if ! grep -q "^i2c-dev" /etc/modules 2>/dev/null; then
|
||||||
|
echo "i2c-dev" | sudo tee -a /etc/modules >/dev/null
|
||||||
|
fi
|
||||||
|
sudo usermod -aG i2c "$USER"
|
||||||
|
sudo udevadm control --reload-rules && sudo udevadm trigger
|
||||||
|
sudo setcap cap_sys_rawio=ep /usr/bin/openrgb 2>/dev/null || true
|
||||||
|
|
||||||
|
echo -e "${GREEN}OpenRGB installed. Reboot or log out/in for i2c group to take effect.${NC}"
|
||||||
|
_pause
|
||||||
|
}
|
||||||
|
|
||||||
|
install_retroarch() {
|
||||||
|
if is_installed "retroarch"; then
|
||||||
|
echo "RetroArch already installed."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
_run_cmd "RetroArch" "sudo apt install -y retroarch libretro-mgba libretro-snes9x libretro-nestopia libretro-gambatte" "Installing RetroArch and classic cores (GBA, SNES, NES, GB)..."
|
||||||
|
|
||||||
|
clear
|
||||||
|
echo "================================================================="
|
||||||
|
echo " 🎮 IMPORTANT RETROARCH NOTICE 🎮"
|
||||||
|
echo "================================================================="
|
||||||
|
echo "Good news! Nintendo (NES/SNES) and Game Boy (GB/GBA) cores"
|
||||||
|
echo "have been automatically installed and are ready to play!"
|
||||||
|
echo ""
|
||||||
|
echo "⚠️ However, due to Debian open-source guidelines:"
|
||||||
|
echo " - Core auto-updates inside the app are disabled."
|
||||||
|
echo " - Heavy/arcade cores or those requiring proprietary BIOS"
|
||||||
|
echo " (like PlayStation or Arcade) must be handled manually."
|
||||||
|
echo ""
|
||||||
|
echo "👉 To learn how to unlock the internal Online Downloader:"
|
||||||
|
echo " Please check our repository's documentation or visit:"
|
||||||
|
echo " https://wiki.debian.org/RetroArch"
|
||||||
|
echo "================================================================="
|
||||||
|
_pause
|
||||||
|
}
|
||||||
+131
-137
@@ -1,164 +1,158 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Detects and installs GPU firmwares for AMD, Intel, and NVIDIA
|
# Graphics Stack — sources submodules and provides install_gpu_drivers()
|
||||||
|
|
||||||
|
_GPU_DIR="${MODULES_DIR}/gpu"
|
||||||
|
source "${_GPU_DIR}/_helpers.sh"
|
||||||
|
source "${_GPU_DIR}/amd_intel.sh"
|
||||||
|
source "${_GPU_DIR}/nvidia.sh"
|
||||||
|
|
||||||
|
# Consumed by gaming.sh to know which NVIDIA driver path was taken
|
||||||
|
NVIDIA_DRIVER_MODE=""
|
||||||
|
|
||||||
install_gpu_drivers() {
|
install_gpu_drivers() {
|
||||||
case "$GPU_TYPE" in
|
# ── Unknown GPU / VM block ──
|
||||||
amd) install_amd ;;
|
if [ "$GPU_TYPE" = "unknown" ] || [ -z "$GPU_TYPE" ]; then
|
||||||
intel) install_intel ;;
|
local mesa_pkgs=(mesa-vulkan-drivers libgl1-mesa-dri libglx-mesa0 libegl-mesa0 mesa-va-drivers)
|
||||||
nvidia) install_nvidia ;;
|
local ref_ver
|
||||||
*)
|
ref_ver=$(apt-cache policy mesa-vulkan-drivers 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
_msg "GPU" "No dedicated GPU detected.\n\nIf you are in a virtual machine, GPU acceleration\ndepends on VM configuration (SPICE, VirtIO).\n\nNo additional drivers will be installed." 12 60
|
local ref_bpo_ver
|
||||||
return
|
ref_bpo_ver=$(apt-cache madison mesa-vulkan-drivers 2>/dev/null | \
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ "$GPU_TYPE" != "nvidia" ] && [ "$(is_backports_enabled)" == true ]; then
|
|
||||||
local mesa_pkgs=""
|
|
||||||
for mpkg in libgl1-mesa-dri mesa-vulkan-drivers; do
|
|
||||||
local bpo_ver
|
|
||||||
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
|
local comp_line="Components: Vulkan, OpenGL, GLX, EGL, VA-API (64-bit)"
|
||||||
mesa_pkgs+=" - ${mpkg} ${bpo_ver} (backports)\n"
|
|
||||||
else
|
|
||||||
mesa_pkgs+=" - ${mpkg} (from stable)\n"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if _confirm_custom "Mesa Backports" "Install Mesa?\n${mesa_pkgs}" "Backports" "Stable"; then
|
|
||||||
_run_cmd "Mesa" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports libgl1-mesa-dri mesa-vulkan-drivers" "Installing Mesa from backports..."
|
|
||||||
else
|
|
||||||
_run_cmd "Mesa" "sudo apt install -y libgl1-mesa-dri mesa-vulkan-drivers" "Installing Mesa from stable..."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
local tool_pkgs
|
if [ -n "$ref_bpo_ver" ] && [ "$(is_backports_enabled)" == "true" ]; then
|
||||||
tool_pkgs=$(pkg_versions nvtop vainfo)
|
local header="No dedicated GPU was detected (VM or headless).\n"
|
||||||
if _confirm "GPU Tools" "Install monitoring tools?\n${tool_pkgs}"; then
|
header+="Install Mesa stack for compute / display acceleration?\n\n"
|
||||||
_run_cmd "GPU Tools" "sudo apt install -y nvtop vainfo" "Installing GPU tools..."
|
header+="Source: Debian ${DEBIAN_CODENAME^}-Backports\n"
|
||||||
vainfo
|
header+="Mesa ${ref_bpo_ver}\n"
|
||||||
|
header+="${comp_line}\n\n"
|
||||||
|
header+="Choose version:"
|
||||||
|
if _confirm_custom "No GPU Detected" "$header" "Backports" "Stable" 14 70; then
|
||||||
|
_run_cmd "Mesa" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports ${mesa_pkgs[*]}" \
|
||||||
|
"Installing Mesa from backports..."
|
||||||
else
|
else
|
||||||
echo "Skipping GPU monitoring tools."
|
_run_cmd "Mesa" "sudo apt install -y ${mesa_pkgs[*]}" \
|
||||||
|
"Installing Mesa from stable..."
|
||||||
fi
|
fi
|
||||||
echo -e "${GREEN}GPU setup complete.${NC}"
|
else
|
||||||
}
|
if _confirm "No GPU Detected" \
|
||||||
|
"No dedicated GPU was detected (VM or headless).\n\nInstall Mesa stack?\n\nSource: Debian Stable\nMesa ${ref_ver}\n${comp_line}" 14 70; then
|
||||||
# ----------------------------------------------------------------------
|
_run_cmd "Mesa" "sudo apt install -y ${mesa_pkgs[*]}" \
|
||||||
# AMD GPU
|
"Installing Mesa..."
|
||||||
# ----------------------------------------------------------------------
|
else
|
||||||
install_amd() {
|
echo "Skipping Mesa installation."
|
||||||
local pkgs
|
offer_generic_tools
|
||||||
pkgs=$(pkg_versions firmware-amd-graphics radeontop)
|
|
||||||
if ! _confirm "AMD GPU" "Install AMD drivers?\n${pkgs}"; then
|
|
||||||
echo "Skipping AMD GPU drivers."
|
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
_run_cmd "AMD" "sudo apt install -y firmware-amd-graphics radeontop" "Installing AMD drivers..."
|
|
||||||
echo -e "${GREEN}AMD drivers installed.${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
|
||||||
# Intel GPU
|
|
||||||
# ----------------------------------------------------------------------
|
|
||||||
install_intel() {
|
|
||||||
local gen
|
|
||||||
gen=$(get_intel_generation)
|
|
||||||
local va_driver
|
|
||||||
if [ "$gen" = "gen7-" ]; then
|
|
||||||
va_driver="i965-va-driver-shaders"
|
|
||||||
else
|
|
||||||
va_driver="intel-media-va-driver-non-free"
|
|
||||||
fi
|
fi
|
||||||
|
offer_generic_tools
|
||||||
local pkgs
|
echo -e "${GREEN}Graphics stack setup complete.${NC}"
|
||||||
pkgs=$(pkg_versions firmware-intel-graphics "$va_driver")
|
|
||||||
if ! _confirm "Intel GPU" "Install Intel drivers?\n${pkgs}"; then
|
|
||||||
echo "Skipping Intel GPU drivers."
|
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_run_cmd "Intel" "sudo apt install -y firmware-intel-graphics" "Installing Intel firmware..."
|
# ── Detectable GPU: build plan ──
|
||||||
|
local plan="The script has automatically detected your graphics hardware\n"
|
||||||
echo "Detected Intel GPU generation: $gen"
|
plan+="and prepared a personalized installation plan.\n\n"
|
||||||
echo "Installing ${va_driver}..."
|
plan+="Detected GPUs:\n"
|
||||||
_run_cmd "Intel" "sudo apt install -y $va_driver" "Installing Intel VA driver..."
|
local gpu_count=0
|
||||||
|
while IFS= read -r gpu_line; do
|
||||||
echo -e "${GREEN}Intel GPU drivers installed.${NC}"
|
gpu_count=$((gpu_count + 1))
|
||||||
}
|
local desc
|
||||||
|
desc=$(echo "$gpu_line" | sed -E 's/.*: //; s/ *\(rev.*//')
|
||||||
# ----------------------------------------------------------------------
|
plan+=" GPU ${gpu_count}: ${desc}\n"
|
||||||
# NVIDIA GPU
|
done < <(lspci -nn | grep -E "VGA|3D" || true)
|
||||||
# ----------------------------------------------------------------------
|
plan+="\nPlanned components:\n"
|
||||||
install_nvidia() {
|
if $HAS_INTEL; then
|
||||||
echo -e "${YELLOW}NVIDIA GPU detected.${NC}"
|
local _gen; _gen=$(get_intel_generation)
|
||||||
|
local _va; [ "$_gen" = "gen7-" ] && _va="i965-va-driver-shaders" || _va="intel-media-va-driver-non-free"
|
||||||
# --- WARNING CHECK: Backports vs NVIDIA ---
|
plan+=" [+] Intel firmware + ${_va}\n"
|
||||||
if [ "$(is_backports_enabled)" == true ]; then
|
|
||||||
echo -e "${YELLOW}============================================${NC}"
|
|
||||||
echo -e "${YELLOW} IMPORTANT: Backports are currently enabled${NC}"
|
|
||||||
echo -e "${YELLOW}============================================${NC}"
|
|
||||||
echo ""
|
|
||||||
echo "If you are using a backports kernel (e.g., 6.19+), the NVIDIA"
|
|
||||||
echo "driver (especially the 550 series on Debian Trixie) may fail to"
|
|
||||||
echo "compile via DKMS due to kernel incompatibilities."
|
|
||||||
echo ""
|
|
||||||
echo "We strongly recommend using the stable Debian kernel with the"
|
|
||||||
echo "NVIDIA driver. The script will now install the recommended driver"
|
|
||||||
echo "from the STABLE repositories only, NOT from backports."
|
|
||||||
|
|
||||||
if ! _confirm "NVIDIA + Backports" "Backports kernel (6.19+) may break NVIDIA driver.\nContinue with stable NVIDIA driver?"; then
|
|
||||||
echo "Skipping NVIDIA driver installation."
|
|
||||||
return 0
|
|
||||||
fi
|
fi
|
||||||
|
if $HAS_AMD; then
|
||||||
|
plan+=" [+] AMD firmware (firmware-amd-graphics)\n"
|
||||||
|
fi
|
||||||
|
if $HAS_NVIDIA; then
|
||||||
|
plan+=" [+] NVIDIA driver (proprietary)\n"
|
||||||
|
fi
|
||||||
|
plan+=" [+] Mesa (version selected in next step)\n"
|
||||||
|
|
||||||
|
_msg "Graphics Stack — Plan" "$plan" 16 70
|
||||||
|
|
||||||
|
if ! _confirm "Graphics Stack" "Install the planned components?"; then
|
||||||
|
echo "Skipping Graphics Stack."
|
||||||
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_run_cmd "NVIDIA" "sudo apt install -y nvidia-detect" "Installing nvidia-detect..."
|
# ── Sequential firmware / driver installs ──
|
||||||
|
if $HAS_INTEL; then
|
||||||
# Run nvidia-detect and parse the recommended package
|
install_intel_firmware
|
||||||
echo "Detecting recommended NVIDIA driver..."
|
|
||||||
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}"
|
|
||||||
echo "Your GPU may not be supported by current Debian packages."
|
|
||||||
return 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Recommended driver package: $recommended"
|
if $HAS_AMD; then
|
||||||
|
install_amd_firmware
|
||||||
|
fi
|
||||||
|
|
||||||
# --- CHECK FOR UNSUPPORTED LEGACY DRIVERS ---
|
if $HAS_NVIDIA; then
|
||||||
if [[ "$recommended" =~ tesla-470|legacy-390|legacy-340 ]]; then
|
if [ "$DEBIAN_VERSION" = "11" ]; then
|
||||||
if [ "$DEBIAN_CODENAME" = "trixie" ]; then
|
if type install_nvidia_bullseye &>/dev/null; then
|
||||||
echo -e "${RED}============================================${NC}"
|
install_nvidia_bullseye
|
||||||
echo -e "${RED} NVIDIA DRIVER NOT AVAILABLE${NC}"
|
|
||||||
echo -e "${RED}============================================${NC}"
|
|
||||||
echo ""
|
|
||||||
echo "Your GPU requires the $recommended driver, which is not available"
|
|
||||||
echo "in Debian 13 (Trixie)."
|
|
||||||
echo ""
|
|
||||||
echo "Options:"
|
|
||||||
echo " 1. Install Debian 12 (Bookworm) where $recommended is still available"
|
|
||||||
echo " 2. Use Debian Sid (Unstable) which may still provide $recommended"
|
|
||||||
echo " 3. Use the open-source Nouveau driver (limited performance)"
|
|
||||||
echo ""
|
|
||||||
echo "No driver will be installed."
|
|
||||||
return 1
|
|
||||||
else
|
else
|
||||||
if [[ "$recommended" =~ legacy-390|legacy-340 ]]; then
|
install_nvidia_driver
|
||||||
echo -e "${RED}Your GPU requires $recommended, which is not available.${NC}"
|
|
||||||
echo "No driver will be installed."
|
|
||||||
return 1
|
|
||||||
fi
|
fi
|
||||||
|
elif [ "$DEBIAN_VERSION" = "12" ]; then
|
||||||
|
if [ "$(is_nvidia_kepler)" = "true" ]; then
|
||||||
|
if type _install_nvidia_bookworm_kepler &>/dev/null; then
|
||||||
|
_install_nvidia_bookworm_kepler
|
||||||
|
else
|
||||||
|
install_nvidia_driver
|
||||||
|
fi
|
||||||
|
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
|
||||||
|
install_nvidia_driver
|
||||||
|
fi
|
||||||
|
elif [ "$DEBIAN_VERSION" = "13" ]; then
|
||||||
|
if [ "$(is_nvidia_kepler)" = "true" ] || [ "$(is_nvidia_fermi)" = "true" ]; then
|
||||||
|
_msg "NVIDIA — Trixie" \
|
||||||
|
"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."
|
||||||
|
NVIDIA_DRIVER_MODE=""
|
||||||
|
else
|
||||||
|
install_nvidia_driver
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
install_nvidia_driver
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local nv_pkgs
|
# ── Mesa (once) ──
|
||||||
nv_pkgs=$(pkg_versions "$recommended" firmware-misc-nonfree nvidia-vaapi-driver)
|
_install_mesa_backports
|
||||||
if ! _confirm "NVIDIA Driver" "Install NVIDIA driver?\n${nv_pkgs}\nReboot required."; then
|
|
||||||
echo "Skipping NVIDIA driver installation."
|
# ── Refresh GPU_VERSION after Mesa install ──
|
||||||
return 0
|
local mesa_ver
|
||||||
|
mesa_ver=$(dpkg -l libgl1-mesa-dri 2>/dev/null | awk '/^ii/ {print $3; exit}' | sed 's/-.*//')
|
||||||
|
[ -n "$mesa_ver" ] && GPU_VERSION="Mesa ${mesa_ver}"
|
||||||
|
|
||||||
|
# ── Vendor-specific tools ──
|
||||||
|
if $HAS_INTEL; then
|
||||||
|
offer_intel_tools
|
||||||
|
fi
|
||||||
|
if $HAS_AMD; then
|
||||||
|
offer_amd_tools
|
||||||
|
fi
|
||||||
|
if $HAS_NVIDIA; then
|
||||||
|
offer_generic_tools
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_run_cmd "NVIDIA" "sudo apt install -y $recommended firmware-misc-nonfree nvidia-vaapi-driver" "Installing NVIDIA driver..."
|
# ── Build summary ──
|
||||||
echo -e "${GREEN}NVIDIA drivers installed. Reboot required.${NC}"
|
local summary=""
|
||||||
|
summary+="Mesa: ${GPU_VERSION:-not available}\n"
|
||||||
|
if $HAS_NVIDIA; then
|
||||||
|
local nv_mode="${NVIDIA_DRIVER_MODE:-unknown}"
|
||||||
|
summary+="NVIDIA: ${nv_mode}\n"
|
||||||
|
fi
|
||||||
|
summary+="Firmware: installed for detected GPUs\n"
|
||||||
|
summary+="Tools: installed per vendor selection"
|
||||||
|
|
||||||
|
_msg "Graphics Stack — Complete" "$summary" 12 65
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,197 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Shared helpers for GPU submodules
|
||||||
|
|
||||||
|
is_nvidia_kepler() {
|
||||||
|
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,,}))
|
||||||
|
|
||||||
|
# Bloque 1: GK107 (escritorio + móvil) — 0x0FC0..0x0FFF
|
||||||
|
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
|
||||||
|
if [ "$dev_int" -ge $((16#1000)) ] && [ "$dev_int" -le $((16#103F)) ]; then echo true; return; fi
|
||||||
|
# Bloque 3: GK104/GK106 (completo) — 0x1180..0x11FF
|
||||||
|
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() {
|
||||||
|
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,,}))
|
||||||
|
|
||||||
|
# GF100 / GF110 — GTX 480, GTX 580, Quadro 6000, Tesla C2050
|
||||||
|
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() {
|
||||||
|
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,,}))
|
||||||
|
|
||||||
|
# GM108/GM107/GM204 — gama media/baja + Quadros M (incluye 980M/970M)
|
||||||
|
if [ "$dev_int" -ge $((16#1340)) ] && [ "$dev_int" -le $((16#13FF)) ]; then echo true; return; fi
|
||||||
|
# GM206 — GTX 960, GTX 950, Quadro M2000
|
||||||
|
if [ "$dev_int" -ge $((16#1400)) ] && [ "$dev_int" -le $((16#14FF)) ]; then echo true; return; fi
|
||||||
|
# GM200 — TITAN X, GTX 980 Ti
|
||||||
|
if [ "$dev_int" -ge $((16#17C0)) ] && [ "$dev_int" -le $((16#17CF)) ]; then echo true; return; 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() {
|
||||||
|
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,,}))
|
||||||
|
|
||||||
|
# GP100 — Tesla P100, Quadro GP100
|
||||||
|
if [ "$dev_int" -ge $((16#15F0)) ] && [ "$dev_int" -le $((16#15FF)) ]; then echo true; return; fi
|
||||||
|
# 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
|
||||||
|
}
|
||||||
|
|
||||||
|
_install_mesa_backports() {
|
||||||
|
if [ "$(is_backports_enabled)" != "true" ]; then
|
||||||
|
install_mesa_stable
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local mesa_pkgs=("mesa-vulkan-drivers" "libgl1-mesa-dri" "libglx-mesa0" "libegl-mesa0" "mesa-va-drivers")
|
||||||
|
local bpo_pkgs=()
|
||||||
|
local stable_pkgs=()
|
||||||
|
|
||||||
|
for mpkg in "${mesa_pkgs[@]}"; do
|
||||||
|
local bpo_ver
|
||||||
|
bpo_ver=$(apt-cache madison "$mpkg" 2>/dev/null | \
|
||||||
|
grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1)
|
||||||
|
if [ -n "$bpo_ver" ]; then
|
||||||
|
bpo_pkgs+=("$mpkg")
|
||||||
|
else
|
||||||
|
stable_pkgs+=("$mpkg")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
local ref_ver
|
||||||
|
ref_ver=$(apt-cache policy mesa-vulkan-drivers 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
|
local ref_bpo_ver
|
||||||
|
ref_bpo_ver=$(apt-cache madison mesa-vulkan-drivers 2>/dev/null | \
|
||||||
|
grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1)
|
||||||
|
local comp_line="Components: Vulkan, OpenGL, GLX, EGL, VA-API (64-bit)"
|
||||||
|
|
||||||
|
if [ ${#bpo_pkgs[@]} -gt 0 ]; then
|
||||||
|
local src_label="Debian ${DEBIAN_CODENAME^}-Backports"
|
||||||
|
[ ${#stable_pkgs[@]} -gt 0 ] && src_label+=" + Stable"
|
||||||
|
local msg="Mesa provides OpenGL/Vulkan/VA-API acceleration.\n\n"
|
||||||
|
msg+="Source: ${src_label}\n"
|
||||||
|
msg+="Mesa ${ref_bpo_ver:-$ref_ver}\n"
|
||||||
|
msg+="${comp_line}\n\n"
|
||||||
|
[ ${#stable_pkgs[@]} -gt 0 ] && msg+="Some packages only available in stable.\n"
|
||||||
|
msg+="Choose version for backports-capable packages:"
|
||||||
|
if _confirm_custom "Mesa (Graphics)" "$msg" "Backports" "Stable" 14 70; then
|
||||||
|
_run_cmd "Mesa (backports)" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports ${bpo_pkgs[*]}" \
|
||||||
|
"Installing Mesa from backports..."
|
||||||
|
if [ ${#stable_pkgs[@]} -gt 0 ]; then
|
||||||
|
_run_cmd "Mesa (stable)" "sudo apt install -y ${stable_pkgs[*]}" \
|
||||||
|
"Installing remaining Mesa packages from stable..."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
_run_cmd "Mesa" "sudo apt install -y ${mesa_pkgs[*]}" \
|
||||||
|
"Installing Mesa from stable..."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
local msg="Mesa provides OpenGL/Vulkan/VA-API acceleration.\n\n"
|
||||||
|
msg+="Source: Debian Stable\n"
|
||||||
|
msg+="Mesa ${ref_ver}\n"
|
||||||
|
msg+="${comp_line}\n\n"
|
||||||
|
msg+="Install Mesa from available repositories?"
|
||||||
|
if _confirm "Mesa (Graphics)" "$msg" 14 70; then
|
||||||
|
_run_cmd "Mesa" "sudo apt install -y ${mesa_pkgs[*]}" \
|
||||||
|
"Installing Mesa..."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
install_mesa_stable() {
|
||||||
|
local mesa_pkgs=("mesa-vulkan-drivers" "libgl1-mesa-dri" "libglx-mesa0" "libegl-mesa0" "mesa-va-drivers")
|
||||||
|
_run_cmd "Mesa" "sudo apt install -y ${mesa_pkgs[*]}" "Installing Mesa from stable..."
|
||||||
|
}
|
||||||
|
|
||||||
|
offer_generic_tools() {
|
||||||
|
if [ "$DEBIAN_VERSION" = "11" ]; then
|
||||||
|
if ! lsmod 2>/dev/null | grep -q "^nvidia "; then
|
||||||
|
echo "nvtop skipped on Bullseye — NVIDIA driver not loaded."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
local tool_pkgs
|
||||||
|
tool_pkgs=$(pkg_versions nvtop vainfo)
|
||||||
|
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..."
|
||||||
|
vainfo
|
||||||
|
_pause "vainfo output shown above."
|
||||||
|
else
|
||||||
|
echo "Skipping GPU monitoring tools."
|
||||||
|
fi
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# AMD and Intel GPU firmware + tools
|
||||||
|
|
||||||
|
install_amd_firmware() {
|
||||||
|
local fw_info
|
||||||
|
fw_info=$(pkg_versions firmware-amd-graphics)
|
||||||
|
if _confirm "AMD Firmware" "Install AMD GPU firmware?\n\n${fw_info}"; then
|
||||||
|
_run_cmd "AMD" "sudo apt install -y firmware-amd-graphics" "Installing AMD GPU firmware..."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
offer_amd_tools() {
|
||||||
|
local amd_tools=("radeontop")
|
||||||
|
local corectrl_available=false
|
||||||
|
|
||||||
|
if [ "$DEBIAN_CODENAME" = "trixie" ]; then
|
||||||
|
corectrl_available=true
|
||||||
|
elif [ "$(is_backports_enabled)" = "true" ] && apt-cache madison corectrl 2>/dev/null | grep -q "bookworm-backports"; then
|
||||||
|
corectrl_available=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
local pkgs
|
||||||
|
if [ "$DEBIAN_VERSION" = "11" ]; then
|
||||||
|
pkgs=$(pkg_versions "${amd_tools[@]}" vainfo)
|
||||||
|
else
|
||||||
|
pkgs=$(pkg_versions "${amd_tools[@]}" nvtop vainfo)
|
||||||
|
fi
|
||||||
|
if $corectrl_available; then
|
||||||
|
local ctrl_ver
|
||||||
|
ctrl_ver=$(apt-cache policy corectrl 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
|
pkgs+=" - corectrl ${ctrl_ver}\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _confirm "AMD Tools" "Install AMD monitoring and control tools?\n\n${pkgs}"; then
|
||||||
|
echo "Skipping AMD tools."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$DEBIAN_VERSION" = "11" ]; then
|
||||||
|
_run_cmd "AMD Tools" "sudo apt install -y ${amd_tools[*]} vainfo" "Installing AMD tools..."
|
||||||
|
else
|
||||||
|
_run_cmd "AMD Tools" "sudo apt install -y ${amd_tools[*]} nvtop vainfo" "Installing AMD tools..."
|
||||||
|
fi
|
||||||
|
vainfo
|
||||||
|
_pause "vainfo output shown above."
|
||||||
|
|
||||||
|
if $corectrl_available; then
|
||||||
|
if [ "$DEBIAN_CODENAME" = "trixie" ]; then
|
||||||
|
_run_cmd "corectrl" "sudo apt install -y corectrl" "Installing corectrl..."
|
||||||
|
else
|
||||||
|
_run_cmd "corectrl" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports corectrl" "Installing corectrl from backports..."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}AMD tools installed.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_intel_firmware() {
|
||||||
|
local gen
|
||||||
|
gen=$(get_intel_generation)
|
||||||
|
local va_driver
|
||||||
|
if [ "$gen" = "gen7-" ]; then
|
||||||
|
va_driver="i965-va-driver-shaders"
|
||||||
|
else
|
||||||
|
va_driver="intel-media-va-driver-non-free"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local fw_info
|
||||||
|
fw_info=$(pkg_versions firmware-intel-graphics "$va_driver")
|
||||||
|
if _confirm "Intel Firmware" "Install Intel GPU firmware?\n\n${fw_info}"; then
|
||||||
|
_run_cmd "Intel" "sudo apt install -y firmware-intel-graphics $va_driver" "Installing Intel GPU firmware..."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
offer_intel_tools() {
|
||||||
|
local driver_info=""
|
||||||
|
local has_xe=false
|
||||||
|
local has_i915=false
|
||||||
|
local pkg_list=()
|
||||||
|
local pkg_info=""
|
||||||
|
|
||||||
|
[ -d "/sys/bus/pci/drivers/xe" ] && has_xe=true
|
||||||
|
[ -d "/sys/bus/pci/drivers/i915" ] && has_i915=true
|
||||||
|
|
||||||
|
if [ "$DEBIAN_VERSION" = "11" ]; then
|
||||||
|
if $has_xe; then
|
||||||
|
echo "Intel Xe GPU detected. No monitoring tools available on Bullseye."
|
||||||
|
return
|
||||||
|
elif $has_i915; then
|
||||||
|
driver_info="Classic Intel GPU detected (i915 driver)."
|
||||||
|
pkg_list=("intel-gpu-tools")
|
||||||
|
else
|
||||||
|
echo "Intel GPU driver not identified. No monitoring tools available on Bullseye."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
elif $has_xe; then
|
||||||
|
driver_info="Modern Intel GPU detected (Xe driver).\nintel-gpu-tools is NOT compatible with Xe.\nOnly nvtop will be offered."
|
||||||
|
pkg_list=("nvtop")
|
||||||
|
elif $has_i915; then
|
||||||
|
driver_info="Classic Intel GPU detected (i915 driver).\nintel-gpu-tools is compatible and will be offered."
|
||||||
|
pkg_list=("intel-gpu-tools" "nvtop")
|
||||||
|
else
|
||||||
|
driver_info="Intel GPU driver not identified.\nOffering nvtop as a safe default."
|
||||||
|
pkg_list=("nvtop")
|
||||||
|
fi
|
||||||
|
|
||||||
|
pkg_info=$(pkg_versions "${pkg_list[@]}" vainfo)
|
||||||
|
|
||||||
|
if _confirm "Intel Tools" "Intel GPU monitoring tools\n\n${driver_info}\n\nPackages:\n${pkg_info}"; then
|
||||||
|
_run_cmd "Intel Tools" "sudo apt install -y ${pkg_list[*]} vainfo" "Installing Intel monitoring tools..."
|
||||||
|
vainfo
|
||||||
|
_pause "vainfo output shown above."
|
||||||
|
else
|
||||||
|
echo "Skipping Intel monitoring tools."
|
||||||
|
fi
|
||||||
|
}
|
||||||
@@ -0,0 +1,359 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# NVIDIA GPU driver installation — 3-CASE dispatch
|
||||||
|
#
|
||||||
|
# CASE A : Trixie + backports kernel → Official NVIDIA CUDA Repo (Pinned v590)
|
||||||
|
# CASE B : Bookworm + backports kernel → Debian backports (-t bookworm-backports)
|
||||||
|
# CASE C : Kernel stable (any distro) → Debian stable (optional backports)
|
||||||
|
|
||||||
|
install_nvidia_driver() {
|
||||||
|
echo -e "${YELLOW}NVIDIA GPU detected.${NC}"
|
||||||
|
NVIDIA_DRIVER_MODE=""
|
||||||
|
|
||||||
|
local is_bpo_kernel; is_bpo_kernel=$(is_backports_kernel)
|
||||||
|
local is_kepler; is_kepler=$(is_nvidia_kepler)
|
||||||
|
local is_maxwell; is_maxwell=$(is_nvidia_maxwell)
|
||||||
|
local is_pascal; is_pascal=$(is_nvidia_pascal)
|
||||||
|
local is_blackwell; is_blackwell=$(is_nvidia_blackwell)
|
||||||
|
|
||||||
|
# ── Blackwell: v550 no soporta GB20x → CUDA repo v590 ──
|
||||||
|
if [ "$DEBIAN_CODENAME" = "trixie" ] && [ "$is_blackwell" = "true" ]; then
|
||||||
|
_msg "NVIDIA Blackwell" \
|
||||||
|
"Your GPU is NVIDIA Blackwell architecture.\n\nDebian 13's nvidia-driver (v550) does not\nsupport Blackwell GPUs.\n\n\
|
||||||
|
The script will enable the official NVIDIA CUDA\nrepository and install the v590 production branch,\nwhich fully supports Blackwell (GB20x)." 14 65
|
||||||
|
_install_nvidia_cuda_repo
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Veto: Kepler en Trixie no tiene driver disponible ──
|
||||||
|
if [ "$is_kepler" = "true" ] && [ "$DEBIAN_CODENAME" = "trixie" ]; then
|
||||||
|
_msg "NVIDIA Kepler" \
|
||||||
|
"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
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Bloqueo: Maxwell/Pascal no son compatibles con v590 ──
|
||||||
|
if [ "$DEBIAN_CODENAME" = "trixie" ] && [ "$is_bpo_kernel" = "true" ]; then
|
||||||
|
if [ "$is_maxwell" = "true" ] || [ "$is_pascal" = "true" ]; then
|
||||||
|
local gpu_gen="Maxwell"
|
||||||
|
[ "$is_pascal" = "true" ] && gpu_gen="Pascal"
|
||||||
|
local block_msg="INCOMPATIBILITY DETECTED: Your NVIDIA ${gpu_gen} GPU\n"
|
||||||
|
block_msg+="is NOT supported by the modern v590 driver.\n\n"
|
||||||
|
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
|
||||||
|
|
||||||
|
# ── Dispatch por casos ──
|
||||||
|
if [ "$DEBIAN_CODENAME" = "trixie" ] && [ "$is_bpo_kernel" = "true" ]; then
|
||||||
|
_install_nvidia_cuda_repo
|
||||||
|
elif [ "$DEBIAN_CODENAME" = "bookworm" ] && [ "$is_bpo_kernel" = "true" ]; then
|
||||||
|
_install_nvidia_bookworm_bpo
|
||||||
|
else
|
||||||
|
_install_nvidia_standard
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# Shared helper: enable NVIDIA CUDA repo via extrepo
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
_enable_cuda_repo() {
|
||||||
|
if [ ! -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
|
||||||
|
if ! command -v extrepo &>/dev/null; then
|
||||||
|
_run_cmd "extrepo" "sudo apt install -y extrepo" "Installing extrepo..."
|
||||||
|
fi
|
||||||
|
_run_cmd "CUDA Repo" \
|
||||||
|
"sudo extrepo enable nvidia-cuda" \
|
||||||
|
"Enabling official NVIDIA CUDA repository..."
|
||||||
|
fi
|
||||||
|
_run_cmd "APT Update" "sudo apt update" "Updating package lists..."
|
||||||
|
}
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# CASE A: Trixie + Backports Kernel → Official CUDA Repo (Pinned v590)
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
_install_nvidia_cuda_repo() {
|
||||||
|
local warn="WARNING: Official Debian NVIDIA driver (v550)\n"
|
||||||
|
warn+="fails to compile on Trixie Backports Kernels.\n\n"
|
||||||
|
warn+="The script will enable the official NVIDIA CUDA\n"
|
||||||
|
warn+="repository and install the production branch v590\n"
|
||||||
|
warn+="using NVIDIA's unified driver pinning packages.\n\n"
|
||||||
|
warn+="Source: Official NVIDIA CUDA Repo (Pinned v590.*)\n"
|
||||||
|
warn+="Driver: Production Branch v590 (unified metapackage)\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?"
|
||||||
|
|
||||||
|
if ! _confirm_custom "NVIDIA Driver — Trixie + Backports" "$warn" "Proceed" "Abort" 18 70; then
|
||||||
|
echo -e "${YELLOW}NVIDIA installation aborted by user.${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 1: Enable CUDA repo via extrepo
|
||||||
|
_enable_cuda_repo
|
||||||
|
|
||||||
|
# Step 2: Create APT pinning to lock v590
|
||||||
|
_run_cmd "APT Pinning" \
|
||||||
|
'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' \
|
||||||
|
"Creating APT pinning to lock NVIDIA to v590 branch..."
|
||||||
|
|
||||||
|
# Step 3: Install NVIDIA unified metapackages (driver pinning)
|
||||||
|
_run_cmd "NVIDIA CUDA" \
|
||||||
|
"sudo apt install -y nvidia-driver-pinning-590 nvidia-driver firmware-nvidia-gsp" \
|
||||||
|
"Installing NVIDIA v590 production driver via unified metapackages..."
|
||||||
|
|
||||||
|
NVIDIA_DRIVER_MODE="cuda-repo"
|
||||||
|
echo -e "${GREEN}NVIDIA Production Driver v590 installed from CUDA repo. 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 "──────────────────────────────────────────────"
|
||||||
|
}
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# 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
|
||||||
|
# sin pasar por nvidia-detect (evita falsa recomendación rama 535)
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
_install_nvidia_bookworm_kepler() {
|
||||||
|
local nv_pkg="nvidia-legacy-470xx-driver"
|
||||||
|
local nv_ver
|
||||||
|
nv_ver=$(apt-cache policy "$nv_pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Kepler GPU detected — forcing ${nv_pkg}.${NC}"
|
||||||
|
|
||||||
|
local msg="Kepler GPU detectada (GKxxx).\n\n"
|
||||||
|
msg+="En Debian 12 Bookworm, Kepler requiere el driver legacy\n"
|
||||||
|
msg+="en lugar del moderno. Se usará el paquete:\n"
|
||||||
|
msg+=" ${nv_pkg} ${nv_ver:-unknown}\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+=" [+] firmware-misc-nonfree\n"
|
||||||
|
msg+=" [+] nvidia-settings\n\n"
|
||||||
|
msg+="Instalar driver legacy para Kepler?"
|
||||||
|
|
||||||
|
if ! _confirm_custom "NVIDIA Kepler — Bookworm" "$msg" "Install" "Skip" 14 70; then
|
||||||
|
echo "Omitiendo driver Kepler."
|
||||||
|
NVIDIA_DRIVER_MODE=""
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
_run_cmd "NVIDIA Kepler" \
|
||||||
|
"sudo apt install -y $nv_pkg firmware-misc-nonfree nvidia-settings" \
|
||||||
|
"Instalando nvidia-legacy-470xx-driver..."
|
||||||
|
|
||||||
|
# Si backports está habilitado, ofrecer actualización
|
||||||
|
if [ "$(is_backports_enabled)" == "true" ]; then
|
||||||
|
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
|
||||||
|
|
||||||
|
NVIDIA_DRIVER_MODE="${NVIDIA_DRIVER_MODE:-stable}"
|
||||||
|
echo -e "${GREEN}Kepler driver (${nv_pkg}) installed. 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 "──────────────────────────────────────────────"
|
||||||
|
}
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
# CASE C: Kernel stable (any distro) → Debian stable, optional backports
|
||||||
|
# -------------------------------------------------------------------
|
||||||
|
_install_nvidia_standard() {
|
||||||
|
local nv_pkg=""
|
||||||
|
local use_bpo=false
|
||||||
|
local is_kepler
|
||||||
|
is_kepler=$(is_nvidia_kepler)
|
||||||
|
|
||||||
|
if [ "$is_kepler" = "true" ]; then
|
||||||
|
if [ "$DEBIAN_CODENAME" = "trixie" ]; then
|
||||||
|
_msg "NVIDIA Kepler" \
|
||||||
|
"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
|
||||||
|
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)
|
||||||
|
local stable_nv_ver
|
||||||
|
stable_nv_ver=$(apt-cache policy "$nv_pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
|
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"
|
||||||
|
$use_bpo && src_label="Debian ${DEBIAN_CODENAME^}-Backports"
|
||||||
|
|
||||||
|
local msg="Source: ${src_label}\n"
|
||||||
|
msg+="NVIDIA Driver: ${nv_pkg} ${stable_nv_ver:-unknown}\n"
|
||||||
|
msg+="[+] firmware-misc-nonfree\n"
|
||||||
|
msg+="[+] nvidia-vaapi-driver\n"
|
||||||
|
msg+="[+] mesa-vdpau-drivers"
|
||||||
|
|
||||||
|
if ! _confirm "NVIDIA Driver" "$msg" 14 70; then
|
||||||
|
echo "Skipping NVIDIA driver installation."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local extra_pkgs="firmware-misc-nonfree nvidia-vaapi-driver mesa-vdpau-drivers"
|
||||||
|
if $use_bpo; then
|
||||||
|
_run_cmd "NVIDIA" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports $nv_pkg $extra_pkgs" \
|
||||||
|
"Installing NVIDIA driver from backports..."
|
||||||
|
NVIDIA_DRIVER_MODE="backports"
|
||||||
|
else
|
||||||
|
_run_cmd "NVIDIA" "sudo apt install -y $nv_pkg $extra_pkgs" \
|
||||||
|
"Installing NVIDIA driver from stable..."
|
||||||
|
NVIDIA_DRIVER_MODE="stable"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}NVIDIA driver installed. 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 "──────────────────────────────────────────────"
|
||||||
|
}
|
||||||
@@ -27,4 +27,5 @@ install_kernel_backports() {
|
|||||||
|
|
||||||
_run_cmd "Kernel" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports linux-image-amd64" "Installing kernel from backports..."
|
_run_cmd "Kernel" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports linux-image-amd64" "Installing kernel from backports..."
|
||||||
echo -e "${GREEN}Kernel installed. Reboot to use it.${NC}"
|
echo -e "${GREEN}Kernel installed. Reboot to use it.${NC}"
|
||||||
|
_pause
|
||||||
}
|
}
|
||||||
|
|||||||
+416
-83
@@ -1,13 +1,17 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
source "${MODULES_DIR}/repos/migrate.sh" 2>/dev/null || true
|
||||||
|
|
||||||
# State for backup/restore
|
# State for backup/restore
|
||||||
REPO_BACKUP_DIR=""
|
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; do
|
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
|
||||||
if [ -f "$f" ]; then
|
if [ -f "$f" ]; then
|
||||||
cp "$f" "$REPO_BACKUP_DIR/$(basename "$f")"
|
mkdir -p "$REPO_BACKUP_DIR/$(dirname "${f#/etc/apt/}")"
|
||||||
|
cp "$f" "$REPO_BACKUP_DIR/$(dirname "${f#/etc/apt/}")/$(basename "$f")"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
@@ -17,17 +21,22 @@ restore_previous_repos() {
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
echo -e "${RED}Restoring previous repository configuration...${NC}"
|
echo -e "${RED}Restoring previous repository configuration...${NC}"
|
||||||
if [ -f "$REPO_BACKUP_DIR/sources.list" ]; then
|
local found=false
|
||||||
sudo cp "$REPO_BACKUP_DIR/sources.list" /etc/apt/sources.list
|
for f in /etc/apt/sources.list /etc/apt/sources.list.d/debian.sources \
|
||||||
else
|
/etc/apt/sources.list.d/debian-backports.list /etc/apt/sources.list.d/debian-backports.sources; do
|
||||||
sudo rm -f /etc/apt/sources.list
|
local rel="${f#/etc/apt/}"
|
||||||
fi
|
local backup_file="$REPO_BACKUP_DIR/$rel"
|
||||||
if [ -f "$REPO_BACKUP_DIR/debian.sources" ]; then
|
if [ -f "$backup_file" ]; then
|
||||||
sudo cp "$REPO_BACKUP_DIR/debian.sources" /etc/apt/sources.list.d/debian.sources
|
sudo cp "$backup_file" "$f"
|
||||||
else
|
found=true
|
||||||
sudo rm -f /etc/apt/sources.list.d/debian.sources
|
elif [ -f "$f" ]; then
|
||||||
|
sudo rm -f "$f"
|
||||||
|
found=true
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
|
if $found; then
|
||||||
sudo rm -f /etc/apt/sources.list.disabled
|
sudo rm -f /etc/apt/sources.list.disabled
|
||||||
|
fi
|
||||||
rm -rf "$REPO_BACKUP_DIR"
|
rm -rf "$REPO_BACKUP_DIR"
|
||||||
REPO_BACKUP_DIR=""
|
REPO_BACKUP_DIR=""
|
||||||
}
|
}
|
||||||
@@ -39,57 +48,295 @@ cleanup_repo_backup() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
finalize_deb822() {
|
# ---------------------------------------------------------------------------
|
||||||
|
# Cleanup helpers for embedded backports
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
_clean_embedded_backports_classic() {
|
||||||
|
local codename="$1"
|
||||||
|
local file="/etc/apt/sources.list"
|
||||||
|
[ ! -f "$file" ] && return
|
||||||
|
grep -qE "^[^#]*${codename}-backports\b" "$file" 2>/dev/null || return
|
||||||
|
if _confirm "Clean Classic Sources" "Remove backports line from ${file}?"; then
|
||||||
|
sudo sed -i "/${codename}-backports/d" "$file"
|
||||||
|
echo "Removed backports from ${file}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_clean_embedded_backports_deb822() {
|
||||||
|
local codename="$1"
|
||||||
|
local file="/etc/apt/sources.list.d/debian.sources"
|
||||||
|
[ ! -f "$file" ] && return
|
||||||
|
|
||||||
|
# Only proceed if the Suites line contains the backports token
|
||||||
|
grep -qE "^Suites:.*${codename}-backports\b" "$file" 2>/dev/null || return
|
||||||
|
|
||||||
|
if _confirm "Clean deb822 Sources" "Remove backports suite from ${file}?"; then
|
||||||
|
# Remove only the backports token, leaving other suites intact
|
||||||
|
sudo sed -i "s/[[:space:]]*${codename}-backports[[:space:]]*/ /g" "$file"
|
||||||
|
# Clean up whitespace on Suites lines
|
||||||
|
sudo sed -i '/^Suites:[[:space:]]*$/d' "$file" 2>/dev/null || true
|
||||||
|
echo "Removed backports suite from ${file}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Write functions – idempotent, with _confirm dialogs
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
_write_deb822() {
|
||||||
|
local codename="$1" action="$2" bp_enabled="$3" bp_location="$4"
|
||||||
|
local components="${5:-main contrib non-free non-free-firmware}"
|
||||||
|
|
||||||
|
local main_file="/etc/apt/sources.list.d/debian.sources"
|
||||||
|
local main_content=""
|
||||||
|
main_content+="Types: deb\n"
|
||||||
|
main_content+="URIs: https://deb.debian.org/debian\n"
|
||||||
|
main_content+="Suites: ${codename} ${codename}-updates\n"
|
||||||
|
main_content+="Components: ${components}\n"
|
||||||
|
main_content+="\n"
|
||||||
|
main_content+="Types: deb\n"
|
||||||
|
main_content+="URIs: https://security.debian.org/debian-security\n"
|
||||||
|
main_content+="Suites: ${codename}-security\n"
|
||||||
|
main_content+="Components: ${components}\n"
|
||||||
|
|
||||||
|
if content_differs "$main_file" "$main_content"; then
|
||||||
|
if _confirm "Deb822 Sources" "Write main deb822 configuration to ${main_file}?"; then
|
||||||
|
sudo mkdir -p /etc/apt/sources.list.d
|
||||||
|
echo -e "$main_content" | sudo tee "$main_file" > /dev/null
|
||||||
|
echo "Wrote ${main_file}"
|
||||||
|
else
|
||||||
|
echo "Main repository configuration skipped."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Backports: always in separate file
|
||||||
|
if [ "$bp_enabled" = true ]; then
|
||||||
|
_write_deb822_backports "$codename"
|
||||||
|
else
|
||||||
|
_remove_deb822_backports "$codename"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# On migration from classic, disable the old file
|
||||||
|
if [ "$action" = "migrate" ] && [ "$bp_location" = "embedded-classic" -o "$bp_location" = "standalone-classic" ]; then
|
||||||
if [ -f /etc/apt/sources.list ]; then
|
if [ -f /etc/apt/sources.list ]; then
|
||||||
|
if _confirm "Disable Classic" "Migrating to deb822. Disable /etc/apt/sources.list?"; then
|
||||||
sudo mv /etc/apt/sources.list /etc/apt/sources.list.disabled
|
sudo mv /etc/apt/sources.list /etc/apt/sources.list.disabled
|
||||||
echo "Classic sources.list disabled (renamed to sources.list.disabled)"
|
echo "Classic sources.list disabled (renamed to sources.list.disabled)"
|
||||||
fi
|
fi
|
||||||
cleanup_repo_backup
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean embedded backports from old classic file if they existed there
|
||||||
|
if [ "$bp_location" = "embedded-classic" ]; then
|
||||||
|
_clean_embedded_backports_classic "$codename"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_write_deb822_backports() {
|
||||||
|
local codename="$1"
|
||||||
|
local bp_file="/etc/apt/sources.list.d/debian-backports.sources"
|
||||||
|
local bp_content=""
|
||||||
|
bp_content+="Types: deb\n"
|
||||||
|
bp_content+="URIs: https://deb.debian.org/debian\n"
|
||||||
|
bp_content+="Suites: ${codename}-backports\n"
|
||||||
|
bp_content+="Components: main contrib non-free non-free-firmware\n"
|
||||||
|
|
||||||
|
if content_differs "$bp_file" "$bp_content"; then
|
||||||
|
if _confirm "Deb822 Backports" "Write backports to ${bp_file}?"; then
|
||||||
|
sudo mkdir -p /etc/apt/sources.list.d
|
||||||
|
echo -e "$bp_content" | sudo tee "$bp_file" > /dev/null
|
||||||
|
echo "Wrote ${bp_file}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 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 && \
|
||||||
|
_clean_embedded_backports_deb822 "$codename"
|
||||||
|
}
|
||||||
|
|
||||||
|
_remove_deb822_backports() {
|
||||||
|
local codename="$1"
|
||||||
|
local bp_file="/etc/apt/sources.list.d/debian-backports.sources"
|
||||||
|
|
||||||
|
if [ -f "$bp_file" ]; then
|
||||||
|
if _confirm "Remove Backports" "Remove ${bp_file}?"; then
|
||||||
|
sudo rm -f "$bp_file"
|
||||||
|
echo "Removed ${bp_file}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 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 && \
|
||||||
|
_clean_embedded_backports_deb822 "$codename"
|
||||||
|
|
||||||
|
# Clean embedded backports from classic file too (safety net)
|
||||||
|
_clean_embedded_backports_classic "$codename"
|
||||||
|
}
|
||||||
|
|
||||||
|
_write_classic() {
|
||||||
|
local codename="$1" action="$2" bp_enabled="$3" bp_location="$4"
|
||||||
|
local components="${5:-main contrib non-free non-free-firmware}"
|
||||||
|
|
||||||
|
local main_file="/etc/apt/sources.list"
|
||||||
|
local main_content=""
|
||||||
|
main_content+="# Official repository\n"
|
||||||
|
main_content+="deb https://deb.debian.org/debian ${codename} ${components}\n"
|
||||||
|
main_content+="# deb-src https://deb.debian.org/debian ${codename} ${components}\n"
|
||||||
|
main_content+="\n"
|
||||||
|
main_content+="# Updates\n"
|
||||||
|
main_content+="deb https://deb.debian.org/debian ${codename}-updates ${components}\n"
|
||||||
|
main_content+="# deb-src https://deb.debian.org/debian ${codename}-updates ${components}\n"
|
||||||
|
main_content+="\n"
|
||||||
|
main_content+="# Security\n"
|
||||||
|
main_content+="deb https://security.debian.org/debian-security ${codename}-security ${components}\n"
|
||||||
|
main_content+="# deb-src https://security.debian.org/debian-security ${codename}-security ${components}\n"
|
||||||
|
|
||||||
|
if content_differs "$main_file" "$main_content"; then
|
||||||
|
if _confirm "Classic Sources" "Write main classic configuration to ${main_file}?"; then
|
||||||
|
echo -e "$main_content" | sudo tee "$main_file" > /dev/null
|
||||||
|
echo "Wrote ${main_file}"
|
||||||
|
else
|
||||||
|
echo "Main repository configuration skipped."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Backports: always in separate file
|
||||||
|
if [ "$bp_enabled" = true ]; then
|
||||||
|
_write_classic_backports "$codename"
|
||||||
|
else
|
||||||
|
_remove_classic_backports "$codename"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# On migration from deb822, disable the old file
|
||||||
|
if [ "$action" = "migrate" ]; then
|
||||||
|
if [ -f /etc/apt/sources.list.d/debian.sources ]; then
|
||||||
|
if _confirm "Disable Deb822" "Migrating to classic format. Disable /etc/apt/sources.list.d/debian.sources?"; then
|
||||||
|
sudo mv /etc/apt/sources.list.d/debian.sources /etc/apt/sources.list.d/debian.sources.disabled
|
||||||
|
echo "Deb822 sources disabled (renamed to debian.sources.disabled)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean embedded backports from old deb822 file if they existed there
|
||||||
|
if [ "$bp_location" = "embedded-deb822" ]; then
|
||||||
|
_clean_embedded_backports_deb822 "$codename"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_write_classic_backports() {
|
||||||
|
local codename="$1"
|
||||||
|
local bp_file="/etc/apt/sources.list.d/debian-backports.list"
|
||||||
|
local bp_content=""
|
||||||
|
bp_content+="# Backports\n"
|
||||||
|
bp_content+="deb https://deb.debian.org/debian ${codename}-backports main contrib non-free non-free-firmware\n"
|
||||||
|
|
||||||
|
if content_differs "$bp_file" "$bp_content"; then
|
||||||
|
if _confirm "Classic Backports" "Write backports to ${bp_file}?"; then
|
||||||
|
sudo mkdir -p /etc/apt/sources.list.d
|
||||||
|
echo -e "$bp_content" | sudo tee "$bp_file" > /dev/null
|
||||||
|
echo "Wrote ${bp_file}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If backports were formerly embedded in sources.list, clean them
|
||||||
|
grep -qE "^[^#]*${codename}-backports\b" /etc/apt/sources.list 2>/dev/null && \
|
||||||
|
_clean_embedded_backports_classic "$codename"
|
||||||
|
}
|
||||||
|
|
||||||
|
_remove_classic_backports() {
|
||||||
|
local codename="$1"
|
||||||
|
local bp_file="/etc/apt/sources.list.d/debian-backports.list"
|
||||||
|
|
||||||
|
if [ -f "$bp_file" ]; then
|
||||||
|
if _confirm "Remove Backports" "Remove ${bp_file}?"; then
|
||||||
|
sudo rm -f "$bp_file"
|
||||||
|
echo "Removed ${bp_file}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Also clean any embedded backports in main sources.list
|
||||||
|
grep -qE "^[^#]*${codename}-backports\b" /etc/apt/sources.list 2>/dev/null && \
|
||||||
|
_clean_embedded_backports_classic "$codename"
|
||||||
|
|
||||||
|
# Clean embedded backports from deb822 file too (safety net)
|
||||||
|
_clean_embedded_backports_deb822 "$codename"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Main entry point
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
configure_repos() {
|
configure_repos() {
|
||||||
echo -e "${YELLOW}Repository configuration...${NC}"
|
echo -e "${YELLOW}Repository configuration...${NC}"
|
||||||
|
|
||||||
local use_deb822=false
|
|
||||||
if [ "$DEBIAN_CODENAME" = "trixie" ]; then
|
|
||||||
if whiptail --title "Repository Format" --defaultno --yesno "Use deb822 format (modern .sources)?" 8 60; then
|
|
||||||
use_deb822=true
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
local enable_backports=false
|
|
||||||
if _confirm "Backports" "Enable backports repository?\n\nProvides newer kernel, drivers, Mesa."; then
|
|
||||||
enable_backports=true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$DEBIAN_CODENAME" ]; then
|
if [ -z "$DEBIAN_CODENAME" ]; then
|
||||||
echo -e "${RED}Error: Could not detect Debian codename. Aborting.${NC}"
|
echo -e "${RED}Error: Could not detect Debian codename. Aborting.${NC}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sync_system_time
|
# ── Repositories submenu ──
|
||||||
|
while true; do
|
||||||
|
local repo_choice
|
||||||
|
|
||||||
backup_current_repos
|
if [ "$DEBIAN_CODENAME" = "sid" ]; then
|
||||||
|
repo_choice=$(_menu "Configure Repositories" \
|
||||||
if $use_deb822; then
|
"Select an option:" $TUI_ALTO $TUI_ANCHO 6 \
|
||||||
generate_deb822_sources "$DEBIAN_CODENAME" "$enable_backports"
|
"1" "Enable Contrib & Non-Free Components" \
|
||||||
|
"2" "Migrate traditional sources.list to DEB822 format" \
|
||||||
|
"3" "Back to main menu")
|
||||||
else
|
else
|
||||||
generate_classic_sources "$DEBIAN_CODENAME" "$enable_backports"
|
repo_choice=$(_menu "Configure Repositories" \
|
||||||
|
"Select an option:" $TUI_ALTO $TUI_ANCHO 6 \
|
||||||
|
"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")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Updating package lists..."
|
[ -z "$repo_choice" ] && break
|
||||||
sudo apt update
|
clear
|
||||||
local apt_rc=$?
|
|
||||||
if [ $apt_rc -eq 0 ]; then
|
|
||||||
REPOS_CONFIGURED=true
|
|
||||||
echo -e "${GREEN}Repositories configured and updated successfully.${NC}"
|
|
||||||
|
|
||||||
if $use_deb822; then
|
case "$repo_choice" in
|
||||||
finalize_deb822
|
1) _repos_enable_components ;;
|
||||||
|
2) _repos_migrate_format ;;
|
||||||
|
3)
|
||||||
|
if [ "$DEBIAN_CODENAME" = "sid" ]; then
|
||||||
|
break
|
||||||
else
|
else
|
||||||
cleanup_repo_backup
|
_repos_setup_backports
|
||||||
fi
|
fi
|
||||||
|
;;
|
||||||
|
4) _branch_migration || true ;;
|
||||||
|
5) break ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Submenu helpers
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
_components_enabled() {
|
||||||
|
if [ -f /etc/apt/sources.list.d/debian.sources ]; then
|
||||||
|
for c in $(grep "^Components:" /etc/apt/sources.list.d/debian.sources 2>/dev/null | cut -d: -f2-); do
|
||||||
|
[ "$c" = "contrib" ] || [ "$c" = "non-free" ] && return 0
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
if [ -f /etc/apt/sources.list ]; then
|
||||||
|
local components
|
||||||
|
components=$(grep "^[^#]*deb .* main" /etc/apt/sources.list 2>/dev/null | head -1 | sed 's/.*main\s*//')
|
||||||
|
for c in $components; do
|
||||||
|
[ "$c" = "contrib" ] || [ "$c" = "non-free" ] && return 0
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_repos_offer_upgrade() {
|
||||||
local upgradable
|
local upgradable
|
||||||
upgradable=$(apt list --upgradable 2>/dev/null | grep -c /)
|
upgradable=$(apt list --upgradable 2>/dev/null | grep -c /)
|
||||||
if [ "$upgradable" -gt 0 ]; then
|
if [ "$upgradable" -gt 0 ]; then
|
||||||
@@ -104,65 +351,151 @@ configure_repos() {
|
|||||||
echo "Skipping upgrade."
|
echo "Skipping upgrade."
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_repos_enable_components() {
|
||||||
|
local current_format bp_enabled bp_location components
|
||||||
|
current_format=$(detect_repo_format)
|
||||||
|
|
||||||
|
if _components_enabled; then
|
||||||
|
if ! _confirm "Disable Components" \
|
||||||
|
"Contrib and non-free are already enabled. Disable them?"; then
|
||||||
|
echo "No changes made."
|
||||||
|
_pause
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
components="main"
|
||||||
|
else
|
||||||
|
if ! _confirm "Enable Components" \
|
||||||
|
"Enable contrib and non-free components?\n\n\
|
||||||
|
Needed for proprietary drivers, firmware, and other
|
||||||
|
popular software (like gaming platforms and proprietary tools)." 12 60; then
|
||||||
|
echo "No changes made."
|
||||||
|
_pause
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
components="main contrib non-free non-free-firmware"
|
||||||
|
fi
|
||||||
|
|
||||||
|
bp_enabled=false
|
||||||
|
bp_location="none"
|
||||||
|
if detect_backports_status "$DEBIAN_CODENAME"; then
|
||||||
|
bp_enabled=true
|
||||||
|
bp_location=$(detect_backports_location "$DEBIAN_CODENAME")
|
||||||
|
fi
|
||||||
|
|
||||||
|
backup_current_repos
|
||||||
|
|
||||||
|
if [ "$current_format" = "deb822" ] || [ "$current_format" = "none" ]; then
|
||||||
|
_write_deb822 "$DEBIAN_CODENAME" "write" "$bp_enabled" "$bp_location" "$components"
|
||||||
|
else
|
||||||
|
_write_classic "$DEBIAN_CODENAME" "write" "$bp_enabled" "$bp_location" "$components"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Updating package lists..."
|
||||||
|
if sudo apt update; then
|
||||||
|
REPOS_CONFIGURED=true
|
||||||
|
cleanup_repo_backup
|
||||||
|
echo -e "${GREEN}Repository components configured.${NC}"
|
||||||
|
_repos_offer_upgrade
|
||||||
else
|
else
|
||||||
restore_previous_repos
|
restore_previous_repos
|
||||||
echo -e "${RED}apt update failed. Previous repository configuration restored.${NC}"
|
echo -e "${RED}apt update failed. Previous configuration restored.${NC}"
|
||||||
return 1
|
|
||||||
fi
|
fi
|
||||||
|
_pause
|
||||||
}
|
}
|
||||||
|
|
||||||
generate_classic_sources() {
|
_repos_migrate_format() {
|
||||||
local codename="$1"
|
local current_format bp_enabled bp_location
|
||||||
local backports="$2"
|
current_format=$(detect_repo_format)
|
||||||
|
|
||||||
local content=""
|
if [ "$current_format" != "classic" ]; then
|
||||||
content="# Official repository\n"
|
echo "Repositories are already in DEB822 format."
|
||||||
content+="deb https://deb.debian.org/debian ${codename} main contrib non-free non-free-firmware\n"
|
_pause
|
||||||
content+="# deb-src https://deb.debian.org/debian ${codename} main contrib non-free non-free-firmware\n\n"
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
content+="# Updates\n"
|
if [ "$DEBIAN_CODENAME" != "trixie" ]; then
|
||||||
content+="deb https://deb.debian.org/debian ${codename}-updates main contrib non-free non-free-firmware\n"
|
echo "Format migration is only relevant for Debian 13 (Trixie)."
|
||||||
content+="# deb-src https://deb.debian.org/debian ${codename}-updates main contrib non-free non-free-firmware\n\n"
|
_pause
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
content+="# Security\n"
|
# Preserve existing backports state across format migration
|
||||||
content+="deb https://security.debian.org/debian-security ${codename}-security main contrib non-free non-free-firmware\n"
|
bp_enabled=false
|
||||||
content+="# deb-src https://security.debian.org/debian-security ${codename}-security main contrib non-free non-free-firmware\n\n"
|
bp_location="none"
|
||||||
|
if detect_backports_status "$DEBIAN_CODENAME"; then
|
||||||
|
bp_enabled=true
|
||||||
|
bp_location=$(detect_backports_location "$DEBIAN_CODENAME")
|
||||||
|
fi
|
||||||
|
|
||||||
if $backports; then
|
backup_current_repos
|
||||||
content+="# Backports (active)\n"
|
_write_deb822 "$DEBIAN_CODENAME" "migrate" "$bp_enabled" "$bp_location"
|
||||||
content+="deb https://deb.debian.org/debian ${codename}-backports main contrib non-free non-free-firmware\n"
|
|
||||||
content+="# deb-src https://deb.debian.org/debian ${codename}-backports main contrib non-free non-free-firmware\n"
|
echo "Updating package lists..."
|
||||||
|
if sudo apt update; then
|
||||||
|
REPOS_CONFIGURED=true
|
||||||
|
cleanup_repo_backup
|
||||||
|
echo -e "${GREEN}Repository format migrated to DEB822.${NC}"
|
||||||
else
|
else
|
||||||
content+="# Backports (not enabled)\n"
|
restore_previous_repos
|
||||||
content+="# deb https://deb.debian.org/debian ${codename}-backports main contrib non-free non-free-firmware\n"
|
echo -e "${RED}apt update failed. Backup restored.${NC}"
|
||||||
fi
|
fi
|
||||||
|
_pause
|
||||||
echo -e "$content" | sudo tee /etc/apt/sources.list > /dev/null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
generate_deb822_sources() {
|
_repos_setup_backports() {
|
||||||
local codename="$1"
|
local current_format bp_status bp_location
|
||||||
local backports="$2"
|
current_format=$(detect_repo_format)
|
||||||
|
|
||||||
sudo mkdir -p /etc/apt/sources.list.d
|
if detect_backports_status "$DEBIAN_CODENAME"; then
|
||||||
|
bp_status="enabled"
|
||||||
|
else
|
||||||
|
bp_status="disabled"
|
||||||
|
fi
|
||||||
|
bp_location=$(detect_backports_location "$DEBIAN_CODENAME")
|
||||||
|
|
||||||
local content=""
|
echo "Backports are currently $bp_status."
|
||||||
content="Types: deb\n"
|
|
||||||
content+="URIs: https://deb.debian.org/debian\n"
|
|
||||||
content+="Suites: ${codename} ${codename}-updates\n"
|
|
||||||
content+="Components: main contrib non-free non-free-firmware\n\n"
|
|
||||||
|
|
||||||
content+="Types: deb\n"
|
local enable_backports=false
|
||||||
content+="URIs: https://security.debian.org/debian-security\n"
|
if _confirm "Backports" "Do you want to enable the official Debian Backports repository?\n\n\
|
||||||
content+="Suites: ${codename}-security\n"
|
Backports provides newer, selectively updated packages from the next\n\
|
||||||
content+="Components: main contrib non-free non-free-firmware\n\n"
|
Debian testing branch, recompiled to run stably on your current system.\n\n\
|
||||||
|
Answer NO to disable or remove backports if they are currently enabled." 16 70; then
|
||||||
if $backports; then
|
enable_backports=true
|
||||||
content+="Types: deb\n"
|
|
||||||
content+="URIs: https://deb.debian.org/debian\n"
|
|
||||||
content+="Suites: ${codename}-backports\n"
|
|
||||||
content+="Components: main contrib non-free non-free-firmware\n"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "$content" | sudo tee /etc/apt/sources.list.d/debian.sources > /dev/null
|
# Nothing to do — already in desired state
|
||||||
|
if { $enable_backports && [ "$bp_status" = "enabled" ]; } || \
|
||||||
|
{ ! $enable_backports && [ "$bp_status" = "disabled" ]; }; then
|
||||||
|
echo "Backports are already configured as requested."
|
||||||
|
_pause
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
backup_current_repos
|
||||||
|
|
||||||
|
if $enable_backports; then
|
||||||
|
if [ "$current_format" = "deb822" ]; then
|
||||||
|
_write_deb822_backports "$DEBIAN_CODENAME"
|
||||||
|
else
|
||||||
|
_write_classic_backports "$DEBIAN_CODENAME"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ "$current_format" = "deb822" ]; then
|
||||||
|
_remove_deb822_backports "$DEBIAN_CODENAME"
|
||||||
|
else
|
||||||
|
_remove_classic_backports "$DEBIAN_CODENAME"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Updating package lists..."
|
||||||
|
if sudo apt update; then
|
||||||
|
cleanup_repo_backup
|
||||||
|
echo -e "${GREEN}Backports configured.${NC}"
|
||||||
|
else
|
||||||
|
restore_previous_repos
|
||||||
|
echo -e "${RED}apt update failed. Backup restored.${NC}"
|
||||||
|
fi
|
||||||
|
_pause
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,176 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# migrate.sh — Stable → Testing / SID branch migration
|
||||||
|
# License GPL v3
|
||||||
|
|
||||||
|
_MIGRATE_BACKUP=""
|
||||||
|
|
||||||
|
_persistent_backup_repos() {
|
||||||
|
local stamp
|
||||||
|
stamp=$(date +%Y%m%d-%H%M%S)
|
||||||
|
_MIGRATE_BACKUP="/var/backups/debianito-repos-${stamp}.tar.gz"
|
||||||
|
sudo mkdir -p /var/backups
|
||||||
|
local files=()
|
||||||
|
[ -f /etc/apt/sources.list ] && files+=("/etc/apt/sources.list")
|
||||||
|
[ -d /etc/apt/sources.list.d ] && files+=("/etc/apt/sources.list.d")
|
||||||
|
[ ${#files[@]} -eq 0 ] && return 1
|
||||||
|
sudo tar czf "$_MIGRATE_BACKUP" "${files[@]}" 2>/dev/null
|
||||||
|
echo "Backup: $_MIGRATE_BACKUP"
|
||||||
|
}
|
||||||
|
|
||||||
|
_restore_backup() {
|
||||||
|
if [ -z "$_MIGRATE_BACKUP" ] || [ ! -f "$_MIGRATE_BACKUP" ]; then
|
||||||
|
_msg "Restore Error" "No backup found at $_MIGRATE_BACKUP.\nCannot restore. Your system may be in an inconsistent state." 10 70
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo -e "${YELLOW}Restoring repository backup...${NC}"
|
||||||
|
sudo tar xzf "$_MIGRATE_BACKUP" -C / 2>/dev/null
|
||||||
|
echo -e "${GREEN}Backup restored from $_MIGRATE_BACKUP${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_write_deb822_branch() {
|
||||||
|
local target="$1"
|
||||||
|
local main_file="/etc/apt/sources.list.d/debian.sources"
|
||||||
|
|
||||||
|
local main_content=""
|
||||||
|
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+="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
|
||||||
|
# testing
|
||||||
|
main_content+="Types: deb\n"
|
||||||
|
main_content+="URIs: https://deb.debian.org/debian\n"
|
||||||
|
main_content+="Suites: testing testing-updates\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: testing-security\n"
|
||||||
|
main_content+="Components: main contrib non-free non-free-firmware\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo mkdir -p /etc/apt/sources.list.d
|
||||||
|
echo -e "$main_content" | sudo tee "$main_file" > /dev/null
|
||||||
|
echo "Wrote $main_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
_branch_migration() {
|
||||||
|
# ── Screen 1: Risk warning ──
|
||||||
|
_msg_red "WARNING: Branch Migration" \
|
||||||
|
"Migrating from Debian Stable to Testing or SID is a\n\
|
||||||
|
MAJOR change and CAN make your system UNBOOTABLE.\n\n\
|
||||||
|
Risks include:\n\
|
||||||
|
• NVIDIA / DKMS drivers may break\n\
|
||||||
|
• System may fail to boot after reboot\n\
|
||||||
|
• Some packages may be removed or replaced\n\
|
||||||
|
• SID (unstable) receives NO security updates\n\n\
|
||||||
|
A full persistent backup will be saved to /var/backups/\n\
|
||||||
|
so you can restore if things go wrong." 16 70
|
||||||
|
|
||||||
|
if ! _confirm "Branch Migration" "Do you want to proceed with the migration?"; then
|
||||||
|
echo "Migration cancelled."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Screen 2: Plan summary ──
|
||||||
|
local plan="This operation will:\n\n"
|
||||||
|
plan+=" 1. Backup current APT sources to /var/backups/\n"
|
||||||
|
plan+=" 2. Remove any backports configuration\n"
|
||||||
|
plan+=" 3. Write new DEB822 sources for the target branch\n"
|
||||||
|
plan+=" 4. Run: apt update\n"
|
||||||
|
plan+=" 5. Run: apt upgrade -y\n"
|
||||||
|
plan+=" 6. Run: apt full-upgrade -y\n"
|
||||||
|
plan+=" 7. Run: apt autoremove -y\n\n"
|
||||||
|
plan+="If apt update fails, the backup is restored immediately."
|
||||||
|
|
||||||
|
_msg_red "Migration Plan" "$plan" 16 70
|
||||||
|
|
||||||
|
if ! _confirm "Migration Plan" "Proceed with the plan?"; then
|
||||||
|
echo "Migration cancelled."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Screen 3: Branch selection ──
|
||||||
|
local branch
|
||||||
|
branch=$(_inputbox "Target Branch" \
|
||||||
|
"Type exactly TESTING or SID (case-sensitive):" 10 60 "")
|
||||||
|
|
||||||
|
[ -z "$branch" ] && { echo "Migration cancelled."; return; }
|
||||||
|
|
||||||
|
if [ "$branch" != "TESTING" ] && [ "$branch" != "SID" ]; then
|
||||||
|
_msg "Invalid Branch" "You typed: $branch\n\nExpected: TESTING or SID (exact, case-sensitive).\nAborting." 10 60
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Normalize to lowercase for internal use
|
||||||
|
local target
|
||||||
|
target=$(echo "$branch" | tr '[:upper:]' '[:lower:]')
|
||||||
|
|
||||||
|
# ── Screen 4: Execution ──
|
||||||
|
echo -e "${YELLOW}Starting branch migration to ${target}...${NC}"
|
||||||
|
|
||||||
|
# 4a. Persistent backup
|
||||||
|
echo "Creating backup..."
|
||||||
|
_persistent_backup_repos || {
|
||||||
|
_msg "Backup Error" "Failed to create backup. Aborting." 8 60
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# 4b. Clean backports
|
||||||
|
echo "Removing backports configuration..."
|
||||||
|
[ -f /etc/apt/sources.list.d/debian-backports.sources ] && sudo rm -f /etc/apt/sources.list.d/debian-backports.sources
|
||||||
|
[ -f /etc/apt/sources.list.d/debian-backports.list ] && sudo rm -f /etc/apt/sources.list.d/debian-backports.list
|
||||||
|
|
||||||
|
# 4c. Remove any old classic source files to avoid conflicts
|
||||||
|
[ -f /etc/apt/sources.list ] && sudo rm -f /etc/apt/sources.list
|
||||||
|
|
||||||
|
# 4d. Write new sources
|
||||||
|
_write_deb822_branch "$target"
|
||||||
|
|
||||||
|
# 4e. SID guardrails: install bug alerts before upgrade
|
||||||
|
if [ "$target" = "sid" ]; then
|
||||||
|
echo -e "${YELLOW}Installing apt-listbugs and apt-listchanges (SID guardrails)...${NC}"
|
||||||
|
sudo apt update -qq 2>/dev/null || true
|
||||||
|
sudo DEBIAN_FRONTEND=noninteractive apt install -y apt-listbugs apt-listchanges || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4f. apt update with rollback on failure
|
||||||
|
echo -e "${YELLOW}Running apt update...${NC}"
|
||||||
|
if ! sudo apt update; then
|
||||||
|
echo -e "${RED}apt update failed. Restoring backup...${NC}"
|
||||||
|
_restore_backup
|
||||||
|
_msg_red "Migration Failed" \
|
||||||
|
"apt update failed. Backup has been restored from:\n\
|
||||||
|
$_MIGRATE_BACKUP\n\n\
|
||||||
|
Your system should be back to its previous state.\n\
|
||||||
|
Run 'sudo apt update' manually to verify." 12 70
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4g. Full upgrade
|
||||||
|
_run_cmd "Upgrade" "sudo apt upgrade -y" "Upgrading packages..."
|
||||||
|
_run_cmd "Full-Upgrade" "sudo apt full-upgrade -y" "Running full-upgrade..."
|
||||||
|
_run_cmd "Autoremove" "sudo apt autoremove -y" "Removing obsolete packages..."
|
||||||
|
|
||||||
|
# 4h. Re-run detection to reflect new branch
|
||||||
|
echo -e "${YELLOW}Re-running system detection for new branch...${NC}"
|
||||||
|
detect_debian_version
|
||||||
|
detect_kernel
|
||||||
|
detect_gpu
|
||||||
|
detect_storage
|
||||||
|
|
||||||
|
echo -e "${GREEN}Branch migration to ${target} completed successfully.${NC}"
|
||||||
|
|
||||||
|
# ── Screen 5: Reboot reminder ──
|
||||||
|
_msg "Migration Complete" \
|
||||||
|
"System has been migrated to ${target}.\n\n\
|
||||||
|
Backup saved at:\n $_MIGRATE_BACKUP\n\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
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
# shellcheck disable=SC2148
|
||||||
|
# repo_detect.sh – Detection-only helpers for idempotent repository configuration.
|
||||||
|
# Part A of the two-part architecture. No user dialogs, no writes.
|
||||||
|
|
||||||
|
# Detect the format of the main repo file
|
||||||
|
# Returns: "deb822", "classic", or "none"
|
||||||
|
detect_repo_format() {
|
||||||
|
if [ -f /etc/apt/sources.list.d/debian.sources ]; then
|
||||||
|
echo "deb822"
|
||||||
|
elif [ -f /etc/apt/sources.list ]; then
|
||||||
|
echo "classic"
|
||||||
|
else
|
||||||
|
echo "none"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check whether backports are currently enabled (any format)
|
||||||
|
# Returns: 0 if enabled, 1 otherwise
|
||||||
|
detect_backports_status() {
|
||||||
|
local codename="$1"
|
||||||
|
|
||||||
|
if [ -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
|
||||||
|
fi
|
||||||
|
if [ -f /etc/apt/sources.list ]; then
|
||||||
|
grep -qE "^[^#]*${codename}-backports" /etc/apt/sources.list 2>/dev/null && return 0
|
||||||
|
fi
|
||||||
|
if [ -f /etc/apt/sources.list.d/debian-backports.sources ]; then
|
||||||
|
grep -qE "^Suites:.*${codename}-backports" /etc/apt/sources.list.d/debian-backports.sources 2>/dev/null && return 0
|
||||||
|
fi
|
||||||
|
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
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Locate where backports are configured
|
||||||
|
# Returns: "standalone-deb822" (debian-backports.sources),
|
||||||
|
# "standalone-classic" (debian-backports.list),
|
||||||
|
# "embedded-deb822" (inside debian.sources),
|
||||||
|
# "embedded-classic" (inside sources.list),
|
||||||
|
# "none"
|
||||||
|
detect_backports_location() {
|
||||||
|
local codename="$1"
|
||||||
|
|
||||||
|
if [ -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
|
||||||
|
echo "standalone-deb822"
|
||||||
|
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
|
||||||
|
echo "standalone-classic"
|
||||||
|
elif [ -f /etc/apt/sources.list.d/debian.sources ] && \
|
||||||
|
grep -qE "^Suites:.*${codename}-backports" /etc/apt/sources.list.d/debian.sources 2>/dev/null; then
|
||||||
|
echo "embedded-deb822"
|
||||||
|
elif [ -f /etc/apt/sources.list ] && \
|
||||||
|
grep -qE "^[^#]*${codename}-backports" /etc/apt/sources.list 2>/dev/null; then
|
||||||
|
echo "embedded-classic"
|
||||||
|
else
|
||||||
|
echo "none"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Compare generated content vs existing file (idempotency check)
|
||||||
|
# Returns: 0 if content differs, 1 if identical
|
||||||
|
content_differs() {
|
||||||
|
local file="$1"
|
||||||
|
local content="$2"
|
||||||
|
|
||||||
|
if [ ! -f "$file" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
local current
|
||||||
|
current=$(cat "$file")
|
||||||
|
local generated
|
||||||
|
generated=$(echo -e "$content")
|
||||||
|
if [ "$current" = "$generated" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# rescue.sh — UEFI boot repair and system rescue utilities
|
||||||
|
|
||||||
|
_rescue_boot_sb() {
|
||||||
|
echo -e "${YELLOW}UEFI Secure Boot repair...${NC}"
|
||||||
|
|
||||||
|
if [ ! -d /sys/firmware/efi ]; then
|
||||||
|
echo -e "${RED}Not a UEFI system. Skipping.${NC}"
|
||||||
|
_pause
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local sb_state
|
||||||
|
sb_state=$(mokutil --sb-state 2>/dev/null)
|
||||||
|
if ! echo "$sb_state" | grep -qi "enabled"; then
|
||||||
|
echo -e "${YELLOW}Secure Boot is not enabled. No refirm needed.${NC}"
|
||||||
|
_pause
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _confirm "Secure Boot Repair" \
|
||||||
|
"Secure Boot is enabled.\n\nReinstall and refirm shim-signed + GRUB?\n\nThis fixes boot issues where Debian is skipped\nin UEFI after kernel/driver changes."; then
|
||||||
|
echo "Skipped."
|
||||||
|
_pause
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local efi_dir="/boot/efi"
|
||||||
|
[ ! -d "$efi_dir" ] && efi_dir="/boot"
|
||||||
|
|
||||||
|
_run_cmd "Refirm" \
|
||||||
|
"sudo apt install --reinstall -y shim-signed grub-efi-amd64-signed linux-image-amd64" \
|
||||||
|
"Reinstalling signed boot packages..."
|
||||||
|
_run_cmd "GRUB Install" \
|
||||||
|
"sudo grub-install --target=x86_64-efi --efi-directory=$efi_dir --bootloader-id=debian --recheck" \
|
||||||
|
"Reinstalling GRUB to EFI partition..."
|
||||||
|
_run_cmd "GRUB Config" \
|
||||||
|
"sudo update-grub" \
|
||||||
|
"Regenerating GRUB configuration..."
|
||||||
|
|
||||||
|
echo -e "${GREEN}Boot repair complete. Reboot to verify.${NC}"
|
||||||
|
_pause
|
||||||
|
}
|
||||||
|
|
||||||
|
_rescue_initramfs() {
|
||||||
|
if ! _confirm "Initramfs" "Regenerate initramfs for all kernels?\n\nFixes boot issues caused by missing drivers\nor corrupted initrd images."; then
|
||||||
|
echo "Skipped."
|
||||||
|
_pause
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
_run_cmd "Initramfs" "sudo update-initramfs -u -k all" "Regenerating initramfs for all kernels..."
|
||||||
|
echo -e "${GREEN}Initramfs regenerated.${NC}"
|
||||||
|
_pause
|
||||||
|
}
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# GRUB helpers
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
_set_grub_var() {
|
||||||
|
local var="$1" val="$2" file="/etc/default/grub"
|
||||||
|
if grep -q "^${var}=" "$file" 2>/dev/null; then
|
||||||
|
sudo sed -i "s/^${var}=.*/${var}=${val}/" "$file"
|
||||||
|
elif grep -q "^#${var}=" "$file" 2>/dev/null; then
|
||||||
|
sudo sed -i "s/^#${var}=.*/${var}=${val}/" "$file"
|
||||||
|
else
|
||||||
|
echo "${var}=${val}" | sudo tee -a "$file" >/dev/null
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_apply_grub_setting() {
|
||||||
|
local timeout="$1" style="$2" recordfail="$3" os_prober="$4"
|
||||||
|
local file="/etc/default/grub"
|
||||||
|
local backup="${file}.backup.$(date +%Y%m%d_%H%M%S)"
|
||||||
|
local override="/etc/default/grub.d/99_script_override.cfg"
|
||||||
|
|
||||||
|
sudo cp "$file" "$backup"
|
||||||
|
|
||||||
|
_set_grub_var GRUB_TIMEOUT "$timeout"
|
||||||
|
_set_grub_var GRUB_TIMEOUT_STYLE "$style"
|
||||||
|
_set_grub_var GRUB_RECORDFAIL_TIMEOUT "$recordfail"
|
||||||
|
[ -n "$os_prober" ] && _set_grub_var GRUB_DISABLE_OS_PROBER "$os_prober"
|
||||||
|
|
||||||
|
sudo mkdir -p /etc/default/grub.d
|
||||||
|
if [ -n "$os_prober" ]; then
|
||||||
|
cat << EOF | sudo tee "$override" > /dev/null
|
||||||
|
GRUB_TIMEOUT_STYLE=$style
|
||||||
|
GRUB_TIMEOUT=$timeout
|
||||||
|
GRUB_RECORDFAIL_TIMEOUT=$recordfail
|
||||||
|
GRUB_DISABLE_OS_PROBER=$os_prober
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
cat << EOF | sudo tee "$override" > /dev/null
|
||||||
|
GRUB_TIMEOUT=$timeout
|
||||||
|
GRUB_TIMEOUT_STYLE=$style
|
||||||
|
GRUB_RECORDFAIL_TIMEOUT=$recordfail
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
local summary
|
||||||
|
summary="Settings applied:\n\n"
|
||||||
|
summary+=" GRUB_TIMEOUT=$timeout\n"
|
||||||
|
summary+=" GRUB_TIMEOUT_STYLE=$style\n"
|
||||||
|
summary+=" GRUB_RECORDFAIL_TIMEOUT=$recordfail\n"
|
||||||
|
[ -n "$os_prober" ] && summary+=" GRUB_DISABLE_OS_PROBER=$os_prober\n"
|
||||||
|
summary+="\nRunning update-grub..."
|
||||||
|
|
||||||
|
echo -e "$summary"
|
||||||
|
|
||||||
|
if sudo update-grub >/dev/null 2>&1; then
|
||||||
|
_msg "GRUB Settings" \
|
||||||
|
"GRUB settings applied successfully!\n\nBackup saved: ${backup}\n\nReboot to see the changes."
|
||||||
|
else
|
||||||
|
echo -e "${RED}update-grub failed. Restoring backup...${NC}"
|
||||||
|
sudo cp "$backup" "$file"
|
||||||
|
sudo rm -f "$override"
|
||||||
|
_msg "Error" "update-grub failed.\nBackup restored from ${backup}\nOverride removed: ${override}."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_grub_menu_settings() {
|
||||||
|
while true; do
|
||||||
|
local choice
|
||||||
|
choice=$(_menu "GRUB Boot Menu Settings" \
|
||||||
|
"Configure when and how the GRUB menu appears${SCROLL_HINT}:" \
|
||||||
|
$TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
||||||
|
"1" "Disable GRUB menu on start (Fastest boot)" \
|
||||||
|
"2" "Faster boot (Show 3-sec countdown)" \
|
||||||
|
"3" "Default boot (Show menu for 5 secs)" \
|
||||||
|
"4" "Custom timeout (Input seconds)" \
|
||||||
|
"5" "Back")
|
||||||
|
|
||||||
|
[ -z "$choice" ] && return
|
||||||
|
clear
|
||||||
|
|
||||||
|
case "$choice" in
|
||||||
|
1)
|
||||||
|
if _confirm "Disable GRUB Menu" \
|
||||||
|
"GRUB menu will be hidden entirely for fastest boot.\n\nTo access the menu on next boot, press and hold ESC\nimmediately after powering on.\n\nProceed?"; then
|
||||||
|
_apply_grub_setting 0 hidden 0 true
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
_apply_grub_setting 3 menu 3 ""
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
_apply_grub_setting 5 menu 5 ""
|
||||||
|
;;
|
||||||
|
4)
|
||||||
|
local custom_timeout
|
||||||
|
custom_timeout=$(whiptail --title "Custom GRUB Timeout" \
|
||||||
|
--inputbox "Enter the GRUB timeout in seconds.\n\nUse -1 for indefinite wait." \
|
||||||
|
10 60 "" 3>&1 1>&2 2>&3 || true)
|
||||||
|
if [ -n "$custom_timeout" ]; then
|
||||||
|
if [[ "$custom_timeout" =~ ^-?[0-9]+$ ]]; then
|
||||||
|
_apply_grub_setting "$custom_timeout" menu "$custom_timeout" ""
|
||||||
|
else
|
||||||
|
_msg "Invalid Input" "Please enter a valid integer (e.g. 0, 5, -1)."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
5) return ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
rescue_boot() {
|
||||||
|
while true; do
|
||||||
|
local choice
|
||||||
|
choice=$(_menu "Boot Rescue + GRUB Configuration" \
|
||||||
|
"Select an operation${SCROLL_HINT}:" \
|
||||||
|
$TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
||||||
|
"1" "GRUB Boot Menu Settings" \
|
||||||
|
"2" "Refirm Secure Boot (shim + GRUB)" \
|
||||||
|
"3" "Regenerate initramfs (all kernels)" \
|
||||||
|
"4" "Return to main menu")
|
||||||
|
|
||||||
|
[ -z "$choice" ] && return
|
||||||
|
clear
|
||||||
|
|
||||||
|
case "$choice" in
|
||||||
|
1) _grub_menu_settings ;;
|
||||||
|
2) _rescue_boot_sb ;;
|
||||||
|
3) _rescue_initramfs ;;
|
||||||
|
4) return ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
+140
-16
@@ -1,30 +1,154 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Adds user to sudo group and optionally enables pwfeedback
|
# sudo_config.sh — User Privileges & Feedback submenu
|
||||||
|
# License GPL v3
|
||||||
|
|
||||||
config_sudo() {
|
config_sudo() {
|
||||||
echo -e "${YELLOW}Configuring sudo...${NC}"
|
echo -e "${YELLOW}User Privileges & Feedback${NC}"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
local choice
|
||||||
|
choice=$(_menu "User Privileges & Feedback" \
|
||||||
|
"Select an option:" $TUI_ALTO $TUI_ANCHO 6 \
|
||||||
|
"1" "Sudo Group Membership" \
|
||||||
|
"2" "Passwordless Sudo (maintenance commands)" \
|
||||||
|
"3" "Repair Home Directory Ownership" \
|
||||||
|
"4" "Sudo Password Feedback (asterisks)" \
|
||||||
|
"5" "Back to main menu")
|
||||||
|
|
||||||
|
[ -z "$choice" ] && return
|
||||||
|
clear
|
||||||
|
|
||||||
|
case "$choice" in
|
||||||
|
1) _check_sudo_group ;;
|
||||||
|
2) _configure_nopasswd ;;
|
||||||
|
3) _repair_home_ownership ;;
|
||||||
|
4) _toggle_pwfeedback ;;
|
||||||
|
5) return ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Option 1: Sudo Group Membership ──
|
||||||
|
_check_sudo_group() {
|
||||||
if groups "$USER" | grep -qE '\bsudo\b'; then
|
if groups "$USER" | grep -qE '\bsudo\b'; then
|
||||||
echo "User is already in the sudo group."
|
_msg "Sudo Group" "User '$USER' is already in the sudo group."
|
||||||
else
|
else
|
||||||
echo "Adding user '$USER' to sudo group..."
|
if _confirm "Sudo Group" \
|
||||||
|
"User '$USER' is NOT in the sudo group.\n\nAdd to sudo group?"; then
|
||||||
if sudo usermod -aG sudo "$USER"; then
|
if sudo usermod -aG sudo "$USER"; then
|
||||||
echo -e "${GREEN}Done. Note: you need to log out and back in for group changes to take effect.${NC}"
|
_msg "Sudo Group" \
|
||||||
|
"User added to sudo group.\n\nLog out and back in for\ngroup changes to take effect." 10 60
|
||||||
|
else
|
||||||
|
_msg "Sudo Group" "Failed to add user to sudo group." 7 60
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Option 2: Passwordless Sudo (NOPASSWD) ──
|
||||||
|
_configure_nopasswd() {
|
||||||
|
local nopasswd_file="/etc/sudoers.d/${USER}-nopasswd"
|
||||||
|
|
||||||
|
if [ -f "$nopasswd_file" ]; then
|
||||||
|
if _confirm "NOPASSWD" \
|
||||||
|
"Passwordless sudo is already configured.\n\nRemove it to restore password prompts?"; then
|
||||||
|
sudo rm -f "$nopasswd_file"
|
||||||
|
echo -e "${GREEN}Passwordless sudo removed.${NC}"
|
||||||
|
fi
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _confirm "NOPASSWD" \
|
||||||
|
"Configure passwordless sudo for maintenance commands?\n\n\
|
||||||
|
- apt / apt-get (package management)\n\
|
||||||
|
- systemctl (service management)\n\
|
||||||
|
- shutdown / reboot / halt (power commands)\n\n\
|
||||||
|
Useful for automation but reduces security." 14 70; then
|
||||||
|
local choices
|
||||||
|
choices=$(_checklist "NOPASSWD Commands" \
|
||||||
|
"Select commands to allow without password:" 12 60 3 \
|
||||||
|
"apt" "APT package management" ON \
|
||||||
|
"systemctl" "Systemd service management" ON \
|
||||||
|
"power" "Shutdown, reboot, halt" ON)
|
||||||
|
clear
|
||||||
|
|
||||||
|
[ -z "$choices" ] && { echo "No commands selected."; return; }
|
||||||
|
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
|
||||||
|
|
||||||
|
local content=""
|
||||||
|
for cmd in $cleaned; do
|
||||||
|
case $cmd in
|
||||||
|
apt)
|
||||||
|
content+="${USER} ALL=(root) NOPASSWD: /usr/bin/apt, /usr/bin/apt-get, /bin/apt, /bin/apt-get\n"
|
||||||
|
;;
|
||||||
|
systemctl)
|
||||||
|
content+="${USER} ALL=(root) NOPASSWD: /usr/bin/systemctl, /bin/systemctl\n"
|
||||||
|
;;
|
||||||
|
power)
|
||||||
|
content+="${USER} ALL=(root) NOPASSWD: /usr/sbin/shutdown, /sbin/shutdown, /usr/sbin/reboot, /sbin/reboot, /usr/sbin/halt, /sbin/halt\n"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
local content_str; content_str=$(echo -e "$content")
|
||||||
|
if _validate_sudoers "$content_str" "$nopasswd_file"; then
|
||||||
|
echo -e "${GREEN}Passwordless sudo configured for selected commands.${NC}"
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Option 3: Repair Home Directory Ownership ──
|
||||||
|
_repair_home_ownership() {
|
||||||
|
local home
|
||||||
|
home=$(eval echo "~$USER")
|
||||||
|
|
||||||
|
if [ ! -d "$home" ]; then
|
||||||
|
_msg "Home Directory" "Home directory '$home' does not exist." 8 60
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local uid uid_owner
|
||||||
|
uid=$(id -u "$USER" 2>/dev/null)
|
||||||
|
uid_owner=$(stat -c '%u' "$home" 2>/dev/null || echo "0")
|
||||||
|
|
||||||
|
if [ "$uid_owner" != "$uid" ]; then
|
||||||
|
local expected_user
|
||||||
|
expected_user=$(id -nu "$uid_owner" 2>/dev/null || echo "UID $uid_owner")
|
||||||
|
if _confirm "Home Permissions" \
|
||||||
|
"Home directory '$home' is owned by\n'$expected_user' (expected: '$USER').\n\nRepair ownership?" 12 65; then
|
||||||
|
if sudo chown -R "$USER:$USER" "$home"; then
|
||||||
|
echo -e "${GREEN}Home directory ownership repaired.${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}Failed to repair home directory ownership.${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
_msg "Home Permissions" "Home directory ownership is correct\n(owner: $USER)." 8 60
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Option 4: Sudo Password Feedback (pwfeedback) ──
|
||||||
|
_toggle_pwfeedback() {
|
||||||
|
local fb_file="/etc/sudoers.d/pwfeedback"
|
||||||
|
|
||||||
|
if [ -f "$fb_file" ]; then
|
||||||
|
if _confirm "Password Feedback" \
|
||||||
|
"Asterisks are currently ENABLED when typing sudo password.\n\nDisable them?"; then
|
||||||
|
sudo rm -f "$fb_file"
|
||||||
|
echo -e "${GREEN}Password feedback disabled.${NC}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if _confirm "Password Feedback" \
|
||||||
|
"Show asterisks when typing the sudo password?"; then
|
||||||
|
if _validate_sudoers 'Defaults pwfeedback' "$fb_file"; then
|
||||||
|
echo -e "${GREEN}Password feedback enabled.${NC}"
|
||||||
else
|
else
|
||||||
echo -e "${RED}Failed to add user to sudo group.${NC}"
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if _confirm "Sudo Password Feedback" "Show asterisks when typing the sudo password?"; then
|
|
||||||
echo 'Defaults pwfeedback' | sudo tee /etc/sudoers.d/pwfeedback > /dev/null
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo -e "${GREEN}Password feedback enabled.${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${RED}Failed to create /etc/sudoers.d/pwfeedback.${NC}"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Skipping password feedback setting."
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
+185
@@ -0,0 +1,185 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# swap.sh — Disk-based swap management (swapfile + swappiness)
|
||||||
|
# Independent of zram.sh. Uses pri=10 to coexist with ZRAM priority=100.
|
||||||
|
|
||||||
|
readonly SWAP_FILE="/swapfile"
|
||||||
|
readonly SWAP_FSTAB_TAG="# debianito-managed-swap"
|
||||||
|
readonly SWAP_PRIORITY="10"
|
||||||
|
readonly SWAP_CONF="/etc/sysctl.d/99-swappiness-debianito.conf"
|
||||||
|
readonly SWAP_LOCK="/run/lock/debianito-swap.lock"
|
||||||
|
|
||||||
|
# ── Helpers ──
|
||||||
|
|
||||||
|
_swap_valid_fstab() {
|
||||||
|
local tmp="$1"
|
||||||
|
sudo findmnt --verify --fstab "$tmp" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
_swap_safe_write_fstab() {
|
||||||
|
local line="$1"
|
||||||
|
local tmp
|
||||||
|
tmp=$(mktemp) || return 1
|
||||||
|
sudo cp /etc/fstab "$tmp"
|
||||||
|
sudo sed -i "/$SWAP_FSTAB_TAG/d" "$tmp"
|
||||||
|
[ -n "$line" ] && printf '%s\n' "$line" >> "$tmp"
|
||||||
|
if _swap_valid_fstab "$tmp"; then
|
||||||
|
sudo install -o root -g root -m 0644 "$tmp" /etc/fstab
|
||||||
|
else
|
||||||
|
local err
|
||||||
|
err=$(sudo findmnt --verify --fstab "$tmp" 2>&1 || true)
|
||||||
|
rm -f "$tmp"
|
||||||
|
_msg "fstab Error" "Validation failed — changes NOT applied.\n\n$err" 12 70
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
rm -f "$tmp"
|
||||||
|
}
|
||||||
|
|
||||||
|
_swap_recommend_gb() {
|
||||||
|
if [ -z "${RAM_GB:-}" ]; then
|
||||||
|
echo 2
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
local ram
|
||||||
|
ram=$(echo "$RAM_GB" | awk '{print int($1)}')
|
||||||
|
if [ "$ram" -ge 16 ]; then
|
||||||
|
echo 2
|
||||||
|
elif [ "$ram" -ge 8 ]; then
|
||||||
|
echo 4
|
||||||
|
else
|
||||||
|
local rec
|
||||||
|
rec=$((ram * 2))
|
||||||
|
[ "$rec" -lt 1 ] && rec=1
|
||||||
|
echo "$rec"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Menu options ──
|
||||||
|
|
||||||
|
_swap_current_status() {
|
||||||
|
local info="── Current swap ──\n"
|
||||||
|
info+="$(sudo swapon --show 2>/dev/null || echo '(none active)')\n\n"
|
||||||
|
info+="swappiness: $(cat /proc/sys/vm/swappiness)\n\n"
|
||||||
|
info+="fstab swap entries:\n"
|
||||||
|
info+="$(grep -E 'swap|SWAP' /etc/fstab 2>/dev/null || echo '(none in fstab)')"
|
||||||
|
_msg "Swap Status" "$info" 14 65
|
||||||
|
}
|
||||||
|
|
||||||
|
_swap_create_file() {
|
||||||
|
local fstype rec_gb
|
||||||
|
fstype=$(stat -f -c %T "$(dirname "$SWAP_FILE")" 2>/dev/null || echo "ext4")
|
||||||
|
rec_gb=$(_swap_recommend_gb)
|
||||||
|
|
||||||
|
local warn=""
|
||||||
|
if [ "$fstype" = "btrfs" ]; then
|
||||||
|
warn="Filesystem: Btrfs\nSwapfile on Btrfs needs extra steps (nodatacow).\nHibernation requires swap ≥ RAM and manual resume= config.\n\n"
|
||||||
|
fi
|
||||||
|
warn+="ZRAM (priority 100) is used first.\nDisk swap (priority $SWAP_PRIORITY) is only consumed after ZRAM fills."
|
||||||
|
|
||||||
|
_msg "Swapfile Info" "$warn" 14 65
|
||||||
|
|
||||||
|
local size_gb
|
||||||
|
size_gb=$(_inputbox "Swapfile Size" "Size in GB for $SWAP_FILE:" 10 60 "$rec_gb")
|
||||||
|
[ -z "$size_gb" ] && return
|
||||||
|
[[ "$size_gb" =~ ^[0-9]+$ ]] && [ "$size_gb" -gt 0 ] || {
|
||||||
|
_msg "Error" "Enter a positive integer." 8 40
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -f "$SWAP_FILE" ]; then
|
||||||
|
_confirm "Swapfile exists" "$SWAP_FILE already exists.\nRecreate it (${size_gb} GB)?" || return
|
||||||
|
sudo swapoff "$SWAP_FILE" 2>/dev/null || true
|
||||||
|
sudo rm -f "$SWAP_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Allocating ${size_gb}G swapfile...${NC}"
|
||||||
|
if [ "$fstype" = "btrfs" ]; then
|
||||||
|
sudo touch "$SWAP_FILE"
|
||||||
|
sudo chattr +C "$SWAP_FILE" 2>/dev/null || true
|
||||||
|
sudo dd if=/dev/zero of="$SWAP_FILE" bs=1M count=$((size_gb * 1024)) status=progress
|
||||||
|
else
|
||||||
|
sudo fallocate -l "${size_gb}G" "$SWAP_FILE" || \
|
||||||
|
sudo dd if=/dev/zero of="$SWAP_FILE" bs=1M count=$((size_gb * 1024)) status=progress
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo chmod 600 "$SWAP_FILE"
|
||||||
|
sudo mkswap "$SWAP_FILE" >/dev/null
|
||||||
|
sudo swapon "$SWAP_FILE"
|
||||||
|
|
||||||
|
local fstab_line
|
||||||
|
fstab_line="$SWAP_FILE none swap sw,pri=$SWAP_PRIORITY 0 0 $SWAP_FSTAB_TAG # pri=$SWAP_PRIORITY (below zram 100)"
|
||||||
|
if _swap_safe_write_fstab "$fstab_line"; then
|
||||||
|
_msg "Swapfile" "Swapfile created and added to fstab (persistent).\n\nPriority: $SWAP_PRIORITY (below ZRAM 100)." 12 65
|
||||||
|
else
|
||||||
|
sudo swapoff "$SWAP_FILE" 2>/dev/null || true
|
||||||
|
sudo rm -f "$SWAP_FILE"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_swap_remove_file() {
|
||||||
|
local has_tag
|
||||||
|
has_tag=$(grep -c "$SWAP_FSTAB_TAG" /etc/fstab 2>/dev/null || echo 0)
|
||||||
|
[ "$has_tag" -eq 0 ] && [ ! -f "$SWAP_FILE" ] && {
|
||||||
|
_msg "Swap" "No managed swapfile found." 8 50
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_confirm "Remove Swapfile" "Disable and delete $SWAP_FILE?\n\nRemoves fstab entry and deletes the file." || return
|
||||||
|
|
||||||
|
sudo swapoff "$SWAP_FILE" 2>/dev/null || true
|
||||||
|
_swap_safe_write_fstab ""
|
||||||
|
sudo rm -f "$SWAP_FILE"
|
||||||
|
_msg "Swap" "Swapfile removed and fstab entry cleaned." 8 60
|
||||||
|
}
|
||||||
|
|
||||||
|
_swap_set_swappiness() {
|
||||||
|
local cur val
|
||||||
|
cur=$(cat /proc/sys/vm/swappiness 2>/dev/null || echo 60)
|
||||||
|
val=$(_inputbox "Swappiness" "Current value: $cur\nEnter new value (0-100):" 10 60 "$cur")
|
||||||
|
[ -z "$val" ] && return
|
||||||
|
[[ "$val" =~ ^[0-9]+$ ]] && [ "$val" -le 100 ] || {
|
||||||
|
_msg "Error" "Value must be 0-100." 8 40
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
local tmp
|
||||||
|
tmp=$(mktemp) || return
|
||||||
|
printf 'vm.swappiness=%s\n' "$val" > "$tmp"
|
||||||
|
sudo install -o root -g root -m 0644 "$tmp" "$SWAP_CONF"
|
||||||
|
sudo sysctl -w "vm.swappiness=$val" >/dev/null
|
||||||
|
rm -f "$tmp"
|
||||||
|
_msg "Swappiness" "swappiness set to $val (persistent)." 8 60
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Entry point ──
|
||||||
|
|
||||||
|
manage_swap() {
|
||||||
|
exec 9>"$SWAP_LOCK"
|
||||||
|
flock -n 9 || {
|
||||||
|
_msg "Busy" "Another swap operation is already running." 8 55
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
local choice
|
||||||
|
choice=$(_menu "Swap Management" \
|
||||||
|
"Select an option:" $TUI_ALTO $TUI_ANCHO 6 \
|
||||||
|
"1" "Show current swap & swappiness" \
|
||||||
|
"2" "Create / resize swapfile" \
|
||||||
|
"3" "Remove swapfile" \
|
||||||
|
"4" "Change swappiness" \
|
||||||
|
"5" "Back to main menu")
|
||||||
|
|
||||||
|
[ -z "$choice" ] && break
|
||||||
|
clear
|
||||||
|
|
||||||
|
case "$choice" in
|
||||||
|
1) _swap_current_status ;;
|
||||||
|
2) _swap_create_file ;;
|
||||||
|
3) _swap_remove_file ;;
|
||||||
|
4) _swap_set_swappiness ;;
|
||||||
|
5) break ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
exec 9>&-
|
||||||
|
}
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
_show_sysinfo() {
|
||||||
|
local msg=""
|
||||||
|
|
||||||
|
# ── OS Block ──
|
||||||
|
msg+="OS: ${DEBIAN_VERSION} (${DEBIAN_CODENAME})\n"
|
||||||
|
msg+="Kernel: ${KERNEL_VERSION}\n"
|
||||||
|
msg+="Display: ${DISPLAY_SERVER}\n"
|
||||||
|
msg+="\n"
|
||||||
|
|
||||||
|
# ── Hardware Block ──
|
||||||
|
msg+="CPU: ${CPU_SUMMARY}\n"
|
||||||
|
msg+="RAM: ${RAM_SUMMARY}\n"
|
||||||
|
msg+="Storage: ${STORAGE_SUMMARY}\n"
|
||||||
|
msg+="\n"
|
||||||
|
|
||||||
|
# ── GPU Block ──
|
||||||
|
local found_gpu=false
|
||||||
|
if command -v lspci &>/dev/null; then
|
||||||
|
local gpu_count=0
|
||||||
|
while IFS= read -r gpu_line; do
|
||||||
|
found_gpu=true
|
||||||
|
gpu_count=$((gpu_count + 1))
|
||||||
|
local desc
|
||||||
|
desc=$(echo "$gpu_line" | sed -E 's/.*: //; s/ *\(rev.*//')
|
||||||
|
|
||||||
|
if echo "$gpu_line" | grep -qi "nvidia"; then
|
||||||
|
local nv_ver=""
|
||||||
|
nv_ver=$(nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -1)
|
||||||
|
[ -z "$nv_ver" ] && nv_ver=$(dpkg -l nvidia-driver 2>/dev/null | awk '/^ii/ {print $3}' | sed 's/-.*//')
|
||||||
|
msg+="GPU ${gpu_count}: ${desc}\n"
|
||||||
|
msg+=" Driver: ${nv_ver:+NVIDIA }${nv_ver:-not installed}\n"
|
||||||
|
else
|
||||||
|
local mesa_ver=""
|
||||||
|
mesa_ver=$(dpkg -l libgl1-mesa-dri 2>/dev/null | awk '/^ii/ {print $3; exit}' | sed 's/-.*//')
|
||||||
|
msg+="GPU ${gpu_count}: ${desc}\n"
|
||||||
|
msg+=" Driver: ${mesa_ver:+Mesa }${mesa_ver:-unknown}\n"
|
||||||
|
fi
|
||||||
|
done < <(lspci -nn | grep -E "VGA|3D" || true)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! $found_gpu; then
|
||||||
|
msg+="GPU: No GPU detected\n"
|
||||||
|
fi
|
||||||
|
msg+="\n"
|
||||||
|
|
||||||
|
# ── Network Block (PCI class + live interfaces) ──
|
||||||
|
msg+="─── Network ───\n"
|
||||||
|
|
||||||
|
# ── 1. Detect ALL Ethernet chipsets (class 0x0200) ──
|
||||||
|
declare -a pci_eth_lines=()
|
||||||
|
while IFS= read -r line; do
|
||||||
|
pci_eth_lines+=("$line")
|
||||||
|
done < <(lspci -d ::0200 2>/dev/null || true)
|
||||||
|
|
||||||
|
# ── 2. Detect ALL WiFi chipsets (class 0x0280 + vendor fallbacks) ──
|
||||||
|
declare -a pci_wifi_lines=()
|
||||||
|
while IFS= read -r line; do
|
||||||
|
pci_wifi_lines+=("$line")
|
||||||
|
done < <(lspci -d ::0280 2>/dev/null || true)
|
||||||
|
|
||||||
|
# Broadcom vendor-ID fallback (14e4) — include only if not already captured
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if echo "$line" | grep -qi '14e4:'; then
|
||||||
|
local already=false
|
||||||
|
for existing in "${pci_wifi_lines[@]}"; do
|
||||||
|
[ "$existing" = "$line" ] && already=true && break
|
||||||
|
done
|
||||||
|
! $already && pci_wifi_lines+=("$line")
|
||||||
|
fi
|
||||||
|
done < <(lspci -nn 2>/dev/null || true)
|
||||||
|
|
||||||
|
# USB WiFi fallback
|
||||||
|
local usb_wifi_lines=()
|
||||||
|
while IFS= read -r line; do
|
||||||
|
usb_wifi_lines+=("$line")
|
||||||
|
done < <(lsusb 2>/dev/null | grep -iE 'wireless|wifi|wlan|802\.11' || true)
|
||||||
|
|
||||||
|
# ── 3. Build chipset description arrays ──
|
||||||
|
local -a eth_descs=()
|
||||||
|
local -a wifi_descs=()
|
||||||
|
local line desc
|
||||||
|
|
||||||
|
for line in "${pci_eth_lines[@]}"; do
|
||||||
|
desc=$(echo "$line" | sed -E 's/^.*\]: //; s/ \[[0-9a-fA-F]{4}:[0-9a-fA-F]{4}\]//; s/ \(rev [0-9a-fA-F]+\)//')
|
||||||
|
eth_descs+=("$desc")
|
||||||
|
done
|
||||||
|
for line in "${pci_wifi_lines[@]}"; do
|
||||||
|
desc=$(echo "$line" | sed -E 's/^.*\]: //; s/ \[[0-9a-fA-F]{4}:[0-9a-fA-F]{4}\]//; s/ \(rev [0-9a-fA-F]+\)//')
|
||||||
|
wifi_descs+=("$desc")
|
||||||
|
done
|
||||||
|
for line in "${usb_wifi_lines[@]}"; do
|
||||||
|
desc=$(echo "$line" | sed 's/^.*ID //')
|
||||||
|
wifi_descs+=("$desc")
|
||||||
|
done
|
||||||
|
|
||||||
|
# ── 4. Enumerate live interfaces ──
|
||||||
|
local -a shown_eth_descs=()
|
||||||
|
local -a shown_wifi_descs=()
|
||||||
|
local has_eth=false has_wifi=false has_other=false
|
||||||
|
|
||||||
|
if ! command -v ip &>/dev/null; then
|
||||||
|
msg+="(install iproute2 for interface details)\n"
|
||||||
|
else
|
||||||
|
while IFS= read -r line; do
|
||||||
|
local iface state ip4 ssid
|
||||||
|
iface=$(echo "$line" | awk -F': ' '{print $2}' | sed 's/@.*//')
|
||||||
|
state=$(echo "$line" | awk '{print $9}')
|
||||||
|
|
||||||
|
case "$iface" in
|
||||||
|
lo|docker*|veth*|br-*|virbr*|tun*|tap*|bond*) continue ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ip4=$(ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}')
|
||||||
|
|
||||||
|
# Determine type by PCI class (most reliable)
|
||||||
|
local pci_class=""
|
||||||
|
pci_class=$(cat "/sys/class/net/${iface}/device/class" 2>/dev/null || true)
|
||||||
|
|
||||||
|
case "$pci_class" in
|
||||||
|
0x0200*)
|
||||||
|
has_eth=true
|
||||||
|
desc="${eth_descs[0]:-Unknown Ethernet chipset}"
|
||||||
|
shown_eth_descs+=("${eth_descs[0]}")
|
||||||
|
;;
|
||||||
|
0x0280*)
|
||||||
|
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)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Fallback: classify by interface name pattern
|
||||||
|
case "$iface" in
|
||||||
|
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
|
||||||
|
|
||||||
|
if [ "$state" = "UP" ]; then
|
||||||
|
msg+="${iface}: ${desc}\n ↑ ${ip4:-no IP}"
|
||||||
|
if [ "$pci_class" = "0x0280" ] || [[ "$iface" == wl* ]]; then
|
||||||
|
[ -n "${ssid:-}" ] && msg+=" \"${ssid}\""
|
||||||
|
fi
|
||||||
|
msg+="\n"
|
||||||
|
else
|
||||||
|
msg+="${iface}: ${desc}\n ↓\n"
|
||||||
|
fi
|
||||||
|
done < <(ip -o link show 2>/dev/null)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── 5. Show chipsets without an active interface ──
|
||||||
|
local chip
|
||||||
|
|
||||||
|
for chip in "${eth_descs[@]}"; do
|
||||||
|
local found=false
|
||||||
|
for shown in "${shown_eth_descs[@]}"; do
|
||||||
|
[ "$chip" = "$shown" ] && found=true && break
|
||||||
|
done
|
||||||
|
if ! $found; then
|
||||||
|
msg+="Ethernet: ${chip}\n (no active interface)\n"
|
||||||
|
shown_eth_descs+=("$chip")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for chip in "${wifi_descs[@]}"; do
|
||||||
|
local found=false
|
||||||
|
for shown in "${shown_wifi_descs[@]}"; do
|
||||||
|
[ "$chip" = "$shown" ] && found=true && break
|
||||||
|
done
|
||||||
|
if ! $found; then
|
||||||
|
msg+="WiFi: ${chip}\n (no active interface)\n"
|
||||||
|
shown_wifi_descs+=("$chip")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# ── 6. Nothing at all ──
|
||||||
|
if ! $has_eth && ! $has_wifi && ! $has_other && [ ${#eth_descs[@]} -eq 0 ] && [ ${#wifi_descs[@]} -eq 0 ]; then
|
||||||
|
if command -v ip &>/dev/null; then
|
||||||
|
msg+="No network interfaces detected\n"
|
||||||
|
else
|
||||||
|
msg+="(install iproute2 for interface details)\n"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
_msg "System Information" "$msg" 22 76
|
||||||
|
}
|
||||||
+417
-53
@@ -4,6 +4,7 @@
|
|||||||
# ------------------
|
# ------------------
|
||||||
# Global variables
|
# Global variables
|
||||||
# ------------------
|
# ------------------
|
||||||
|
readonly SCROLL_HINT=" [↑↓]"
|
||||||
CPU_SUMMARY=""
|
CPU_SUMMARY=""
|
||||||
RAM_SUMMARY=""
|
RAM_SUMMARY=""
|
||||||
GPU_TYPE=""
|
GPU_TYPE=""
|
||||||
@@ -11,8 +12,15 @@ GPU_DESC=""
|
|||||||
GPU_VERSION=""
|
GPU_VERSION=""
|
||||||
INTEL_GPU_DEVICE_ID=""
|
INTEL_GPU_DEVICE_ID=""
|
||||||
NVIDIA_GPU_DEVICE_ID=""
|
NVIDIA_GPU_DEVICE_ID=""
|
||||||
|
HAS_NVIDIA=false
|
||||||
|
HAS_AMD=false
|
||||||
|
HAS_INTEL=false
|
||||||
KERNEL_VERSION=""
|
KERNEL_VERSION=""
|
||||||
|
DISPLAY_SERVER="unknown"
|
||||||
|
STORAGE_SUMMARY=""
|
||||||
WIFI_CHIPSET=""
|
WIFI_CHIPSET=""
|
||||||
|
DESKTOP_ENV=""
|
||||||
|
AUDIO_SERVER=""
|
||||||
|
|
||||||
# --------------------------
|
# --------------------------
|
||||||
# Pre-flight checks
|
# Pre-flight checks
|
||||||
@@ -32,19 +40,56 @@ check_sudo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# --------------------------------
|
# --------------------------------
|
||||||
# Time sync before network ops
|
# Time sync detection + NTP
|
||||||
# --------------------------------
|
# --------------------------------
|
||||||
sync_system_time() {
|
check_system_time() {
|
||||||
if command -v timedatectl &> /dev/null; then
|
command -v timedatectl &>/dev/null || return
|
||||||
|
|
||||||
|
local year
|
||||||
|
year=$(date +%Y)
|
||||||
|
|
||||||
|
if [ "$year" -lt 2025 ]; then
|
||||||
|
local msg="System date/time appears to be incorrect\n"
|
||||||
|
msg+="($(date '+%Y-%m-%d %H:%M')). This will prevent Debian\n"
|
||||||
|
msg+="repositories from working properly.\n\n"
|
||||||
|
msg+="Attempt automatic NTP synchronization?\n"
|
||||||
|
msg+="(requires network access and timedatectl)"
|
||||||
|
if _confirm "System Date" "$msg"; then
|
||||||
|
sync_system_time
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Warning: System time is incorrect. Package installations may fail.${NC}"
|
||||||
|
fi
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
local ntp_active
|
local ntp_active
|
||||||
ntp_active=$(timedatectl show --property=NTP --value 2>/dev/null || echo "no")
|
ntp_active=$(timedatectl show --property=NTP --value 2>/dev/null || echo "no")
|
||||||
if [ "$ntp_active" != "yes" ]; then
|
if [ "$ntp_active" != "yes" ]; then
|
||||||
echo -e "${YELLOW}NTP not active. Attempting to enable time sync...${NC}"
|
sync_system_time
|
||||||
sudo timedatectl set-ntp true 2>/dev/null || true
|
|
||||||
sleep 2
|
|
||||||
fi
|
fi
|
||||||
elif command -v hwclock &> /dev/null && command -v ntpd &> /dev/null; then
|
}
|
||||||
sudo hwclock --hctosys 2>/dev/null || true
|
|
||||||
|
sync_system_time() {
|
||||||
|
command -v timedatectl &>/dev/null || return
|
||||||
|
|
||||||
|
if ! is_installed systemd-timesyncd; then
|
||||||
|
sudo DEBIAN_FRONTEND=noninteractive apt install -y systemd-timesyncd || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! systemctl is-enabled systemd-timesyncd &>/dev/null; then
|
||||||
|
sudo systemctl enable systemd-timesyncd || true
|
||||||
|
fi
|
||||||
|
if ! systemctl is-active systemd-timesyncd &>/dev/null; then
|
||||||
|
sudo systemctl start systemd-timesyncd || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo timedatectl set-ntp true || true
|
||||||
|
sleep 4
|
||||||
|
|
||||||
|
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.${NC}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,19 +102,19 @@ detect_debian_version() {
|
|||||||
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
|
||||||
if [ -z "$DEBIAN_CODENAME" ]; then
|
if [ -z "$DEBIAN_CODENAME" ]; then
|
||||||
echo -e "${YELLOW}Installing lsb-release...${NC}"
|
sync_system_time || true
|
||||||
sync_system_time
|
sudo apt update -qq 2>/dev/null && sudo apt install -y -qq lsb-release || true
|
||||||
sudo apt update -qq 2>/dev/null && sudo apt install -y -qq lsb-release
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if [ -z "$DEBIAN_CODENAME" ]; then
|
if [ -z "$DEBIAN_CODENAME" ]; then
|
||||||
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" ;;
|
||||||
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 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
|
||||||
@@ -93,6 +138,19 @@ get_ram_summary() {
|
|||||||
echo "$RAM_SUMMARY"
|
echo "$RAM_SUMMARY"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ----------------------------------
|
||||||
|
# Check if running backports kernel
|
||||||
|
# ----------------------------------
|
||||||
|
is_backports_kernel() {
|
||||||
|
local kver
|
||||||
|
kver=$(uname -r)
|
||||||
|
if echo "$kver" | grep -q 'bpo'; then
|
||||||
|
echo true
|
||||||
|
else
|
||||||
|
echo false
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# ----------------------------------
|
# ----------------------------------
|
||||||
# Package installed check
|
# Package installed check
|
||||||
# ----------------------------------
|
# ----------------------------------
|
||||||
@@ -100,6 +158,10 @@ is_installed() {
|
|||||||
dpkg -l "$1" 2>/dev/null | grep -q '^ii'
|
dpkg -l "$1" 2>/dev/null | grep -q '^ii'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_state() {
|
||||||
|
is_installed "$1" && echo "ON" || echo "OFF"
|
||||||
|
}
|
||||||
|
|
||||||
# ----------------------------------
|
# ----------------------------------
|
||||||
# Package version lookup
|
# Package version lookup
|
||||||
# ----------------------------------
|
# ----------------------------------
|
||||||
@@ -128,28 +190,49 @@ detect_kernel() {
|
|||||||
# GPU detection
|
# GPU detection
|
||||||
# ----------------------------------
|
# ----------------------------------
|
||||||
detect_gpu() {
|
detect_gpu() {
|
||||||
local gpu_line
|
local gpu_lines
|
||||||
gpu_line=$(lspci -nn | grep -E "VGA|3D" | head -n1) || true
|
gpu_lines=$(lspci -nn | grep -E "VGA|3D") || true
|
||||||
if [ -z "$gpu_line" ]; then
|
if [ -z "$gpu_lines" ]; then
|
||||||
GPU_TYPE="unknown"
|
GPU_TYPE="unknown"
|
||||||
GPU_DESC="No GPU detected"
|
GPU_DESC="No GPU detected"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
local has_nvidia=false has_amd=false has_intel=false
|
||||||
|
local desc_lines="" nvidia_dev_id="" intel_dev_id=""
|
||||||
|
|
||||||
GPU_DESC=$(echo "$gpu_line" | sed -E 's/.*: //; s/ *\(rev.*//')
|
while IFS= read -r line; do
|
||||||
|
local desc
|
||||||
|
desc=$(echo "$line" | sed -E 's/.*: //; s/ *\(rev.*//')
|
||||||
|
[ -n "$desc_lines" ] && desc_lines+=" + "
|
||||||
|
desc_lines+="$desc"
|
||||||
|
|
||||||
if echo "$gpu_line" | grep -qi "AMD"; then
|
if echo "$line" | grep -qi "nvidia"; then
|
||||||
GPU_TYPE="amd"
|
has_nvidia=true
|
||||||
elif echo "$gpu_line" | grep -qi "Intel"; then
|
[ -z "$nvidia_dev_id" ] && nvidia_dev_id=$(echo "$line" | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1)
|
||||||
GPU_TYPE="intel"
|
elif echo "$line" | grep -qi "amd"; then
|
||||||
INTEL_GPU_DEVICE_ID=$(echo "$gpu_line" | grep -oP '8086:\K[0-9a-fA-F]+' | head -n1)
|
has_amd=true
|
||||||
if [ -n "$INTEL_GPU_DEVICE_ID" ]; then
|
elif echo "$line" | grep -qi "intel"; then
|
||||||
INTEL_GPU_DEVICE_ID="0x${INTEL_GPU_DEVICE_ID,,}"
|
has_intel=true
|
||||||
|
[ -z "$intel_dev_id" ] && intel_dev_id=$(echo "$line" | grep -oP '8086:\K[0-9a-fA-F]+' | head -n1)
|
||||||
fi
|
fi
|
||||||
elif echo "$gpu_line" | grep -qi "NVIDIA"; then
|
done <<< "$gpu_lines"
|
||||||
|
|
||||||
|
GPU_DESC="$desc_lines"
|
||||||
|
HAS_NVIDIA=$has_nvidia
|
||||||
|
HAS_AMD=$has_amd
|
||||||
|
HAS_INTEL=$has_intel
|
||||||
|
|
||||||
|
if $has_nvidia; then
|
||||||
GPU_TYPE="nvidia"
|
GPU_TYPE="nvidia"
|
||||||
NVIDIA_GPU_DEVICE_ID=$(echo "$gpu_line" | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1)
|
[ -n "$nvidia_dev_id" ] && NVIDIA_GPU_DEVICE_ID="$nvidia_dev_id"
|
||||||
|
elif $has_amd; then
|
||||||
|
GPU_TYPE="amd"
|
||||||
|
elif $has_intel; then
|
||||||
|
GPU_TYPE="intel"
|
||||||
|
if [ -n "$intel_dev_id" ]; then
|
||||||
|
INTEL_GPU_DEVICE_ID="0x${intel_dev_id,,}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
GPU_TYPE="unknown"
|
GPU_TYPE="unknown"
|
||||||
fi
|
fi
|
||||||
@@ -185,6 +268,17 @@ WIFI_CHIPSET=""
|
|||||||
WIFI_DESC=""
|
WIFI_DESC=""
|
||||||
ETH_DESC=""
|
ETH_DESC=""
|
||||||
|
|
||||||
|
declare -a ETH_NAMES=()
|
||||||
|
declare -a ETH_DESCS=()
|
||||||
|
declare -a ETH_STATES=()
|
||||||
|
declare -a ETH_IPS=()
|
||||||
|
|
||||||
|
declare -a WIFI_NAMES=()
|
||||||
|
declare -a WIFI_DESCS=()
|
||||||
|
declare -a WIFI_STATES=()
|
||||||
|
declare -a WIFI_IPS=()
|
||||||
|
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=$(lspci -nn | grep -i 'Ethernet controller' | head -n1) || true
|
||||||
@@ -193,11 +287,147 @@ detect_network() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
local wifi_line
|
local wifi_line
|
||||||
wifi_line=$(lspci -nn | grep -i 'Network controller' | head -n1) || true
|
# 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
|
||||||
|
# Layer 2: grep by exact PCI class code 0x0280 (Network controller)
|
||||||
|
if [ -z "$wifi_line" ]; then
|
||||||
|
wifi_line=$(lspci -d ::0280 2>/dev/null | head -n1) || true
|
||||||
|
fi
|
||||||
|
# Layer 3: Broadcom vendor ID fallback (14e4)
|
||||||
|
if [ -z "$wifi_line" ]; then
|
||||||
|
wifi_line=$(lspci -nn 2>/dev/null | grep -i '14e4:' | head -n1) || true
|
||||||
|
fi
|
||||||
if [ -n "$wifi_line" ]; then
|
if [ -n "$wifi_line" ]; then
|
||||||
WIFI_CHIPSET="$wifi_line"
|
WIFI_CHIPSET="$wifi_line"
|
||||||
WIFI_DESC=$(echo "$wifi_line" | sed -E 's/^.*\]: //; s/ \[[0-9a-fA-F]{4}:[0-9a-fA-F]{4}\]//; s/ \(rev [0-9a-fA-F]+\)//')
|
WIFI_DESC=$(echo "$wifi_line" | sed -E 's/^.*\]: //; s/ \[[0-9a-fA-F]{4}:[0-9a-fA-F]{4}\]//; s/ \(rev [0-9a-fA-F]+\)//')
|
||||||
fi
|
fi
|
||||||
|
# Layer 4: USB WiFi adapter (no PCI device)
|
||||||
|
if [ -z "$wifi_line" ] && command -v lsusb &>/dev/null; then
|
||||||
|
local usb_wifi
|
||||||
|
usb_wifi=$(lsusb 2>/dev/null | grep -iE 'wireless|wifi|wlan|802\.11' | head -n1) || true
|
||||||
|
if [ -n "$usb_wifi" ]; then
|
||||||
|
WIFI_CHIPSET="$usb_wifi"
|
||||||
|
WIFI_DESC=$(echo "$usb_wifi" | sed 's/^.*ID //')
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Safeguard: if ip is not installed, skip runtime parsing ──
|
||||||
|
if ! command -v ip &>/dev/null; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local iface state ip4 ssid
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
iface=$(echo "$line" | awk -F': ' '{print $2}' | sed 's/@.*//')
|
||||||
|
state=$(echo "$line" | awk '{print $9}')
|
||||||
|
case "$iface" in
|
||||||
|
eth*|enp*|ens*|enx*|eno*)
|
||||||
|
ip4=$(ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}')
|
||||||
|
ETH_NAMES+=("$iface")
|
||||||
|
ETH_STATES+=("$state")
|
||||||
|
ETH_IPS+=("${ip4:-}")
|
||||||
|
ETH_DESCS+=("${ETH_DESC:-}")
|
||||||
|
;;
|
||||||
|
wl*|wlp*|wlo*|wlan*)
|
||||||
|
ip4=$(ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}')
|
||||||
|
ssid=""
|
||||||
|
[ "$state" = "UP" ] && ssid=$(iwgetid -r "$iface" 2>/dev/null || true)
|
||||||
|
WIFI_NAMES+=("$iface")
|
||||||
|
WIFI_STATES+=("$state")
|
||||||
|
WIFI_IPS+=("${ip4:-}")
|
||||||
|
WIFI_SSIDS+=("${ssid:-}")
|
||||||
|
WIFI_DESCS+=("${WIFI_DESC:-}")
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done < <(ip -o link show 2>/dev/null)
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------
|
||||||
|
# Display Server detection (Wayland / X11 / tty)
|
||||||
|
# ---------------------------------------
|
||||||
|
detect_displayserver() {
|
||||||
|
local st="${XDG_SESSION_TYPE:-}"
|
||||||
|
case "$st" in
|
||||||
|
wayland) DISPLAY_SERVER="Wayland" ;;
|
||||||
|
x11) DISPLAY_SERVER="X11" ;;
|
||||||
|
tty) DISPLAY_SERVER="none (tty)" ;;
|
||||||
|
*)
|
||||||
|
if [ -n "${WAYLAND_DISPLAY:-}" ]; then
|
||||||
|
DISPLAY_SERVER="Wayland"
|
||||||
|
elif [ -n "${DISPLAY:-}" ]; then
|
||||||
|
DISPLAY_SERVER="X11"
|
||||||
|
else
|
||||||
|
DISPLAY_SERVER="unknown"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------
|
||||||
|
# Storage summary via lsblk (NVMe / SSD / HDD / USB-SD)
|
||||||
|
# ---------------------------------------
|
||||||
|
detect_storage() {
|
||||||
|
local parts=()
|
||||||
|
local name size rota type rm
|
||||||
|
|
||||||
|
while read -r name size rota type; do
|
||||||
|
[ "$name" = "NAME" ] && continue
|
||||||
|
echo "$name" | grep -q "zram" && continue
|
||||||
|
[ "$type" = "loop" ] || [ "$type" = "rom" ] && continue
|
||||||
|
|
||||||
|
if echo "$name" | grep -q "nvme"; then
|
||||||
|
type="NVMe"
|
||||||
|
elif [ "$rota" = "1" ]; then
|
||||||
|
type="HDD"
|
||||||
|
else
|
||||||
|
rm=$(cat /sys/block/"$name"/removable 2>/dev/null || echo 0)
|
||||||
|
if [ "$rm" = "1" ]; then
|
||||||
|
type="USB/SD"
|
||||||
|
else
|
||||||
|
type="SSD"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
parts+=("${size} ${type}")
|
||||||
|
done < <(lsblk -d -o NAME,SIZE,ROTA,TYPE -e 7,11 2>/dev/null || true)
|
||||||
|
|
||||||
|
if [ ${#parts[@]} -eq 0 ]; then
|
||||||
|
STORAGE_SUMMARY="No disks detected"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local result=""
|
||||||
|
local p
|
||||||
|
for p in "${parts[@]}"; do
|
||||||
|
[ -n "$result" ] && result+=" + "
|
||||||
|
result+="$p"
|
||||||
|
done
|
||||||
|
STORAGE_SUMMARY="$result"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------
|
||||||
|
# Desktop environment detection
|
||||||
|
# ---------------------------------------
|
||||||
|
detect_desktop_environment() {
|
||||||
|
case "${XDG_CURRENT_DESKTOP:-}" in
|
||||||
|
*GNOME*) DESKTOP_ENV="gnome" ;;
|
||||||
|
*KDE*) DESKTOP_ENV="kde" ;;
|
||||||
|
*XFCE*) DESKTOP_ENV="xfce" ;;
|
||||||
|
*) DESKTOP_ENV="other" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------
|
||||||
|
# Audio server detection (PipeWire / PulseAudio)
|
||||||
|
# ---------------------------------------
|
||||||
|
detect_audio_server() {
|
||||||
|
if command -v pw-cli &>/dev/null && pw-cli info &>/dev/null 2>&1; then
|
||||||
|
AUDIO_SERVER="pipewire"
|
||||||
|
elif command -v pactl &>/dev/null; then
|
||||||
|
AUDIO_SERVER="pulseaudio"
|
||||||
|
else
|
||||||
|
AUDIO_SERVER="none"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ---------------------------------------
|
# ---------------------------------------
|
||||||
@@ -223,24 +453,26 @@ get_intel_generation() {
|
|||||||
# Check if backports repository is enabled (active line without #)
|
# Check if backports repository is enabled (active line without #)
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
is_backports_enabled() {
|
is_backports_enabled() {
|
||||||
# Check classic sources.list
|
local codename="${DEBIAN_CODENAME:-}"
|
||||||
if [ -f /etc/apt/sources.list ]; then
|
[ -z "$codename" ] && { echo false; return; }
|
||||||
if grep -Eq '^[^#]*[ \t]+bookworm-backports[ \t]+' /etc/apt/sources.list 2>/dev/null; then
|
|
||||||
echo true
|
local c_pattern="^[^#]*${codename}-backports[[:space:]]+"
|
||||||
return
|
local d_pattern="Suites:.*${codename}-backports"
|
||||||
fi
|
|
||||||
if grep -Eq '^[^#]*[ \t]+trixie-backports[ \t]+' /etc/apt/sources.list 2>/dev/null; then
|
# Classic embedded (sources.list)
|
||||||
echo true
|
if [ -f /etc/apt/sources.list ] && grep -Eq "$c_pattern" /etc/apt/sources.list 2>/dev/null; then
|
||||||
return
|
echo true; return
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check deb822 .sources files
|
# Classic standalone (new — debian-backports.list)
|
||||||
if [ -d /etc/apt/sources.list.d ]; then
|
if [ -f /etc/apt/sources.list.d/debian-backports.list ] && \
|
||||||
if grep -qr 'Suites:.*-backports' /etc/apt/sources.list.d/*.sources 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
|
||||||
|
if grep -qr "$d_pattern" /etc/apt/sources.list.d/*.sources 2>/dev/null; then
|
||||||
|
echo true; return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo false
|
echo false
|
||||||
@@ -249,6 +481,7 @@ is_backports_enabled() {
|
|||||||
|
|
||||||
install_backports_or_stable() {
|
install_backports_or_stable() {
|
||||||
local pkg="$1"
|
local pkg="$1"
|
||||||
|
local pkg_desc="${2:-$pkg}"
|
||||||
|
|
||||||
local bpo_ver=""
|
local bpo_ver=""
|
||||||
if [ "$(is_backports_enabled)" == true ]; then
|
if [ "$(is_backports_enabled)" == true ]; then
|
||||||
@@ -275,19 +508,18 @@ install_backports_or_stable() {
|
|||||||
if [ -n "$bpo_ver" ]; then
|
if [ -n "$bpo_ver" ]; then
|
||||||
local stable_ver
|
local stable_ver
|
||||||
stable_ver=$(apt-cache policy "$pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
stable_ver=$(apt-cache policy "$pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
if _confirm_custom "${pkg}" "Install from backports?\n\nBackports: ${bpo_ver}\nStable: ${stable_ver:-N/A}" "Backports" "Stable"; then
|
if _confirm_custom "${pkg}" "Install ${pkg_desc}?\n\n Backports: ${bpo_ver} (newer, recommended for gaming/newer HW)\n Stable: ${stable_ver:-N/A}\n\nChoose version:" "Backports" "Stable"; then
|
||||||
_run_cmd "Backports" \
|
_run_cmd "Backports" \
|
||||||
"sudo DEBIAN_FRONTEND=noninteractive apt install -y -t ${DEBIAN_CODENAME}-backports $pkg" \
|
"sudo DEBIAN_FRONTEND=noninteractive apt install -y -t ${DEBIAN_CODENAME}-backports $pkg" \
|
||||||
"Installing $pkg from backports..."
|
"Installing $pkg from backports..."
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
# User chose "Stable" — install stable directly, no re-prompt
|
|
||||||
_run_cmd "APT" "sudo DEBIAN_FRONTEND=noninteractive apt install -y $pkg" "Installing $pkg from stable..."
|
_run_cmd "APT" "sudo DEBIAN_FRONTEND=noninteractive apt install -y $pkg" "Installing $pkg from stable..."
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
local stable_ver
|
local stable_ver
|
||||||
stable_ver=$(apt-cache policy "$pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
stable_ver=$(apt-cache policy "$pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
if _confirm "Install: ${pkg}" "Install ${pkg} ${stable_ver:-} from stable?"; then
|
if _confirm "Install: ${pkg}" "Install ${pkg} ${stable_ver:-}?"; then
|
||||||
_run_cmd "APT" "sudo DEBIAN_FRONTEND=noninteractive apt install -y $pkg" "Installing $pkg..."
|
_run_cmd "APT" "sudo DEBIAN_FRONTEND=noninteractive apt install -y $pkg" "Installing $pkg..."
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -297,28 +529,70 @@ install_backports_or_stable() {
|
|||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
_confirm() {
|
_confirm() {
|
||||||
whiptail --title "$1" --yes-button "Execute" --no-button "Skip" \
|
whiptail --title "$1" --yes-button "Yes" --no-button "No" \
|
||||||
--yesno "$2" "${3:-10}" "${4:-65}"
|
--yesno "$2" "${3:-10}" "${4:-65}"
|
||||||
}
|
}
|
||||||
|
|
||||||
_confirm_custom() {
|
_confirm_custom() {
|
||||||
local title="$1" text="$2" yes_btn="$3" no_btn="$4"
|
local title="$1" text="$2" yes_btn="$3" no_btn="$4"
|
||||||
shift 4
|
shift 4
|
||||||
|
local height="${1:-20}"
|
||||||
|
local width="${2:-78}"
|
||||||
whiptail --title "$title" --yes-button "$yes_btn" --no-button "$no_btn" \
|
whiptail --title "$title" --yes-button "$yes_btn" --no-button "$no_btn" \
|
||||||
--yesno "$text" "${@:-10 65}"
|
--yesno "$text" "$height" "$width"
|
||||||
}
|
}
|
||||||
|
|
||||||
_msg() {
|
_msg() {
|
||||||
whiptail --title "$1" --msgbox "$2" "${3:-10}" "${4:-65}"
|
whiptail --title "$1" --msgbox "$2" "${3:-10}" "${4:-65}" || true
|
||||||
}
|
}
|
||||||
|
|
||||||
# Blocks 2-4: clear → run → pause
|
_msg_red() {
|
||||||
|
whiptail --colors --title "\Z1$1\Zn" --msgbox "\Z1$2\Zn" "${3:-12}" "${4:-70}" || true
|
||||||
|
}
|
||||||
|
|
||||||
|
_menu() {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
_checklist() {
|
||||||
|
local title="$1" text="$2" h="$3" w="$4" lh="$5"; shift 5
|
||||||
|
whiptail --title "$title" --checklist "$text" "$h" "$w" "$lh" "$@" 3>&1 1>&2 2>&3 || true
|
||||||
|
}
|
||||||
|
|
||||||
|
_inputbox() {
|
||||||
|
whiptail --title "$1" --inputbox "$2" "${3:-10}" "${4:-60}" "${5:-}" 3>&1 1>&2 2>&3 || true
|
||||||
|
}
|
||||||
|
|
||||||
|
_validate_sudoers() {
|
||||||
|
local content="$1" dest="$2"
|
||||||
|
local tmpfile
|
||||||
|
tmpfile=$(mktemp) || return 1
|
||||||
|
echo "$content" > "$tmpfile"
|
||||||
|
if ! /usr/sbin/visudo -cf "$tmpfile" &>/dev/null; then
|
||||||
|
local err
|
||||||
|
err=$(/usr/sbin/visudo -cf "$tmpfile" 2>&1 || true)
|
||||||
|
rm -f "$tmpfile"
|
||||||
|
_msg "Sudoers Error" "Invalid sudoers syntax in:\n\n${err}\n\nFile was NOT written.\nThis prevents broken sudo access." 12 70
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
sudo cp "$tmpfile" "$dest"
|
||||||
|
sudo chmod 0440 "$dest"
|
||||||
|
rm -f "$tmpfile"
|
||||||
|
}
|
||||||
|
|
||||||
|
_pause() {
|
||||||
|
local msg="${1:-Press Enter to continue...}"
|
||||||
|
echo -e "$msg"
|
||||||
|
read -r || true
|
||||||
|
}
|
||||||
|
|
||||||
|
# Blocks 2-4: run → pause
|
||||||
_run_cmd() {
|
_run_cmd() {
|
||||||
local title="$1" command="$2" success_msg="${3:-Running...}"
|
local title="$1" command="$2" success_msg="${3:-Running...}"
|
||||||
clear
|
|
||||||
echo -e "${GREEN}[+]${NC} $success_msg"
|
echo -e "${GREEN}[+]${NC} $success_msg"
|
||||||
echo "──────────────────────────────────────────────"
|
echo "──────────────────────────────────────────────"
|
||||||
eval "$command"
|
bash -c "$command"
|
||||||
local rc=$?
|
local rc=$?
|
||||||
echo "──────────────────────────────────────────────"
|
echo "──────────────────────────────────────────────"
|
||||||
if [ $rc -eq 0 ]; then
|
if [ $rc -eq 0 ]; then
|
||||||
@@ -326,11 +600,10 @@ _run_cmd() {
|
|||||||
else
|
else
|
||||||
echo -e "${RED}[-]${NC} Failed (exit code: $rc)."
|
echo -e "${RED}[-]${NC} Failed (exit code: $rc)."
|
||||||
fi
|
fi
|
||||||
echo "Press [ENTER] to continue..."
|
_pause
|
||||||
read -r
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Blocks 1-4: confirm → clear → run → pause
|
# Blocks 1-4: confirm → run → pause
|
||||||
_run() {
|
_run() {
|
||||||
if _confirm "$1" "$2"; then
|
if _confirm "$1" "$2"; then
|
||||||
_run_cmd "$1" "$3" "$4"
|
_run_cmd "$1" "$3" "$4"
|
||||||
@@ -365,6 +638,16 @@ _run_install_batch() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_run_install_pkg() {
|
||||||
|
local pkg="$1"
|
||||||
|
local ver
|
||||||
|
ver=$(apt-cache policy "$pkg" 2>/dev/null | awk 'NR==3 {print $2; exit}')
|
||||||
|
[ -z "$ver" ] && ver="(unknown)"
|
||||||
|
if _confirm "Install: ${pkg}" "Package: ${pkg}\nVersion: ${ver}\n\nProceed with installation?"; then
|
||||||
|
_run_cmd "Install" "sudo DEBIAN_FRONTEND=noninteractive apt install -y $pkg" "Installing $pkg..."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
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 | \
|
||||||
@@ -375,3 +658,84 @@ get_backports_kernel_version() {
|
|||||||
echo "unknown"
|
echo "unknown"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ----------------------------------
|
||||||
|
# Language helpers
|
||||||
|
# ----------------------------------
|
||||||
|
_detect_lang() {
|
||||||
|
local sys_lang
|
||||||
|
sys_lang=$(echo "${LANG:-en}" | cut -c1-2 | tr '[:upper:]' '[:lower:]')
|
||||||
|
echo "$sys_lang"
|
||||||
|
}
|
||||||
|
|
||||||
|
_detect_lang_pkg() {
|
||||||
|
local base="$1"
|
||||||
|
local lang2
|
||||||
|
lang2=$(_detect_lang)
|
||||||
|
|
||||||
|
[ "$lang2" = "en" ] && echo "" && return
|
||||||
|
|
||||||
|
local full="${LANG%%.*}"
|
||||||
|
local hyphenated_full
|
||||||
|
hyphenated_full=$(echo "$full" | tr '[:upper:]' '[:lower:]' | tr '_' '-')
|
||||||
|
local pkg
|
||||||
|
|
||||||
|
pkg=$(apt-cache search "^${base}-${hyphenated_full}$" 2>/dev/null | awk 'NR==1{print $1}')
|
||||||
|
[ -z "$pkg" ] && pkg=$(apt-cache search "^${base}-${lang2}$" 2>/dev/null | awk 'NR==1{print $1}')
|
||||||
|
[ -z "$pkg" ] && pkg=$(apt-cache search "^${base}-all$" 2>/dev/null | awk 'NR==1{print $1}')
|
||||||
|
|
||||||
|
echo "$pkg"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ----------------------------------
|
||||||
|
# Network connectivity check
|
||||||
|
# ----------------------------------
|
||||||
|
_check_network() {
|
||||||
|
local target="${1:-deb.debian.org}"
|
||||||
|
|
||||||
|
if command -v ping &>/dev/null; then
|
||||||
|
ping -c 1 -W 3 "$target" &>/dev/null && return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v wget &>/dev/null; then
|
||||||
|
wget -q --timeout=5 --spider "http://${target}" &>/dev/null && return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v curl &>/dev/null; then
|
||||||
|
curl -s --connect-timeout 5 -o /dev/null "http://${target}" &>/dev/null && return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# ----------------------------------
|
||||||
|
# LightDM configuration
|
||||||
|
# ----------------------------------
|
||||||
|
_configure_lightdm() {
|
||||||
|
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 ! is_installed lightdm-gtk-greeter-settings; then
|
||||||
|
echo -e "${YELLOW}Installing lightdm-gtk-greeter-settings...${NC}"
|
||||||
|
sudo DEBIAN_FRONTEND=noninteractive apt install -y lightdm-gtk-greeter-settings
|
||||||
|
fi
|
||||||
|
|
||||||
|
local conf_dir="/etc/lightdm/lightdm.conf.d"
|
||||||
|
local conf_file="${conf_dir}/99-show-users.conf"
|
||||||
|
|
||||||
|
if [ -f "$conf_file" ] && grep -q '^greeter-hide-users=false' "$conf_file"; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo mkdir -p "$conf_dir"
|
||||||
|
printf '[Seat:*]\ngreeter-hide-users=false\n' | sudo tee "$conf_file" > /dev/null
|
||||||
|
echo -e "${GREEN}LightDM configured to show user list.${NC}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Lazy system state refresh ──
|
||||||
|
refresh_system_state() {
|
||||||
|
detect_debian_version
|
||||||
|
detect_gpu
|
||||||
|
detect_cpu_ram
|
||||||
|
}
|
||||||
|
|||||||
+9
-16
@@ -9,21 +9,14 @@ install_zram() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local half_ram_mb=$((RAM_KB / 2 / 1024))
|
local half_ram_mb=$(( ((RAM_KB / 1024 / 1024 + 1) / 2) * 1024 ))
|
||||||
|
|
||||||
local algo
|
local algo
|
||||||
algo=$(whiptail --title "ZRAM Compression" --menu \
|
algo=$(_menu "ZRAM Configuration" \
|
||||||
"ZRAM compresses a portion of RAM into compressed swap,\
|
"ZRAM creates a compressed block device in RAM to use as swap. This reduces disk I/O and can significantly improve responsiveness on systems with limited memory (e.g., 4GB RAM or less), at the cost of a small amount of CPU usage." \
|
||||||
effectively increasing available memory.
|
|
||||||
|
|
||||||
Useful for systems with limited RAM or when you need
|
|
||||||
more swap space without disk writes.
|
|
||||||
|
|
||||||
Choose compression algorithm:" \
|
|
||||||
$TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
$TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
|
||||||
"lz4" "Fastest, low CPU (recommended)" \
|
"lz4" "Fastest compression/decompression. Lowest CPU overhead. (Default)" \
|
||||||
"zstd" "Better ratio, more CPU" \
|
"zstd" "Higher compression ratio. Saves slightly more memory but uses more CPU.")
|
||||||
3>&1 1>&2 2>&3)
|
|
||||||
|
|
||||||
if [ -z "$algo" ]; then
|
if [ -z "$algo" ]; then
|
||||||
echo "ZRAM configuration cancelled."
|
echo "ZRAM configuration cancelled."
|
||||||
@@ -31,12 +24,11 @@ Choose compression algorithm:" \
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
local zram_size
|
local zram_size
|
||||||
if _confirm "ZRAM Size" "Use 50% of RAM for ZRAM? (${half_ram_mb} MB out of ${RAM_SUMMARY})"; then
|
if _confirm "ZRAM Size" "Use recommended size for ZRAM? (${half_ram_mb} MB out of ${RAM_SUMMARY})"; then
|
||||||
zram_size=$half_ram_mb
|
zram_size=$half_ram_mb
|
||||||
else
|
else
|
||||||
zram_size=$(whiptail --title "ZRAM Size" --inputbox \
|
zram_size=$(_inputbox "ZRAM Size" "Enter ZRAM size in MB:" 8 60 "$half_ram_mb")
|
||||||
"Enter ZRAM size in MB:" 8 60 "$half_ram_mb" 3>&1 1>&2 2>&3)
|
if [ -z "$zram_size" ] || ! [[ "$zram_size" =~ ^[0-9]+$ ]] || [ "$zram_size" -eq 0 ]; then
|
||||||
if [ -z "$zram_size" ] || ! [[ "$zram_size" =~ ^[0-9]+$ ]]; then
|
|
||||||
echo "ZRAM configuration cancelled."
|
echo "ZRAM configuration cancelled."
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -65,4 +57,5 @@ EOF
|
|||||||
sudo zramctl
|
sudo zramctl
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${GREEN}You can verify with: sudo zramctl${NC}"
|
echo -e "${GREEN}You can verify with: sudo zramctl${NC}"
|
||||||
|
_pause
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user