critical-fixes, swap module & gaming overhaul

- Fixed script crashes from `whiptail` Cancel/Esc under `set -e`. Added `_menu()`, `_checklist()` and `_inputbox()` wrappers with `|| true` to prevent premature exits.
- Resolved startup failures by using defaults instead of relying on unset variables with `set -u`.
- Hardened sudoers management — `_validate_sudoers()` writes to temp file, validates with `visudo -cf`, only copies if successful.
- Replaced `eval` in `_run_cmd` with safer `bash -c` execution.

Swap Management Module (`modules/swap.sh`)
- New standalone module with 9 internal functions and `manage_swap()` entry point.
- Btrfs CoW detection — applies `chattr +C` before swapfile creation to prevent mkswap rejection on Btrfs.
- Dynamic swappiness configuration — reads current system value instead of hardcoding 60, pre-fills inputbox with existing setting.
- Uses `/run/lock/debianito-swap.lock` for early init compatibility (added as option 9 in main menu).

Repository & Branch Migration (`modules/repos/migrate.sh`)
- Handles branch migration from stable (11/12) to Testing or SID with 5-screen UX flow.
- Persistent backup system — creates timestamped tar.gz backups of `/etc/apt/sources.list*`, auto-restores on apt update failure.
- SID guardrails — installs `apt-listbugs` and `apt-listchanges` before upgrade to warn about critical bugs in unstable packages.
- Dynamic menu options based on Debian version (SID shows only 1-2-3 Exit, non-SID includes backports + branch migration).
- New `_components_enabled()` helper detects current contrib/non-free state.

Gaming Module Overhaul
- Unified gaming checklist — merged i386 toggle into single prompt with lazy evaluation instead of separate pre-check.
- Lazy 32-bit architecture enablement — only enables i386 when needed (steam/lutris/i386 selected) and installs graphics drivers if `need_32bit=true`.
- New `_install_nvidia_32bit()` helper with proper driver detection, version pinning, and legacy/tesla variant handling.

Heroic & OpenRGB Downloads
- Heroic — fetches latest release from GitHub API using `jq` to extract amd64.deb URL, validates with `dpkg-deb --info`.
- OpenRGB — downloads from Codeberg Gitea API with SHA256 verification when available, fallback to `dpkg-deb` validation.
- Dynamic codename detection — now detects Bookworm vs Trixie at runtime instead of hardcoded static values for .deb download URLs.

