diff --git a/.gitignore b/.gitignore index 3df2db3..c5f797f 100644 --- a/.gitignore +++ b/.gitignore @@ -90,3 +90,5 @@ fabric.properties # Built Visual Studio Code Extensions *.vsix + +.junie/plans diff --git a/00-run-as-root.sh b/00-run-as-root.sh deleted file mode 100755 index 20f816a..0000000 --- a/00-run-as-root.sh +++ /dev/null @@ -1,15 +0,0 @@ -if [ "$(id -u)" -ne 0 ]; then - echo "❌ The Skript has to be run as root!" - exit 1 -fi - -# Update -apt update && apt upgrade -y - -# Install first important Packages -apt install ca-certificates curl git gpg imagemagick lsb-release network-manager openssh-server rsync sudo wget - -sudo usermod -aG sudo $USER -sudo usermod -aG sudo root - -echo "Now, you have to relogin for the next scripts to work!" diff --git a/01-apt-configure.sh b/01-apt-configure.sh deleted file mode 100755 index 0b2b816..0000000 --- a/01-apt-configure.sh +++ /dev/null @@ -1,27 +0,0 @@ -if [ "$(id -u)" -ne 0 ]; then - echo "❌ The Skript has to be run as root!" - exit 1 -fi - -apt modernize-sources -# Add 32bit-Architecture -#dpkg --add-architecture i386 - -# Install gitea Keyrings -sudo curl https://gitea.creative-dragonslayer.de/api/packages/Linuxapps/debian/repository.key -o /etc/apt/keyrings/gitea-Linuxapps.asc -sudo curl https://gitea.creative-dragonslayer.de/api/packages/Mirror/debian/repository.key -o /etc/apt/keyrings/gitea-Mirror.asc - -# Install my apt-sources -rm /etc/apt/sources.list -rm /etc/apt/sources.list~ -rm /etc/apt/sources.list.bak -rm -r /etc/apt/sources.list.d -mkdir -p /etc/apt/sources.list.d -cp ./data/apt/sources.list.d/* /etc/apt/sources.list.d/ - -# Install my apt-pinning -rm -r /etc/apt/preferences.d -mkdir -p /etc/apt/preferences.d -cp ./data/apt/preferences.d/* /etc/apt/preferences.d/ - -apt update diff --git a/02-execute-as-user.sh b/02-execute-as-user.sh deleted file mode 100755 index 0c71132..0000000 --- a/02-execute-as-user.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -sh <(curl -L https://raw.githubusercontent.com/LinuxBeginnings/Debian-Hyprland/main/auto-install.sh) diff --git a/03-install.sh b/03-install.sh deleted file mode 100755 index 2ded16a..0000000 --- a/03-install.sh +++ /dev/null @@ -1,132 +0,0 @@ -#!/bin/bash - -if [ "$(id -u)" -ne 0 ]; then - echo "❌ The Skript has to be run as root!" - exit 1 -fi - -# Install XanModKernel -wget -qO - https://dl.xanmod.org/archive.key | gpg --dearmor -vo /etc/apt/keyrings/xanmod-archive-keyring.gpg -echo "deb [signed-by=/etc/apt/keyrings/xanmod-archive-keyring.gpg] http://deb.xanmod.org $(lsb_release -sc) main" | tee /etc/apt/sources.list.d/xanmod-release.list -apt update && apt install linux-xanmod-x64v3 - -# Install apt-Packages -apt install -y 7zip -apt install -y adb amberol apparmor apparmor-notify apparmor-profiles apparmor-profiles-extra apparmor-utils aptitude apt-listbugs apt-listchanges -apt install -y baobab bat bleachbit blueman bluetooth bluez bruno btop -apt install -y cava clamav clamav-daemon clamav-docs clamav-freshclam codium command-not-found cpupower-gui cryptomator -apt install -y dconf-editor debian-goodies -apt install -y easyeffects -apt install -y fastfetch ffmpeg file-roller firmware-linux firmware-linux-nonfree firmware-misc-nonfree flameshot flatpak flatseal floorp fragments fzf -apt install -y gameconqueror gamemode gamescope gimp glances gnome-calculator gnome-decoder gnome-disk-utility gnome-firmware gnome-font-viewer gnome-keyring gnome-logs gnome-snapshot gnome-system-monitor gnome-text-editor gparted grim -apt install -y htop hunspell hunspell-de-de-frami -apt install -y impression input-remapper irqbalance -# j -apt install -y keepassxc -apt install -y libreoffice libreoffice-gtk4 libreoffice-l10n-de localsend loupe lsd -apt install -y man mangoapp mangohud mesa-utils mesa-vulkan-drivers vulkan-tools -apt install -y network-manager-gnome nodejs nwg-displays nwg-look -apt install -y obfuscate openrgb -apt install -y pipewire pipewire-pulse plymouth plymouth-themes prismlauncher protontricks -# q -apt install -y radeontop remmina resources rfkill ripgrep rpi-imager -apt install -y sddm simple-scan sl slurp speech-dispatcher steam-devices swappy swaybg systemd-timesyncd -apt install -y tar tealdeer timeshift thunar topgrade tree -apt install -y unrar unzip -apt install -y vesktop vlc vlc-data vlc-l10n vlc-plugin-access-extra vlc-plugin-base vlc-plugin-notify vlc-plugin-pipewire vlc-plugin-qt vlc-plugin-video-output -apt install -y wayland-utils wine winetricks wireplumber wl-clipboard -apt install -y xdg-user-dirs -apt install -y yazi -apt install -y zram-tools zsh - -# TODO PDF-Editor finden - -# Enable Services -sudo systemctl enable apparmor -sudo systemctl start apparmor - -# Set Default Apps -xdg-mime default org.gnome.Loupe.desktop image/jpeg -xdg-mime default org.gnome.Loupe.desktop image/png - -xdg-mime default io.bassi.Amberol.desktop audio/mpeg -xdg-mime default io.bassi.Amberol.desktop audio/x-wav -xdg-mime default io.bassi.Amberol.desktop audio/flac -xdg-mime default io.bassi.Amberol.desktop audio/ogg - -xdg-mime default org.gnome.TextEditor.desktop text/plain -xdg-mime default org.gnome.TextEditor.desktop text/x-log -xdg-mime default org.gnome.TextEditor.desktop text/markdown - -# Set plymout-Theme -sudo plymouth-set-default-theme -R solar - -sudo update-initramfs -u -sudo update-grub - -# Add flathub -flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo - -# Install Docker -# Add Docker's official GPG key: -sudo install -m 0755 -d /etc/apt/keyrings -sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc -sudo chmod a+r /etc/apt/keyrings/docker.asc - -# Add the repository to Apt sources: -sudo tee /etc/apt/sources.list.d/docker.sources <> /etc/zsh/zprofile - -# copy config folder -cp -r $HOME/.config $DEFAULT_USR_FOLDER/.config - -# copy templates -cp -r ./data/home/templates $DEFAULT_USR_FOLDER/templates - -# set zsh as default shell -USER_ENTRY=$(getent passwd "$USER") -cp /etc/passwd /etc/passwd.bak - -if grep -q "^$USER:" /etc/passwd; then - sed -i "/^$USER:/s|[^:]*$|/bin/zsh|" /etc/passwd -else - UPDATED_ENTRY=$(echo "$USER_ENTRY" | awk -F: -v OFS=: '{ $NF="/bin/zsh"; print }') - echo "$UPDATED_ENTRY" >>/etc/passwd -fi diff --git a/06-fonts.sh b/06-fonts.sh deleted file mode 100755 index 108e161..0000000 --- a/06-fonts.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -FONT_DIR=/usr/share/fonts - -if [ "$(id -u)" -ne 0 ]; then - echo "❌ The Skript has to be run as root!" - exit 1 -fi - -# Install Jetbrains Mono Nerd Font -wget -q https://github.com/ryanoasis/nerd-fonts/releases/latest/download/JetBrainsMono.tar.xz -mkdir -p $FONT_DIR/JetBrainsMonoNerd -tar -xJkf JetBrainsMono.tar.xz -C $FONT_DIR/JetBrainsMonoNerd - -# Install Fantasque Mono Nerd Font -wget -q https://github.com/ryanoasis/nerd-fonts/releases/download/v3.3.0/FantasqueSansMono.zip -mkdir -p $FONT_DIR/FantasqueSansMonoNerd -unzip -o -q "FantasqueSansMono.zip" -d "$FONT_DIR/FantasqueSansMonoNerd" - -# Install Victor Mono Font -wget -q https://rubjo.github.io/victor-mono/VictorMonoAll.zip -mkdir -p $FONT_DIR/VictorMono -unzip -o -q "VictorMonoAll.zip" -d "$FONT_DIR/VictorMono" - -fc-cache -v - -if [ -d "JetBrainsMono.tar.xz" ]; then - rm -r JetBrainsMono.tar.xz 2>&1 | tee -a "$LOG" -fi diff --git a/07-programs.sh b/07-programs.sh deleted file mode 100755 index 63565a1..0000000 --- a/07-programs.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -# Betterbird als Standard-Mail-Programm setzen -flatpak install eu.betterbird.Betterbird -y # TODO Durch Melia ersetzen -xdg-mime default org.betterbird.Betterbird.desktop x-scheme-handler/mailto - -# Alpaca -flatpak install flathub com.jeffser.Alpaca -y - -# Web App Hub -flatpak install flathub org.pvermeer.WebAppHub -y -# Musescore -flatpak install flathub org.musescore.MuseScore -y -# Fluffychat (Matrix) -flatpak install flathub im.fluffychat.Fluffychat -y -# Flatsweep -flatpak install flathub io.github.giantpinkrobots.flatsweep -y - -# Steam -flatpak install flathub com.valvesoftware.Steam -y -# Heroic -flatpak install flathub com.heroicgameslauncher.hgl -y -# Lutris -flatpak install flathub net.lutris.Lutris -y - -# Gamescope -flatpak install flathub org.freedesktop.Platform.VulkanLayer.gamescope -y -# MangoHud -flatpak install flathub org.freedesktop.Platform.VulkanLayer.MangoHud -y -# GE-Proton -flatpak install flathub com.valvesoftware.Steam.CompatibilityTool.Proton-GE -y - -# Proton Up-QT -flatpak install flathub net.davidotek.pupgui2 -y -# Scopebuddy GUI -flatpak install flathub io.github.rfrench3.scopebuddy-gui -y diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..f8d7b8c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,201 @@ +# AGENTS.md — Richtlinien und Architektur-Leitfaden für KI-Agenten + +Dieses Dokument enthält Richtlinien, Architekturstandards, Konventionen und Arbeitsanweisungen für KI-Agenten und Entwickler, die an diesem Repository arbeiten oder es warten. + +--- + +## 1. Projektübersicht + +Dieses Repository ist ein modulares, automatisiertes Setup- und Konfigurations-Framework für **Debian GNU/Linux Unstable (Sid)** mit: +- **Hyprland** (Wayland-Compositor) und Waybar-Desktopumgebung +- **XanMod-Kernel** (main/edge) mit CPU P-State-Tuning (AMD/Intel) und `auto-cpufreq` +- **Bootloader & Splash**: GRUB-Konfiguration mit Vimix-Theme und Plymouth Solar-Splash +- **Gaming & Multimedia**: MangoHud, Gamescope, Lutris, Steam, Wine, Pro-Audio via PipeWire +- **Virtualisierung & Container**: QEMU/KVM, Libvirt, Docker, Waydroid +- **Paket- und Anwendungsmanagement**: Deb822-Quellen, APT-Pinning, Flatpaks (Flathub), isolierte Schriften-Installation + +--- + +## 2. Projekt- und Verzeichnisstruktur + +``` +. +├── setup.sh # Zentraler Orchestrator (CLI Flags & whiptail TUI) +├── lib/ # Wiederverwendbare Funktionsbibliotheken +│ ├── utils.sh # Logging, Error-Traps, Benutzer- und Pfadermittlung, Backups +│ ├── apt.sh # Deb822-Quellen, Keyrings (/etc/apt/keyrings), APT-Pinning, Paketinstallation +│ └── tui.sh # Whiptail-TUI-Menüs und Dialoge +├── config/ # Konfigurationsdateien & Paketlisten +│ ├── setup.conf # Globale Umgebungsvariablen und Standardwerte +│ └── packages/ # Thematisch gegliederte Paketlisten (*.list) +│ ├── 01-base.list # Basiswerkzeuge, Firmware, Microcode +│ ├── 02-desktop.list # Hyprland, Waybar, SDDM, XDG-Portale, PipeWire +│ ├── 03-gaming.list # Steam-Devices, Lutris, Gamescope, MangoHud, Wine +│ ├── 04-virtualization.list # QEMU, KVM, Libvirt, Bridge-Tools +│ ├── 05-multimedia.list # VLC, Amberol, GIMP, Loupe, LibreOffice +│ └── 06-flatpaks.list # Flathub App-IDs +├── stages/ # Sequenziell und modular ausführbare Phasen (00 bis 09) +│ ├── 00-preflight.sh # Systemvoraussetzungen, Root/User-Erkennung, Internetverbindung +│ ├── 01-apt-unstable.sh # Deb822-Quellen, Keyrings, Pinning, apt-listbugs, dist-upgrade +│ ├── 02-kernel-hardware.sh # XanMod-Kernel, CPU P-State, Microcode, auto-cpufreq +│ ├── 03-bootloader.sh # GRUB Kernel-Parameter, Vimix-Theme, Plymouth Solar +│ ├── 04-packages.sh # Installation der thematischen Paketlisten +│ ├── 05-fonts.sh # Download & Installation von Coding- & Nerd-Fonts +│ ├── 06-services.sh # Aktivierung von AppArmor, Docker, Libvirt, zram +│ ├── 07-skel-and-user.sh # /etc/skel Vorlagen, ZSH-Shell-Setzen, Dotfiles-Sync +│ ├── 08-flatpaks-apps.sh # Flathub Setup, Flatpaks, Spotify, Waydroid, MIME-Types +│ └── 09-hyprland.sh # LinuxBeginnings Debian-Hyprland Auto-Installer +├── data/ # Statische Konfigurationsdateien & Vorlagen +│ ├── apt/ +│ │ ├── sources.list.d/ # Deb822-Quellen (debian-unstable.sources, xanmod.sources) +│ │ └── preferences.d/ # Pinning-Konfigurationen +│ ├── etc/ +│ │ ├── environment.d/ # Globale Umgebungsvariablen (Raytracing, Upscaling) +│ │ └── profile.d/ # Globale Profil-Skripte (z. B. XDG User Dirs Update) +│ ├── skel/ # Vorlagen für /etc/skel (.zshrc, Dokumentvorlagen) +│ └── usr/share/applications/ # Desktop-Starter-Dateien +├── README.md # Projektdokumentation für Endanwender +└── LICENSE # MIT-Lizenz +``` + +--- + +## 3. Architekturprinzipien und Entwicklungsrichtlinien + +### 3.1 Idempotenz (Mehrfache Ausführbarkeit) +- Jedes Skript und jede Phase muss **vollständig idempotent** sein: Die wiederholte Ausführung darf keine Fehler erzeugen und keine doppelten Konfigurationseinträge hinterlassen. +- Verwende vor dem Hinzufügen von Zeilen zu Konfigurationsdateien Prüfungen (z. B. `grep -q`) oder nutze saubere Konfigurationsverzeichnisse (`.d/`-Verzeichnisse). + +### 3.2 Strikte Trennung von Root- und Benutzerrechten +- Die Skripte laufen grundsätzlich mit Root-Rechten (`sudo ./setup.sh`). +- **Niemals** Benutzerkonfigurationen unter `/root/` ablegen, wenn sie für den Desktop-Benutzer gedacht sind. +- Der Zielbenutzer wird in `$TARGET_USER` gespeichert (ermittelt über `prompt_target_user` in `lib/utils.sh`). +- Befehle im Kontext des regulären Benutzers **müssen** über `run_as_user ""` ausgeführt werden. +- Das Home-Verzeichnis des Zielbenutzers muss über `get_target_home "$TARGET_USER"` ermittelt werden. + +### 3.3 Fehlerbehandlung und Shell-Standards +- Alle Bash-Skripte **müssen** mit folgenden Flags starten: + ```bash + #!/usr/bin/env bash + set -euo pipefail + ``` +- Binde `lib/utils.sh` ein und rufe `setup_err_trap` am Anfang jedes Skripts auf: + ```bash + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + # shellcheck source=lib/utils.sh + source "$SCRIPT_DIR/../lib/utils.sh" + setup_err_trap + ``` +- Verwende für temporäre Verzeichnisse immer `mktemp -d` und stelle sicher, dass am Skriptende oder bei Fehlern aufgeräumt wird: + ```bash + TMP_DIR="$(mktemp -d)" + trap 'rm -rf "$TMP_DIR"' EXIT + ``` + +### 3.4 Dateisicherungen (Backups) +- Modifiziere bestehende Konfigurationsdateien (z. B. in `/etc/default/grub` oder `/etc/apt/`) nie ohne vorheriges Backup. +- Nutze die Bibliotheksfunktion `backup_file "$DATEIPFAD"`. Diese erstellt Backups im Format `.backup_YYYYMMDD_HHMMSS`. + +### 3.5 Debian-Standards & APT-Hygiene +- **Deb822-Format**: Neue Paketquellen ausschließlich im Deb822-Format (`.sources`) unter `/etc/apt/sources.list.d/` ablegen. +- **Keyrings**: GPG-Schlüsselbunde gehören nach `/etc/apt/keyrings/` mit Rechten `644`. Das veraltete `apt-key` darf **nicht** verwendet werden. +- **Pinning**: APT-Prioritäten in `/etc/apt/preferences.d/` verwalten. +- **Nicht-interaktive Paketinstallation**: APT-Befehle müssen immer `DEBIAN_FRONTEND=noninteractive` und `-y` bzw. `--no-install-recommends` (sofern passend) verwenden. Verwende bevorzugt die Wrapper in `lib/apt.sh` (`safe_apt_update`, `install_packages_from_file`). + +### 3.6 Keine gefährlichen Login-Hooks & Shell-Verwaltung +- **Keine Live-Downloads** (`curl | sh` / `wget | bash`) in `/etc/profile.d/` oder Login-Skripten. +- Dotfiles und Vorlagen gehören nach `/etc/skel/` und werden bei Bedarf einmalig für bestehende Nutzer synchronisiert (`stages/07-skel-and-user.sh`). +- Ändere Login-Shells niemals durch direkte Bearbeitung von `/etc/passwd` via `sed` oder `awk`, sondern ausschließlich über `chsh -s "$(command -v zsh)" "$TARGET_USER"`. + +--- + +## 4. Hilfsbibliotheken (`lib/`) + +### `lib/utils.sh` +- `log_info "Nachricht"`: Blaue Info-Meldung. +- `log_success "Nachricht"`: Grüne Erfolgsmeldung (`[✓]`). +- `log_warn "Nachricht"`: Gelbe Warnung (`[WARN]`). +- `log_error "Nachricht"`: Rote Fehlermeldung (`[ERROR]`). +- `log_step "Titel"`: Hervorgehobener Abschnitts-Header. +- `log_substep "Titel"`: Eingerückter Unterabschnitt. +- `require_root`: Bricht ab, wenn das Skript nicht mit Root-Rechten ausgeführt wird. +- `command_exists "tool"`: Prüft, ob ein Befehl im Pfad verfügbar ist. +- `prompt_target_user`: Erkennt `$SUDO_USER` oder fragt interaktiv nach dem Zielbenutzer. +- `get_target_home [username]`: Gibt den absoluten Pfad des Home-Verzeichnisses des Nutzers zurück. +- `run_as_user "command"`: Führt einen Befehl als `$TARGET_USER` via `su - "$TARGET_USER" -c ...` aus. +- `backup_file "filepath"`: Erstellt ein Backup einer Datei mit Zeitstempel. + +### `lib/apt.sh` +- `safe_apt_update`: Führt ein abgesichertes `apt-get update` durch. +- `install_apt_keyring "name" "url"`: Lädt einen GPG-Schlüssel herunter, de-armort ihn sauber und speichert ihn in `/etc/apt/keyrings/.gpg`. +- `install_packages_from_file "filepath"`: Liest eine `.list`-Datei ein (ignoriert Kommentare `#` und Leerzeilen) und installiert alle Pakete via `apt-get install -y`. + +### `lib/tui.sh` +- `tui_show_stage_selection`: Zeigt ein `whiptail` Checklist-Menü zur interaktiven Auswahl der auszuführenden Phasen. + +--- + +## 5. Arbeitsanweisungen für Modifikationen + +### Neue Phase (Stage) hinzufügen +1. Erstelle eine neue Datei `stages/XX-.sh` (nummeriert nach Reihenfolge, mit `chmod +x`). +2. Nutze das Standard-Template: + ```bash + #!/usr/bin/env bash + # ============================================================================== + # stages/XX-.sh - Kurzbeschreibung der Phase + # ============================================================================== + set -euo pipefail + + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + # shellcheck source=lib/utils.sh + source "$SCRIPT_DIR/../lib/utils.sh" + + setup_err_trap + require_root + + log_step "Stage XX: " + + TARGET_USER="${TARGET_USER:-$(prompt_target_user)}" + TARGET_HOME="$(get_target_home "$TARGET_USER")" + + # Implementierung (idempotent) ... + + log_success "Stage XX abgeschlossen." + ``` +3. Registriere die neue Phase im Orchestrator `setup.sh` (Hilfetext `show_help`, Validierung in `run_stages`). +4. Ergänze die Phase im TUI-Auswahlmenü in `lib/tui.sh`. +5. Aktualisiere `README.md`. + +### Paketlisten anpassen +- Paketdateien liegen unter `config/packages/.list`. +- Jede Zeile enthält genau einen Paketnamen. +- Kommentare beginnen mit `#`. Leerzeilen sind erlaubt. + +### Vorlagen und Skel-Dateien hinzufügen +- Konfigurationsvorlagen für neue Benutzer gehören in `data/skel/`. +- Dateivorlagen für den Dateimanager (XDG Templates) gehören nach `data/skel/Templates/`. + +--- + +## 6. Verifikation & Qualitätssicherung + +Bevor Änderungen eingecheckt oder abgeschlossen werden: + +1. **ShellCheck ausführen**: + Alle Bash-Skripte auf statische Fehler und Warnungen prüfen: + ```bash + shellcheck setup.sh lib/*.sh stages/*.sh + ``` +2. **Dry-Run Validierung**: + Sicherstellen, dass der Orchestrator im Simulationsmodus funktioniert: + ```bash + ./setup.sh --dry-run --stages 00,01,02 + ``` +3. **Syntaxprüfung**: + ```bash + bash -n setup.sh + for f in lib/*.sh stages/*.sh; do bash -n "$f"; done + ``` +4. **Pfad- und Berechtigungskonsistenz**: + Prüfen, dass keine absoluten Pfade auf Benutzerverzeichnisse (`/home/...`) hartcodiert sind. diff --git a/README.md b/README.md index 35a7107..e65084e 100644 --- a/README.md +++ b/README.md @@ -1,71 +1,130 @@ -# Setup +# Debian Unstable (Sid) & Hyprland Setup Framework -## Übersicht +Ein modulares, sicheres und erweiterbares Framework zur automatisierten Einrichtung von **Debian GNU/Linux Unstable (Sid)** mit Hyprland Desktop, XanMod-Kernel, Hardware-Tuning und thematisch gegliederten Anwendungen. -Dieses Repository enthält Skripte um ein Linux System mit Hyprland und diversen Programmen aufzusetzen. -Die entsprechenden Skripte befinden sich in den Branches zur jeweiligen Distribution. +--- -Der Hauptbranch ist für ein aktuelles Debian-System gedacht! +## 🚀 Schnellstart -## Anforderungen - -Um die Skripte in diesem Repository auszuführen, stelle sicher, dass die folgenden Voraussetzungen erfüllt sind: - -- Die Skripte sind als bash-Skripte konzipiert. -- Für die Skripte muss der richtige Branch der jewiligen Distribution ausgewählt werden. -- Daten werden vor der Ausführung nicht gesichert. Datenverlust möglich! - -## Nutzung - -1. Klone das Repository: - ```bash - git clone https://gitea.creative-dragonslayer.de/Scripts/Setup.git - ``` -2. Wechsle in den richtigen Branch. -3. Navigiere in das Verzeichnis `Setup`, um die ausführbaren Dateien und Ressourcen zu finden. -4. Folge den spezifischen Anweisungen in einzelnen Dateien oder Skripten für die korrekte Ausführung. - -## Nach der Nutzung -### Für AMD-CPUs -#### Game-Launchparameter +### 1. Interaktiver TUI-Modus (Empfohlen) +Starte das grafische Terminal-Menü (`whiptail`) zur flexiblen Auswahl einzelner Module: ```bash -GLOBAL — All games: -RADV_PERFTEST=gpl,rt DXVK_ASYNC=1 VKD3D_CONFIG=dxr,dxr11 MESA_VK_WSI_PRESENT_MODE=mailbox gamemoderun gamescope -W 2560 -H 1440 --force-grab-cursor --hdr-enabled --adaptive-sync -f -o 240 -r 240 -- mangohud %command% +sudo ./setup.sh +``` -DEMANDING GAMES — No RT: -RADV_PERFTEST=gpl,ngg_streamout WINE_FULLSCREEN_FSR=1 DXVK_ASYNC=1 gamemoderun gamescope -W 2560 -H 1440 --force-grab-cursor --hdr-enabled --adaptive-sync -f -o 240 -r 240 -- mangohud %command% +### 2. Vollautomatischer CLI-Modus +Führe alle Phasen (`00` bis `09`) ohne Interaktion aus: +```bash +sudo ./setup.sh --all +``` -RAY TRACING — DX12 titles: +### 3. Gezielte Modulauswahl +Installiere nur bestimmte Phasen (z. B. nur Paketlisten und Schriften): +```bash +sudo ./setup.sh --stages 04,05 +``` + +### 4. Simulationslauf (Dry-Run) +Überprüfe geplante Aktionen, ohne Änderungen am System vorzunehmen: +```bash +./setup.sh --dry-run --stages 01,02,04 +``` + +--- + +## 🛠️ CLI-Optionen + +| Option | Argument | Beschreibung | +| :--- | :--- | :--- | +| `-a`, `--all` | – | Führt alle Phasen (`00` bis `09`) sequenziell aus | +| `-s`, `--stages` | `<01,02,...>` | Kommagetrennte Liste der auszuführenden Phasen | +| `-u`, `--user` | `` | Zielbenutzer für Userland/Dotfiles (Standard: `$SUDO_USER` mit Bestätigungsabfrage) | +| `-d`, `--dry-run` | – | Simuliert die Ausführung ohne Systemänderungen | +| `-h`, `--help` | – | Zeigt die Hilfe und alle verfügbaren Stages an | + +--- + +## 📁 Projektstruktur + +``` +. +├── setup.sh # Zentraler Orchestrator (CLI Flags & whiptail TUI) +├── lib/ # Wiederverwendbare Hilfsbibliotheken +│ ├── utils.sh # Logging, Error-Traps (set -euo pipefail), Root/User-Erkennung & Abfrage +│ ├── apt.sh # APT-Keyring-Management (/etc/apt/keyrings/), Deb822, Pinning +│ └── tui.sh # Whiptail-Menüs und Dialoge +├── config/ # Konfigurationsdateien & Paketlisten +│ ├── setup.conf # Globale Variablen (Kernel, GRUB-Theme, Plymouth) +│ └── packages/ # Thematische Paketlisten +│ ├── 01-base.list # Grundlegende Systemwerkzeuge, Firmware, Microcode +│ ├── 02-desktop.list # Hyprland, Waybar, SDDM, Portale, Pipewire +│ ├── 03-gaming.list # Steam-Devices, Lutris, Gamescope, MangoHud, Wine +│ ├── 04-virtualization.list # QEMU, KVM, Libvirt, Bridge-Tools +│ ├── 05-multimedia.list # VLC, Amberol, GIMP, Loupe, LibreOffice +│ └── 06-flatpaks.list # Flatpak App-IDs & Flathub +├── stages/ # Sequenzielle, modular ausführbare Phasen +│ ├── 00-preflight.sh # Prüfung von Rechten, Ziel-User ($SUDO_USER) und Internet +│ ├── 01-apt-unstable.sh # Deb822-Quellen, Keyrings, Pinning, apt-listbugs, dist-upgrade +│ ├── 02-kernel-hardware.sh # XanMod-Kernel (main/edge), CPU P-State, Microcode, auto-cpufreq (Source) +│ ├── 03-bootloader.sh # GRUB Kernel-Parameter, Vimix-Theme, Plymouth Solar +│ ├── 04-packages.sh # Installation der ausgewählten thematischen Paketlisten +│ ├── 05-fonts.sh # Download & Installation von JetBrainsMono, Fantasque, VictorMono +│ ├── 06-services.sh # Aktivierung von AppArmor, Docker, Libvirt, zram +│ ├── 07-skel-and-user.sh # /etc/skel Vorlagen, ZSH-Shell-Setzen, Dotfiles-Sync +│ ├── 08-flatpaks-apps.sh # Flathub Setup, Flatpaks, Spotify, Waydroid, MIME-Types +│ └── 09-hyprland.sh # LinuxBeginnings Debian-Hyprland Auto-Installer & Dotfiles +└── data/ # Statische Konfigurationsdateien & Vorlagen + ├── apt/ + │ ├── sources.list.d/ # debian-unstable.sources, xanmod.sources + │ └── preferences.d/ # Pinning-Konfigurationen (unstable, xanmod) + ├── etc/ + │ ├── environment.d/ # 99-raytracing.conf, 99-upscaling.conf + │ └── profile.d/ # Bereinigte System-Profile-Skripte + ├── skel/ # .zshrc, Templates für Dokumente & Skripte + └── usr/share/applications/ # Desktop-Dateien (z. B. Spotify) +``` + +--- + +## 🔒 Sicherheits- & Stabilitätsmerkmale + +1. **Rechte- und Nutzertrennung**: + - Automatische Erkennung des regulären Desktop-Benutzers via `$SUDO_USER` / interactivem Fallback. + - Benutzerkonfigurationen und Gruppenrechte (`sudo`, `docker`, `libvirt`) werden sauber für den Zielbenutzer gesetzt. +2. **Keine gefährlichen Login-Hooks**: + - Vollständige Beseitigung unkontrollierter Live-Downloads (`curl | sh`) beim Login. + - Standardkonforme Bereitstellung über `/etc/skel` für neue und bestehende Benutzer. +3. **Idempotenz & Backups**: + - Alle Phasen können beliebig oft wiederholt werden. + - Vorhandene Dotfiles (`~/.zshrc`) und Konfigurationen (`/etc/default/grub`) werden vor Änderungen automatisch mit Zeitstempel (`.backup_YYYYMMDD_HHMMSS`) gesichert. +4. **Debian Unstable Absicherung**: + - Moderne Deb822-Quellen und dedizierte Keyrings in `/etc/apt/keyrings/`. + - Installation von `apt-listbugs` und `apt-listchanges` vor dem `dist-upgrade` schützt vor bekannten kritischen Paketproblemen. +5. **Sichere Shell-Verwaltung**: + - Standardkonforme Änderung der Login-Shell via `chsh -s` statt direkter `/etc/passwd`-Modifikation. + +--- + +## 🎮 Gaming & Performance-Optimierungen + +### CPU P-State & Kernel-Parameter +In `stages/03-bootloader.sh` wird der CPU-Hersteller automatisch ermittelt und in `/etc/default/grub` eingetragen: +- **AMD CPUs**: `amd_pstate=active` +- **Intel CPUs**: `intel_pstate=active` +- **Latenz-Optimierung**: `rcutree.rcu_idle_gp_delay=1 threadirqs` + +### Game Launch-Parameter (Steam / Lutris) +```bash +# Standard Gaming Launch-Optionen mit MangoHud & Gamescope +gamemoderun gamescope -W 2560 -H 1440 --force-grab-cursor --hdr-enabled --adaptive-sync -f -o 240 -r 240 -- mangohud %command% + +# Raytracing für DX12 Titel (RADV / Mesa) RADV_PERFTEST=gpl,rt,ngg_streamout VKD3D_CONFIG=dxr,dxr11 DXVK_ASYNC=1 AMD_VULKAN_ICD=RADV gamemoderun gamescope -W 2560 -H 1440 --force-grab-cursor --hdr-enabled --adaptive-sync -f -o 240 -r 240 -- mangohud %command% - -MAXIMUM RT PERFORMANCE — with FSR: -RADV_PERFTEST=gpl,rt,ngg_streamout VKD3D_CONFIG=dxr,dxr11 DXVK_ASYNC=1 AMD_VULKAN_ICD=RADV WINE_FULLSCREEN_FSR=1 gamemoderun gamescope -W 2560 -H 1440 --force-grab-cursor --hdr-enabled --adaptive-sync -f -o 240 -r 240 -- mangohud %command% ``` -#### Parameter in /etc/environment.d/99-raytracing.conf -```bash -# AMD RDNA Ray Tracing Optimisations -RADV_PERFTEST=gpl,rt,ngg_streamout -VKD3D_CONFIG=dxr,dxr11 -DXVK_ASYNC=1 -AMD_VULKAN_ICD=RADV -mesa_glthread=true -MESA_VK_WSI_PRESENT_MODE=mailbox -``` +--- -#### Parameter in /etc/environment.d/99-upscaling.conf -```bash -# AMD FSR 4 + FSR 3 Upscaling — March 2026 -# FSR 4: use PROTON_FSR4_UPGRADE=1 launch option (RDNA4=native, RDNA3=fallback) -WINE_FULLSCREEN_FSR=1 -WINE_FULLSCREEN_FSR_STRENGTH=2 -MESA_VK_WSI_PRESENT_MODE=mailbox -``` +## 📜 Lizenz & Autor -## Lizenz - -Dieses Projekt steht unter einer Open-Source-Lizenz. Weitere Informationen findest du in der Datei `LICENSE`. - -## Autor - -Erstellt und gepflegt von DragonSlayer_14. +- **Lizenz**: MIT License (siehe `LICENSE`) +- **Autor**: DragonSlayer_14 diff --git a/config/packages/01-base.list b/config/packages/01-base.list new file mode 100644 index 0000000..9d0db80 --- /dev/null +++ b/config/packages/01-base.list @@ -0,0 +1,62 @@ +# ============================================================================== +# config/packages/01-base.list - Base system utilities, firmware, shell & diagnostics +# ============================================================================== + +7zip +adb +apparmor +apparmor-notify +apparmor-profiles +apparmor-profiles-extra +apparmor-utils +aptitude +baobab +bat +bleachbit +bluetooth +blueman +bluez +btop +ca-certificates +clamav +clamav-daemon +command-not-found +cryptomator +curl +dconf-editor +debian-goodies +fastfetch +file-roller +firmware-linux +firmware-linux-nonfree +firmware-misc-nonfree +flatpak +flatseal +fzf +glances +gnome-disk-utility +gnome-firmware +gnome-logs +gnome-system-monitor +gparted +htop +hunspell +hunspell-de-de-frami +irqbalance +keepassxc +lsd +man +network-manager-gnome +rfkill +ripgrep +rpi-imager +shellcheck +systemd-timesyncd +tar +tealdeer +timeshift +tree +unrar +unzip +zram-tools +zsh diff --git a/config/packages/02-desktop.list b/config/packages/02-desktop.list new file mode 100644 index 0000000..1be9564 --- /dev/null +++ b/config/packages/02-desktop.list @@ -0,0 +1,34 @@ +# ============================================================================== +# config/packages/02-desktop.list - Wayland/Hyprland desktop, display manager & tools +# ============================================================================== + +cava +dconf-editor +flameshot +gnome-calculator +gnome-decoder +gnome-font-viewer +gnome-keyring +gnome-snapshot +gnome-text-editor +grim +impression +input-remapper +localsend +nodejs +nwg-displays +nwg-look +obfuscate +pipewire +pipewire-pulse +sddm +slurp +speech-dispatcher +swappy +swaybg +thunar +wayland-utils +wireplumber +wl-clipboard +xdg-user-dirs +yazi diff --git a/config/packages/03-gaming.list b/config/packages/03-gaming.list new file mode 100644 index 0000000..470016f --- /dev/null +++ b/config/packages/03-gaming.list @@ -0,0 +1,19 @@ +# ============================================================================== +# config/packages/03-gaming.list - Gaming tools, Vulkan drivers, Wine & Emulation +# ============================================================================== + +gameconqueror +gamemode +gamescope +mangohud +mangoapp +mesa-utils +mesa-vulkan-drivers +openrgb +prismlauncher +protontricks +radeontop +steam-devices +vulkan-tools +wine +winetricks diff --git a/config/packages/04-virtualization.list b/config/packages/04-virtualization.list new file mode 100644 index 0000000..2c6047d --- /dev/null +++ b/config/packages/04-virtualization.list @@ -0,0 +1,10 @@ +# ============================================================================== +# config/packages/04-virtualization.list - QEMU, KVM & Libvirt packages +# ============================================================================== + +bridge-utils +libvirt-clients +libvirt-daemon-system +qemu-system-x86 +qemu-utils +virt-manager diff --git a/config/packages/05-multimedia.list b/config/packages/05-multimedia.list new file mode 100644 index 0000000..0b7dbbb --- /dev/null +++ b/config/packages/05-multimedia.list @@ -0,0 +1,22 @@ +# ============================================================================== +# config/packages/05-multimedia.list - Audio, Video, Graphics & Productivity +# ============================================================================== + +amberol +easyeffects +ffmpeg +gimp +libreoffice +libreoffice-gtk4 +libreoffice-l10n-de +loupe +simple-scan +vlc +vlc-data +vlc-l10n +vlc-plugin-access-extra +vlc-plugin-base +vlc-plugin-notify +vlc-plugin-pipewire +vlc-plugin-qt +vlc-plugin-video-output diff --git a/config/packages/06-flatpaks.list b/config/packages/06-flatpaks.list new file mode 100644 index 0000000..7e13969 --- /dev/null +++ b/config/packages/06-flatpaks.list @@ -0,0 +1,23 @@ +# ============================================================================== +# config/packages/06-flatpaks.list - Flathub Flatpak Application IDs +# ============================================================================== + +# Communication & Productivity +eu.betterbird.Betterbird +im.fluffychat.Fluffychat +org.pvermeer.WebAppHub +io.github.giantpinkrobots.flatsweep + +# Creativity & AI +org.musescore.MuseScore +com.jeffser.Alpaca + +# Gaming & Compatibility +com.valvesoftware.Steam +com.heroicgameslauncher.hgl +net.lutris.Lutris +org.freedesktop.Platform.VulkanLayer.gamescope +org.freedesktop.Platform.VulkanLayer.MangoHud +com.valvesoftware.Steam.CompatibilityTool.Proton-GE +net.davidotek.pupgui2 +io.github.rfrench3.scopebuddy-gui diff --git a/config/setup.conf b/config/setup.conf new file mode 100644 index 0000000..46b4a66 --- /dev/null +++ b/config/setup.conf @@ -0,0 +1,20 @@ +# ============================================================================== +# config/setup.conf - Configuration parameters for Debian Unstable Setup +# ============================================================================== + +# Kernel & Hardware +# XanMod branches: "main" (stable & recommended), "edge" (bleeding-edge), "lts" (long-term support), "rt" (real-time) +XANMOD_BRANCH="main" +CPU_PSTATE_AUTO=1 + +# Bootloader & Appearance +GRUB_THEME="vimix" +PLYMOUTH_THEME="solar" +GRUB_TIMEOUT=0 +GRUB_TIMEOUT_STYLE="hidden" + +# Shell & Userland +DEFAULT_SHELL="zsh" + +# Default Stages (if --all is passed or in default batch mode) +ALL_STAGES="00 01 02 03 04 05 06 07 08 09" diff --git a/data/apt/preferences.d/01-unstable.pref b/data/apt/preferences.d/01-unstable.pref new file mode 100644 index 0000000..a5622a7 --- /dev/null +++ b/data/apt/preferences.d/01-unstable.pref @@ -0,0 +1,7 @@ +Package: * +Pin: release a=unstable +Pin-Priority: 900 + +Package: * +Pin: release a=experimental +Pin-Priority: 100 diff --git a/data/apt/preferences.d/50-xanmod.pref b/data/apt/preferences.d/50-xanmod.pref new file mode 100644 index 0000000..8ee09ee --- /dev/null +++ b/data/apt/preferences.d/50-xanmod.pref @@ -0,0 +1,3 @@ +Package: * +Pin: origin deb.xanmod.org +Pin-Priority: 900 diff --git a/data/apt/sources.list.d/xanmod.sources b/data/apt/sources.list.d/xanmod.sources new file mode 100644 index 0000000..ae96307 --- /dev/null +++ b/data/apt/sources.list.d/xanmod.sources @@ -0,0 +1,5 @@ +Types: deb +URIs: http://deb.xanmod.org +Suites: releases +Components: main +Signed-By: /etc/apt/keyrings/xanmod-archive-keyring.gpg diff --git a/data/etc/environment.d/99-raytracing.conf b/data/etc/environment.d/99-raytracing.conf new file mode 100644 index 0000000..d5f5e13 --- /dev/null +++ b/data/etc/environment.d/99-raytracing.conf @@ -0,0 +1,3 @@ +# Raytracing support environment flags for RADV / Mesa +VKD3D_CONFIG=dxr11,dxr +RADV_PERFTEST=rt diff --git a/data/etc/environment.d/99-upscaling.conf b/data/etc/environment.d/99-upscaling.conf new file mode 100644 index 0000000..e9ac053 --- /dev/null +++ b/data/etc/environment.d/99-upscaling.conf @@ -0,0 +1,3 @@ +# Upscaling and gaming enhancement variables +WINE_FULLSCREEN_FSR=1 +WINE_FULLSCREEN_FSR_STRENGTH=2 diff --git a/data/etc/profile.d/00-update-xdg-user-dirs.sh b/data/etc/profile.d/00-update-xdg-user-dirs.sh index d263d9e..31c8841 100755 --- a/data/etc/profile.d/00-update-xdg-user-dirs.sh +++ b/data/etc/profile.d/00-update-xdg-user-dirs.sh @@ -1,3 +1,5 @@ -#!/bin/bash - -xdg-user-dirs-update +#!/bin/sh +# Update XDG User Dirs if tool is present +if command -v xdg-user-dirs-update >/dev/null 2>&1; then + xdg-user-dirs-update +fi diff --git a/data/etc/profile.d/copy_user_config.sh b/data/etc/profile.d/copy_user_config.sh deleted file mode 100755 index a48c04e..0000000 --- a/data/etc/profile.d/copy_user_config.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -DEFAULT_USR_FOLDER="/usr/share/debian-gaming/home" - -CONFIG_FOLDER="$HOME/.config/" - -CHECK_FILE="$HOME/.config/.debian_gaming_configs_copied" - -TEMPLATES_DIR=$(xdg-user-dir TEMPLATES 2>/dev/null || echo "$HOME/Templates") - -if [ ! -e "$CHECK_FILE" ]; then - if [ -d "$DEFAULT_USR_FOLDER" ]; then - - sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" - - if [ -e "$HOME/.config" ]; then - mv $HOME/.config $HOME/.config.bak - fi - - if [ -e "$HOME/.zshrc" ]; then - mv $HOME/.zshrc $HOME/.zshrc.bak - fi - - mkdir -p $HOME/.config - - cp -r $DEFAULT_USR_FOLDER/.config/* $HOME/.config - cp -r $DEFAULT_USR_FOLDER/templates/* $TEMPLATES_DIR - cp $DEFAULT_USR_FOLDER/zshrc $HOME/.zshrc - - touch $CHECK_FILE - - fi -fi diff --git a/data/etc/profile.d/hide_waydroid_apps.sh b/data/etc/profile.d/hide_waydroid_apps.sh index 0a24e52..067b2d4 100755 --- a/data/etc/profile.d/hide_waydroid_apps.sh +++ b/data/etc/profile.d/hide_waydroid_apps.sh @@ -1,3 +1,10 @@ -for app in ~/.local/share/applications/waydroid.*.desktop; do - grep -q NoDisplay $app || sed '/^Icon=/a NoDisplay=true' -i $app -done +#!/bin/sh +# Hide Waydroid desktop applications from standard desktop menus +if [ -d "$HOME/.local/share/applications" ]; then + for app in "$HOME"/.local/share/applications/waydroid.*.desktop; do + [ -f "$app" ] || continue + if ! grep -q "NoDisplay" "$app"; then + sed -i '/^Icon=/a NoDisplay=true' "$app" 2>/dev/null || true + fi + done +fi diff --git a/data/etc/profile.d/sbin_in_path.sh b/data/etc/profile.d/sbin_in_path.sh index 43b2385..42ae80b 100755 --- a/data/etc/profile.d/sbin_in_path.sh +++ b/data/etc/profile.d/sbin_in_path.sh @@ -1,10 +1,12 @@ -if groups | grep -q "\bsudo\b"; then - case ":$PATH:" in - *":/sbin:"*) ;; - *) export PATH="$PATH:/sbin" ;; - esac - case ":$PATH:" in - *":/usr/sbin:"*) ;; - *) export PATH="$PATH:/usr/sbin" ;; - esac +#!/bin/sh +# Add sbin and /usr/sbin to PATH for sudoers if not already present +if groups 2>/dev/null | grep -q "\bsudo\b"; then + case ":$PATH:" in + *":/sbin:"*) ;; + *) export PATH="$PATH:/sbin" ;; + esac + case ":$PATH:" in + *":/usr/sbin:"*) ;; + *) export PATH="$PATH:/usr/sbin" ;; + esac fi diff --git a/data/etc/profile.d/sudo_hint.sh b/data/etc/profile.d/sudo_hint.sh index 7d4ae88..40251a2 100755 --- a/data/etc/profile.d/sudo_hint.sh +++ b/data/etc/profile.d/sudo_hint.sh @@ -1,18 +1,18 @@ -#!/bin/bash - +#!/bin/sh +# Display sudo reminder for administrative users once after initial setup SUDO_FILE="$HOME/.sudo_as_admin_successful" HUSH_FILE="$HOME/.hushlogin" -ONE_WEEK_AGO=$(date -d '7 days ago' +%s) -if [ -e "$SUDO_FILE" ]; then - FILE_MOD_TIME=$(stat -c %Y "$SUDO_FILE") - if [ "$FILE_MOD_TIME" -lt "$ONE_WEEK_AGO" ]; then +if [ -f "$SUDO_FILE" ]; then + FILE_MOD_TIME=$(stat -c %Y "$SUDO_FILE" 2>/dev/null || echo 0) + ONE_WEEK_AGO=$(date -d '7 days ago' +%s 2>/dev/null || echo 0) + if [ "$FILE_MOD_TIME" -gt 0 ] && [ "$ONE_WEEK_AGO" -gt 0 ] && [ "$FILE_MOD_TIME" -lt "$ONE_WEEK_AGO" ]; then rm -f "$SUDO_FILE" fi fi if [ ! -e "$SUDO_FILE" ] && [ ! -e "$HUSH_FILE" ]; then - case " $(groups) " in + case " $(groups 2>/dev/null) " in *\ admin\ *|*\ sudo\ *) if [ -x /usr/bin/sudo ]; then echo 'To run a command as administrator (user "root"), use "sudo ".' @@ -21,4 +21,3 @@ if [ ! -e "$SUDO_FILE" ] && [ ! -e "$HUSH_FILE" ]; then ;; esac fi - diff --git a/data/home/zshrc b/data/home/zshrc deleted file mode 100755 index db107ae..0000000 --- a/data/home/zshrc +++ /dev/null @@ -1,49 +0,0 @@ -# If you come from bash you might have to change your $PATH. -# export PATH=$HOME/bin:/usr/local/bin:$PATH - -export ZSH="$HOME/.oh-my-zsh" - -apt_pref='apt' -apt_upgr='upgrade' - -ZSH_THEME="agnosterzak" - -plugins=( - alias-finder - aliases - colored-man-pages - command-not-found - common-aliases - composer - cp - debian - docker - git - jsontools - kitty - python - ssh - symfony - themes - vscode - zsh-autosuggestions - zsh-syntax-highlighting -) - -source $ZSH/oh-my-zsh.sh - - -# Display Pokemon-colorscripts -# Project page: https://gitlab.com/phoneybadger/pokemon-colorscripts#on-other-distros-and-macos -#pokemon-colorscripts --no-title -s -r #without fastfetch -#pokemon-colorscripts --no-title -s -r | fastfetch -c $HOME/.config/fastfetch/config-pokemon.jsonc --logo-type fi> - -# fastfetch. Will be disabled if above colorscript was chosen to install -fastfetch -c $HOME/.config/fastfetch/config-compact.jsonc - -# Set-up icons for files/directories in terminal using lsd -alias ls='lsd' -alias l='ls -l' -alias la='ls -a' -alias lla='ls -la' -alias lt='ls --tree' diff --git a/data/skel/.zshrc b/data/skel/.zshrc new file mode 100755 index 0000000..3a390ca --- /dev/null +++ b/data/skel/.zshrc @@ -0,0 +1,54 @@ +# If you come from bash you might have to change your $PATH. +# export PATH=$HOME/bin:/usr/local/bin:$PATH + +export ZSH="$HOME/.oh-my-zsh" + +apt_pref='apt' +apt_upgr='upgrade' + +ZSH_THEME="agnosterzak" + +plugins=( + alias-finder + aliases + colored-man-pages + command-not-found + common-aliases + composer + cp + debian + docker + git + jsontools + kitty + python + ssh + symfony + themes + vscode + zsh-autosuggestions + zsh-syntax-highlighting +) + +# Oh-My-Zsh configuration +if [[ -d "$ZSH" && -f "$ZSH/oh-my-zsh.sh" ]]; then + source "$ZSH/oh-my-zsh.sh" +fi + +# Fastfetch system info banner +if command -v fastfetch >/dev/null 2>&1; then + if [[ -f "$HOME/.config/fastfetch/config-compact.jsonc" ]]; then + fastfetch -c "$HOME/.config/fastfetch/config-compact.jsonc" + else + fastfetch + fi +fi + +# Aliases using modern tools with fallback +if command -v lsd >/dev/null 2>&1; then + alias ls='lsd' + alias l='ls -l' + alias la='ls -a' + alias lla='ls -la' + alias lt='ls --tree' +fi diff --git a/data/home/templates/Bash-Skript.sh b/data/skel/Templates/Bash-Skript.sh similarity index 100% rename from data/home/templates/Bash-Skript.sh rename to data/skel/Templates/Bash-Skript.sh diff --git a/data/home/templates/Calc.ods b/data/skel/Templates/Calc.ods similarity index 100% rename from data/home/templates/Calc.ods rename to data/skel/Templates/Calc.ods diff --git a/data/home/templates/Markdown-Dokument.md b/data/skel/Templates/Markdown-Dokument.md similarity index 100% rename from data/home/templates/Markdown-Dokument.md rename to data/skel/Templates/Markdown-Dokument.md diff --git a/data/home/templates/Python-Skript.py b/data/skel/Templates/Python-Skript.py similarity index 100% rename from data/home/templates/Python-Skript.py rename to data/skel/Templates/Python-Skript.py diff --git a/data/home/templates/Textdokument.txt b/data/skel/Templates/Textdokument.txt similarity index 100% rename from data/home/templates/Textdokument.txt rename to data/skel/Templates/Textdokument.txt diff --git a/data/home/templates/Writer.odt b/data/skel/Templates/Writer.odt similarity index 100% rename from data/home/templates/Writer.odt rename to data/skel/Templates/Writer.odt diff --git a/lib/apt.sh b/lib/apt.sh new file mode 100755 index 0000000..eb5e443 --- /dev/null +++ b/lib/apt.sh @@ -0,0 +1,140 @@ +#!/usr/bin/env bash +# ============================================================================== +# lib/apt.sh - APT, Deb822, GPG Keyring and Package installation utilities +# ============================================================================== + +set -euo pipefail + +APT_KEYRINGS_DIR="/etc/apt/keyrings" +APT_SOURCES_DIR="/etc/apt/sources.list.d" +APT_PREFERENCES_DIR="/etc/apt/preferences.d" + +# Ensure the standard keyring directory exists +apt_ensure_keyrings_dir() { + if [[ ! -d "$APT_KEYRINGS_DIR" ]]; then + log_info "Creating keyrings directory: $APT_KEYRINGS_DIR" + mkdir -p "$APT_KEYRINGS_DIR" + chmod 0755 "$APT_KEYRINGS_DIR" + fi +} + +# Download and install a GPG key into /etc/apt/keyrings/ +# Usage: apt_add_keyring_from_url "https://example.com/key.gpg" "example.gpg" +apt_add_keyring_from_url() { + local url="$1" + local keyring_filename="$2" + local dest_path="$APT_KEYRINGS_DIR/$keyring_filename" + + apt_ensure_keyrings_dir + + log_substep "Fetching GPG keyring from: $url -> $dest_path" + + local tmp_key + tmp_key="$(mktemp /tmp/apt-key.XXXXXX)" + + if curl -fsSL "$url" -o "$tmp_key"; then + # Check if the key is ASCII armored or binary + if gpg --dry-run --quiet --import "$tmp_key" >/dev/null 2>&1; then + if file "$tmp_key" | grep -q "PGP public key block"; then + gpg --dearmor -o "$dest_path" < "$tmp_key" 2>/dev/null || cp "$tmp_key" "$dest_path" + else + cp "$tmp_key" "$dest_path" + fi + chmod 0644 "$dest_path" + log_success "Keyring installed: $dest_path" + else + # If gpg check fails, fallback to direct copy if non-empty + if [[ -s "$tmp_key" ]]; then + cp "$tmp_key" "$dest_path" + chmod 0644 "$dest_path" + log_success "Keyring installed (raw): $dest_path" + else + log_error "Downloaded key from $url is empty or invalid." + rm -f "$tmp_key" + return 1 + fi + fi + rm -f "$tmp_key" + else + rm -f "$tmp_key" + log_error "Failed to download GPG key from $url" + return 1 + fi +} + +# Install Deb822 sources file +# Usage: apt_install_sources_file "/path/to/source.sources" "debian-unstable.sources" +apt_install_sources_file() { + local src_path="$1" + local dest_name="$2" + local dest_path="$APT_SOURCES_DIR/$dest_name" + + if [[ ! -f "$src_path" ]]; then + log_error "Source file does not exist: $src_path" + return 1 + fi + + mkdir -p "$APT_SOURCES_DIR" + cp "$src_path" "$dest_path" + chmod 0644 "$dest_path" + log_success "Installed APT Deb822 source: $dest_path" +} + +# Install APT preferences file +# Usage: apt_install_preference_file "/path/to/pinning.pref" "99-custom.pref" +apt_install_preference_file() { + local src_path="$1" + local dest_name="$2" + local dest_path="$APT_PREFERENCES_DIR/$dest_name" + + if [[ ! -f "$src_path" ]]; then + log_error "Preference file does not exist: $src_path" + return 1 + fi + + mkdir -p "$APT_PREFERENCES_DIR" + cp "$src_path" "$dest_path" + chmod 0644 "$dest_path" + log_success "Installed APT preference: $dest_path" +} + +# Update APT package indexes +apt_update() { + log_step "Updating APT package indexes..." + DEBIAN_FRONTEND=noninteractive apt-get update -y +} + +# Dist-upgrade system +apt_dist_upgrade() { + log_step "Upgrading system packages (dist-upgrade)..." + DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y +} + +# Install packages from a .list file +# Usage: apt_install_package_list_file "/path/to/packages.list" +apt_install_package_list_file() { + local list_file="$1" + + if [[ ! -f "$list_file" ]]; then + log_error "Package list file not found: $list_file" + return 1 + fi + + local -a pkgs=() + while IFS= read -r line || [[ -n "$line" ]]; do + # Trim leading/trailing whitespace + line="$(echo "$line" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + # Skip empty lines and comment lines + [[ -z "$line" || "$line" =~ ^# ]] && continue + pkgs+=("$line") + done < "$list_file" + + if [[ ${#pkgs[@]} -eq 0 ]]; then + log_info "No packages to install from $list_file" + return 0 + fi + + log_info "Installing ${#pkgs[@]} packages from $(basename "$list_file")..." + DEBIAN_FRONTEND=noninteractive apt-get install -y "${pkgs[@]}" + log_success "Installed packages from $(basename "$list_file")" +} diff --git a/lib/tui.sh b/lib/tui.sh new file mode 100755 index 0000000..afaa5b2 --- /dev/null +++ b/lib/tui.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +# ============================================================================== +# lib/tui.sh - Interactive Whiptail TUI dialogs and checklists +# ============================================================================== + +set -euo pipefail + +# Check if whiptail is available +tui_check_whiptail() { + if ! command_exists whiptail; then + log_warn "whiptail is not installed. Attempting to install whiptail..." + DEBIAN_FRONTEND=noninteractive apt-get update -y && DEBIAN_FRONTEND=noninteractive apt-get install -y whiptail + fi +} + +# Display welcome message +tui_welcome() { + whiptail --title "Debian Unstable Setup & Hyprland Installer" \ + --msgbox "Willkommen beim Debian Unstable & Desktop Setup!\n\nDieses Skript führt dich durch die modulare Einrichtung deines Debian Sid Systems mit XanMod-Kernel, Hyprland und Optimierungen.\n\nDrücke ENTER um zur Modulauswahl zu gelangen." \ + 14 70 +} + +# Present stage checklist to user +# Returns space-separated list of selected stage numbers (e.g., "01 02 03 04 05 06 07 08 09") +tui_select_stages() { + local choices + choices=$(whiptail --title "Modulauswahl / Stages" \ + --checklist "Wähle die gewünschten Installations-Phasen mit der LEERTASTE aus:" \ + 22 78 9 \ + "01" "Debian Unstable (Deb822, Pinning, Upgrade)" ON \ + "02" "Kernel & Hardware (XanMod, P-State, Microcode)" ON \ + "03" "Bootloader & Theme (GRUB, Vimix, Plymouth)" ON \ + "04" "Pakete (Base, Desktop, Gaming, Virtualisierung)" ON \ + "05" "Coding & Nerd Fonts (JetBrainsMono, VictorMono)" ON \ + "06" "System-Dienste (AppArmor, Docker, Libvirt, zram)" ON \ + "07" "Userland & Skel (Zsh, Skel-Templates, Dotfiles)" ON \ + "08" "Flatpaks & Apps (Flathub, Flatpaks, MIME)" ON \ + "09" "Hyprland Desktop (LinuxBeginnings Installer)" ON \ + 3>&1 1>&2 2>&3) || { + log_info "Setup durch Benutzer abgebrochen." + exit 0 + } + + # Clean quotes from whiptail output (e.g. '"01" "02"' -> '01 02') + local cleaned_choices + cleaned_choices=$(echo "$choices" | tr -d '"') + echo "$cleaned_choices" +} + +# Prompt user for target user via Whiptail dialog +tui_prompt_target_user() { + local default_user="${1:-}" + local chosen="" + + if [[ -n "$default_user" && "$default_user" != "root" ]]; then + if whiptail --title "Ziel-Benutzer bestätigen" \ + --yes-button "Verwenden" \ + --no-button "Anderer Benutzer" \ + --yesno "Erkannter Ziel-Benutzer: $default_user\n\nMöchtest du diesen Benutzer für die Konfiguration (Dotfiles, Gruppen, Hyprland) verwenden?" \ + 10 65; then + chosen="$default_user" + fi + fi + + while [[ -z "$chosen" ]]; do + local input_user + input_user=$(whiptail --title "Ziel-Benutzer eingeben" \ + --inputbox "Bitte gib den Benutzernamen des Desktop-Benutzers ein:" \ + 10 60 "$default_user" \ + 3>&1 1>&2 2>&3) || { + log_info "Setup durch Benutzer abgebrochen." + exit 0 + } + input_user="$(echo "$input_user" | tr -d '[:space:]')" + if [[ -z "$input_user" || "$input_user" == "root" ]]; then + whiptail --title "Ungültiger Benutzer" --msgbox "Ungültiger Benutzername (darf nicht leer oder root sein)." 8 50 + continue + fi + if ! id "$input_user" >/dev/null 2>&1; then + whiptail --title "Benutzer nicht gefunden" --msgbox "Benutzer '$input_user' existiert nicht im System." 8 50 + continue + fi + chosen="$input_user" + done + + export TARGET_USER="$chosen" + echo "$chosen" +} + +# Confirmation dialog before running +tui_confirm_execution() { + local selected_stages="$1" + local target_user="$2" + + whiptail --title "Installation starten" \ + --yesno "Folgende Konfiguration wird ausgeführt:\n\n- Ziel-Benutzer: $target_user\n- Ausgewählte Stages: $selected_stages\n\nMöchtest du die Installation jetzt starten?" \ + 14 70 +} diff --git a/lib/utils.sh b/lib/utils.sh new file mode 100755 index 0000000..199ce72 --- /dev/null +++ b/lib/utils.sh @@ -0,0 +1,212 @@ +#!/usr/bin/env bash +# ============================================================================== +# lib/utils.sh - Common utilities, logging, error handling & user detection +# ============================================================================== + +set -euo pipefail + +# ANSI Color Codes +export CLR_RESET='\033[0m' +export CLR_BOLD='\033[1m' +export CLR_DIM='\033[2m' +export CLR_RED='\033[0;31m' +export CLR_GREEN='\033[0;32m' +export CLR_YELLOW='\033[0;33m' +export CLR_BLUE='\033[0;34m' +export CLR_MAGENTA='\033[0;35m' +export CLR_CYAN='\033[0;36m' +export CLR_WHITE='\033[0;37m' + +# Disable colors if not running in a terminal +if [[ ! -t 1 ]]; then + CLR_RESET="" + CLR_BOLD="" + CLR_DIM="" + CLR_RED="" + CLR_GREEN="" + CLR_YELLOW="" + CLR_BLUE="" + CLR_MAGENTA="" + CLR_CYAN="" + CLR_WHITE="" +fi + +# Logging functions +log_info() { + printf "${CLR_BLUE}[INFO]${CLR_RESET} %s\n" "$*" +} + +log_success() { + printf "${CLR_GREEN}[✓]${CLR_RESET} %s\n" "$*" +} + +log_warn() { + printf "${CLR_YELLOW}[WARN]${CLR_RESET} %s\n" "$*" >&2 +} + +log_error() { + printf "${CLR_RED}[ERROR]${CLR_RESET} %s\n" "$*" >&2 +} + +log_step() { + printf "\n${CLR_BOLD}${CLR_CYAN}==>${CLR_RESET} ${CLR_BOLD}%s${CLR_RESET}\n" "$*" +} + +log_substep() { + printf " ${CLR_CYAN}->${CLR_RESET} %s\n" "$*" +} + +# Error trap handler +setup_err_trap() { + trap 'error_handler $? $LINENO "$BASH_COMMAND"' ERR +} + +error_handler() { + local exit_code="$1" + local line_no="$2" + local bash_command="$3" + log_error "Command failed with exit code $exit_code at line $line_no: '$bash_command'" + exit "$exit_code" +} + +# Root permission check +require_root() { + if [[ "$(id -u)" -ne 0 ]]; then + log_error "This script must be run as root (or via sudo)!" + exit 1 + fi +} + +# Check if command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Determine and prompt for the non-root target user +prompt_target_user() { + if [[ -n "${TARGET_USER:-}" ]]; then + echo "$TARGET_USER" + return 0 + fi + + local candidate="" + if [[ -n "${SUDO_USER:-}" && "${SUDO_USER}" != "root" ]]; then + candidate="$SUDO_USER" + elif [[ -n "${PKEXEC_UID:-}" ]]; then + candidate="$(id -nu "$PKEXEC_UID" 2>/dev/null || true)" + elif [[ "$(id -u)" -ne 0 ]]; then + candidate="$(id -un)" + fi + + # If candidate is still empty or root, try to detect the first normal user with UID >= 1000 + if [[ -z "$candidate" || "$candidate" == "root" ]]; then + candidate="$(awk -F: '$3 >= 1000 && $3 < 60000 && $1 != "nobody" {print $1; exit}' /etc/passwd 2>/dev/null || true)" + fi + + local chosen="" + local is_interactive=0 + if [[ -t 0 || -c /dev/tty ]] && [[ "${DEBIAN_FRONTEND:-}" != "noninteractive" && "${CI:-}" != "1" && "${AUTO_CONFIRM:-}" != "1" ]]; then + is_interactive=1 + fi + + if [[ "$is_interactive" -eq 1 ]]; then + local tty_in="/dev/tty" + local tty_out="/dev/tty" + if [[ ! -c /dev/tty ]]; then + tty_in="/dev/stdin" + tty_out="/dev/stderr" + fi + + if [[ -n "$candidate" && "$candidate" != "root" ]]; then + printf "\n${CLR_CYAN}Target User Detection:${CLR_RESET}\n" > "$tty_out" + printf "Detected target user: ${CLR_BOLD}%s${CLR_RESET}\n" "$candidate" > "$tty_out" + local answer="" + read -r -p "Use target user '$candidate'? [Y/n]: " answer < "$tty_in" > "$tty_out" 2>&1 || answer="y" + if [[ -z "$answer" || "$answer" =~ ^[YyJj] ]]; then + chosen="$candidate" + fi + fi + + while [[ -z "$chosen" ]]; do + local input_user="" + read -r -p "Please enter the target desktop username: " input_user < "$tty_in" > "$tty_out" 2>&1 || true + input_user="$(echo "$input_user" | tr -d '[:space:]')" + if [[ -z "$input_user" ]]; then + printf "${CLR_YELLOW}Username cannot be empty.${CLR_RESET}\n" > "$tty_out" + continue + fi + if [[ "$input_user" == "root" ]]; then + printf "${CLR_YELLOW}Root cannot be used as target desktop user.${CLR_RESET}\n" > "$tty_out" + continue + fi + if ! id "$input_user" >/dev/null 2>&1; then + printf "${CLR_YELLOW}User '%s' does not exist on this system.${CLR_RESET}\n" "$input_user" > "$tty_out" + continue + fi + chosen="$input_user" + done + else + chosen="$candidate" + fi + + if [[ -z "$chosen" || "$chosen" == "root" ]]; then + log_error "Could not determine a valid non-root desktop target user." + return 1 + fi + + if ! id "$chosen" >/dev/null 2>&1; then + log_error "Target user '$chosen' does not exist." + return 1 + fi + + export TARGET_USER="$chosen" + echo "$chosen" +} + +# Get the target user (memoized / exported in TARGET_USER) +get_target_user() { + prompt_target_user +} + +# Get home directory of target user +get_target_home() { + local user + user="$(get_target_user)" + local user_home + user_home="$(getent passwd "$user" | cut -d: -f6)" + if [[ -z "$user_home" || ! -d "$user_home" ]]; then + user_home="/home/$user" + fi + echo "$user_home" +} + +# Run a command as the target user +run_as_target_user() { + local user + user="$(get_target_user)" + if [[ "$(id -un)" == "$user" ]]; then + "$@" + else + su -l "$user" -s /bin/bash -c "$(printf "%q " "$@")" + fi +} + +# Create a safe temporary directory with auto-cleanup +create_temp_dir() { + local prefix="${1:-setup-temp}" + local tmp_dir + tmp_dir="$(mktemp -d "/tmp/${prefix}.XXXXXX")" + echo "$tmp_dir" +} + +# Safe backup function +backup_file_or_dir() { + local target="$1" + local timestamp + timestamp="$(date +%Y%m%d_%H%M%S)" + if [[ -e "$target" ]]; then + local backup_path="${target}.backup_${timestamp}" + cp -r "$target" "$backup_path" + log_info "Created backup: $backup_path" + fi +} diff --git a/plan b/plan deleted file mode 100755 index a8b97a3..0000000 --- a/plan +++ /dev/null @@ -1,60 +0,0 @@ -Debian Paketquellen installieren -> sources nach /etc/apt/sources.list.d - -sudo apt install git sudo network-manager software-properties-common wget curl - -XanMod Kernel - Repo + Keyring installieren -> https://xanmod.org -Apt-Pinning konfigurieren - -sudo apt update - -sudo apt install apt-listbugs apt-listchanges -apt policy hyprland wlroots wayland wayland-protocols mesa -=> wayland -> trixie - mesa -> trixie-backports - hyprland -> unstable - -sudo apt install linux-xanmod-x64v3 -sudo apt install -t trixie-backports mesa mesa-vulkan-drivers gamemode gamescope mangohud pipewire pipewire-pulse wireplumber -sudo apt install -t unstable hyprland wlroots wayland-protocols xdg-desktop-portal-wlr rofi-wayland waybar ags -sudo apt install grim slurp wl-clipboard swaybg irqbalance cpupower timeshift zsh 7zip unrar unzip codium fzf rg rsync clamav clamav-freshclam clamav-docs libclamunrar9 clamav-daemon flatpak rfkill xdg-user-dirs tree bluetooth bleachbit network-manager-gnome steam-installer libreoffice tealdeer gnome-disk-utility gnome-system-monitor keepassxc -sudo flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo - -Lutris installieren -Spotify installieren --> Spotify .desktop-Datei hinterlegen -Waydroid installieren - -sudo apt update -sudo apt upgrade - -Grub-Config anpassen --> GRUB_TIMEOUT=0 --> GRUB_TIMEOUT_STYLE=hidden --> GRUB_CMDLINE_LINUX_DEFAULT="quiet splash usbcore.autosuspend=-1 vt.global_cursor_default=0 loglevel=3 rd.luks.options=discard plymouth.ignore-serial-consoles" --> GRUB_CMDLINE_LINUS="rcutree.rcu_idle_gp_delay=1" - -Grub-Theme installieren -Plymouth installieren (Theme = Spinner) - -update-grub - -./etc/profile.d entsprechend kopieren - -OhMyZsh installieren --> sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" -./home/.zshrc entsprechend kopieren -./home/.oh-my-zsh/themes entsprechend kopieren -source /etc/profile in /etc/zsh/zprofile einfügen - -Shell des Users auf ZSH setzen - -Portmaster installieren - -Floorp installieren - -Standardvorlagen hinterlegen - -.config Ordner ziehen und hinterlegen - -sudo timeshift --create --comments "initial install" --tags D - diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..50f203f --- /dev/null +++ b/setup.sh @@ -0,0 +1,209 @@ +#!/usr/bin/env bash +# ============================================================================== +# setup.sh - Central Orchestrator for Debian Unstable Setup & Hyprland Installer +# ============================================================================== + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Source Libraries & Config +source "$SCRIPT_DIR/lib/utils.sh" +source "$SCRIPT_DIR/lib/apt.sh" +source "$SCRIPT_DIR/lib/tui.sh" + +if [[ -f "$SCRIPT_DIR/config/setup.conf" ]]; then + # shellcheck source=/dev/null + source "$SCRIPT_DIR/config/setup.conf" +fi + +setup_err_trap + +# Show help text +show_help() { + cat < Comma-separated list of stages to run (e.g. --stages 01,02,04) + -u, --user Specify target desktop user (defaults to \$SUDO_USER) + -d, --dry-run Simulate stage execution without modifying the system + -h, --help Show this help message and exit + +Available Stages: + 00: Pre-flight Checks (System, Privileges, Internet) + 01: Debian Unstable Migration (Deb822, Pinning, apt-listbugs, dist-upgrade) + 02: Kernel & Hardware Tuning (XanMod, AMD/Intel P-State, auto-cpufreq) + 03: Bootloader & Splash (GRUB configuration, Vimix Theme, Plymouth Solar) + 04: Package Installation (Base, Desktop, Gaming, Virtualization, Multimedia) + 05: Font Installation (JetBrainsMono, FantasqueSans, VictorMono) + 06: System Services (AppArmor, Docker, Libvirt, zram) + 07: Skel & User Environment (Zsh, Templates, Dotfiles Sync) + 08: Flatpaks & Applications (Flathub, Steam, Lutris, MIME types) + 09: Hyprland Desktop (LinuxBeginnings Auto-Installer) + +Examples: + sudo ./setup.sh # Interactive TUI mode + sudo ./setup.sh --all # Full automated install + sudo ./setup.sh --stages 04,05 # Install only packages and fonts + sudo ./setup.sh --stages 01 --dry-run # Dry-run stage 01 +EOF +} + +# CLI Flags +FLAG_ALL=0 +FLAG_STAGES="" +FLAG_DRY_RUN=0 +CLI_USER="" + +# Parse CLI arguments +while [[ $# -gt 0 ]]; do + case "$1" in + -a|--all) + FLAG_ALL=1 + shift + ;; + -s|--stages) + if [[ -n "${2:-}" && ! "$2" =~ ^- ]]; then + FLAG_STAGES="$2" + shift 2 + else + log_error "Option '$1' requires a comma-separated list of stages." + exit 1 + fi + ;; + -u|--user) + if [[ -n "${2:-}" && ! "$2" =~ ^- ]]; then + CLI_USER="$2" + shift 2 + else + log_error "Option '$1' requires a username." + exit 1 + fi + ;; + -d|--dry-run) + FLAG_DRY_RUN=1 + shift + ;; + -h|--help) + show_help + exit 0 + ;; + *) + log_error "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +if [[ -n "$CLI_USER" ]]; then + export TARGET_USER="$CLI_USER" +fi + +# Ensure root privileges unless dry-run +if [[ "$FLAG_DRY_RUN" -eq 0 ]]; then + require_root +fi + +# Determine stages to run +SELECTED_STAGES=() + +if [[ "$FLAG_ALL" -eq 1 ]]; then + SELECTED_STAGES=(01 02 03 04 05 06 07 08 09) +elif [[ -n "$FLAG_STAGES" ]]; then + IFS=',' read -r -a raw_stages <<< "$FLAG_STAGES" + for st in "${raw_stages[@]}"; do + # Format single digit numbers to two digits (e.g. 1 -> 01) + st="$(echo "$st" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + if [[ "$st" =~ ^[0-9]$ ]]; then + st="0$st" + fi + SELECTED_STAGES+=("$st") + done +else + # Interactive TUI Mode + if [[ -t 0 && -t 1 ]]; then + tui_check_whiptail + tui_welcome + TUI_SELECTION=$(tui_select_stages) + + if [[ -z "$TUI_SELECTION" ]]; then + log_warn "No stages selected. Exiting." + exit 0 + fi + + read -r -a SELECTED_STAGES <<< "$TUI_SELECTION" + + DETECTED_USER="${TARGET_USER:-$(get_target_user 2>/dev/null || true)}" + TARGET_USER_NAME="$(tui_prompt_target_user "$DETECTED_USER")" + export TARGET_USER="$TARGET_USER_NAME" + + if ! tui_confirm_execution "${SELECTED_STAGES[*]}" "$TARGET_USER_NAME"; then + log_info "Installation aborted by user." + exit 0 + fi + else + log_info "Non-interactive shell and no parameters provided. Defaulting to --all." + SELECTED_STAGES=(01 02 03 04 05 06 07 08 09) + fi +fi + +# Ensure TARGET_USER is determined and confirmed for all stages +if [[ -z "${TARGET_USER:-}" ]]; then + TARGET_USER="$(get_target_user)" + export TARGET_USER +fi + +# Map stage identifier to script file +get_stage_script() { + local stage_id="$1" + local match + match="$(find "$SCRIPT_DIR/stages" -maxdepth 1 -name "${stage_id}-*.sh" -type f | head -n1)" + echo "$match" +} + +# Always run preflight check first unless dry-run +if [[ "$FLAG_DRY_RUN" -eq 0 ]]; then + PREFLIGHT_SCRIPT="$(get_stage_script "00")" + if [[ -n "$PREFLIGHT_SCRIPT" && -f "$PREFLIGHT_SCRIPT" ]]; then + bash "$PREFLIGHT_SCRIPT" + fi +fi + +# Banner +log_step "Starting Debian Unstable Setup Execution" +log_info "Target User: $(get_target_user)" +log_info "Planned Stages: ${SELECTED_STAGES[*]}" +if [[ "$FLAG_DRY_RUN" -eq 1 ]]; then + log_warn "DRY-RUN MODE: No changes will be made to the system." +fi + +# Execute Selected Stages +for stage in "${SELECTED_STAGES[@]}"; do + # Skip 00 if it was manually added since it already ran + if [[ "$stage" == "00" ]]; then + continue + fi + + SCRIPT="$(get_stage_script "$stage")" + if [[ -z "$SCRIPT" || ! -f "$SCRIPT" ]]; then + log_warn "Stage script for '$stage' not found in $SCRIPT_DIR/stages! Skipping." + continue + fi + + STAGE_NAME="$(basename "$SCRIPT" .sh)" + log_step "Executing Stage: $STAGE_NAME" + + if [[ "$FLAG_DRY_RUN" -eq 1 ]]; then + log_info "[DRY-RUN] Would execute: bash $SCRIPT" + else + bash "$SCRIPT" + log_success "Completed Stage: $STAGE_NAME" + fi +done + +log_step "All selected setup stages completed successfully!" diff --git a/stages/00-preflight.sh b/stages/00-preflight.sh new file mode 100755 index 0000000..8a8445d --- /dev/null +++ b/stages/00-preflight.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +# ============================================================================== +# stages/00-preflight.sh - System pre-flight checks, permissions & internet connectivity +# ============================================================================== + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +source "$SCRIPT_DIR/lib/utils.sh" + +setup_err_trap + +log_step "Running Stage 00: Pre-flight System Checks..." + +# 1. Check Root Privileges +log_substep "Checking root privileges..." +require_root +log_success "Running with root privileges." + +# 2. Check Target Desktop User +log_substep "Detecting non-root target user..." +TARGET_USER="$(get_target_user)" +TARGET_HOME="$(get_target_home)" + +if [[ -z "$TARGET_USER" || "$TARGET_USER" == "root" ]]; then + log_error "Could not determine target user. Run via 'sudo ./setup.sh' as the desktop user or set TARGET_USER=." + exit 1 +fi + +log_success "Target user identified: $TARGET_USER (Home: $TARGET_HOME)" + +# 3. Check Internet Connectivity +log_substep "Checking internet connectivity..." +INTERNET_OK=0 +for host in "deb.debian.org" "1.1.1.1" "8.8.8.8"; do + if ping -c 1 -W 3 "$host" >/dev/null 2>&1 || curl -s --head --connect-timeout 3 "http://$host" >/dev/null 2>&1; then + INTERNET_OK=1 + break + fi +done + +if [[ "$INTERNET_OK" -ne 1 ]]; then + log_error "No active internet connection detected. Please connect to the internet and try again." + exit 1 +fi +log_success "Internet connection verified." + +# 4. Check Operating System +log_substep "Verifying operating system..." +if [[ -f /etc/os-release ]]; then + # shellcheck source=/dev/null + source /etc/os-release + log_info "Detected OS: ${NAME:-Debian} ${VERSION_ID:-} (${VERSION_CODENAME:-sid})" + if [[ "${ID:-}" != "debian" && "${ID_LIKE:-}" != *"debian"* ]]; then + log_warn "This setup script is optimized for Debian GNU/Linux. Current ID is '${ID:-unknown}'." + fi +else + log_warn "/etc/os-release not found. Proceeding with caution." +fi + +# 5. Check Disk Space +log_substep "Checking available disk space..." +AVAILABLE_KB=$(df --output=avail / | tail -n1) +if [[ "$AVAILABLE_KB" -lt 5242880 ]]; then # Less than 5 GB + log_warn "Less than 5 GB of free space available on root partition ($(( AVAILABLE_KB / 1024 )) MB free)." +else + log_success "Sufficient disk space available ($(( AVAILABLE_KB / 1024 / 1024 )) GB free)." +fi + +log_success "Stage 00: Pre-flight checks passed successfully." diff --git a/stages/01-apt-unstable.sh b/stages/01-apt-unstable.sh new file mode 100755 index 0000000..92e7635 --- /dev/null +++ b/stages/01-apt-unstable.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# ============================================================================== +# stages/01-apt-unstable.sh - Migration to Debian Unstable (Deb822), Pinning & Upgrade +# ============================================================================== + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +source "$SCRIPT_DIR/lib/utils.sh" +source "$SCRIPT_DIR/lib/apt.sh" + +setup_err_trap + +log_step "Running Stage 01: Debian Unstable Migration & Package Sources Configuration" + +require_root + +# 1. Install prerequisites for APT HTTPS & Keyrings +log_substep "Installing APT prerequisites (curl, gnupg, ca-certificates)..." +DEBIAN_FRONTEND=noninteractive apt-get update -y +DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + curl \ + gnupg \ + gpg \ + ca-certificates \ + apt-transport-https \ + debian-archive-keyring + +# 2. Ensure Keyrings directory exists +apt_ensure_keyrings_dir + +# 3. Migrate /etc/apt/sources.list to Deb822 format +log_substep "Migrating APT sources to Deb822 format..." +if [[ -f /etc/apt/sources.list && ! -f /etc/apt/sources.list.bak_pre_unstable ]]; then + cp /etc/apt/sources.list /etc/apt/sources.list.bak_pre_unstable + # Comment out active lines in legacy sources.list to avoid duplicate source warnings + sed -i 's/^[[:space:]]*deb/# deb/' /etc/apt/sources.list +fi + +# Deploy debian-unstable.sources +if [[ -f "$SCRIPT_DIR/data/apt/sources.list.d/debian-unstable.sources" ]]; then + apt_install_sources_file "$SCRIPT_DIR/data/apt/sources.list.d/debian-unstable.sources" "debian-unstable.sources" +fi + +# 4. Deploy APT Preferences / Pinning +log_substep "Configuring APT Pinning preferences..." +mkdir -p /etc/apt/preferences.d +if compgen -G "$SCRIPT_DIR/data/apt/preferences.d/*.pref" > /dev/null; then + for pref_file in "$SCRIPT_DIR"/data/apt/preferences.d/*.pref; do + apt_install_preference_file "$pref_file" "$(basename "$pref_file")" + done +fi + +# 5. Install apt-listbugs and apt-listchanges to safeguard Unstable upgrades +log_substep "Installing protection tools (apt-listbugs, apt-listchanges)..." +apt_update +DEBIAN_FRONTEND=noninteractive apt-get install -y apt-listbugs apt-listchanges + +# 6. Perform Full Dist-Upgrade +log_substep "Performing full distribution upgrade to Debian Sid..." +apt_dist_upgrade + +log_success "Stage 01: Debian Unstable migration and upgrade completed successfully!" diff --git a/stages/02-kernel-hardware.sh b/stages/02-kernel-hardware.sh new file mode 100755 index 0000000..befa2a0 --- /dev/null +++ b/stages/02-kernel-hardware.sh @@ -0,0 +1,121 @@ +#!/usr/bin/env bash +# ============================================================================== +# stages/02-kernel-hardware.sh - XanMod Kernel, Microcode, auto-cpufreq & Hardware Tuning +# ============================================================================== + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +source "$SCRIPT_DIR/lib/utils.sh" +source "$SCRIPT_DIR/lib/apt.sh" + +if [[ -f "$SCRIPT_DIR/config/setup.conf" ]]; then + # shellcheck source=/dev/null + source "$SCRIPT_DIR/config/setup.conf" +fi + +setup_err_trap + +log_step "Running Stage 02: Kernel & Hardware Tuning" + +require_root + +# 1. Setup XanMod Kernel Repository +log_substep "Configuring XanMod Kernel repository..." +apt_ensure_keyrings_dir +apt_add_keyring_from_url "https://dl.xanmod.org/archive.key" "xanmod-archive-keyring.gpg" + +if [[ -f "$SCRIPT_DIR/data/apt/sources.list.d/xanmod.sources" ]]; then + apt_install_sources_file "$SCRIPT_DIR/data/apt/sources.list.d/xanmod.sources" "xanmod.sources" +fi + +apt_update + +# 2. Determine XanMod Kernel Package +log_substep "Detecting CPU microarchitecture level and XanMod branch..." +BRANCH="${XANMOD_BRANCH:-main}" +log_info "Configured XanMod branch: $BRANCH" + +BRANCH_SUFFIX="" +if [[ "$BRANCH" != "main" && -n "$BRANCH" ]]; then + BRANCH_SUFFIX="-$BRANCH" +fi + +# Detect CPU x86-64 microarchitecture level +ARCH_SUFFIX="-x64v2" +if grep -q "avx2" /proc/cpuinfo 2>/dev/null; then + ARCH_SUFFIX="-x64v3" + log_info "CPU supports x86-64-v3 (AVX2 detected)." +else + log_info "CPU does not support AVX2. Using x86-64-v2." +fi + +KERNEL_PKG="linux-xanmod${BRANCH_SUFFIX}${ARCH_SUFFIX}" +FALLBACK_PKG="linux-xanmod${BRANCH_SUFFIX}" + +log_substep "Installing XanMod kernel package ($KERNEL_PKG)..." +if ! DEBIAN_FRONTEND=noninteractive apt-get install -y "$KERNEL_PKG"; then + log_warn "Failed to install $KERNEL_PKG, trying fallback package $FALLBACK_PKG..." + DEBIAN_FRONTEND=noninteractive apt-get install -y "$FALLBACK_PKG" || log_warn "XanMod installation failed, standard kernel will remain active." +fi + +# 3. CPU Microcode Detection and Installation +log_substep "Detecting CPU vendor for microcode installation..." +CPU_VENDOR=$(lscpu 2>/dev/null | grep -oP 'Vendor ID:\s*\K.*' | tr -d ' ' || true) + +case "$CPU_VENDOR" in + "AuthenticAMD") + log_info "AMD CPU detected ($CPU_VENDOR) -> Installing amd64-microcode" + DEBIAN_FRONTEND=noninteractive apt-get install -y amd64-microcode + ;; + "GenuineIntel") + log_info "Intel CPU detected ($CPU_VENDOR) -> Installing intel-microcode" + DEBIAN_FRONTEND=noninteractive apt-get install -y intel-microcode + ;; + *) + log_warn "Unknown CPU vendor '$CPU_VENDOR'. Skipping vendor-specific microcode." + ;; +esac + +# 4. Install & Enable auto-cpufreq from source repository +log_substep "Installing and configuring auto-cpufreq..." +if command_exists auto-cpufreq; then + log_info "auto-cpufreq is already installed." +else + log_info "Cloning and building auto-cpufreq from GitHub repository..." + # Ensure git and python3 build essentials are available + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends git python3 python3-pip python3-setuptools 2>/dev/null || true + + TEMP_DIR="$(create_temp_dir "auto-cpufreq")" + if git clone --depth=1 https://github.com/AdnanHodzic/auto-cpufreq.git "$TEMP_DIR" 2>/dev/null; then + ( + cd "$TEMP_DIR" + ./auto-cpufreq-installer --install || ./auto-cpufreq-installer --install --non-interactive || true + ) + rm -rf "$TEMP_DIR" + else + log_warn "Failed to clone auto-cpufreq repository from GitHub." + fi +fi + +if command_exists auto-cpufreq; then + auto-cpufreq --install 2>/dev/null || true + if command_exists systemctl; then + systemctl enable --now auto-cpufreq 2>/dev/null || log_warn "Could not enable auto-cpufreq systemd service." + fi + log_success "auto-cpufreq installed and service enabled." +else + log_warn "auto-cpufreq installation could not be completed." +fi + +# 5. Environment configuration (Raytracing & Upscaling) +log_substep "Deploying graphics and performance environment configurations..." +mkdir -p /etc/environment.d +if compgen -G "$SCRIPT_DIR/data/etc/environment.d/*.conf" > /dev/null; then + for env_file in "$SCRIPT_DIR"/data/etc/environment.d/*.conf; do + cp "$env_file" /etc/environment.d/ + log_info "Installed environment config: $(basename "$env_file")" + done +fi + +log_success "Stage 02: Kernel and Hardware Tuning completed successfully!" diff --git a/stages/03-bootloader.sh b/stages/03-bootloader.sh new file mode 100755 index 0000000..19c6f32 --- /dev/null +++ b/stages/03-bootloader.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash +# ============================================================================== +# stages/03-bootloader.sh - GRUB configuration, CPU P-State, Vimix Theme & Plymouth +# ============================================================================== + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +source "$SCRIPT_DIR/lib/utils.sh" + +if [[ -f "$SCRIPT_DIR/config/setup.conf" ]]; then + # shellcheck source=/dev/null + source "$SCRIPT_DIR/config/setup.conf" +fi + +setup_err_trap + +log_step "Running Stage 03: Bootloader & Splash Screen Configuration" + +require_root + +GRUB_CFG="/etc/default/grub" +GRUB_TIMEOUT="${GRUB_TIMEOUT:-0}" +GRUB_TIMEOUT_STYLE="${GRUB_TIMEOUT_STYLE:-hidden}" +GRUB_CMDLINE_LINUX_DEFAULT_BASE="quiet splash apparmor=1 usbcore.autosuspend=-1 vt.global_cursor_default=0 loglevel=3 rd.luks.options=discard plymouth.ignore-serial-consoles threadirqs" +GRUB_CMDLINE_LINUX="rcutree.rcu_idle_gp_delay=1" +GRUB_THEME_DIR="/usr/share/debian-gaming/grub/grub2-themes" + +# 1. CPU P-State Detection +log_substep "Detecting CPU vendor for P-State parameter..." +CPU_VENDOR=$(lscpu 2>/dev/null | grep -oP 'Vendor ID:\s*\K.*' | tr -d ' ' || true) +CPU_MODEL=$(lscpu 2>/dev/null | grep -oP 'Model name:\s*\K.*' | head -c 30 || true) + +log_info "Detected CPU: $CPU_MODEL ($CPU_VENDOR)" + +CPU_PARAM="" +case "$CPU_VENDOR" in + "AuthenticAMD") + CPU_PARAM="amd_pstate=active" + log_info "AMD CPU detected -> Adding amd_pstate=active" + ;; + "GenuineIntel") + CPU_PARAM="intel_pstate=active" + log_info "Intel CPU detected -> Adding intel_pstate=active" + ;; + *) + log_warn "Unknown CPU Vendor '$CPU_VENDOR' - no CPU pstate parameter added." + ;; +esac + +if [[ -n "$CPU_PARAM" ]]; then + GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT_BASE $CPU_PARAM" +else + GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT_BASE" +fi + +# 2. Configure /etc/default/grub +if [[ -f "$GRUB_CFG" ]]; then + log_substep "Updating $GRUB_CFG..." + backup_file_or_dir "$GRUB_CFG" + + # Set parameters with sed + sed -i "s|^GRUB_TIMEOUT=.*|GRUB_TIMEOUT=$GRUB_TIMEOUT|" "$GRUB_CFG" + sed -i "s|^GRUB_TIMEOUT_STYLE=.*|GRUB_TIMEOUT_STYLE=$GRUB_TIMEOUT_STYLE|" "$GRUB_CFG" + sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"$GRUB_CMDLINE_LINUX_DEFAULT\"|" "$GRUB_CFG" + sed -i "s|^GRUB_CMDLINE_LINUX=.*|GRUB_CMDLINE_LINUX=\"$GRUB_CMDLINE_LINUX\"|" "$GRUB_CFG" + + # Ensure entries exist if sed didn't find them + grep -q '^GRUB_TIMEOUT=' "$GRUB_CFG" || echo "GRUB_TIMEOUT=$GRUB_TIMEOUT" >> "$GRUB_CFG" + grep -q '^GRUB_TIMEOUT_STYLE=' "$GRUB_CFG" || echo "GRUB_TIMEOUT_STYLE=$GRUB_TIMEOUT_STYLE" >> "$GRUB_CFG" + grep -q '^GRUB_CMDLINE_LINUX_DEFAULT=' "$GRUB_CFG" || echo "GRUB_CMDLINE_LINUX_DEFAULT=\"$GRUB_CMDLINE_LINUX_DEFAULT\"" >> "$GRUB_CFG" + grep -q '^GRUB_CMDLINE_LINUX=' "$GRUB_CFG" || echo "GRUB_CMDLINE_LINUX=\"$GRUB_CMDLINE_LINUX\"" >> "$GRUB_CFG" +else + log_warn "$GRUB_CFG not found. Is GRUB installed?" +fi + +# 3. Install & Configure Plymouth +log_substep "Installing and configuring Plymouth splash theme..." +if DEBIAN_FRONTEND=noninteractive apt-get install -y plymouth plymouth-themes 2>/dev/null; then + PLYMOUTH_THEME="${PLYMOUTH_THEME:-solar}" + if command_exists plymouth-set-default-theme; then + plymouth-set-default-theme -R "$PLYMOUTH_THEME" 2>/dev/null || log_warn "Could not set Plymouth theme to $PLYMOUTH_THEME" + log_success "Plymouth configured with theme: $PLYMOUTH_THEME" + fi +fi + +# 4. Install Vimix GRUB Theme +log_substep "Installing Vimix GRUB theme..." +DEBIAN_FRONTEND=noninteractive apt-get install -y git 2>/dev/null || true +mkdir -p "$GRUB_THEME_DIR" +if [[ ! -d "$GRUB_THEME_DIR/.git" ]]; then + if git clone --depth 1 https://github.com/vinceliuice/grub2-themes.git "$GRUB_THEME_DIR" 2>/dev/null; then + "$GRUB_THEME_DIR/install.sh" -b -t "${GRUB_THEME:-vimix}" 2>/dev/null || log_warn "Vimix theme installer encountered an issue." + log_success "Vimix GRUB theme installed." + else + log_warn "Failed to clone grub2-themes repository. Skipping theme." + fi +else + log_info "GRUB Theme repository already cloned; updating..." + (cd "$GRUB_THEME_DIR" && git pull 2>/dev/null && ./install.sh -b -t "${GRUB_THEME:-vimix}" 2>/dev/null) || log_warn "Vimix theme update skipped." +fi + +# 5. Update GRUB & Initramfs +log_substep "Running update-grub and update-initramfs..." +if command_exists update-grub; then + update-grub +fi +if command_exists update-initramfs; then + update-initramfs -u 2>/dev/null || true +fi + +log_success "Stage 03: Bootloader and Splash configuration completed successfully!" diff --git a/stages/04-packages.sh b/stages/04-packages.sh new file mode 100755 index 0000000..9a48ebd --- /dev/null +++ b/stages/04-packages.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# ============================================================================== +# stages/04-packages.sh - Installation of categorised system and desktop packages +# ============================================================================== + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +source "$SCRIPT_DIR/lib/utils.sh" +source "$SCRIPT_DIR/lib/apt.sh" + +setup_err_trap + +log_step "Running Stage 04: Thematic Package Installation" + +require_root + +PACKAGES_DIR="$SCRIPT_DIR/config/packages" + +if [[ ! -d "$PACKAGES_DIR" ]]; then + log_error "Package configuration directory $PACKAGES_DIR not found!" + exit 1 +fi + +# List of APT package lists to process (excluding flatpaks which are handled in stage 08) +APT_LISTS=( + "01-base.list" + "02-desktop.list" + "03-gaming.list" + "04-virtualization.list" + "05-multimedia.list" +) + +log_substep "Updating package lists before installation..." +apt_update + +for list_name in "${APT_LISTS[@]}"; do + list_path="$PACKAGES_DIR/$list_name" + if [[ -f "$list_path" ]]; then + log_step "Installing package category: $list_name" + apt_install_package_list_file "$list_path" || log_warn "Some packages from $list_name could not be installed." + else + log_warn "Package list file $list_name not found in $PACKAGES_DIR." + fi +done + +log_success "Stage 04: Thematic package installation completed successfully!" diff --git a/stages/05-fonts.sh b/stages/05-fonts.sh new file mode 100755 index 0000000..9d04e66 --- /dev/null +++ b/stages/05-fonts.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# ============================================================================== +# stages/05-fonts.sh - Download and clean installation of Coding & Nerd Fonts +# ============================================================================== + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +source "$SCRIPT_DIR/lib/utils.sh" + +setup_err_trap + +log_step "Running Stage 05: Coding & Nerd Fonts Installation" + +require_root + +FONT_DIR="/usr/share/fonts" +TEMP_DIR="$(create_temp_dir "fonts-setup")" + +# Ensure cleanup of temp directory on exit +cleanup() { + if [[ -d "$TEMP_DIR" ]]; then + log_info "Cleaning up temporary font download directory: $TEMP_DIR" + rm -rf "$TEMP_DIR" + fi +} +trap cleanup EXIT ERR + +mkdir -p "$FONT_DIR" + +# 1. JetBrains Mono Nerd Font +log_substep "Downloading and installing JetBrainsMono Nerd Font..." +JB_ARCHIVE="$TEMP_DIR/JetBrainsMono.tar.xz" +JB_DEST="$FONT_DIR/JetBrainsMonoNerd" +if curl -fsSL "https://github.com/ryanoasis/nerd-fonts/releases/latest/download/JetBrainsMono.tar.xz" -o "$JB_ARCHIVE"; then + mkdir -p "$JB_DEST" + tar -xJkf "$JB_ARCHIVE" -C "$JB_DEST" 2>/dev/null || tar -xJf "$JB_ARCHIVE" -C "$JB_DEST" + log_success "JetBrainsMono Nerd Font installed to $JB_DEST" +else + log_warn "Failed to download JetBrainsMono Nerd Font." +fi + +# 2. Fantasque Sans Mono Nerd Font +log_substep "Downloading and installing Fantasque Sans Mono Nerd Font..." +FANTASQUE_ARCHIVE="$TEMP_DIR/FantasqueSansMono.zip" +FANTASQUE_DEST="$FONT_DIR/FantasqueSansMonoNerd" +if curl -fsSL "https://github.com/ryanoasis/nerd-fonts/releases/download/v3.3.0/FantasqueSansMono.zip" -o "$FANTASQUE_ARCHIVE"; then + mkdir -p "$FANTASQUE_DEST" + unzip -o -q "$FANTASQUE_ARCHIVE" -d "$FANTASQUE_DEST" + log_success "FantasqueSansMono Nerd Font installed to $FANTASQUE_DEST" +else + log_warn "Failed to download FantasqueSansMono Nerd Font." +fi + +# 3. Victor Mono Font +log_substep "Downloading and installing Victor Mono Font..." +VICTOR_ARCHIVE="$TEMP_DIR/VictorMonoAll.zip" +VICTOR_DEST="$FONT_DIR/VictorMono" +if curl -fsSL "https://rubjo.github.io/victor-mono/VictorMonoAll.zip" -o "$VICTOR_ARCHIVE"; then + mkdir -p "$VICTOR_DEST" + unzip -o -q "$VICTOR_ARCHIVE" -d "$VICTOR_DEST" + log_success "Victor Mono Font installed to $VICTOR_DEST" +else + log_warn "Failed to download Victor Mono Font." +fi + +# 4. Refresh Font Cache +log_substep "Updating font cache..." +if command_exists fc-cache; then + fc-cache -f + log_success "Font cache refreshed." +fi + +log_success "Stage 05: Fonts installation completed successfully!" diff --git a/stages/06-services.sh b/stages/06-services.sh new file mode 100755 index 0000000..3d75697 --- /dev/null +++ b/stages/06-services.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash +# ============================================================================== +# stages/06-services.sh - System services activation (AppArmor, Docker, Libvirt, zram) +# ============================================================================== + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +source "$SCRIPT_DIR/lib/utils.sh" +source "$SCRIPT_DIR/lib/apt.sh" + +setup_err_trap + +log_step "Running Stage 06: System Services Configuration & User Privileges" + +require_root + +TARGET_USER="$(get_target_user)" + +# 1. AppArmor Service +log_substep "Enabling and starting AppArmor service..." +if command_exists systemctl; then + systemctl enable apparmor 2>/dev/null || true + systemctl start apparmor 2>/dev/null || true + log_success "AppArmor service enabled." +fi + +# 2. zram-tools Configuration +log_substep "Configuring zram swap service..." +if command_exists systemctl; then + systemctl enable --now zramswap.service 2>/dev/null || true + log_success "zram service enabled." +fi + +# 3. Docker Service & Repository +log_substep "Setting up Docker service & repository..." +apt_ensure_keyrings_dir +apt_add_keyring_from_url "https://download.docker.com/linux/debian/gpg" "docker.asc" + +DEBIAN_CODENAME="sid" +if [[ -f /etc/os-release ]]; then + # shellcheck source=/dev/null + source /etc/os-release + DEBIAN_CODENAME="${VERSION_CODENAME:-sid}" + # Docker uses 'bookworm' or 'trixie' upstream repo suite for Debian testing/unstable if sid is not explicitly provided + if [[ "$DEBIAN_CODENAME" == "sid" ]]; then + DEBIAN_CODENAME="trixie" + fi +fi + +ARCH="$(dpkg --print-architecture)" +cat < /etc/apt/sources.list.d/docker.sources +Types: deb +URIs: https://download.docker.com/linux/debian +Suites: $DEBIAN_CODENAME +Components: stable +Architectures: $ARCH +Signed-By: /etc/apt/keyrings/docker.asc +EOF +chmod 0644 /etc/apt/sources.list.d/docker.sources + +apt_update +DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + docker-ce \ + docker-ce-cli \ + containerd.io \ + docker-buildx-plugin \ + docker-compose-plugin 2>/dev/null || log_warn "Could not install all Docker packages." + +if command_exists systemctl; then + systemctl enable --now docker.service 2>/dev/null || true +fi + +# 4. Libvirt / KVM Virtualization +log_substep "Configuring Virtualization (Libvirt / KVM)..." +HAS_VIRT=$(grep -Eoc '(vmx|svm)' /proc/cpuinfo 2>/dev/null || echo 0) +if [[ "$HAS_VIRT" -gt 0 ]]; then + log_info "Hardware virtualization support detected." + if command_exists systemctl; then + systemctl enable --now libvirtd.service 2>/dev/null || true + fi + if command_exists virsh; then + virsh net-start default 2>/dev/null || true + virsh net-autostart default 2>/dev/null || true + fi + # Add target user to libvirt and kvm groups + groupadd -f libvirt + groupadd -f kvm + usermod -aG libvirt,kvm "$TARGET_USER" + log_success "Target user $TARGET_USER added to libvirt & kvm groups." +else + log_info "No hardware virtualization extensions (VT-x/AMD-V) detected in /proc/cpuinfo." +fi + +# 5. User Group Memberships +log_substep "Updating user group memberships for $TARGET_USER..." +groupadd -f sudo +groupadd -f docker +usermod -aG sudo,docker "$TARGET_USER" +log_success "Target user $TARGET_USER added to sudo and docker groups." + +log_success "Stage 06: System services configuration completed successfully!" diff --git a/stages/07-skel-and-user.sh b/stages/07-skel-and-user.sh new file mode 100755 index 0000000..3f8782a --- /dev/null +++ b/stages/07-skel-and-user.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +# ============================================================================== +# stages/07-skel-and-user.sh - /etc/skel templates, Zsh setup, user environment sync & chsh +# ============================================================================== + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +source "$SCRIPT_DIR/lib/utils.sh" + +setup_err_trap + +log_step "Running Stage 07: User Environment, Skel Templates & Shell Configuration" + +require_root + +TARGET_USER="$(get_target_user)" +TARGET_HOME="$(get_target_home)" + +log_info "Configuring userland environment for target user: $TARGET_USER ($TARGET_HOME)" + +# 1. Deploy System Profile Scripts (/etc/profile.d) +log_substep "Deploying system profile scripts to /etc/profile.d/..." +mkdir -p /etc/profile.d +if [[ -d "$SCRIPT_DIR/data/etc/profile.d" ]]; then + for profile_script in "$SCRIPT_DIR"/data/etc/profile.d/*.sh; do + [[ -f "$profile_script" ]] || continue + cp "$profile_script" /etc/profile.d/ + chmod 0755 "/etc/profile.d/$(basename "$profile_script")" + log_info "Installed profile script: $(basename "$profile_script")" + done +fi + +# Ensure Zsh profiles source /etc/profile +mkdir -p /etc/zsh +grep -q '^source /etc/profile' /etc/zsh/zprofile 2>/dev/null || echo 'source /etc/profile' >> /etc/zsh/zprofile + +# 2. Provision /etc/skel for Future New Users +log_substep "Provisioning /etc/skel with default templates and configs..." +mkdir -p /etc/skel/Templates +if [[ -d "$SCRIPT_DIR/data/skel/Templates" ]]; then + cp -r "$SCRIPT_DIR"/data/skel/Templates/* /etc/skel/Templates/ 2>/dev/null || true +fi +if [[ -f "$SCRIPT_DIR/data/skel/.zshrc" ]]; then + cp "$SCRIPT_DIR/data/skel/.zshrc" /etc/skel/.zshrc +fi +chown -R root:root /etc/skel + +# 3. Synchronize User Environment for Target User +log_substep "Synchronizing Dotfiles & Templates into $TARGET_HOME..." +mkdir -p "$TARGET_HOME/Templates" + +# Backup existing .zshrc if present +if [[ -f "$TARGET_HOME/.zshrc" ]]; then + backup_file_or_dir "$TARGET_HOME/.zshrc" +fi + +if [[ -f "$SCRIPT_DIR/data/skel/.zshrc" ]]; then + cp "$SCRIPT_DIR/data/skel/.zshrc" "$TARGET_HOME/.zshrc" +fi + +if [[ -d "$SCRIPT_DIR/data/skel/Templates" ]]; then + cp -r "$SCRIPT_DIR"/data/skel/Templates/* "$TARGET_HOME/Templates/" 2>/dev/null || true +fi + +# 4. Install Oh-My-Zsh for Target User (if not already installed) +if [[ ! -d "$TARGET_HOME/.oh-my-zsh" ]]; then + log_substep "Installing Oh-My-Zsh repository for $TARGET_USER..." + if command_exists git; then + run_as_target_user git clone --depth=1 https://github.com/ohmyzsh/ohmyzsh.git "$TARGET_HOME/.oh-my-zsh" 2>/dev/null || log_warn "Could not clone Oh-My-Zsh repository." + fi +fi + +# Fix ownership +chown -R "$TARGET_USER:$TARGET_USER" "$TARGET_HOME/.zshrc" "$TARGET_HOME/Templates" +if [[ -d "$TARGET_HOME/.oh-my-zsh" ]]; then + chown -R "$TARGET_USER:$TARGET_USER" "$TARGET_HOME/.oh-my-zsh" +fi + +# 5. Set Default Shell to Zsh using standard chsh +log_substep "Setting default shell to Zsh for $TARGET_USER..." +ZSH_BIN="$(command -v zsh || echo "/usr/bin/zsh")" +if [[ -x "$ZSH_BIN" ]]; then + # Ensure zsh is listed in /etc/shells + grep -q "^$ZSH_BIN$" /etc/shells 2>/dev/null || echo "$ZSH_BIN" >> /etc/shells + + CURRENT_SHELL="$(getent passwd "$TARGET_USER" | cut -d: -f7)" + if [[ "$CURRENT_SHELL" != "$ZSH_BIN" ]]; then + chsh -s "$ZSH_BIN" "$TARGET_USER" + log_success "Default shell for $TARGET_USER set to $ZSH_BIN" + else + log_info "Default shell for $TARGET_USER is already $ZSH_BIN" + fi +else + log_warn "Zsh binary not found at $ZSH_BIN. Skipping chsh." +fi + +log_success "Stage 07: Skel & userland configuration completed successfully!" diff --git a/stages/08-flatpaks-apps.sh b/stages/08-flatpaks-apps.sh new file mode 100755 index 0000000..12d7759 --- /dev/null +++ b/stages/08-flatpaks-apps.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +# ============================================================================== +# stages/08-flatpaks-apps.sh - Flathub setup, Flatpaks, Spotify, Waydroid & MIME associations +# ============================================================================== + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +source "$SCRIPT_DIR/lib/utils.sh" +source "$SCRIPT_DIR/lib/apt.sh" + +setup_err_trap + +log_step "Running Stage 08: Flatpaks, Additional Apps & MIME Associations" + +require_root + +TARGET_USER="$(get_target_user)" +TARGET_HOME="$(get_target_home)" + +# 1. Flathub Repository Setup +log_substep "Configuring Flathub remote repository..." +if command_exists flatpak; then + flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo || log_warn "Could not add Flathub remote." + log_success "Flathub repository enabled." +else + log_warn "flatpak command not found. Skipping Flatpak installation." +fi + +# 2. Install Flatpaks from config/packages/06-flatpaks.list +FLATPAK_LIST="$SCRIPT_DIR/config/packages/06-flatpaks.list" +if command_exists flatpak && [[ -f "$FLATPAK_LIST" ]]; then + log_substep "Installing Flatpak applications from $FLATPAK_LIST..." + while IFS= read -r app_id || [[ -n "$app_id" ]]; do + app_id="$(echo "$app_id" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" + [[ -z "$app_id" || "$app_id" =~ ^# ]] && continue + log_info "Installing Flatpak: $app_id" + flatpak install -y flathub "$app_id" 2>/dev/null || log_warn "Failed to install Flatpak: $app_id" + done < "$FLATPAK_LIST" +fi + +# 3. Spotify Client Installation (Debian APT repo) +log_substep "Configuring Spotify repository and client..." +apt_ensure_keyrings_dir +if curl -fsSL https://download.spotify.com/debian/pubkey_5384CE82BA52C83A.asc | gpg --dearmor -o /etc/apt/keyrings/spotify.gpg 2>/dev/null; then + chmod 0644 /etc/apt/keyrings/spotify.gpg + cat < /etc/apt/sources.list.d/spotify.sources +Types: deb +URIs: http://repository.spotify.com +Suites: stable +Components: non-free +Signed-By: /etc/apt/keyrings/spotify.gpg +EOF + chmod 0644 /etc/apt/sources.list.d/spotify.sources + apt_update + DEBIAN_FRONTEND=noninteractive apt-get install -y spotify-client 2>/dev/null || log_warn "Could not install spotify-client via APT." +fi + +# 4. Deploy Custom Desktop Applications +if [[ -d "$SCRIPT_DIR/data/usr/share/applications" ]]; then + log_substep "Deploying custom desktop entries..." + mkdir -p /usr/share/applications + cp -r "$SCRIPT_DIR"/data/usr/share/applications/* /usr/share/applications/ 2>/dev/null || true +fi + +# 5. Waydroid Container Setup +log_substep "Checking Waydroid installation..." +if ! command_exists waydroid; then + log_info "Installing Waydroid repository and package..." + if curl -fsSL https://repo.waydro.id | bash 2>/dev/null; then + DEBIAN_FRONTEND=noninteractive apt-get install -y waydroid 2>/dev/null || log_warn "Failed to install waydroid package." + fi +fi +if command_exists systemctl && command_exists waydroid; then + systemctl enable --now waydroid-container 2>/dev/null || true + log_success "Waydroid container service enabled." +fi + +# 6. Set Default Desktop MIME Types for Target User +log_substep "Setting default XDG MIME handlers for $TARGET_USER..." +run_as_target_user xdg-mime default org.gnome.Loupe.desktop image/jpeg 2>/dev/null || true +run_as_target_user xdg-mime default org.gnome.Loupe.desktop image/png 2>/dev/null || true +run_as_target_user xdg-mime default io.bassi.Amberol.desktop audio/mpeg 2>/dev/null || true +run_as_target_user xdg-mime default io.bassi.Amberol.desktop audio/x-wav 2>/dev/null || true +run_as_target_user xdg-mime default io.bassi.Amberol.desktop audio/flac 2>/dev/null || true +run_as_target_user xdg-mime default io.bassi.Amberol.desktop audio/ogg 2>/dev/null || true +run_as_target_user xdg-mime default org.gnome.TextEditor.desktop text/plain 2>/dev/null || true +run_as_target_user xdg-mime default org.gnome.TextEditor.desktop text/x-log 2>/dev/null || true +run_as_target_user xdg-mime default org.gnome.TextEditor.desktop text/markdown 2>/dev/null || true +run_as_target_user xdg-mime default eu.betterbird.Betterbird.desktop x-scheme-handler/mailto 2>/dev/null || true + +log_success "Stage 08: Flatpaks, Applications and MIME associations completed successfully!" diff --git a/stages/09-hyprland.sh b/stages/09-hyprland.sh new file mode 100644 index 0000000..8191b86 --- /dev/null +++ b/stages/09-hyprland.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# ============================================================================== +# stages/09-hyprland.sh - LinuxBeginnings Debian-Hyprland auto-installer & desktop setup +# ============================================================================== + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +source "$SCRIPT_DIR/lib/utils.sh" + +setup_err_trap + +log_step "Running Stage 09: Hyprland Desktop (LinuxBeginnings Installer)" + +require_root + +TARGET_USER="$(get_target_user)" +TARGET_HOME="$(get_target_home)" + +log_info "Configuring Hyprland Desktop for target user: $TARGET_USER ($TARGET_HOME)" + +log_substep "Downloading and executing LinuxBeginnings Debian-Hyprland installer..." +INSTALLER_URL="https://raw.githubusercontent.com/LinuxBeginnings/Debian-Hyprland/main/auto-install.sh" +TEMP_INSTALLER="$(mktemp "/tmp/hyprland-install.XXXXXX.sh")" + +if curl -fsSL "$INSTALLER_URL" -o "$TEMP_INSTALLER"; then + chmod +x "$TEMP_INSTALLER" + chown "$TARGET_USER:$TARGET_USER" "$TEMP_INSTALLER" + + log_info "Running LinuxBeginnings auto-installer under user '$TARGET_USER'..." + if run_as_target_user bash "$TEMP_INSTALLER"; then + log_success "LinuxBeginnings Debian-Hyprland installation completed successfully." + else + log_warn "LinuxBeginnings installer exited with non-zero status. Check logs if needed." + fi + rm -f "$TEMP_INSTALLER" +else + log_error "Failed to download LinuxBeginnings Debian-Hyprland installer from $INSTALLER_URL" + exit 1 +fi + +log_success "Stage 09: Hyprland Desktop installation completed successfully!"