diff --git a/README.md b/README.md index d226832..0c9e467 100644 --- a/README.md +++ b/README.md @@ -47,34 +47,54 @@ After running the script: | Option | Description | What it does | |--------|-------------|--------------| -| **1** | System Info | Show detected Os, CPU, RAM, GPU and others | -| **2** | User Privileges & Feedback | Add user to sudo group, enable `pwfeedback` for password visibility | +| **1** | System Info | Show detected OS, CPU, RAM, GPU and hardware details | +| **2** | [User Privileges & Feedback](#user-privileges--feedback) | 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)| | **4** | Setup Wireless & Firmware | Install WiFi firmware for Broadcom, Intel, and other chipsets| | **5** | Configure Graphics Stack | AMD/Intel/NVIDIA drivers + monitoring tools | | **6** | Update Kernel to Backports | Install latest stable kernel from Debian backports| -| **7** | Gaming Setup and Performance | Steam, Heroic Games Launcher, GameMode, MangoHud and others| +| **7** | Gaming Setup and Performance | Steam, Heroic Games Launcher, GameMode, MangoHud, Java JRE (Temurin 8/17/21) | | **8** | Install ZRAM (compressed swap) | Configure compressed RAM for memory optimization| | **9** | Install Programs and Software | Selection across 10 categories (Dev, Themes, System, etc.) | | **10** | Exit | Return to terminal | ### Extra Applications Categories (Option 9) -The submenu offers 11 categories: +The submenu offers the next categories: -| Option | Category | Description | -|--------|----------|-------------| -| **0** | Essential Pack | Quick install of common tools (compression, system info, VLC, MS fonts) | -| **1** | Customization System | Desktop themes, icon themes, cursor themes, and fonts| -| **2** | Download & Network | Downloaders (aria2, ytdlp, FileZilla) + Torrent clients (qBittorrent, Deluge, Transmission)| -| **3** | Internet | Browsers (Firefox/Mozilla, LibreWolf, Floorp, Chromium), email clients, VPN tools| -| **4** | Media Players | VLC and MPV| -| **5** | Multimedia & Design | GIMP, Kdenlive, Blender, OBS Studio, Audacity, Inkscape and HandBrake| -| **6** | Programming Applications | Development tools (Docker, Nginx/Apache, PostgreSQL/MariaDB, SSH, fail2ban, Python)| -| **7** | Security & Networking | Additional security and networking utilities | -| **8** | System Tools | htop, btop, ncdu, timeshift, tmux, flatpak, extrepo and virtualization tools| -| **9** | Fetch / System Info | Fastfetch/Neofetch, hyfetch, Linux logo and Screenfetch | -| **10** | Back to main menu | Return to the main script menu | +| Option | Category Title | Description | +|--------|-------------------------------|-------------| +| **0** | Essential Pack | Quick install of common tools (compression, system info, VLC, MS fonts)| +| **1** | Customization System | Desktop themes, icon themes, cursor themes, and fonts | +| **2** | Download & Network | Downloaders (aria2, ytdlp, FileZilla) + Torrent clients (qBittorrent, Deluge, Transmission) | +| **3** | Internet (Browsers, Email Clients, VPN Tools) | Web browsers (Firefox/Mozilla, LibreWolf, Floorp, Chromium, Brave, Tor), email clients (Thunderbird), and VPN tools including Riseup | +| **4** | Media Players | Multimedia playback with VLC media player and MPV for advanced video/audio support | +| **5** | Multimedia & Design | image editing (GIMP), video editing (Kdenlive, HandBrake), 3D modeling (Blender), audio recording (Audacity), and graphics design (Inkscape) | +| **6** | Code Editors & IDEs | vim, vim-gtk3, Neovim, Helix, nano, Emacs, Kate, Mousepad, Gedit, Geany, GNOME Text Editor, and VSCodium (VS Code open-source) | +| **7** | Servers & Dev Tools | Web servers (Nginx/Apache), databases (PostgreSQL/MariaDB), Java Development Kit (Temurin 17/21/25 JDK), Docker, Python, SSH tools, fail2ban, and essential utilities | +| **8** | Security & Networking | Wireshark, tcpdump, Zenmap, ClamAV, UFW, Fail2ban | +| **9** | System Tools | htop/btop, ncdu, Timeshift, tmux/screen, Flatpak support, extension repository manager, and qemu/virtmanager | +| **10** | Fetch / System Info | fastfetch/neofetch, hyfetch, Linux logo and screenfetch | +| **11** | Back to Main Menu | Return directly to the main Debianito menu (exit submenu) | + +--- + +## User Privileges & Feedback + +Admin rights, passwordless commands, and file ownership fixes—optimized for Debian users. + +### 1. Sudo Group Membership +If you just installed Debian and can’t install software or change system settings (you get "Permission denied"), this option adds your user to the sudo group. This gives you admin privileges so you can manage your system. Changes take effect after you log out and back in. + +### 2. Passwordless Sudo for Frequent Tasks +Every time you run sudo apt install or sudo reboot, Linux asks for your password. This option lets you skip typing your password for common commands like installing/updating software (apt), restarting or shutting down (systemctl). +- ⚠️ Security Note: While convenient, this reduces security if someone else uses your PC physically. + +### 3. Repair Home Directory Ownership +Sometimes, when you use sudo incorrectly (e.g., installing games or apps), files get "stolen" by the system (root) instead of your user. This causes apps to fail (e.g., saving settings or game progress). This option fixes ownership so all your files and folders belong to you again. + +### 4. Sudo Password Feedback (Asterisks) +By default, Debian’s terminal hides your password (no asterisks or feedback). This option adds visual feedback (e.g., ****) so you can see how many characters you’ve typed. Toggle it on/off as needed. --- @@ -87,52 +107,67 @@ The submenu offers 11 categories: | `/modules/extras/` | Split-by-category sub-modules for the "Install Programs and Software" menu (Option 9). | ```bash -├── debianito.sh # Main entry point; TUI menu + system detection -├── modules/ -│ ├── utils.sh # System info helpers: CPU/RAM/GPU/WiFi detection, Debian version check ([`detect_debian_version()`](utils.sh#L79)) -│ ├── sudo_config.sh # User group + pwfeedback setup -│ ├── repos.sh # Repository configuration (deb822/classic format) with backup/restore -│ ├── firmware.sh # WiFi microcode and chipset-specific support via [`firmware-linux-nonfree`](modules/firmware.sh) -│ ├── gpu.sh # AMD/Intel/NVIDIA driver handling ([`detect_gpu()`](utils.sh#L168)); NVIDIA Kepler/Turing detection veto (line 203+) -│ ├── kernel.sh # Update Kernel to Backports with NVIDIA compatibility warnings -│ ├── gaming.sh # Steam, GameMode, MangoHud, Heroic Games Launcher -│ ├── zram.sh # ZRAM compressed swap configuration -│ ├── gpu/ # NVIDIA-specific modules for Debian 12+ (Bookworm/Trixie) -│ │ ├── _helpers.sh # Shared helpers including [`is_nvidia_kepler()`](gpu/_helpers.sh#LXX) with four isolated blocks for legacy detection -│ │ └── nvidia.sh # NVIDIA driver installation ([`_install_nvidia_bookworm_kepler()`](gpu/nvidia.sh#LXX)) -│ ├── bullseye/ # Legacy support modules for Debian 11 (Bullseye) with ultra-minimalist rescue environment -│ │ ├── legacy.sh # Fermi GPU detection (NVIDIA-390xx drivers), [install_gaming_bullseye](bullseye/legacy.sh#LXX) function -│ │ ├── repos.sh # Classic `/etc/apt/sources.list` format with Archive Phase 2026 configuration -│ │ └── extras.sh # Utilities installation with purged package list for unavailable packages on Debian 11 -│ └── extras/ # Category modules organized by function (Option 9 submenu) -│ ├── _helpers.sh # Shared helpers: [`_inst()`](utils.sh#L418), [`_state()`] for package management -│ ├── essential/ # Essential Pack (compression, system info, VLC, MS fonts) -│ │ └── essential.sh # One-click essentials installation -│ ├── system/ # System Tools (htop, btop, ncdu, timeshift, tmux, flatpak, extrepo, virtualization tools) -│ │ └── system.sh # 25+ system utility packages -│ ├── dev/ # Development & Servers (Docker, Nginx/Apache, PostgreSQL/MariaDB, SSH, fail2ban, Python) -│ │ └── dev.sh # 15 development/server tools -│ ├── players/ # Media Players (VLC, MPV) -│ │ └── players.sh # Video player packages -│ ├── internet/ # Internet: Firefox (Mozilla), LibreWolf, Floorp, Chromium, Thunderbird, Riseup VPN, Tor Browser -│ │ └── internet.sh # Browsers, email clients, VPN tools -│ ├── themes/ # Customization submenu with 4 options -│ │ ├── themes.sh # Submenu dispatcher for customization categories -│ │ ├── desktop-themes/ # Desktop Themes (GTK/KDE): Arc, Numix, Breeze GTK, Bluebird, Blackbird, Greybird, Orchis -│ │ │ └── desktop-themes.sh -│ │ ├── icons/ # Icon Themes: Papirus, Numix, Elementary, Deepin, Suru, Obsidian, Breeze, Moka -│ │ │ └── icons.sh # 11-12 icon theme packages -│ │ ├── cursors/ # Cursor Themes: Bibata, Breeze, Chameleon, DMZ, XCursor, Oxygen -│ │ │ └── cursors.sh # 6 cursor theme packages -│ │ └── fonts/ # Fonts: Bebas Neue, Anonymous Pro, ADF Verana, 3270, Liberation, MS Core, Ubuntu, Recommended -│ │ └── fonts.sh # 8 font packages including MS Core fonts -│ ├── fetch/ # Fetch Tools (Neofetch/Fastfetch, hyfetch, Linux logo, Screenfetch) -│ │ └── fetch.sh # System info display tools -│ ├── download/ # Downloaders & Torrent Clients: aria2, ytdlp, FileZilla, qBittorrent, Deluge, Transmission, mktorrent -│ │ └── download.sh # Download manager + torrent client packages -│ └── design/ # Multimedia & Design (GIMP, Kdenlive, Blender, OBS Studio, Audacity, Inkscape, HandBrake) -│ └── design.sh # 12+ creative applications +├── debianito.sh +├── modules +│   ├── bullseye +│   │   ├── extras.sh +│   │   ├── legacy.sh +│   │   └── repos.sh +│   ├── extras +│   │   ├── design +│   │   │   └── design.sh +│   │   ├── dev +│   │   │   └── dev.sh +│   │   ├── download +│   │   │   └── download.sh +│   │   ├── essential +│   │   │   └── essential.sh +│   │   ├── fetch +│   │   │   └── fetch.sh +│   │   ├── _helpers.sh +│   │   ├── internet +│   │   │   └── internet.sh +│   │   ├── java.sh +│   │   ├── players +│   │   │   └── players.sh +│   │   ├── programming +│   │   │   └── programming.sh +│   │   ├── security +│   │   │   └── security.sh +│   │   ├── system +│   │   │   └── 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.sh +│   ├── sudo_config.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. diff --git a/debianito.sh b/debianito.sh index 46ae55b..2ee7ce2 100644 --- a/debianito.sh +++ b/debianito.sh @@ -17,6 +17,7 @@ MODULES_DIR="${SCRIPT_DIR}/modules" source "${MODULES_DIR}/utils.sh" source "${MODULES_DIR}/sudo_config.sh" +source "${MODULES_DIR}/repos/repo_detect.sh" source "${MODULES_DIR}/repos.sh" [ -f "${MODULES_DIR}/firmware.sh" ] && source "${MODULES_DIR}/firmware.sh" [ -f "${MODULES_DIR}/gpu.sh" ] && source "${MODULES_DIR}/gpu.sh" @@ -24,6 +25,7 @@ source "${MODULES_DIR}/repos.sh" [ -f "${MODULES_DIR}/gaming.sh" ] && source "${MODULES_DIR}/gaming.sh" [ -f "${MODULES_DIR}/extras.sh" ] && source "${MODULES_DIR}/extras.sh" [ -f "${MODULES_DIR}/zram.sh" ] && source "${MODULES_DIR}/zram.sh" +[ -f "${MODULES_DIR}/extras/java.sh" ] && source "${MODULES_DIR}/extras/java.sh" # ── Bullseye-specific modules (loaded only on Debian 11) ── if [ -d "${MODULES_DIR}/bullseye" ]; then diff --git a/modules/bullseye/extras.sh b/modules/bullseye/extras.sh index 10c27d1..9691d4a 100644 --- a/modules/bullseye/extras.sh +++ b/modules/bullseye/extras.sh @@ -49,43 +49,34 @@ Instalar?"; then # ====================================================================== _cat_customization_bullseye() { - local items=() - if [ -f "${MODULES_DIR}/extras/themes/icons/icons.sh" ]; then - local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6)) - local sub - sub=$(whiptail --title "Customization (Bullseye)" --menu \ - "Select type:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \ - "1" "Desktop Themes (GTK/KDE)" \ - "2" "Icon Themes" \ - "3" "Cursor Themes" \ - "4" "Fonts" \ - 3>&1 1>&2 2>&3) - [ -z "$sub" ] && return - case $sub in - 1) _cat_themes_bullseye ;; - 2) _cat_icons_bullseye ;; - 3) _cat_cursors_bullseye ;; - 4) _cat_fonts_bullseye ;; - esac - else - _msg "Customization" "Themes submodules not found." 8 50 - fi + local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6)) + local sub + sub=$(whiptail --title "Customization (Bullseye)" --menu \ + "Select type:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \ + "1" "Desktop Themes (GTK/KDE)" \ + "2" "Icon Themes" \ + "3" "Cursor Themes" \ + "4" "Fonts" \ + 3>&1 1>&2 2>&3) + [ -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 theme_state; theme_state=$(_state "breeze") - local numix_state; numix_state=$(_state "numix-gtk-theme") - - if [ "$theme_state" = "OFF" ] && [ "$numix_state" = "OFF" ]; then - theme_state="ON" - fi - local choices choices=$(whiptail --title "Desktop Themes (Bullseye)" --checklist \ - "Available themes in Bullseye repos ($TUI_ALTO linea):" \ - $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ - "breeze" "Breeze GTK theme (KDE)$(_inst breeze)" "$theme_state" \ - "numix-gtk-theme" "Numix GTK theme$(_inst numix-gtk-theme)" "$numix_state" \ + "Select desktop themes:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ + "arc-theme" "Arc GTK theme$(_inst arc-theme)" "$(_state arc-theme)" \ + "blackbird-gtk-theme" "Blackbird GTK theme$(_inst blackbird-gtk-theme)" "$(_state blackbird-gtk-theme)" \ + "bluebird-gtk-theme" "Bluebird GTK theme$(_inst bluebird-gtk-theme)" "$(_state bluebird-gtk-theme)" \ + "breeze-gtk-theme" "Breeze GTK theme (KDE port)$(_inst breeze-gtk-theme)" "$(_state breeze-gtk-theme)" \ + "greybird-gtk-theme" "Greybird GTK theme$(_inst greybird-gtk-theme)" "$(_state greybird-gtk-theme)" \ + "numix-gtk-theme" "Numix GTK theme$(_inst numix-gtk-theme)" "$(_state numix-gtk-theme)" \ 3>&1 1>&2 2>&3) clear [ -z "$choices" ] && return @@ -97,19 +88,21 @@ _cat_themes_bullseye() { } _cat_icons_bullseye() { - _msg "Icon Themes (Bullseye)" \ - "Adwaita, Humanity, DMZ y otros temas de iconos\n\ -están disponibles desde los repos oficiales.\n\n\ -Seleccione desde el menú de GNOME/KDE o instale\n\ -el paquete 'gnome-icon-theme' o 'breeze-icon-theme'." 12 60 - + local items=( + "breeze-icon-theme" "Breeze icon theme$(_inst breeze-icon-theme)" "$(_state breeze-icon-theme)" + "deepin-icon-theme" "Deepin icon theme$(_inst deepin-icon-theme)" "$(_state deepin-icon-theme)" + "moka-icon-theme" "Moka icon theme$(_inst moka-icon-theme)" "$(_state moka-icon-theme)" + "numix-icon-theme" "Numix icon theme$(_inst numix-icon-theme)" "$(_state numix-icon-theme)" + "numix-icon-theme-circle" "Numix Circle icon theme$(_inst numix-icon-theme-circle)" "$(_state numix-icon-theme-circle)" + "obsidian-icon-theme" "Obsidian icon theme$(_inst obsidian-icon-theme)" "$(_state obsidian-icon-theme)" + "papirus-icon-theme" "Papirus icon theme$(_inst papirus-icon-theme)" "$(_state papirus-icon-theme)" + "paper-icon-theme" "Paper icon theme$(_inst paper-icon-theme)" "$(_state paper-icon-theme)" + "suru-icon-theme" "Suru icon theme$(_inst suru-icon-theme)" "$(_state suru-icon-theme)" + ) local choices choices=$(whiptail --title "Icon Themes (Bullseye)" --checklist \ - "Available icon themes:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ - "gnome-icon-theme" "GNOME icon theme$(_inst gnome-icon-theme)" "$(_state gnome-icon-theme)" \ - "breeze-icon-theme" "Breeze icon theme$(_inst breeze-icon-theme)" "$(_state breeze-icon-theme)" \ - "papirus-icon-theme" "Papirus icon theme$(_inst papirus-icon-theme)" "$(_state papirus-icon-theme)" \ - 3>&1 1>&2 2>&3) + "Select icon themes:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ + "${items[@]}" 3>&1 1>&2 2>&3) clear [ -z "$choices" ] && return local cleaned; cleaned=$(echo "$choices" | tr -d '"') @@ -122,10 +115,12 @@ el paquete 'gnome-icon-theme' o 'breeze-icon-theme'." 12 60 _cat_cursors_bullseye() { local choices choices=$(whiptail --title "Cursor Themes (Bullseye)" --checklist \ - "Available cursor themes:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ - "dmz-cursor-theme" "DMZ cursor theme$(_inst dmz-cursor-theme)" "$(_state dmz-cursor-theme)" \ - "breeze-cursor-theme" "Breeze cursor theme$(_inst breeze-cursor-theme)" "$(_state breeze-cursor-theme)" \ - "oxygen-cursor-theme" "Oxygen cursor theme$(_inst oxygen-cursor-theme)" "$(_state oxygen-cursor-theme)" \ + "Select cursor themes:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ + "breeze-cursor-theme" "Breeze cursors (KDE)$(_inst breeze-cursor-theme)" "$(_state breeze-cursor-theme)" \ + "chameleon-cursor-theme" "Chameleon cursors$(_inst chameleon-cursor-theme)" "$(_state chameleon-cursor-theme)" \ + "dmz-cursor-theme" "DMZ cursors$(_inst dmz-cursor-theme)" "$(_state dmz-cursor-theme)" \ + "oxygencursors" "Oxygen cursors (KDE legacy)$(_inst oxygencursors)" "$(_state oxygencursors)" \ + "xcursor-themes" "X11 base cursors$(_inst xcursor-themes)" "$(_state xcursor-themes)" \ 3>&1 1>&2 2>&3) clear [ -z "$choices" ] && return @@ -155,19 +150,32 @@ _cat_fonts_bullseye() { } _cat_download_bullseye() { - local choices - choices=$(whiptail --title "Download & Torrent (Bullseye)" --checklist \ + local choices1 choices2="" + + choices1=$(whiptail --title "Downloaders" --checklist \ "Select download tools:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ - "aria2" "Multiprotocol downloader (CLI)$(_inst aria2)" "$(_state aria2)" \ - "filezilla" "FTP/SFTP client (GUI)$(_inst filezilla)" "$(_state filezilla)" \ - "qbittorrent" "BitTorrent client (Qt)$(_inst qbittorrent)" "$(_state qbittorrent)" \ - "transmission-gtk" "BitTorrent client (GTK)$(_inst transmission-gtk)" "$(_state transmission-gtk)" \ - "transmission-qt" "BitTorrent client (Qt)$(_inst transmission-qt)" "$(_state transmission-qt)" \ - "deluge" "BitTorrent client (GTK)$(_inst deluge)" "$(_state deluge)" \ + "aria2" "Multiprotocol downloader (CLI)$(_inst aria2)" "$(_state aria2)" \ + "filezilla" "FTP/SFTP client (GUI)$(_inst filezilla)" "$(_state filezilla)" \ 3>&1 1>&2 2>&3) clear - [ -z "$choices" ] && return - local cleaned; cleaned=$(echo "$choices" | tr -d '"') + + choices2=$(whiptail --title "Torrent Clients" --checklist \ + "Select torrent clients:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ + "deluge" "BitTorrent client (GTK)$(_inst deluge)" "$(_state deluge)" \ + "deluged" "BitTorrent daemon/server$(_inst deluged)" "$(_state deluged)" \ + "mktorrent" "Torrent metainfo creator (CLI)$(_inst mktorrent)" "$(_state mktorrent)" \ + "qbittorrent" "BitTorrent client (Qt)$(_inst qbittorrent)" "$(_state qbittorrent)" \ + "qbittorrent-nox" "BitTorrent WebUI/CLI$(_inst qbittorrent-nox)" "$(_state qbittorrent-nox)" \ + "transmission-cli" "BitTorrent client (CLI)$(_inst transmission-cli)" "$(_state transmission-cli)" \ + "transmission-gtk" "BitTorrent client (GTK)$(_inst transmission-gtk)" "$(_state transmission-gtk)" \ + "transmission-qt" "BitTorrent client (Qt)$(_inst transmission-qt)" "$(_state transmission-qt)" \ + 3>&1 1>&2 2>&3) + 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" @@ -175,35 +183,46 @@ _cat_download_bullseye() { echo "$pkg already installed." fi done - echo -e "${GREEN}Download tools installed.${NC}" + echo -e "${GREEN}Download & network tools installed.${NC}" } _cat_internet_bullseye() { - local ff_state; ff_state=$(_state "firefox-esr") - local tbird_state; tbird_state=$(_state "thunderbird") - local chr_state; chr_state=$(_state "chromium") - local choices choices=$(whiptail --title "Internet (Bullseye)" --checklist \ "Select browsers, email:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ - "firefox-esr" "Firefox ESR (official Debian)$(_inst firefox-esr)" "$ff_state" \ - "chromium" "Chromium web browser$(_inst chromium)" "$chr_state" \ - "thunderbird" "Email client$(_inst thunderbird)" "$tbird_state" \ - "dillo" "Lightweight graphical browser$(_inst dillo)" "$(_state dillo)" \ - "elinks" "Text-mode web browser$(_inst elinks)" "$(_state elinks)" \ - "konqueror" "KDE file manager / web browser$(_inst konqueror)" "$(_state konqueror)" \ - "w3m" "Text-mode browser + deps$(_inst w3m)" "$(_state w3m)" \ - "torbrowser-launcher" "Tor Browser launcher$(_inst torbrowser-launcher)" "$(_state torbrowser-launcher)" \ + "chromium" "Chromium web browser$(_inst chromium)" "$(_state chromium)" \ + "dillo" "Lightweight graphical browser$(_inst dillo)" "$(_state dillo)" \ + "elinks" "Text-mode web browser$(_inst elinks)" "$(_state elinks)" \ + "epiphany-browser" "GNOME web browser$(_inst epiphany-browser)" "$(_state epiphany-browser)" \ + "falkon" "KDE web browser (QtWebEngine)$(_inst falkon)" "$(_state falkon)" \ + "firefox-esr" "Firefox ESR (official Debian)$(_inst firefox-esr)" "$(_state firefox-esr)" \ + "konqueror" "KDE file manager / web browser$(_inst konqueror)" "$(_state konqueror)" \ + "qutebrowser" "Keyboard-driven browser (Qt)$(_inst qutebrowser)" "$(_state qutebrowser)" \ + "thunderbird" "Email client$(_inst thunderbird)" "$(_state thunderbird)" \ + "torbrowser-launcher" "Tor Browser launcher$(_inst torbrowser-launcher)" "$(_state torbrowser-launcher)" \ + "w3m" "Text-mode browser + deps$(_inst w3m)" "$(_state w3m)" \ 3>&1 1>&2 2>&3) 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 + 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}" } @@ -232,14 +251,19 @@ _cat_design_bullseye() { local choices choices=$(whiptail --title "Multimedia & Design (Bullseye)" --checklist \ "Select multimedia and design tools:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ - "audacity" "Audio editor/recorder$(_inst audacity)" "$(_state audacity)" \ - "blender" "3D modeling/animation suite$(_inst blender)" "$(_state blender)" \ - "ffmpeg" "Multimedia framework (CLI)$(_inst ffmpeg)" "$(_state ffmpeg)" \ - "gimp" "Image editor$(_inst gimp)" "$(_state gimp)" \ - "inkscape" "Vector graphics editor$(_inst inkscape)" "$(_state inkscape)" \ - "kdenlive" "Video editor (KDE)$(_inst kdenlive)" "$(_state kdenlive)" \ - "obs-studio" "Streaming/recording studio$(_inst obs-studio)" "$(_state obs-studio)" \ - "scribus" "Desktop publishing$(_inst scribus)" "$(_state scribus)" \ + "ardour" "Digital audio workstation$(_inst ardour)" "$(_state ardour)" \ + "audacity" "Audio editor/recorder$(_inst audacity)" "$(_state audacity)" \ + "blender" "3D modeling/animation suite$(_inst blender)" "$(_state blender)" \ + "ffmpeg" "Multimedia framework (CLI)$(_inst ffmpeg)" "$(_state ffmpeg)" \ + "gimp" "Image editor$(_inst gimp)" "$(_state gimp)" \ + "handbrake" "Video transcoder (DVD ripper)$(_inst handbrake)" "$(_state handbrake)" \ + "inkscape" "Vector graphics editor$(_inst inkscape)" "$(_state inkscape)" \ + "kdenlive" "Video editor (KDE)$(_inst kdenlive)" "$(_state kdenlive)" \ + "krita" "Digital painting/illustration$(_inst krita)" "$(_state krita)" \ + "obs-studio" "Screen recording/streaming$(_inst obs-studio)" "$(_state obs-studio)" \ + "openshot-qt" "Video editor (simple)$(_inst openshot-qt)" "$(_state openshot-qt)" \ + "scribus" "Desktop publishing (DTP)$(_inst scribus)" "$(_state scribus)" \ + "shotcut" "Video editor (cross-platform)$(_inst shotcut)" "$(_state shotcut)" \ 3>&1 1>&2 2>&3) clear [ -z "$choices" ] && return @@ -251,24 +275,22 @@ _cat_design_bullseye() { echo "$pkg already installed." fi done - echo -e "${GREEN}Design tools installed.${NC}" + echo -e "${GREEN}Multimedia & design tools installed.${NC}" } _cat_programming_bullseye() { local choices - choices=$(whiptail --title "Programming (Bullseye)" --checklist \ - "Select programming tools:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ - "build-essential" "GCC/Clang compilers$(_inst build-essential)" "$(_state build-essential)" \ - "python3" "Python 3 interpreter$(_inst python3)" "$(_state python3)" \ - "python3-pip" "Python 3 package manager$(_inst python3-pip)" "$(_state python3-pip)" \ - "nodejs" "Node.js (Debian repo)$(_inst nodejs)" "$(_state nodejs)" \ - "npm" "Node.js package manager$(_inst npm)" "$(_state npm)" \ - "openjdk-17-jdk" "OpenJDK 17 JDK$(_inst openjdk-17-jdk)" "$(_state openjdk-17-jdk)" \ - "git" "Version control system$(_inst git)" "$(_state git)" \ - "vim" "Text editor (Vim)$(_inst vim)" "$(_state vim)" \ - "nano" "Text editor (Nano)$(_inst nano)" "$(_state nano)" \ - "geany" "Lightweight IDE$(_inst geany)" "$(_state geany)" \ - "codeblocks" "Cross-platform IDE$(_inst codeblocks)" "$(_state codeblocks)" \ + choices=$(whiptail --title "Code Editors & IDEs (Bullseye)" --checklist \ + "Select editors and IDEs:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ + "vim" "Classic terminal editor$(_inst vim)" "$(_state vim)" \ + "vim-gtk3" "Vim with GTK3 GUI$(_inst vim-gtk3)" "$(_state vim-gtk3)" \ + "neovim" "Modern vim fork$(_inst neovim)" "$(_state neovim)" \ + "nano" "Simple terminal editor$(_inst nano)" "$(_state nano)" \ + "emacs" "Extensible editor / IDE$(_inst emacs)" "$(_state emacs)" \ + "kate" "KDE advanced text editor$(_inst kate)" "$(_state kate)" \ + "mousepad" "Xfce text editor$(_inst mousepad)" "$(_state mousepad)" \ + "gedit" "GNOME text editor$(_inst gedit)" "$(_state gedit)" \ + "geany" "Lightweight IDE$(_inst geany)" "$(_state geany)" \ 3>&1 1>&2 2>&3) clear [ -z "$choices" ] && return @@ -280,57 +302,120 @@ _cat_programming_bullseye() { echo "$pkg already installed." fi done - echo -e "${GREEN}Programming tools installed.${NC}" + echo -e "${GREEN}Code editors & IDEs installed.${NC}" +} + +_cat_dev_bullseye() { + local choices + choices=$(whiptail --title "Servers & Dev Tools (Bullseye)" --checklist \ + "Select development tools and servers:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ + "apache2" "Apache web server$(_inst apache2)" "$(_state apache2)" \ + "build-essential" "C/C++ build tools (gcc, make)$(_inst build-essential)" "$(_state build-essential)" \ + "docker" "Docker container runtime$(_inst docker.io)" "$(_state docker.io)" \ + "mariadb-server" "MariaDB database server$(_inst mariadb-server)" "$(_state mariadb-server)" \ + "netcat-openbsd" "TCP/IP networking utility$(_inst netcat-openbsd)" "$(_state netcat-openbsd)" \ + "nginx" "Nginx web server$(_inst nginx)" "$(_state nginx)" \ + "openssh-server" "SSH server$(_inst openssh-server)" "$(_state openssh-server)" \ + "openssl" "OpenSSL cryptography toolkit$(_inst openssl)" "$(_state openssl)" \ + "postgresql" "PostgreSQL database server$(_inst postgresql)" "$(_state postgresql)" \ + "python3-pip" "Python 3 pip + venv + dev$(_inst python3-pip)" "$(_state python3-pip)" \ + "redis-server" "Redis key-value store$(_inst redis-server)" "$(_state redis-server)" \ + "sqlite3" "SQLite database engine$(_inst sqlite3)" "$(_state sqlite3)" \ + "openjdk-dev-env" "Adoptium Temurin JDK (17, 21, 25 LTS)$(_any_jdk_installed_desc)" "$(_any_jdk_state)" \ + 3>&1 1>&2 2>&3) + 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 + ;; + 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 choices choices=$(whiptail --title "Security & Networking (Bullseye)" --checklist \ - "Select security tools:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ - "nmap" "Network scanner$(_inst nmap)" "$(_state nmap)" \ - "wireshark" "Packet analyzer$(_inst wireshark)" "$(_state wireshark)" \ - "nikto" "Web server scanner$(_inst nikto)" "$(_state nikto)" \ - "sqlmap" "SQL injection tool$(_inst sqlmap)" "$(_state sqlmap)" \ - "gobuster" "Directory/file brute-forcer$(_inst gobuster)" "$(_state gobuster)" \ - "hydra" "Login cracker$(_inst hydra)" "$(_state hydra)" \ - "john" "John the Ripper password cracker$(_inst john)" "$(_state john)" \ - "aircrack-ng" "Wireless security tool$(_inst aircrack-ng)" "$(_state aircrack-ng)" \ + "Select security and networking tools:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ + "wireshark" "Network protocol analyzer (GUI)$(_inst wireshark)" "$(_state wireshark)" \ + "tcpdump" "Command-line packet analyzer$(_inst tcpdump)" "$(_state tcpdump)" \ + "fail2ban" "Brute-force protection daemon$(_inst fail2ban)" "$(_state fail2ban)" \ + "ufw" "Uncomplicated firewall$(_inst ufw)" "$(_state ufw)" \ + "clamav" "Antivirus engine (ClamAV)$(_inst clamav)" "$(_state clamav)" \ 3>&1 1>&2 2>&3) 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 + 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 tools installed.${NC}" + echo -e "${GREEN}Security & networking tools installed.${NC}" } _cat_general_bullseye() { local choices choices=$(whiptail --title "System Tools (Bullseye)" --checklist \ "Select system utilities:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ - "compress" "Compression tools (zip, unrar, p7zip)$(_inst zip)" "$(_state zip)" \ - "conky" "System monitor for desktop$(_inst conky)" "$(_state conky)" \ - "cpu-x" "CPU-X (alternative to CPU-Z)$(_inst cpu-x)" "$(_state cpu-x)" \ - "curl-wget" "HTTP transfer tools (curl, wget)$(_inst curl)" "$(_state curl)" \ - "flatpak" "Flatpak sandbox (Bullseye native)$(_inst flatpak)" "$(_state flatpak)" \ - "fwupd" "Firmware update daemon$(_inst fwupd)" "$(_state fwupd)" \ - "gnome-disk-utility" "Disk management GUI$(_inst gnome-disk-utility)" "$(_state gnome-disk-utility)" \ - "gparted" "Partition editor$(_inst gparted)" "$(_state gparted)" \ - "htop" "Interactive process viewer$(_inst htop)" "$(_state htop)" \ - "inxi" "System information tool$(_inst inxi)" "$(_state inxi)" \ - "kvm" "QEMU/KVM virtualization$(_inst virt-manager)" "$(_state virt-manager)" \ - "lshw" "List hardware details$(_inst lshw)" "$(_state lshw)" \ - "mc" "Midnight Commander$(_inst mc)" "$(_state mc)" \ - "ncdu" "Disk usage analyzer$(_inst ncdu)" "$(_state ncdu)" \ - "psensor" "Temperature monitor$(_inst psensor)" "$(_state psensor)" \ - "timeshift" "System restore snapshots$(_inst timeshift)" "$(_state timeshift)" \ - "tmux" "Terminal multiplexer$(_inst tmux)" "$(_state tmux)" \ - "wine" "Windows compatibility layer$(_inst wine)" "$(_state wine)" \ + "compress" "Compression tools (zip, unrar, p7zip)$(_inst zip)" "$(_state zip)" \ + "conky" "System monitor for desktop$(_inst conky)" "$(_state conky)" \ + "cpu-x" "CPU-X (alternative to CPU-Z)$(_inst cpu-x)" "$(_state cpu-x)" \ + "curl-wget" "HTTP transfer tools (curl, wget)$(_inst curl)" "$(_state curl)" \ + "flatpak" "Flatpak sandbox (Bullseye native)$(_inst flatpak)" "$(_state flatpak)" \ + "fwupd" "Firmware update daemon$(_inst fwupd)" "$(_state fwupd)" \ + "gnome-disk-utility" "Disk management GUI$(_inst gnome-disk-utility)" "$(_state gnome-disk-utility)" \ + "gparted" "Partition editor$(_inst gparted)" "$(_state gparted)" \ + "htop" "Interactive process viewer$(_inst htop)" "$(_state htop)" \ + "inxi" "System information tool$(_inst inxi)" "$(_state inxi)" \ + "kvm" "QEMU/KVM virtualization$(_inst virt-manager)" "$(_state virt-manager)" \ + "lshw" "List hardware details$(_inst lshw)" "$(_state lshw)" \ + "mc" "Midnight Commander$(_inst mc)" "$(_state mc)" \ + "ncdu" "Disk usage analyzer$(_inst ncdu)" "$(_state ncdu)" \ + "psensor" "Temperature monitor$(_inst psensor)" "$(_state psensor)" \ + "timeshift" "System restore snapshots$(_inst timeshift)" "$(_state timeshift)" \ + "tmux" "Terminal multiplexer$(_inst tmux)" "$(_state tmux)" \ + "wine" "Windows compatibility layer$(_inst wine)" "$(_state wine)" \ 3>&1 1>&2 2>&3) clear [ -z "$choices" ] && return @@ -345,9 +430,7 @@ _cat_general_bullseye() { ! is_installed "unrar" && need+=("unrar") ! is_installed "p7zip-full" && need+=("p7zip-full") ! is_installed "p7zip-rar" && need+=("p7zip-rar") - if [ ${#need[@]} -gt 0 ]; then - _run_install_batch "${need[@]}" - fi + [ ${#need[@]} -gt 0 ] && _run_install_batch "${need[@]}" ;; curl-wget) local need=() @@ -409,7 +492,7 @@ _cat_general_bullseye() { _cat_fetch_bullseye() { local items=( - "neofetch" "System info fetcher$(_inst neofetch)" "$(_state neofetch)" + "neofetch" "System info fetcher$(_inst neofetch)" "$(_state neofetch)" "screenfetch" "System info (BSD/Linux)$(_inst screenfetch)" "$(_state screenfetch)" "linuxlogo" "Linux logo + system info$(_inst linuxlogo)" "$(_state linuxlogo)" ) @@ -436,22 +519,24 @@ _cat_fetch_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=$(whiptail --title "Extra Software — Bullseye" --menu \ "Select a category:" $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" "Programming Applications" \ - "7" "Security & Networking" \ - "8" "System Tools" \ - "9" "Fetch / System Info" \ - "10" "Back to main menu" \ + "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" "System Tools" \ + "10" "Fetch / System Info" \ + "11" "Back to main menu" \ 3>&1 1>&2 2>&3) [ -z "$cat_choice" ] && return @@ -465,10 +550,11 @@ install_extras_bullseye() { 4) _cat_players_bullseye ;; 5) _cat_design_bullseye ;; 6) _cat_programming_bullseye ;; - 7) _cat_security_bullseye ;; - 8) _cat_general_bullseye ;; - 9) _cat_fetch_bullseye ;; - 10) return ;; + 7) _cat_dev_bullseye ;; + 8) _cat_security_bullseye ;; + 9) _cat_general_bullseye ;; + 10) _cat_fetch_bullseye ;; + 11) return ;; esac clear done diff --git a/modules/bullseye/legacy.sh b/modules/bullseye/legacy.sh index 076e582..a18f0c4 100644 --- a/modules/bullseye/legacy.sh +++ b/modules/bullseye/legacy.sh @@ -116,18 +116,18 @@ install_gaming_bullseye() { local enable_32bit=false if _confirm "32-bit Support" \ - "Habilitar arquitectura i386 para juegos?\n\n\ -Requieren los juegos nativos de 32 bits y ciertas\n\ -bibliotecas de emulación."; then + "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 "Activando soporte multiarquitectura i386..." + 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" "Actualizando listas..." + _run_cmd "APT Update" "sudo apt update" "Updating package lists..." if [ "$GPU_TYPE" = "nvidia" ]; then local nv32_pkg="nvidia-driver-libs:i386" @@ -139,10 +139,10 @@ bibliotecas de emulación."; then 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}" \ - "Instalando librerías NVIDIA 32-bit..." + "Installing NVIDIA 32-bit libraries..." fi else - echo "nvidia-driver-libs:i386 no disponible en Bullseye." + echo "nvidia-driver-libs:i386 not available on Bullseye." fi else # Mesa 32-bit @@ -158,20 +158,20 @@ bibliotecas de emulación."; then 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 para gaming.\n\n" + 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+="Instalar drivers 32-bit?" + 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[*]}" \ - "Instalando Mesa 32-bit..." + "Installing Mesa 32-bit..." fi fi fi - # Gaming tools checklist (sin Steam ni Heroic) + # Gaming tools checklist (no Steam, no Heroic) local choices choices=$(whiptail --title "Gaming Tools — Bullseye" --checklist \ "Select gaming optimization tools:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \ @@ -179,6 +179,7 @@ bibliotecas de emulación."; then "mangohud" "Performance overlay (Vulkan/OpenGL)" ON \ "goverlay" "MangoHud config GUI" ON \ "lutris" "Game launcher/manager" OFF \ + "java" "Java Runtimes (8, 17, 21)" OFF \ 3>&1 1>&2 2>&3) if [ -z "$choices" ]; then @@ -192,20 +193,21 @@ bibliotecas de emulación."; then for pkg in $cleaned; do case $pkg in mangohud) - _run_cmd "MangoHud" "sudo apt install -y mangohud" "Instalando MangoHud..." + _run_cmd "MangoHud" "sudo apt install -y mangohud" "Installing 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 _run_cmd "MangoHud" "sudo apt install -y mangohud:i386" \ - "Instalando MangoHud 32-bit..." + "Installing MangoHud 32-bit..." fi fi ;; - gamemode) _run_cmd "GameMode" "sudo apt install -y gamemode" "Instalando GameMode..." ;; - goverlay) _run_cmd "GOverlay" "sudo apt install -y goverlay" "Instalando GOverlay..." ;; - lutris) _run_cmd "Lutris" "sudo apt install -y lutris" "Instalando Lutris..." ;; + gamemode) _run_cmd "GameMode" "sudo apt install -y gamemode" "Installing GameMode..." ;; + goverlay) _run_cmd "GOverlay" "sudo apt install -y goverlay" "Installing GOverlay..." ;; + lutris) _run_cmd "Lutris" "sudo apt install -y lutris" "Installing Lutris..." ;; + java) _install_gaming_java ;; *) _run_install "$pkg" ;; esac done diff --git a/modules/bullseye/repos.sh b/modules/bullseye/repos.sh index 04d4184..647595d 100644 --- a/modules/bullseye/repos.sh +++ b/modules/bullseye/repos.sh @@ -5,19 +5,19 @@ configure_repos_bullseye() { echo -e "${YELLOW}Repository configuration — Debian 11 Bullseye${NC}" - local info="Configuración de repositorios para Debian 11 Bullseye.\n\n" - info+="Se usarán los repositorios oficiales con componentes\n" - info+="main, contrib y non-free (sin non-free-firmware).\n" - info+="No se utiliza formato DEB822.\n" + 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+="\nModo Archive: Las URLs apuntarán a archive.debian.org\n" - info+="(Bullseye LTS finalizó el 31 Ago 2026)." + info+="\nArchive Mode: URLs will point to archive.debian.org\n" + info+="(Bullseye LTS ended on 31 Aug 2026)." fi - _msg "Repositorios — Bullseye" "$info" 12 65 + _msg "Repositories — Bullseye" "$info" 12 65 if [ -f /etc/apt/sources.list ]; then - if ! _confirm "Repositorios" "Ya existe /etc/apt/sources.list.\n\nSobrescribir con la configuración de Bullseye?"; then - echo "Manteniendo configuración actual." + if ! _confirm "Repositories" "/etc/apt/sources.list already exists.\n\nOverwrite with Bullseye configuration?"; then + echo "Keeping current configuration." return 0 fi fi @@ -34,21 +34,17 @@ configure_repos_bullseye() { content+="deb ${base_uri} bullseye main contrib non-free\n" content+="#deb-src ${base_uri} bullseye main contrib non-free\n\n" - content+="# Updates\n" - content+="deb ${base_uri} bullseye-updates main contrib non-free\n" - content+="#deb-src ${base_uri} bullseye-updates 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 "Actualizando listas de paquetes..." + echo "Updating package lists..." if sudo apt update; then - echo -e "${GREEN}Repositorios de Debian 11 Bullseye configurados.${NC}" + echo -e "${GREEN}Debian 11 Bullseye repositories configured.${NC}" else - echo -e "${RED}apt update falló. Revise su conexión de red.${NC}" + echo -e "${RED}apt update failed. Check your network connection.${NC}" return 1 fi } diff --git a/modules/extras.sh b/modules/extras.sh index 6414ef8..7d4052c 100644 --- a/modules/extras.sh +++ b/modules/extras.sh @@ -35,11 +35,12 @@ install_extras() { "3" "Internet (Browsers, Email, VPN)" \ "4" "Media Players" \ "5" "Multimedia & Design" \ - "6" "Programming Applications" \ - "7" "Security & Networking" \ - "8" "System Tools" \ - "9" "Fetch / System Info" \ - "10" "Back to main menu" \ + "6" "Code Editors & IDEs" \ + "7" "Servers & Dev Tools" \ + "8" "Security & Networking" \ + "9" "System Tools" \ + "10" "Fetch / System Info" \ + "11" "Back to main menu" \ 3>&1 1>&2 2>&3) [ -z "$cat_choice" ] && return @@ -53,10 +54,11 @@ install_extras() { 4) _cat_players ;; 5) _cat_design ;; 6) _cat_programming ;; - 7) _cat_security ;; - 8) _cat_general ;; - 9) _cat_fetch ;; - 10) return ;; + 7) _cat_dev ;; + 8) _cat_security ;; + 9) _cat_general ;; + 10) _cat_fetch ;; + 11) return ;; esac clear done diff --git a/modules/extras/_helpers.sh b/modules/extras/_helpers.sh index 3187e4f..b0a95d3 100644 --- a/modules/extras/_helpers.sh +++ b/modules/extras/_helpers.sh @@ -8,3 +8,24 @@ _inst() { _state() { is_installed "$1" && echo "ON" || echo "OFF" } + +_install_clamav() { + if is_installed "clamav"; then + echo "ClamAV already installed." + return + fi + _run_install "clamav" + echo -e "${GREEN}ClamAV installed.${NC}" + + if _confirm "ClamAV" "Update virus signatures now (freshclam)?"; then + sudo systemctl stop clamav-freshclam 2>/dev/null || true + sudo freshclam || true + sudo systemctl start clamav-freshclam 2>/dev/null || true + 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 +} diff --git a/modules/extras/dev/dev.sh b/modules/extras/dev/dev.sh index 466cc81..ca30820 100644 --- a/modules/extras/dev/dev.sh +++ b/modules/extras/dev/dev.sh @@ -17,6 +17,8 @@ _cat_dev() { local pip_state; pip_state=$(_state "python3-pip") local redis_state; redis_state=$(_state "redis-server") local sqlite_state; sqlite_state=$(_state "sqlite3") + local jdk_desc; jdk_desc=$(_any_jdk_installed_desc) + local jdk_state; jdk_state=$(_any_jdk_state) local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6)) local choices @@ -35,6 +37,7 @@ _cat_dev() { "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" \ + "openjdk-dev-env" "Adoptium Temurin JDK (17, 21, 25 LTS)${jdk_desc}" "${jdk_state}" \ 3>&1 1>&2 2>&3) clear @@ -65,6 +68,9 @@ _cat_dev() { echo "Docker already installed." fi ;; + openjdk-dev-env) + _install_dev_java + ;; *) if ! is_installed "$pkg"; then _run_install "$pkg" diff --git a/modules/extras/java.sh b/modules/extras/java.sh new file mode 100644 index 0000000..8054a7e --- /dev/null +++ b/modules/extras/java.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# java.sh — Adoptium Temurin repository setup and Java version selectors +# License GPL v3 + +_ensure_adoptium_repo() { + [ -f /etc/apt/sources.list.d/adoptium.list ] && return 0 + + local deps=() + ! is_installed "wget" && deps+=("wget") + ! is_installed "apt-transport-https" && deps+=("apt-transport-https") + ! is_installed "gpg" && deps+=("gpg") + [ ${#deps[@]} -gt 0 ] && _run_install_batch "${deps[@]}" + + wget -qO - "https://packages.adoptium.net/artifactory/api/gpg/key/public" \ + | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/adoptium.gpg 2>/dev/null + + local codename + codename=$(awk -F= '/^VERSION_CODENAME/{print$2}' /etc/os-release) + echo "deb https://packages.adoptium.net/artifactory/deb ${codename} main" \ + | sudo tee /etc/apt/sources.list.d/adoptium.list > /dev/null + + sudo apt update \ + -o Dir::Etc::sourcelist=/etc/apt/sources.list.d/adoptium.list \ + -o Dir::Etc::sourceparts="-" \ + 2>/dev/null || true +} + +_install_gaming_java() { + local ver + ver=$(whiptail --title "Java Runtimes for Gaming" --menu \ + "Select Java version:" 12 65 3 \ + "8" "Java 8 — For classic mods & Minecraft <= 1.16.5" \ + "17" "Java 17 — For Minecraft era 1.17 to 1.20.4" \ + "21" "Java 21 — For modern Minecraft >= 1.20.5 & 1.21+" \ + 3>&1 1>&2 2>&3) + [ -z "$ver" ] && { echo "No Java version selected."; return; } + _ensure_adoptium_repo + _run_install "temurin-${ver}-jre" +} + +_install_dev_java() { + local ver + ver=$(whiptail --title "Java Development Kits (JDK)" --menu \ + "Select JDK version:" 12 60 3 \ + "17" "Java 17 LTS Development Kit" \ + "21" "Java 21 LTS Development Kit" \ + "25" "Java 25 LTS Development Kit" \ + 3>&1 1>&2 2>&3) + [ -z "$ver" ] && { echo "No JDK version selected."; return; } + _ensure_adoptium_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" +} diff --git a/modules/extras/security/security.sh b/modules/extras/security/security.sh index 4e3a3aa..8b92029 100644 --- a/modules/extras/security/security.sh +++ b/modules/extras/security/security.sh @@ -9,16 +9,18 @@ _cat_security() { local zenmap_state; zenmap_state=$(_state "zenmap") local fail2ban_state; fail2ban_state=$(_state "fail2ban") local ufw_state; ufw_state=$(_state "ufw") + local clamav_state; clamav_state=$(_state "clamav") local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6)) local choices choices=$(whiptail --title "Security & Networking" --checklist \ - "Select security and networking tools (5 items):" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \ + "Select security and networking tools (6 items):" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \ "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" \ + "clamav" "Antivirus engine (ClamAV)$(_inst clamav)" "$clamav_state" \ 3>&1 1>&2 2>&3) clear @@ -31,6 +33,9 @@ _cat_security() { zenmap) install_backports_or_stable zenmap ;; + clamav) + _install_clamav + ;; *) if ! is_installed "$pkg"; then _run_install "$pkg" diff --git a/modules/gaming.sh b/modules/gaming.sh index 91b4435..8e08e4d 100644 --- a/modules/gaming.sh +++ b/modules/gaming.sh @@ -128,6 +128,7 @@ install_gaming() { "gamemode" "Game performance optimization" ON \ "mangohud" "Performance overlay (Vulkan/OpenGL)" ON \ "heroic" "Heroic Launcher (Epic/GOG)" OFF \ + "java-jre" "Java Runtimes (8, 17, 21)" OFF \ "goverlay" "MangoHud config GUI" ON \ "lutris" "Game launcher/manager" OFF \ 3>&1 1>&2 2>&3) @@ -157,6 +158,7 @@ install_gaming() { fi ;; heroic) install_heroic ;; + java) _install_gaming_java ;; mangohud) install_mangohud ;; gamemode) install_gamemode ;; goverlay) install_goverlay ;; diff --git a/modules/gpu/_helpers.sh b/modules/gpu/_helpers.sh index 96554ac..c163bc9 100644 --- a/modules/gpu/_helpers.sh +++ b/modules/gpu/_helpers.sh @@ -134,6 +134,12 @@ install_mesa_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 diff --git a/modules/gpu/amd_intel.sh b/modules/gpu/amd_intel.sh index 5e9427a..2d359ac 100644 --- a/modules/gpu/amd_intel.sh +++ b/modules/gpu/amd_intel.sh @@ -20,7 +20,11 @@ offer_amd_tools() { fi local pkgs - pkgs=$(pkg_versions "${amd_tools[@]}" nvtop vainfo) + 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}') @@ -32,7 +36,11 @@ offer_amd_tools() { return fi - _run_cmd "AMD Tools" "sudo apt install -y ${amd_tools[*]} nvtop vainfo" "Installing AMD tools..." + 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 if $corectrl_available; then @@ -73,7 +81,18 @@ offer_intel_tools() { [ -d "/sys/bus/pci/drivers/xe" ] && has_xe=true [ -d "/sys/bus/pci/drivers/i915" ] && has_i915=true - if $has_xe; then + 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 diff --git a/modules/repos.sh b/modules/repos.sh index 19faf3a..e926ff9 100644 --- a/modules/repos.sh +++ b/modules/repos.sh @@ -5,9 +5,11 @@ REPO_BACKUP_DIR="" backup_current_repos() { 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 - 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 done } @@ -17,17 +19,22 @@ restore_previous_repos() { return fi echo -e "${RED}Restoring previous repository configuration...${NC}" - if [ -f "$REPO_BACKUP_DIR/sources.list" ]; then - sudo cp "$REPO_BACKUP_DIR/sources.list" /etc/apt/sources.list - else - sudo rm -f /etc/apt/sources.list + local found=false + 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 + local rel="${f#/etc/apt/}" + local backup_file="$REPO_BACKUP_DIR/$rel" + if [ -f "$backup_file" ]; then + sudo cp "$backup_file" "$f" + found=true + elif [ -f "$f" ]; then + sudo rm -f "$f" + found=true + fi + done + if $found; then + sudo rm -f /etc/apt/sources.list.disabled fi - if [ -f "$REPO_BACKUP_DIR/debian.sources" ]; then - sudo cp "$REPO_BACKUP_DIR/debian.sources" /etc/apt/sources.list.d/debian.sources - else - sudo rm -f /etc/apt/sources.list.d/debian.sources - fi - sudo rm -f /etc/apt/sources.list.disabled rm -rf "$REPO_BACKUP_DIR" REPO_BACKUP_DIR="" } @@ -39,40 +46,312 @@ cleanup_repo_backup() { fi } -finalize_deb822() { - if [ -f /etc/apt/sources.list ]; then - sudo mv /etc/apt/sources.list /etc/apt/sources.list.disabled - echo "Classic sources.list disabled (renamed to sources.list.disabled)" +# --------------------------------------------------------------------------- +# 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 - cleanup_repo_backup } -configure_repos() { - echo -e "${YELLOW}Repository configuration...${NC}" +_clean_embedded_backports_deb822() { + local codename="$1" + local file="/etc/apt/sources.list.d/debian.sources" + [ ! -f "$file" ] && return - 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 + # 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 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: 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: ${codename}-security\n" + main_content+="Components: main contrib non-free non-free-firmware\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 - local enable_backports=false - if _confirm "Backports" "Enable backports repository?\n\nProvides newer kernel, drivers, Mesa."; then - enable_backports=true + # 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 _confirm "Disable Classic" "Migrating to deb822. Disable /etc/apt/sources.list?"; then + sudo mv /etc/apt/sources.list /etc/apt/sources.list.disabled + echo "Classic sources.list disabled (renamed to sources.list.disabled)" + fi + 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 main_file="/etc/apt/sources.list" + local main_content="" + main_content+="# Official repository\n" + main_content+="deb https://deb.debian.org/debian ${codename} main contrib non-free non-free-firmware\n" + main_content+="# deb-src https://deb.debian.org/debian ${codename} main contrib non-free non-free-firmware\n" + main_content+="\n" + main_content+="# Updates\n" + main_content+="deb https://deb.debian.org/debian ${codename}-updates main contrib non-free non-free-firmware\n" + main_content+="# deb-src https://deb.debian.org/debian ${codename}-updates main contrib non-free non-free-firmware\n" + main_content+="\n" + main_content+="# Security\n" + main_content+="deb https://security.debian.org/debian-security ${codename}-security main contrib non-free non-free-firmware\n" + main_content+="# deb-src https://security.debian.org/debian-security ${codename}-security main contrib non-free non-free-firmware\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() { + echo -e "${YELLOW}Repository configuration...${NC}" + if [ -z "$DEBIAN_CODENAME" ]; then echo -e "${RED}Error: Could not detect Debian codename. Aborting.${NC}" return 1 fi + # Detect current state + local current_format + current_format=$(detect_repo_format) + local bp_status + if detect_backports_status "$DEBIAN_CODENAME"; then + bp_status="enabled" + else + bp_status="disabled" + fi + local bp_location + bp_location=$(detect_backports_location "$DEBIAN_CODENAME") + + echo "Current format: ${current_format:-none}" + echo "Backports: $bp_status (location: $bp_location)" + + # Choose format (only Trixie gets the choice) + local use_deb822=false + if [ "$DEBIAN_CODENAME" = "trixie" ]; then + local default_text="no" + [ "$current_format" = "deb822" ] && default_text="yes" + if whiptail --title "Repository Format" --defaultno --yesno "Use deb822 format (modern .sources)?" 8 60; then + use_deb822=true + fi + elif [ "$current_format" = "deb822" ]; then + use_deb822=true + fi + + # Choose backports + local enable_backports=false + if _confirm "Backports" "Enable backports repository?\n\nProvides newer kernel, drivers, Mesa."; then + enable_backports=true + fi + + # Determine what to do + local target_format + $use_deb822 && target_format="deb822" || target_format="classic" + + if [ "$current_format" = "none" ]; then + local action="write" + elif [ "$target_format" != "$current_format" ]; then + local action="migrate" + else + local action="update" + fi + + # If nothing changed (same format + same backports state), skip + if [ "$action" = "update" ] && [ "$enable_backports" = "$bp_status" ]; then + # Check if backports location is correct (standalone) + if $enable_backports; then + local correct_location="standalone-deb822" + $use_deb822 || correct_location="standalone-classic" + if [ "$bp_location" = "$correct_location" ]; then + # Also verify no embedded backports linger + if [ "$target_format" = "deb822" ]; then + ! grep -qE "^Suites:.*${DEBIAN_CODENAME}-backports\b" /etc/apt/sources.list.d/debian.sources 2>/dev/null || { action="update"; true; } + else + ! grep -qE "^[^#]*${DEBIAN_CODENAME}-backports\b" /etc/apt/sources.list 2>/dev/null || { action="update"; true; } + fi + if [ "$action" = "update" ]; then + echo "Repository configuration is already up-to-date. Skipping." + return 0 + fi + fi + else + # Backports disabled: verify no backports files exist + if [ ! -f /etc/apt/sources.list.d/debian-backports.sources ] && \ + [ ! -f /etc/apt/sources.list.d/debian-backports.list ]; then + echo "Repository configuration is already up-to-date. Skipping." + return 0 + fi + fi + fi + backup_current_repos if $use_deb822; then - generate_deb822_sources "$DEBIAN_CODENAME" "$enable_backports" + _write_deb822 "$DEBIAN_CODENAME" "$action" "$enable_backports" "$bp_location" else - generate_classic_sources "$DEBIAN_CODENAME" "$enable_backports" + _write_classic "$DEBIAN_CODENAME" "$action" "$enable_backports" "$bp_location" fi echo "Updating package lists..." @@ -83,11 +362,14 @@ configure_repos() { echo -e "${GREEN}Repositories configured and updated successfully.${NC}" if $use_deb822; then - finalize_deb822 + # Remove any leftover disabled files from old classic format + [ -f /etc/apt/sources.list.disabled ] && sudo rm -f /etc/apt/sources.list.disabled else - cleanup_repo_backup + [ -f /etc/apt/sources.list.d/debian.sources.disabled ] && sudo rm -f /etc/apt/sources.list.d/debian.sources.disabled fi + cleanup_repo_backup + local upgradable upgradable=$(apt list --upgradable 2>/dev/null | grep -c /) if [ "$upgradable" -gt 0 ]; then @@ -108,59 +390,3 @@ configure_repos() { return 1 fi } - -generate_classic_sources() { - local codename="$1" - local backports="$2" - - local content="" - content="# Official repository\n" - content+="deb https://deb.debian.org/debian ${codename} main contrib non-free non-free-firmware\n" - content+="# deb-src https://deb.debian.org/debian ${codename} main contrib non-free non-free-firmware\n\n" - - content+="# Updates\n" - content+="deb https://deb.debian.org/debian ${codename}-updates main contrib non-free non-free-firmware\n" - content+="# deb-src https://deb.debian.org/debian ${codename}-updates main contrib non-free non-free-firmware\n\n" - - content+="# Security\n" - content+="deb https://security.debian.org/debian-security ${codename}-security main contrib non-free non-free-firmware\n" - content+="# deb-src https://security.debian.org/debian-security ${codename}-security main contrib non-free non-free-firmware\n\n" - - if $backports; then - content+="# Backports (active)\n" - 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" - else - content+="# Backports (not enabled)\n" - content+="# deb https://deb.debian.org/debian ${codename}-backports main contrib non-free non-free-firmware\n" - fi - - echo -e "$content" | sudo tee /etc/apt/sources.list > /dev/null -} - -generate_deb822_sources() { - local codename="$1" - local backports="$2" - - sudo mkdir -p /etc/apt/sources.list.d - - local content="" - 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" - content+="URIs: https://security.debian.org/debian-security\n" - content+="Suites: ${codename}-security\n" - content+="Components: main contrib non-free non-free-firmware\n\n" - - if $backports; then - 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 - - echo -e "$content" | sudo tee /etc/apt/sources.list.d/debian.sources > /dev/null -} diff --git a/modules/repos/repo_detect.sh b/modules/repos/repo_detect.sh new file mode 100644 index 0000000..c16d51d --- /dev/null +++ b/modules/repos/repo_detect.sh @@ -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 +} diff --git a/modules/sudo_config.sh b/modules/sudo_config.sh index 6a35d5f..103e254 100644 --- a/modules/sudo_config.sh +++ b/modules/sudo_config.sh @@ -1,30 +1,159 @@ #!/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() { - echo -e "${YELLOW}Configuring sudo...${NC}" + echo -e "${YELLOW}User Privileges & Feedback${NC}" + while true; do + local choice + choice=$(whiptail --title "User Privileges & Feedback" --menu \ + "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" \ + 3>&1 1>&2 2>&3) + [ -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 - echo "User is already in the sudo group." + _msg "Sudo Group" "User '$USER' is already in the sudo group." else - echo "Adding user '$USER' to sudo group..." - 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}" + 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 + _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=$(whiptail --title "NOPASSWD Commands" --checklist \ + "Select commands to allow without password:" 12 60 3 \ + "apt" "APT package management" ON \ + "systemctl" "Systemd service management" ON \ + "power" "Shutdown, reboot, halt" ON \ + 3>&1 1>&2 2>&3) + 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 + + echo -e "$content" | sudo tee "$nopasswd_file" > /dev/null + sudo chmod 0440 "$nopasswd_file" + if [ -f "$nopasswd_file" ]; then + echo -e "${GREEN}Passwordless sudo configured for selected commands.${NC}" else - echo -e "${RED}Failed to add user to sudo group.${NC}" + echo -e "${RED}Failed to configure passwordless sudo.${NC}" return 1 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}" +# ── 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 - echo "Skipping password feedback setting." + _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 echo 'Defaults pwfeedback' | sudo tee "$fb_file" > /dev/null 2>&1; then + echo -e "${GREEN}Password feedback enabled.${NC}" + else + echo -e "${RED}Failed to create $fb_file${NC}" + return 1 + fi + fi fi }