|Other Improvements
- Renumbered main menu: 8=ZRAM, 9=Swap Management, 10=Extras, 11=Boot Rescue, 12=Exit.
- Improved `detect_storage()` — excludes loop/CD-ROM devices via `lsblk -e 7,11`, explicitly skips zram, detects USB/SD via `/sys/block/$name/removable`.
- Standardized SCROLL_HINT across all files with centralized readonly variable.
This commit is contained in:
stornic56
2026-07-10 01:42:57 -05:00
committed by GitHub
parent 4ef48eac3b
commit a91b0caa25
32 changed files with 892 additions and 456 deletions
+34 -51
View File
@@ -60,13 +60,12 @@ Instalar?"; then
_cat_customization_bullseye() {
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 \
sub=$(_menu "Customization (Bullseye)" "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 ;;
@@ -78,15 +77,14 @@ _cat_customization_bullseye() {
_cat_themes_bullseye() {
local choices
choices=$(whiptail --title "Desktop Themes (Bullseye)" --checklist \
"Select desktop themes${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Desktop Themes (Bullseye)" "Select desktop themes${SCROLL_HINT}:" $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
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
@@ -109,9 +107,8 @@ _cat_icons_bullseye() {
"suru-icon-theme" "Suru icon theme$(_inst suru-icon-theme)" "$(_state suru-icon-theme)"
)
local choices
choices=$(whiptail --title "Icon Themes (Bullseye)" --checklist \
"Select icon themes${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"${items[@]}" 3>&1 1>&2 2>&3)
choices=$(_checklist "Icon Themes (Bullseye)" "Select icon themes${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"${items[@]}" )
clear
[ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
@@ -123,14 +120,13 @@ _cat_icons_bullseye() {
_cat_cursors_bullseye() {
local choices
choices=$(whiptail --title "Cursor Themes (Bullseye)" --checklist \
"Select cursor themes${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Cursor Themes (Bullseye)" "Select cursor themes${SCROLL_HINT}:" $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
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
@@ -142,13 +138,12 @@ _cat_cursors_bullseye() {
_cat_fonts_bullseye() {
local choices
choices=$(whiptail --title "Fonts (Bullseye)" --checklist \
"Available fonts${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Fonts (Bullseye)" "Available fonts${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"fonts-firacode" "Fira Code monospace font$(_inst fonts-firacode)" "$(_state fonts-firacode)" \
"fonts-noto" "Noto fonts (Google)$(_inst fonts-noto)" "$(_state fonts-noto)" \
"fonts-dejavu-core" "DejaVu core fonts$(_inst fonts-dejavu-core)" "$(_state fonts-dejavu-core)" \
"ttf-mscorefonts-installer" "Microsoft Core Fonts$(_inst ttf-mscorefonts-installer)" "$(_state ttf-mscorefonts-installer)" \
3>&1 1>&2 2>&3)
)
clear
[ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
@@ -161,15 +156,13 @@ _cat_fonts_bullseye() {
_cat_download_bullseye() {
local choices1 choices2=""
choices1=$(whiptail --title "Downloaders" --checklist \
"Select download tools:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices1=$(_checklist "Downloaders" "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)" \
3>&1 1>&2 2>&3)
)
clear
choices2=$(whiptail --title "Torrent Clients" --checklist \
"Select torrent clients${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices2=$(_checklist "Torrent Clients" "Select torrent clients${SCROLL_HINT}:" $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)" \
@@ -178,7 +171,7 @@ _cat_download_bullseye() {
"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
@@ -197,8 +190,7 @@ _cat_download_bullseye() {
_cat_internet_bullseye() {
local choices
choices=$(whiptail --title "Internet (Bullseye)" --checklist \
"Select browsers, email${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Internet (Bullseye)" "Select browsers, email${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"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)" \
@@ -210,7 +202,7 @@ _cat_internet_bullseye() {
"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 '"')
@@ -238,11 +230,10 @@ _cat_internet_bullseye() {
_cat_players_bullseye() {
local choices
choices=$(whiptail --title "Media Players (Bullseye)" --checklist \
"Select media players${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Media Players (Bullseye)" "Select media players${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"mpv" "Lightweight media player$(_inst mpv)" "$(_state mpv)" \
"vlc" "VLC media player$(_inst vlc)" "$(_state vlc)" \
3>&1 1>&2 2>&3)
)
clear
[ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
@@ -258,8 +249,7 @@ _cat_players_bullseye() {
_cat_design_bullseye() {
local choices
choices=$(whiptail --title "Multimedia & Design (Bullseye)" --checklist \
"Select multimedia and design tools${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Multimedia & Design (Bullseye)" "Select multimedia and design tools${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"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)" \
@@ -273,7 +263,7 @@ _cat_design_bullseye() {
"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
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
@@ -289,8 +279,7 @@ _cat_design_bullseye() {
_cat_programming_bullseye() {
local choices
choices=$(whiptail --title "Code Editors & IDEs (Bullseye)" --checklist \
"Select editors and IDEs${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Code Editors & IDEs (Bullseye)" "Select editors and IDEs${SCROLL_HINT}:" $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)" \
@@ -300,7 +289,7 @@ _cat_programming_bullseye() {
"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
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
@@ -316,8 +305,7 @@ _cat_programming_bullseye() {
_cat_dev_bullseye() {
local choices
choices=$(whiptail --title "Servers & Dev Tools (Bullseye)" --checklist \
"Select development tools and servers${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Servers & Dev Tools (Bullseye)" "Select development tools and servers${SCROLL_HINT}:" $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)" \
@@ -332,7 +320,7 @@ _cat_dev_bullseye() {
"sqlite3" "SQLite database engine$(_inst sqlite3)" "$(_state sqlite3)" \
"jellyfin" "Jellyfin Media Server (Web GUI on port 8096)$(_inst jellyfin)" OFF \
"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 '"')
@@ -379,14 +367,13 @@ _cat_dev_bullseye() {
}
_cat_security_bullseye() {
local choices
choices=$(whiptail --title "Security & Networking (Bullseye)" --checklist \
"Select security and networking tools${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Security & Networking (Bullseye)" "Select security and networking tools${SCROLL_HINT}:" $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 '"')
@@ -409,8 +396,7 @@ _cat_security_bullseye() {
_cat_general_bullseye() {
local choices
choices=$(whiptail --title "System Tools (Bullseye)" --checklist \
"Select system utilities${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "System Tools (Bullseye)" "Select system utilities${SCROLL_HINT}:" $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)" \
@@ -430,7 +416,7 @@ _cat_general_bullseye() {
"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
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
@@ -519,9 +505,8 @@ _cat_fetch_bullseye() {
)
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
local choices
choices=$(whiptail --title "Fetch Tools (Bullseye)" --checklist \
"Select system info tools:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
"${items[@]}" 3>&1 1>&2 2>&3)
choices=$(_checklist "Fetch Tools (Bullseye)" "Select system info tools:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
"${items[@]}" )
clear
[ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
@@ -544,8 +529,7 @@ install_extras_bullseye() {
while true; do
local cat_choice
cat_choice=$(whiptail --title "Extra Software — Bullseye" --menu \
"Select a category${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
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" \
@@ -559,7 +543,7 @@ install_extras_bullseye() {
"10" "System Tools" \
"11" "Fetch / System Info" \
"12" "Back to main menu" \
3>&1 1>&2 2>&3)
)
[ -z "$cat_choice" ] && return
clear
@@ -585,11 +569,10 @@ install_extras_bullseye() {
_cat_software_centers_bullseye() {
local sc_choice
sc_choice=$(whiptail --title "Software Centers" --menu \
"Choose a software store to install:" 12 65 2 \
sc_choice=$(_menu "Software Centers" "Choose a software store to install:" 12 65 2 \
"gnome-software" "Software Center for GNOME$(_inst gnome-software)" \
"plasma-discover" "Software manager for Plasma$(_inst plasma-discover)" \
3>&1 1>&2 2>&3)
)
[ -z "$sc_choice" ] && return
_run_cmd "Install" "sudo apt install -y $sc_choice" "Installing ${sc_choice}..."
+2 -3
View File
@@ -164,14 +164,13 @@ Installs matching 32-bit graphics drivers."; then
# Gaming tools checklist (no Steam, no Heroic)
local choices
choices=$(whiptail --title "Gaming Tools — Bullseye" --checklist \
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 \
3>&1 1>&2 2>&3)
"java" "Java Runtimes (8, 17, 21)" OFF)
if [ -z "$choices" ]; then
echo "No gaming tools selected."
+2 -3
View File
@@ -27,7 +27,7 @@ install_extras() {
while true; do
local cat_choice
cat_choice=$(whiptail --title "Extra Software" --menu \
cat_choice=$(_menu "Extra Software" \
"Select a category${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"0" "Essential Pack" \
"1" "Customization System" \
@@ -42,8 +42,7 @@ install_extras() {
"10" "Office & Productivity" \
"11" "System Tools" \
"12" "Fetch / System Info" \
"13" "Back to main menu" \
3>&1 1>&2 2>&3)
"13" "Back to main menu")
[ -z "$cat_choice" ] && return
clear
+2 -3
View File
@@ -19,8 +19,7 @@ _cat_design() {
local shotcut_state; shotcut_state=$(_state "shotcut")
local choices
choices=$(whiptail --title "Multimedia & Design" --checklist \
"Select multimedia and design tools${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Multimedia & Design" "Select multimedia and design tools${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"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" \
@@ -34,7 +33,7 @@ _cat_design() {
"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
[ -z "$choices" ] && return
+2 -3
View File
@@ -22,8 +22,7 @@ _cat_dev() {
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
local choices
choices=$(whiptail --title "Development & Servers" --checklist \
"Select development tools and servers${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
choices=$(_checklist "Development & Servers" "Select development tools and servers${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
"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" \
@@ -39,7 +38,7 @@ _cat_dev() {
"sqlite3" "SQLite database engine$(_inst sqlite3)" "$sqlite_state" \
"jellyfin" "Jellyfin Media Server (Web GUI on port 8096)$(_inst jellyfin)" OFF \
"openjdk-dev-env" "Adoptium Temurin JDK (17, 21, 25 LTS)${jdk_desc}" "${jdk_state}" \
3>&1 1>&2 2>&3)
)
clear
[ -z "$choices" ] && return
+4 -6
View File
@@ -21,17 +21,15 @@ _cat_download() {
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
local choices1 choices2=""
choices1=$(whiptail --title "Downloaders" --checklist \
"Select download tools:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
choices1=$(_checklist "Downloaders" "Select download tools:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
"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
choices2=$(whiptail --title "Torrent Clients" --checklist \
"Select torrent clients:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices2=$(_checklist "Torrent Clients" "Select torrent clients:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"deluge" "BitTorrent client (GTK)$(_inst deluge)" "$deluge_state" \
"deluged" "BitTorrent daemon/server$(_inst deluged)" "$deluged_state" \
"mktorrent" "Torrent metainfo creator (CLI)$(_inst mktorrent)" "$mktorrent_state" \
@@ -40,7 +38,7 @@ _cat_download() {
"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
local cleaned
+2 -3
View File
@@ -37,10 +37,9 @@ _cat_fetch() {
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
local choices
choices=$(whiptail --title "Fetch Tools" --checklist \
"Select system info tools:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
choices=$(_checklist "Fetch Tools" "Select system info tools:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
"${items[@]}" \
3>&1 1>&2 2>&3)
)
clear
[ -z "$choices" ] && return
+2 -3
View File
@@ -144,8 +144,7 @@ _cat_internet() {
local protonvpn_state; protonvpn_state=$(_state "protonvpn")
local choices
choices=$(whiptail --title "Internet" --checklist \
"Select browsers, email, and VPN tools${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Internet" "Select browsers, email, and VPN tools${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"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" \
@@ -167,7 +166,7 @@ _cat_internet() {
"mullvad-vpn" "Mullvad VPN client (WireGuard)$(_inst mullvad-vpn)" "$mullvad_state" \
"mullvad-browser" "Mullvad privacy browser$(_inst mullvad-browser)" "$mullvadbrowser_state" \
"protonvpn" "ProtonVPN client$(_inst protonvpn)" "$protonvpn_state" \
3>&1 1>&2 2>&3)
)
clear
[ -z "$choices" ] && return
+4 -6
View File
@@ -15,12 +15,11 @@ _enable_temurin_repo() {
install_minecraft_java() {
local choices
choices=$(whiptail --title "Java Runtimes for Minecraft" --checklist \
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 \
3>&1 1>&2 2>&3)
"21" "Java 21 — Modern Minecraft >= 1.20.5 & 1.21+" OFF)
[ -z "$choices" ] && { echo "No Java version selected."; return; }
_enable_temurin_repo
local cleaned
@@ -33,12 +32,11 @@ install_minecraft_java() {
_install_dev_java() {
local ver
ver=$(whiptail --title "Java Development Kits (JDK)" --menu \
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" \
3>&1 1>&2 2>&3)
"25" "Java 25 LTS Development Kit")
[ -z "$ver" ] && { echo "No JDK version selected."; return; }
_enable_temurin_repo
_run_install "temurin-${ver}-jdk"
+2 -3
View File
@@ -61,11 +61,10 @@ install_libreoffice_bpo() {
_cat_office() {
local choices
choices=$(whiptail --title "Office & Productivity" --checklist \
"Select office applications${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Office & Productivity" "Select office applications${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"onlyoffice" "OnlyOffice Desktop Editors (extrepo)" OFF \
"libreoffice" "LibreOffice (backports on Bookworm/Trixie)" OFF \
3>&1 1>&2 2>&3)
)
[ -z "$choices" ] && return
local cleaned; cleaned=$(echo "$choices" | tr -d '"')
+2 -3
View File
@@ -9,11 +9,10 @@ _cat_players() {
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
local choices
choices=$(whiptail --title "Media Players" --checklist \
"Select media players:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
choices=$(_checklist "Media Players" "Select media players:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
"mpv" "Lightweight media player$(_inst mpv)" "$mpv_state" \
"vlc" "VLC media player$(_inst vlc)" "$vlc_state" \
3>&1 1>&2 2>&3)
)
clear
[ -z "$choices" ] && return
+2 -3
View File
@@ -22,8 +22,7 @@ _cat_programming() {
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
local choices
choices=$(whiptail --title "Programming Applications" --checklist \
"Select editors and IDEs${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
choices=$(_checklist "Programming Applications" "Select editors and IDEs${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
"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" \
@@ -36,7 +35,7 @@ _cat_programming() {
"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 (extrepo)$(_inst codium)" "$codium_state" \
3>&1 1>&2 2>&3)
)
clear
[ -z "$choices" ] && return
+2 -3
View File
@@ -13,15 +13,14 @@ _cat_security() {
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
local choices
choices=$(whiptail --title "Security & Networking" --checklist \
"Select security and networking tools${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
choices=$(_checklist "Security & Networking" "Select security and networking tools${SCROLL_HINT}:" $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
[ -z "$choices" ] && return
+2 -3
View File
@@ -4,11 +4,10 @@ _cat_software_centers() {
local de_type
de_type=$(_detect_desktop_type)
local sc_choice
sc_choice=$(whiptail --title "Software Centers" --menu \
"Choose a software store to install:" 12 65 2 \
sc_choice=$(_menu "Software Centers" "Choose a software store to install:" 12 65 2 \
"gnome-software" "Software Center for GNOME$(_inst gnome-software)" \
"plasma-discover" "Software manager for Plasma$(_inst plasma-discover)" \
3>&1 1>&2 2>&3)
)
[ -z "$sc_choice" ] && return
if { [ "$de_type" = "qt" ] && [ "$sc_choice" = "gnome-software" ]; } || \
+2 -3
View File
@@ -61,8 +61,7 @@ _cat_general() {
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
local choices
choices=$(whiptail --title "System Tools" --checklist \
"Select system utilities to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
choices=$(_checklist "System Tools" "Select system utilities to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
"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" \
@@ -92,7 +91,7 @@ _cat_general() {
"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
[ -z "$choices" ] && return
+2 -3
View File
@@ -10,15 +10,14 @@ _cat_cursors() {
local oxygen_state; oxygen_state=$(_state "oxygencursors")
local choices
choices=$(whiptail --title "Cursor Themes" --checklist \
"Select cursor themes to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Cursor Themes" "Select cursor themes to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"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
[ -z "$choices" ] && return
@@ -13,8 +13,7 @@ _cat_themes() {
local orchis_state; orchis_state=$(_state "orchis-gtk-theme")
local choices
choices=$(whiptail --title "Desktop Themes (GTK/KDE)" --checklist \
"Select desktop themes to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Desktop Themes (GTK/KDE)" "Select desktop themes to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"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" \
@@ -22,7 +21,7 @@ _cat_themes() {
"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
[ -z "$choices" ] && return
+2 -3
View File
@@ -12,8 +12,7 @@ _cat_fonts() {
local recommended_state; recommended_state=$(_state "fonts-recommended")
local choices
choices=$(whiptail --title "Fonts" --checklist \
"Select fonts to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Fonts" "Select fonts to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"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" \
@@ -22,7 +21,7 @@ _cat_fonts() {
"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
[ -z "$choices" ] && return
+2 -3
View File
@@ -41,10 +41,9 @@ _cat_icons() {
fi
local choices
choices=$(whiptail --title "Icon Themes" --checklist \
"Select icon themes to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
choices=$(_checklist "Icon Themes" "Select icon themes to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"${items[@]}" \
3>&1 1>&2 2>&3)
)
clear
[ -z "$choices" ] && return
+2 -3
View File
@@ -4,13 +4,12 @@
_cat_customization() {
local TUI_ANCHO_REFORZADO=$((TUI_ANCHO + 6))
local sub
sub=$(whiptail --title "Customization System" --menu \
"Select type:" $TUI_ALTO $TUI_ANCHO_REFORZADO $TUI_ALTO_LISTA \
sub=$(_menu "Customization System" "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 ;;
+35 -97
View File
@@ -49,105 +49,20 @@ ensure_contrib_repo() {
install_gaming() {
echo -e "${YELLOW}Gaming setup...${NC}"
# 1. 32-bit support prompt FIRST
local enable_32bit=false
if _confirm "32-bit Support" "Enable i386 architecture for 32-bit games?\n\nRequired by Steam/Proton for 32-bit games.\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
case "${NVIDIA_DRIVER_MODE:-stable}" in
cuda-repo)
local nv32_pkg="nvidia-driver-libs:i386"
local nv32_ver
nv32_ver=$(dpkg -l "$nv32_pkg" 2>/dev/null | awk '/^ii/ {print $3}')
if [ -z "$nv32_ver" ] || ! echo "$nv32_ver" | grep -q "^590"; then
local msg="Source: NVIDIA CUDA Repository (Pinned v590)\n"
msg+="NVIDIA 32-bit Libraries (v590 branch)\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 32-bit NVIDIA libraries from CUDA repo..."
fi
else
_msg "NVIDIA 32-bit" \
"32-bit NVIDIA CUDA libraries already deployed.\n\nv590 ${nv32_ver}" 10 70
fi
;;
backports)
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}')
local msg="Source: Debian ${DEBIAN_CODENAME^}-Backports\n"
msg+="NVIDIA 32-bit Libraries ${nv32_ver:-unknown}\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 -t ${DEBIAN_CODENAME}-backports ${nv32_pkg}" \
"Installing 32-bit NVIDIA drivers from backports..."
fi
;;
stable)
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}')
local use_bpo32=false
if [ "$(is_backports_enabled)" == "true" ]; then
local bpo_nv32_ver
bpo_nv32_ver=$(apt-cache madison "$nv32_pkg" 2>/dev/null | \
grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1)
if [ -n "$bpo_nv32_ver" ]; then
local msg="Source: Debian ${DEBIAN_CODENAME^} (Backports available)\n"
msg+="NVIDIA 32-bit Libraries: ${nv32_pkg}\n\n"
msg+=" Backports: ${bpo_nv32_ver}\n"
msg+=" Stable: ${nv32_ver:-unknown}\n\n"
msg+="Choose version:"
if _confirm_custom "NVIDIA 32-bit" "$msg" "Backports" "Stable" 14 70; then
use_bpo32=true
fi
fi
fi
if $use_bpo32; then
_run_cmd "32-bit NVIDIA" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports ${nv32_pkg}" \
"Installing 32-bit NVIDIA drivers from backports..."
else
local msg="Source: Debian ${DEBIAN_CODENAME^} Stable\n"
msg+="NVIDIA 32-bit Libraries ${nv32_ver:-unknown}\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 32-bit NVIDIA drivers..."
fi
fi
;;
esac
else
_install_mesa_32bit
fi
fi
# 2. Gaming packages checklist
# 1. Single checklist with ALL options (including i386 toggle)
local choices
choices=$(whiptail --title "Gaming Setup" --checklist \
choices=$(_checklist "Gaming Setup" \
"Select gaming packages to install${SCROLL_HINT}:" $TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"steam" "Steam (requires 32-bit support)" ON \
"gamemode" "Game performance optimization" ON \
"mangohud" "Performance overlay (Vulkan/OpenGL)" ON \
"heroic" "Heroic Launcher (Epic/GOG)" OFF \
"java" "Java Runtimes (8, 17, 21)" OFF \
"goverlay" "MangoHud config GUI" ON \
"heroic" "Heroic Launcher (Epic/GOG)" OFF \
"java" "Minecraft Java Runtime" OFF \
"openrgb" "OpenRGB (RGB lighting control)$(_inst openrgb)" OFF \
"lutris" "Game launcher/manager" OFF \
"lutris" "Lutris + Wine (requires 32-bit support)" OFF \
"retroarch" "RetroArch Emulator Frontend$(_inst retroarch)" OFF \
3>&1 1>&2 2>&3)
"i386" "Enable 32-bit (i386) architecture" ON)
if [ -z "$choices" ]; then
echo "No gaming packages selected."
@@ -158,14 +73,37 @@ install_gaming() {
local cleaned
cleaned=$(echo "$choices" | tr -d '"')
# 3. Warn if Steam selected without 32-bit
if echo "$cleaned" | grep -qw "steam" && ! $enable_32bit; then
echo -e "${YELLOW}Warning: Steam requires 32-bit support.${NC}"
echo "Installation may fail. Re-run this option and enable 32-bit support."
# 2. Determine if 32-bit is needed (steam, lutris, or explicit i386 toggle)
local need_32bit=false
for p in $cleaned; do
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
# 4. Install selected packages
for pkg in $cleaned; do
# 4. Install 32-bit graphics drivers only if 32-bit is needed
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
steam)
if ensure_contrib_repo; then
+68 -55
View File
@@ -2,66 +2,79 @@
# Shared helpers for gaming submodules
_install_mesa_32bit() {
local mesa_pkgs=(
"mesa-vulkan-drivers" "mesa-vulkan-drivers:i386"
"libgl1-mesa-dri" "libgl1-mesa-dri:i386"
"libglx-mesa0" "libglx-mesa0:i386"
"libegl-mesa0" "libegl-mesa0:i386"
"mesa-va-drivers" "mesa-va-drivers:i386"
local base_pkgs=(
"mesa-vulkan-drivers"
"libgl1-mesa-dri"
"libglx-mesa0"
"libegl-mesa0"
"mesa-va-drivers"
"mesa-libgallium"
)
local ref_ver
ref_ver=$(apt-cache policy mesa-vulkan-drivers:i386 2>/dev/null | awk 'NR==3 {print $2; exit}')
local ref_bpo_ver
ref_bpo_ver=$(apt-cache madison mesa-vulkan-drivers:i386 2>/dev/null | \
grep "${DEBIAN_CODENAME}-backports" | awk '{print $3}' | head -1)
local comp_line="Components: Vulkan:i386, OpenGL:i386, GLX:i386, EGL:i386, VA-API:i386"
local i386_active=false
dpkg --print-foreign-architectures 2>/dev/null | grep -q i386 && i386_active=true
if [ "$(is_backports_enabled)" == "true" ] && [ -n "$ref_bpo_ver" ]; then
local bpo_pkgs=()
local stable_pkgs=()
local install_list=()
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 src_label="Debian ${DEBIAN_CODENAME^}-Backports"
[ ${#stable_pkgs[@]} -gt 0 ] && src_label+=" + Stable"
local msg="Mesa 32-bit drivers required for gaming.\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:"
if _confirm_custom "Mesa 32-bit" "$msg" "Backports" "Stable" 14 70; then
_run_cmd "Mesa 32-bit" "sudo apt install -y -t ${DEBIAN_CODENAME}-backports ${bpo_pkgs[*]}" \
"Installing 32-bit Mesa from backports..."
if [ ${#stable_pkgs[@]} -gt 0 ]; then
_run_cmd "Mesa 32-bit" "sudo apt install -y ${stable_pkgs[*]}" \
"Installing remaining 32-bit Mesa from stable..."
fi
else
_run_cmd "Mesa 32-bit" "sudo apt install -y ${mesa_pkgs[*]}" \
"Installing 32-bit Mesa from stable..."
for p in "${base_pkgs[@]}"; do
if apt-cache show "$p" >/dev/null 2>&1; then
install_list+=("$p")
fi
else
local msg="Mesa 32-bit drivers required for gaming.\n\n"
msg+="Source: Debian Stable\n"
msg+="Mesa ${ref_ver}\n"
msg+="${comp_line}\n\n"
msg+="Install Mesa 32-bit drivers?"
if _confirm "Mesa 32-bit" "$msg" 14 70; then
_run_cmd "Mesa 32-bit" "sudo apt install -y ${mesa_pkgs[*]}" \
"Installing 32-bit Mesa..."
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)..."
}
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
}
+32 -12
View File
@@ -3,17 +3,37 @@
install_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
_run_cmd "Heroic" "wget -O $heroic_deb $gh_url" "Downloading Heroic..."
_run_cmd "Heroic" "sudo apt install -y $heroic_deb" "Installing Heroic..."
rm -f "$heroic_deb"
echo -e "${GREEN}Heroic Games Launcher installed.${NC}"
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}"
}
+48 -20
View File
@@ -26,34 +26,63 @@ install_lutris() {
}
install_openrgb() {
local url
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"
else
echo "OpenRGB requires Debian 12 (Bookworm) or 13 (Trixie)."
return 1
fi
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" "curl -L -o ${deb_path} -A '${ua}' '${url}'" "Downloading OpenRGB..."
_run_cmd "OpenRGB" "sudo apt install -y curl jq" "Installing dependencies..."
if [ ! -s "${deb_path}" ]; then
echo -e "${RED}[-]${NC} Download failed: empty or missing file."
rm -f "${deb_path}"
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
echo -e "${GREEN}[+]${NC} Installing OpenRGB package..."
if ! sudo apt install -y "${deb_path}"; then
rm -f "${deb_path}"
echo -e "${RED}[-]${NC} Package installation failed."
return 1
_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
@@ -62,8 +91,7 @@ install_openrgb() {
sudo udevadm control --reload-rules && sudo udevadm trigger
sudo setcap cap_sys_rawio=ep /usr/bin/openrgb 2>/dev/null || true
rm -f "${deb_path}"
echo -e "${GREEN}OpenRGB installed. NOTE: You must reboot or log out/in for the 'i2c' group to take effect.${NC}"
echo -e "${GREEN}OpenRGB installed. Reboot or log out/in for i2c group to take effect.${NC}"
_pause
}
+200 -121
View File
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
source "${MODULES_DIR}/repos/migrate.sh" 2>/dev/null || true
# State for backup/restore
REPO_BACKUP_DIR=""
@@ -84,18 +86,19 @@ _clean_embedded_backports_deb822() {
_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: main contrib non-free non-free-firmware\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: main contrib non-free non-free-firmware\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
@@ -174,20 +177,21 @@ _remove_deb822_backports() {
_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} 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+="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 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+="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 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"
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
@@ -273,144 +277,219 @@ configure_repos() {
return 1
fi
# ── Informational banner ──
_msg "Repositories" \
"This section will automatically enable the 'contrib' and \n\
'non-free' branches in your official Debian repositories. \n\
(The 'non-free-firmware' branch is already enabled by default in Debian 12 and 13.)\n\n\
This is CRUCIAL for obtaining proprietary software packages and\n\
essential hardware drivers, including graphics drivers,\n\
Wi-Fi firmware, and CPU microcode." 14 70
# ── Repositories submenu ──
while true; do
local repo_choice
# Detect current state
local current_format
if [ "$DEBIAN_CODENAME" = "sid" ]; then
repo_choice=$(_menu "Repositories" \
"Select an option:" $TUI_ALTO $TUI_ANCHO 6 \
"1" "Enable Contrib & Non-Free Components" \
"2" "Migrate traditional sources.list to DEB822 format" \
"3" "Back to main menu")
else
repo_choice=$(_menu "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
[ -z "$repo_choice" ] && break
clear
case "$repo_choice" in
1) _repos_enable_components ;;
2) _repos_migrate_format ;;
3)
if [ "$DEBIAN_CODENAME" = "sid" ]; then
break
else
_repos_setup_backports
fi
;;
4) _branch_migration || true ;;
5) break ;;
esac
done
}
# ---------------------------------------------------------------------------
# Submenu helpers
# ---------------------------------------------------------------------------
_components_enabled() {
if [ -f /etc/apt/sources.list.d/debian.sources ]; then
grep -qE "^Components:.*\b(contrib|non-free)\b" /etc/apt/sources.list.d/debian.sources 2>/dev/null && return 0
fi
if [ -f /etc/apt/sources.list ]; then
grep -qE "^[^#]*\b(contrib|non-free)\b" /etc/apt/sources.list 2>/dev/null && return 0
fi
return 1
}
_repos_offer_upgrade() {
local upgradable
upgradable=$(apt list --upgradable 2>/dev/null | grep -c /)
if [ "$upgradable" -gt 0 ]; then
if _confirm "Upgrade System" "$upgradable packages can be upgraded. Upgrade now?"; then
sudo apt-mark hold tzdata 2>/dev/null || true
_run_cmd "Upgrade" "sudo apt upgrade -y" "Upgrading system..."
sudo apt-mark unhold tzdata 2>/dev/null || true
sudo apt autoremove -y
sudo apt autoclean
echo -e "${GREEN}System upgraded.${NC}"
else
echo "Skipping upgrade."
fi
fi
}
_repos_enable_components() {
local current_format bp_enabled bp_location components
current_format=$(detect_repo_format)
local bp_status
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\n\
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
restore_previous_repos
echo -e "${RED}apt update failed. Previous configuration restored.${NC}"
fi
_pause
}
_repos_migrate_format() {
local current_format bp_enabled bp_location
current_format=$(detect_repo_format)
if [ "$current_format" != "classic" ]; then
echo "Repositories are already in DEB822 format."
_pause
return
fi
if [ "$DEBIAN_CODENAME" != "trixie" ]; then
echo "Format migration is only relevant for Debian 13 (Trixie)."
_pause
return
fi
# Preserve existing backports state across format migration
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
_write_deb822 "$DEBIAN_CODENAME" "migrate" "$bp_enabled" "$bp_location"
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
restore_previous_repos
echo -e "${RED}apt update failed. Backup restored.${NC}"
fi
_pause
}
_repos_setup_backports() {
local current_format bp_status bp_location
current_format=$(detect_repo_format)
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)"
echo "Backports are currently $bp_status."
# ── Format selection dialog (only Trixie gets the choice) ──
local use_deb822=false
if [ "$DEBIAN_CODENAME" = "trixie" ]; then
if whiptail --title "Repository Format" --defaultno --yesno \
"Do you want to migrate your repositories to the new
DEB822 (.sources) format?
DEB822 is the modern, structured Debian standard. It won't
harm your system, and the script will handle the transition
safely if you accept.
NOTE: 'NO' (default) is recommended to maintain the classic
linear format as it comes pre-configured in Debian 13 (Trixie)." 16 70; then
use_deb822=true
fi
elif [ "$current_format" = "deb822" ]; then
use_deb822=true
fi
# Choose backports
local enable_backports=false
if _confirm "Backports" "Do you want to enable the official Debian Backports repository?\n\n\
Backports provides newer, selectively updated packages from the\n\
next Debian testing branch, recompiled to run stably on your\n\
current system.\n\n\
This is HIGHLY RECOMMENDED if you have modern hardware, as it\n\
delivers newer Linux Kernels, updated display drivers, and modern\n\
Mesa versions without compromising overall system stability." 16 70; then
Backports provides newer, selectively updated packages from the next\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
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
# 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 $use_deb822; then
_write_deb822 "$DEBIAN_CODENAME" "$action" "$enable_backports" "$bp_location"
if $enable_backports; then
if [ "$current_format" = "deb822" ]; then
_write_deb822_backports "$DEBIAN_CODENAME"
else
_write_classic_backports "$DEBIAN_CODENAME"
fi
else
_write_classic "$DEBIAN_CODENAME" "$action" "$enable_backports" "$bp_location"
if [ "$current_format" = "deb822" ]; then
_remove_deb822_backports "$DEBIAN_CODENAME"
else
_remove_classic_backports "$DEBIAN_CODENAME"
fi
fi
echo "Updating package lists..."
sudo apt update
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
# Remove any leftover disabled files from old classic format
[ -f /etc/apt/sources.list.disabled ] && sudo rm -f /etc/apt/sources.list.disabled
else
[ -f /etc/apt/sources.list.d/debian.sources.disabled ] && sudo rm -f /etc/apt/sources.list.d/debian.sources.disabled
fi
if sudo apt update; then
cleanup_repo_backup
local upgradable
upgradable=$(apt list --upgradable 2>/dev/null | grep -c /)
if [ "$upgradable" -gt 0 ]; then
if _confirm "Upgrade System" "$upgradable packages can be upgraded. Upgrade now?"; then
sudo apt-mark hold tzdata 2>/dev/null || true
_run_cmd "Upgrade" "sudo apt upgrade -y" "Upgrading system..."
sudo apt-mark unhold tzdata 2>/dev/null || true
sudo apt autoremove -y
sudo apt autoclean
echo -e "${GREEN}System upgraded.${NC}"
_pause
else
echo "Skipping upgrade."
fi
fi
echo -e "${GREEN}Backports configured.${NC}"
else
restore_previous_repos
echo -e "${RED}apt update failed. Previous repository configuration restored.${NC}"
_pause
return 1
echo -e "${RED}apt update failed. Backup restored.${NC}"
fi
_pause
}
+176
View File
@@ -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 "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 || true
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 "Migration Plan" "$plan" 16 70 || true
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 "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
}
+2 -3
View File
@@ -56,13 +56,12 @@ _rescue_initramfs() {
rescue_boot() {
while true; do
local choice
choice=$(whiptail --title "Boot Rescue & Repair" --menu \
choice=$(_menu "Boot Rescue & Repair" \
"Select a rescue operation${SCROLL_HINT}:" \
$TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"1" "Refirm Secure Boot (shim + GRUB)" \
"2" "Regenerate initramfs (all kernels)" \
"3" "Return to main menu" \
3>&1 1>&2 2>&3)
"3" "Return to main menu")
[ -z "$choice" ] && return
clear
+7 -12
View File
@@ -7,14 +7,13 @@ config_sudo() {
while true; do
local choice
choice=$(whiptail --title "User Privileges & Feedback" --menu \
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" \
3>&1 1>&2 2>&3)
"5" "Back to main menu")
[ -z "$choice" ] && return
clear
@@ -67,12 +66,11 @@ _configure_nopasswd() {
- shutdown / reboot / halt (power commands)\n\n\
Useful for automation but reduces security." 14 70; then
local choices
choices=$(whiptail --title "NOPASSWD Commands" --checklist \
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 \
3>&1 1>&2 2>&3)
"power" "Shutdown, reboot, halt" ON)
clear
[ -z "$choices" ] && { echo "No commands selected."; return; }
@@ -93,12 +91,10 @@ Useful for automation but reduces security." 14 70; then
esac
done
echo -e "$content" | sudo tee "$nopasswd_file" > /dev/null
sudo chmod 0440 "$nopasswd_file"
if [ -f "$nopasswd_file" ]; then
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
echo -e "${RED}Failed to configure passwordless sudo.${NC}"
return 1
fi
fi
@@ -148,10 +144,9 @@ _toggle_pwfeedback() {
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
if _validate_sudoers 'Defaults pwfeedback' "$fb_file"; then
echo -e "${GREEN}Password feedback enabled.${NC}"
else
echo -e "${RED}Failed to create $fb_file${NC}"
return 1
fi
fi
+187
View File
@@ -0,0 +1,187 @@
#!/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() {
echo "── Current swap ──"
sudo swapon --show 2>/dev/null || echo "(none active)"
echo ""
echo "swappiness: $(cat /proc/sys/vm/swappiness)"
echo ""
echo "fstab swap entries:"
grep -E 'swap|SWAP' /etc/fstab 2>/dev/null || echo "(none in fstab)"
_pause
}
_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 (disk)" \
"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>&-
}
+46 -7
View File
@@ -369,23 +369,31 @@ detect_displayserver() {
}
# ---------------------------------------
# Storage summary via lsblk (NVMe / SSD / HDD)
# Storage summary via lsblk (NVMe / SSD / HDD / USB-SD)
# ---------------------------------------
detect_storage() {
local parts=()
local name size rota type
local name size rota type rm
while read -r name size rota; do
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
type="SSD"
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 2>/dev/null || true)
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"
@@ -539,7 +547,38 @@ _confirm_custom() {
}
_msg() {
whiptail --title "$1" --msgbox "$2" "${3:-10}" "${4:-65}"
whiptail --title "$1" --msgbox "$2" "${3:-10}" "${4:-65}" || 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 ! visudo -cf "$tmpfile" &>/dev/null; then
local err
err=$(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() {
@@ -554,7 +593,7 @@ _run_cmd() {
clear
echo -e "${GREEN}[+]${NC} $success_msg"
echo "──────────────────────────────────────────────"
eval "$command"
bash -c "$command"
local rc=$?
echo "──────────────────────────────────────────────"
if [ $rc -eq 0 ]; then
+3 -5
View File
@@ -12,7 +12,7 @@ install_zram() {
local half_ram_mb=$(( ((RAM_KB / 1024 / 1024 + 1) / 2) * 1024 ))
local algo
algo=$(whiptail --title "ZRAM Compression" --menu \
algo=$(_menu "ZRAM Compression" \
"ZRAM compresses a portion of RAM into compressed swap,\
effectively increasing available memory.
@@ -22,8 +22,7 @@ more swap space without disk writes.
Choose compression algorithm:" \
$TUI_ALTO $TUI_ANCHO $TUI_ALTO_LISTA \
"lz4" "Fastest, low CPU (recommended)" \
"zstd" "Better ratio, more CPU" \
3>&1 1>&2 2>&3)
"zstd" "Better ratio, more CPU")
if [ -z "$algo" ]; then
echo "ZRAM configuration cancelled."
@@ -34,8 +33,7 @@ Choose compression algorithm:" \
if _confirm "ZRAM Size" "Use recommended size for ZRAM? (${half_ram_mb} MB out of ${RAM_SUMMARY})"; then
zram_size=$half_ram_mb
else
zram_size=$(whiptail --title "ZRAM Size" --inputbox \
"Enter ZRAM size in MB:" 8 60 "$half_ram_mb" 3>&1 1>&2 2>&3)
zram_size=$(_inputbox "ZRAM Size" "Enter ZRAM size in MB:" 8 60 "$half_ram_mb")
if [ -z "$zram_size" ] || ! [[ "$zram_size" =~ ^[0-9]+$ ]] || [ "$zram_size" -eq 0 ]; then
echo "ZRAM configuration cancelled."
return 0