139 Commits
Author SHA1 Message Date
DragonSlayer_14andJunie f093cce7dc fix(install): prevent stdin stream truncation when running via pipe
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 16:13:51 +02:00
DragonSlayer_14andJunie 85408020c6 Feat: Automatische Konfiguration aller LAN-Schnittstellen und Loopback im Debian-Installer-Standard
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 15:56:54 +02:00
DragonSlayer_14andJunie c35f49d9fc Add install.sh web installer bootstrap script for curl one-liner execution
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 15:31:06 +02:00
DragonSlayer_14andJunie 37a2c49855 feat(bootloader): add grub-btrfs snapshot boot support
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 15:19:23 +02:00
DragonSlayer_14andJunie 74803cd258 Feat: Automatische Timeshift Boot- und APT-Update-Snapshots sowie Retention-Limit konfiguriert
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 15:06:24 +02:00
DragonSlayer_14andJunie d0f88a3608 Feat: Automatische Timeshift Btrfs-Snapshots an kritischen Meilensteinen integriert
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 14:53:37 +02:00
DragonSlayer_14andJunie 5889acd1e3 Feat: Automatische Btrfs-Root-Erkennung und Subvolume-Migration (@, @home) hinzugefügt
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 14:44:24 +02:00
DragonSlayer_14andJunie a949899168 Docs: Schnellstart-One-Liner zum Klonen und Ausführen zu README.md hinzugefügt
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 13:40:20 +02:00
DragonSlayer_14andJunie 20d4952740 Refactor: Aufteilung in Stage 08 (Flatpaks), 09 (Apps & MIME) und 10 (Hyprland) sowie ShellCheck-Bereinigung
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 13:36:52 +02:00
DragonSlayer_14andJunie 579489fa9c Feat: OpenDeck-Installation zu Stage 08 hinzugefügt
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 13:30:27 +02:00
DragonSlayer_14andJunie d69534d286 Feat: Ollama-Installation und systemd-Service-Konfiguration mit anpassbarem Modellpfad hinzugefügt
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 13:23:32 +02:00
DragonSlayer_14andJunie 6cd6e789ba Fix: Keyring-Handling, Error-Traps und Docker/Spotify-Repositorys korrigiert
- lib/apt.sh: GPG-Dearmor mit --yes --batch und ASCII-Armor-Erkennung über grep

- stages/05-fonts.sh: Bereinigung nur noch bei EXIT trappen

- stages/06-services.sh: Standard-Codename für Docker-Repo auf trixie gesetzt

- stages/08-flatpaks-apps.sh: Einheitliche Hilfsfunktion apt_add_keyring_from_url für Spotify genutzt

Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 13:12:37 +02:00
DragonSlayer_14 8e36e4ce0d FEat: Fügt Architectures: amd64 in sources.list ein 2026-09-06 13:01:04 +02:00
DragonSlayer_14andJunie 4afce9cdb1 Feat: Fehlende APT-Pakete wiederhergestellt und Gitea-Paketquellen eingerichtet
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 12:58:30 +02:00
DragonSlayer_14andJunie bb3e42a8e3 Feat: Native Installation von Steam, Heroic und Lutris über APT sowie 32-Bit-Multiarch-Aktivierung
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 12:39:57 +02:00
DragonSlayer_14andJunie c4241d7015 feat(zsh): provision Oh-My-Zsh and plugins for all users on login
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 12:30:51 +02:00
DragonSlayer_14andJunie 28319183b6 feat(hyprland): add Junie CLI and AwesomeJunieSkills to first-login setup
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 12:17:57 +02:00
DragonSlayer_14andJunie 04a68df15c Feat: Hyprland-Desktop mit Debian-Hyprland-Installer und interaktivem Dotfiles-Setup
Co-authored-by: Junie <junie@jetbrains.com>
2026-09-06 12:05:35 +02:00
DragonSlayer_14 3c1601fc2f Feat: Fütgt kitty in den Packages hinzu 2026-09-06 11:14:46 +02:00
DragonSlayer_14 d424b5eed7 Feat: Überarbeitet die Install Struktur 2026-09-06 11:11:46 +02:00
DragonSlayer_14 90dd188555 Feat: Fügt speech-dispatcher hinzu 2026-09-01 17:21:00 +02:00
DragonSlayer_14 24d8ba379f Feat: Fügt glances hinzu 2026-08-31 21:56:09 +02:00
DragonSlayer_14 ad7b31a67a Feat: FÜgt htop hinzu 2026-08-31 21:53:45 +02:00
DragonSlayer_14 b237de1fc5 Feat: Kommentiert Docker wieder ein 2026-08-31 21:49:17 +02:00
DragonSlayer_14 6e303b041f Feat: Passt .gitignore an 2026-08-31 21:26:40 +02:00
DragonSlayer_14 3788422797 Feat: Entfernt LM-Studio 2026-08-31 21:23:31 +02:00
DragonSlayer_14 10aec5458a Feat: Ersetzt lm-studio AppImage durch lm-studio Flatpak 2026-08-31 20:51:25 +02:00
DragonSlayer_14 4feb815d97 Feat: Installiert LM-Studio als AppImage 2026-08-30 21:13:21 +02:00
DragonSlayer_14 279a137132 Feat: Fügt LM-Studio hinzu 2026-08-30 21:09:28 +02:00
DragonSlayer_14 fe02dd23c6 Ref: Passt Sortierung an 2026-08-30 13:51:59 +02:00
DragonSlayer_14 8a5c4094ba Feat: Fügt command-not-found hinzu 2026-08-30 09:32:33 +02:00
DragonSlayer_14 9b0dce0d84 Feat: Fügt gparted hinzu 2026-08-30 09:29:37 +02:00
DragonSlayer_14 8d2e4b3b0e Feat: Installiert Lutris als Flatpak 2026-08-30 00:08:15 +02:00
DragonSlayer_14 f810149f95 Feat: Fügt vulkan-tools hinzu 2026-08-30 00:07:24 +02:00
DragonSlayer_14 f32e1ca6d4 Feat: INstalliert Heroic als Flatpak 2026-08-30 00:06:12 +02:00
DragonSlayer_14 da0367a43c Feat: Fügt mangoapp hinzu 2026-08-29 19:39:07 +02:00
DragonSlayer_14 3a9cf54b2f Feat: Fügt -y bei apt install hinzu 2026-08-29 00:02:31 +02:00
DragonSlayer_14 4f87611c66 Feat: Sortiert apt-Pakete um 2026-08-29 00:00:38 +02:00
DragonSlayer_14 ace5cfee5c Feat: Installiert heroic über den Mirror 2026-08-28 23:33:00 +02:00
DragonSlayer_14 858b3a4cb5 Feat: Installiert topgrade über den Mirror 2026-08-28 23:25:45 +02:00
DragonSlayer_14 b92c49048b Feat: Entfernt deb-get 2026-08-28 23:25:03 +02:00
DragonSlayer_14 394746f658 Feat: Fügt TODO ein 2026-08-28 23:22:38 +02:00
DragonSlayer_14 d86a1dde3d Feat: Passt Sortierung an 2026-08-28 23:21:36 +02:00
DragonSlayer_14 22b4ca5c9e Feat: Installiert codium über den Mirror 2026-08-28 23:19:56 +02:00
DragonSlayer_14 c48ebeda9c Feat: Kommentriert Spotify wieder ein 2026-08-28 23:14:45 +02:00
DragonSlayer_14 b74436b7c0 Feat: Installiert Floorp über den Mirror 2026-08-28 23:14:10 +02:00
DragonSlayer_14 13a40d5ac5 Feat: Installiert Vesktop über den Mirror 2026-08-28 23:05:26 +02:00
DragonSlayer_14 f1ba8513fc Feat: Fügt lutris hinzu 2026-08-28 22:59:46 +02:00
DragonSlayer_14 3d06340314 Feat: Fügt yazi hinzu 2026-08-28 22:54:19 +02:00
DragonSlayer_14 c2611debfa Feat: Fügt Kommentar hinzu 2026-08-28 22:48:38 +02:00
DragonSlayer_14 9cb077e4fb Feat: Passt Sortierung der Flatpak-Pakete an 2026-08-28 22:45:29 +02:00
DragonSlayer_14 5c4b9ad08d Feat: Ersetzt das Flatpak localsend durch das apt-Paket 2026-08-28 22:43:39 +02:00
DragonSlayer_14 5bc8227773 Feat: Ersetzt das Flatpak rpi-imager durch das apt-Paket 2026-08-28 22:34:29 +02:00
DragonSlayer_14 0c0b6da0ea Feat: Ersetzt das Flatpak cryptomator durch das apt-Paket 2026-08-28 22:25:57 +02:00
DragonSlayer_14 7c2ca5b6b2 Feat: Ersetzt das Flatpak bruno durch das apt-Paket bruno 2026-08-28 22:14:51 +02:00
DragonSlayer_14 4b0047484d Fix: Passt Signed-By Wert für gitea-mirror.sources an 2026-08-28 22:12:40 +02:00
DragonSlayer_14 d5b1da9745 Feat: Fügt apt-Mirror https://gitea.creative-dragonslayer.de/api/packages/Mirror/debian hinzu 2026-08-28 22:07:28 +02:00
DragonSlayer_14 dc8c4c9062 Feat: Ersetzt das Flatpak decoder durch das apt-Paket gnome-decoder 2026-08-28 22:01:18 +02:00
DragonSlayer_14 aa68e0e1f7 Feat: Ersetzt das Flatpak TextEditor durch das apt-Paket gnome-text-editor 2026-08-28 21:59:57 +02:00
DragonSlayer_14 bff9822c86 Ersetzt das Flatpak font-viewer durch das apt-Paket gnome-font-viewer 2026-08-28 21:57:39 +02:00
DragonSlayer_14 1aa3a164ab Ersetzt das Flatpak calculator durch das Apt-Paket gnome-calculator 2026-08-28 21:55:50 +02:00
DragonSlayer_14 742cee14f1 Feat: Ersetzt Logs durch das Apt-Paket gnome-logs 2026-08-28 21:50:41 +02:00
DragonSlayer_14 532d34a6ae Feat: Ersetzt das Amberol-Flatpak durch das apt-Paket 2026-08-28 21:49:14 +02:00
DragonSlayer_14 61034975db Fix: Passt .desktop-Name von Loupe an 2026-08-28 21:47:51 +02:00
DragonSlayer_14 d4de7d0056 Feat: Ersetzt das Flatpak snapshot durch das apt Paket gnome-snapshot 2026-08-28 21:40:01 +02:00
DragonSlayer_14 93f0757f49 Feat: Ersetzt das Flatpak SimpleScan durch das entsprechende apt-Paket 2026-08-28 21:37:46 +02:00
DragonSlayer_14 697196c99b Update default image viewer to Loupe and adjust dependencies
Replaced default image viewer with Loupe for JPEG and PNG files in `03-install.sh` and removed redundant installation and configuration steps from `07-programs.sh`. Ensured required dependency `loupe` is included in the apt package list.
2026-08-28 21:36:39 +02:00
DragonSlayer_14 a3630b9d28 Set Betterbird as default mail app with a TODO note
Betterbird is installed and set as the default mail application. A TODO comment is added to replace Betterbird with Melia in the future.
2026-08-28 21:31:10 +02:00
DragonSlayer_14 176240f3b7 Add 'bat' package to the installation script
The 'bat' package has been added to the list of stable packages in 03-install.sh. This enhances the toolset by providing a modern alternative to 'cat' with additional features like syntax highlighting and Git integration.
2026-08-28 18:39:17 +02:00
DragonSlayer_14 7af43e0850 Update package lists and adjust Easyeffects installation method
Added "easyeffects" to apt installation in `03-install.sh` and removed its Flatpak installation from `07-programs.sh`. This ensures Easyeffects is installed via the system package manager instead of Flatpak for better integration.
2026-08-27 19:23:49 +02:00
DragonSlayer_14 5b3fd6848d Add Remmina to apt install and remove its Flatpak version
Replaced Remmina's Flatpak installation with its APT package counterpart for consistency with other system-installed software. This ensures better integration and potentially reduced redundancy in package management.
2026-08-27 19:22:39 +02:00
DragonSlayer_14 ef08a0221b Add PrismLauncher to APT install and remove Flatpak installation
PrismLauncher is now installed via the system package manager (APT) instead of Flatpak for consistency and better integration with the system. The Flatpak installation of PrismLauncher has been removed accordingly.
2026-08-27 19:17:43 +02:00
DragonSlayer_14 29948841cd Add Flameshot to APT installation; remove redundant Flatpak install
Moved Flameshot installation to APT package list for consistency and removed its duplicate Flatpak installation from the programs script. This change ensures that Flameshot is installed via the system's package manager instead of Flatpak for better integration.
2026-08-27 19:14:00 +02:00
DragonSlayer_14 cf24a033da Update package lists and remove redundant Flatseal install
Added "Flatseal" to the apt package list and removed its redundant Flatpak installation in the scripts. This change ensures consistency by managing Flatseal through the system package manager instead of Flatpak.
2026-08-27 19:12:48 +02:00
DragonSlayer_14 4516129bec Add 'obfuscate' package to apt and remove its Flatpak version
Moved the 'obfuscate' package installation from Flatpak to apt for consistency in package management. Removed the Flatpak-specific installation step and added 'obfuscate' to the apt package install list.
2026-08-27 19:10:47 +02:00
DragonSlayer_14 7176a8d796 Update package list and remove redundant flatpak install
Added "resources" to the apt package list, replacing its previous installation via flatpak. Removed the flatpak installation of "net.nokyan.Resources" as it is now included as a system package. This ensures better consistency and avoids duplicate installations.
2026-08-27 19:09:00 +02:00
DragonSlayer_14 01e7b63c7f Add 'impression' package to APT and remove redundant Flatpak
The package 'impression' was added to the APT installation list for improved management while its Flatpak installation was removed from the script. This ensures consistency by reducing duplication and aligning package management under APT.
2026-08-27 19:05:34 +02:00
DragonSlayer_14 934dbd1ea6 Update package list and remove redundant Flatpak installation
Added 'fragments' to the APT package installation list while removing its Flatpak installation to streamline package management. This ensures consistency and avoids duplicate installations across package managers.
2026-08-27 19:03:07 +02:00
DragonSlayer_14 fc6385d400 Remove installation of Cartridges application
The Cartridges app installation command was removed from the script, likely due to redundancy or a change in requirements. This ensures the script installs only the necessary applications.
2026-08-27 18:59:59 +02:00
DragonSlayer_14 6fdd50341c Remove Ente Authenticator flatpak installation
The installation command for Ente Authenticator has been removed from the script. This change simplifies the setup process by excluding unnecessary software.
2026-08-27 18:59:26 +02:00
DragonSlayer_14 aab24c5d1d Update package list to include VLC and remove Flatpak install
Added VLC and its related plugins to installation via apt in `03-install.sh` for system-wide availability. Removed redundant Flatpak-based VLC installation from `07-programs.sh` to streamline the setup process.
2026-08-27 18:55:20 +02:00
DragonSlayer_14 5c4097bb6e Update package list and reorganize installation steps
Added 'baobab' to apt package installations and removed its Flatpak counterpart from the program script to streamline installation. Also included a comment placeholder for installing 'yazi' with a link to its documentation.
2026-08-27 18:44:17 +02:00
DragonSlayer_14 6885535b72 Add gnome-keyring to the list of installed packages
Included gnome-keyring to enhance GNOME desktop functionality. This ensures better keyring management and integration for secure storage of credentials. Other packages remain unchanged.
2026-08-23 12:19:13 +02:00
DragonSlayer_14 0c9cc435d5 Add wayland-utils to the package installation list
Included wayland-utils as part of the stable package installation in `03-install.sh` to support Wayland-specific functionality. This ensures better compatibility and enhances user experience on Wayland-based systems.
2026-08-19 22:54:56 +02:00
DragonSlayer_14 1b1be169cf Add installation of GE-Proton via Flatpak
This commit includes the installation command for GE-Proton, a Steam compatibility tool, using Flatpak. This ensures improved game compatibility for Steam users.
2026-08-18 19:44:06 +02:00
DragonSlayer_14 07fe48a33e Add steam-devices to the package installation list.
This change ensures that the steam-devices package is included during the installation process, which is essential for better hardware support in gaming scenarios. No other modifications were made to the script.
2026-08-17 17:11:06 +02:00
DragonSlayer_14 13da1e980b Add MangoHud installation to 07-programs.sh
Included the MangoHud Vulkan layer installation via Flatpak. This provides an overlay for monitoring performance metrics in games.
2026-08-16 11:34:00 +02:00
DragonSlayer_14 b13a0831fa Add Gamescope installation via Flatpak
This commit includes the addition of a Flatpak command to install Gamescope, a Vulkan-based compositor for gaming. It ensures a more complete setup for gaming-related tools.
2026-08-16 11:28:41 +02:00
DragonSlayer_14 f60be958f6 Add Scopebuddy GUI to Flatpak install list
This commit adds the Scopebuddy GUI application to the programs installed via Flatpak in the script. This ensures the tool is included alongside other essential applications for consistency.
2026-08-16 11:21:35 +02:00
DragonSlayer_14 b8c856a7d3 Remove unused Steam Homebrew installation script
The Steam Homebrew installation script was deemed unnecessary and has been removed from the program setup file. Flatpak installation for Steam remains as the primary method.
2026-08-16 11:17:56 +02:00
DragonSlayer_14 94996e1bb8 Reorganize and relocate installer commands for clarity
Moved Linutil and Steam Homebrew installer commands to more relevant sections in the scripts. This enhances organization and ensures commands are executed in appropriate contexts.
2026-08-16 11:14:55 +02:00
DragonSlayer_14 2481f515b8 Disable addition of i386 architecture in apt setup
Commented out the command for adding i386 architecture to apt, likely aiming to prevent compatibility issues or unnecessary package handling. This change ensures a cleaner and more controlled apt configuration process.
2026-08-16 11:01:55 +02:00
DragonSlayer_14 39b9de3443 Update package installations and add Steam via Flatpak
Removed Steam installer from aptitude to avoid redundancy and added Steam installation through Flatpak. This ensures consistency with the Flatpak approach and streamlines dependency management.
2026-08-16 11:00:49 +02:00
DragonSlayer_14 eca438f7cb Add Local Send flatpak installation
This commit adds the installation command for Local Send via Flatpak and ensures the Flatsweep installation command uses the `-y` flag for automated installation. These changes improve the script's functionality and user experience.
2026-08-15 19:05:57 +02:00
DragonSlayer_14 ddf8585a16 Update installation script with QEMU setup and auto-cpufreq fix
Removed unnecessary sudo from auto-cpufreq installation command for better compatibility. Added a conditional QEMU and virtualization setup to streamline virtual machine installations and configurations. Includes user group adjustments and default network setup for libvirt.
2026-08-13 17:16:56 +02:00
DragonSlayer_14 cb89d422e7 Add dconf-editor to the list of installable packages
Included `dconf-editor` in the stable package installation list for easier system configuration management. This ensures users have access to a critical GUI tool for editing system settings.
2026-08-09 19:29:40 +02:00
DragonSlayer_14 8c1b7168bc Update APT sources to use Debian unstable
Replaced the Debian stable sources configuration with Debian unstable. This change ensures access to the latest packages and updates from the unstable distribution. The security sources for the stable suite were also removed as part of this update.
2026-08-09 13:38:59 +02:00
DragonSlayer_14 f8cbcc1cc6 Feat: Aktualisiert das System auf Debian-unstable und fügt gitea-apt-REpositories hinzu. 2026-08-09 12:00:51 +02:00
DragonSlayer_14 36e56b67b7 Disable installation steps for Lutris, Spotify, Floorp, and Codium.
Commented out commands for installing Lutris, Spotify, Floorp, and Codium in the installation script. This prevents these applications from being installed during script execution. No functional changes to remaining installation steps.
2026-08-09 11:55:05 +02:00
DragonSlayer_14 7c4db527cc Disable Docker and deb-get setup in install script
Commented out Docker installation and deb-get setup steps to streamline the script for specific use cases. Adjusted the AppImage installer to use the home directory for temporary files. Further changes ensure the script aligns with simplified installation requirements.
2026-08-09 11:43:03 +02:00
DragonSlayer_14 a12f135d3f Add protontricks to package installation list
Protontricks was added to the list of stable packages to ensure better compatibility and management of Proton configurations in gaming setups. This enhances the utility of the install script for users running Steam with Proton.
2026-08-09 00:07:15 +02:00
DragonSlayer_14 12240a0ec5 Add AMD CPU-specific game optimization parameters to README
Added detailed launch parameters and configuration examples for optimizing gaming performance on AMD CPUs. Includes settings for ray tracing, upscaling, and general performance improvements to enhance user guidance.
2026-08-08 23:48:25 +02:00
DragonSlayer_14 4a77bb10d6 Add zram-tools to the package installation list
Updated the 03-install.sh script to include zram-tools in the stable package installation section. This addition ensures better memory compression and system performance optimization where zram-tools is applicable.
2026-08-08 23:36:09 +02:00
DragonSlayer_14 fbea2fef38 Add CPU vendor detection and dynamic kernel parameter updates
Implement logic to detect CPU vendor (Intel/AMD) and append appropriate pstate parameters to GRUB configuration. Improve localization, enhance idempotency when setting parameters, and include backup creation and theme update handling.
2026-08-08 23:27:00 +02:00
DragonSlayer_14 6fbc4ff9d0 Set threadirqs in GRUB_CMDLINE_LINUX_DEFAULT
Added the 'threadirqs' parameter to the kernel command line to improve interrupt handling and optimize performance for threaded IRQs. This change ensures better responsiveness and system behavior in specific workloads.
2026-08-08 23:18:14 +02:00
DragonSlayer_14 6f67a5b034 Add radeontop to the list of installed stable packages
Included `radeontop` in the installation script to provide GPU monitoring capabilities for Radeon users. This enhances system resource monitoring and troubleshooting during usage.
2026-08-08 23:07:32 +02:00
DragonSlayer_14 9b7f391cb0 Add script to run Linutil during installation
Integrated the Linutil script from christitus.com into the installation process. This addition enhances system setup by automating essential Linux configurations.
2026-08-08 22:50:46 +02:00
DragonSlayer_14 7290ffdc4a Add installation of 32-bit libs and Steam Brew script
Install `libssl-dev:i386` for 32-bit compatibility and add a script to set up Steam Brew. These changes support better gaming functionality and system setup.
2026-08-08 22:39:56 +02:00
DragonSlayer_14 1dfd42dd1a Add Heroic Games Launcher installation to script
This update adds a command to install the Heroic Games Launcher using deb-get. It ensures users have an easy way to set up the launcher during the script execution.
2026-08-08 22:14:47 +02:00
DragonSlayer_14 82f23a9651 Add auto-cpufreq installation to 03-install.sh
Integrates automated CPU performance and power optimization by including the installation of auto-cpufreq. Clones the repository, runs the installer, and enables the service for system-wide use.
2026-08-08 22:10:40 +02:00
DragonSlayer_14 c1873b34bf Add installation script for AM - AppImage Manager
This commit adds a script to install AM, the AppImage Manager, using a curl command to download and execute the installer. The script ensures proper cleanup by removing the installer after execution.
2026-08-08 22:00:57 +02:00
DragonSlayer_14 b8efa35307 Add installation step for topgrade via deb-get
This ensures that the topgrade tool is installed automatically as part of the script. It simplifies the process for users by combining all necessary installations into the same setup routine.
2026-08-08 21:54:54 +02:00
DragonSlayer_14 778c845db1 Remove redundant apt update and install; add deb-get setup
The apt update and ca-certificates/curl install commands were removed as they were unnecessary for the script's context. Additionally, support for installing deb-get was added to streamline package management.
2026-08-08 21:54:40 +02:00
DragonSlayer_14 bf976533ba Enable AppArmor in GRUB boot configuration.
Added the `apparmor=1` parameter to the `GRUB_CMDLINE_LINUX_DEFAULT` option to explicitly enable AppArmor. This enhances security by enforcing mandatory access control policies.
2026-08-08 21:44:58 +02:00
DragonSlayer_14 504c1f0494 Add AppArmor installation and enable by default
AppArmor packages are now included in the list of installations, and the service is enabled and started by default. This enhances system security by proactively managing application privileges.
2026-08-08 21:41:47 +02:00
DragonSlayer_14 5f6851c65e Add Docker installation to setup script
This update incorporates commands for installing Docker, including setting up its repository, importing the GPG key, and installing necessary packages. These changes streamline Docker installation during the setup process.
2026-08-08 12:00:52 +02:00
DragonSlayer_14 9d6ed39b5e Add gnome-firmware to the list of stable packages
This update enhances the system setup script by including gnome-firmware in the stable packages installation list. Gnome-firmware allows for better firmware management and updates directly within the system. This addition improves overall system functionality and user experience.
2026-07-29 17:54:30 +02:00
DragonSlayer_14 468b900561 Fix typo in Flatpak install command comment
Corrected a missing comment symbol in the Flatpak install command for RPI-Imager. This ensures consistency and avoids unintended execution or errors in the script.
2026-07-14 18:28:37 +02:00
DragonSlayer_14 f0ee6a0dce Add RPI-Imager installation to 07-programs.sh
Included the command to install the Raspberry Pi Imager via Flatpak. This ensures the tool is available for creating and managing Raspberry Pi OS images efficiently.
2026-07-14 18:11:17 +02:00
DragonSlayer_14 ddc142da78 Add Flatsweep installation to programs script
Flatsweep is now included in the list of Flatpak installations in `07-programs.sh`. This ensures easier setup and uniformity when deploying required applications.
2026-07-11 12:19:58 +02:00
DragonSlayer_14 33d5c78cd5 Add firmware-linux packages to installation script
Included firmware-linux, firmware-linux-nonfree, and firmware-misc-nonfree in the package installation list. This ensures better hardware compatibility and support for devices requiring proprietary firmware.
2026-06-20 21:03:10 +02:00
DragonSlayer_14 0aeb0fd221 Feat: Fügt systemd-timesyncd und adb hinzu 2026-06-07 12:59:47 +02:00
DragonSlayer_14 9fdb2c4982 Feat: Fügt systemd-timesyncd hinzu 2026-05-25 15:34:19 +02:00
DragonSlayer_14 21115bbcd1 Feat: Passt Pfade an 2026-05-21 00:26:04 +02:00
DragonSlayer_14 3f1a3fb554 Fix: Liest HOME richtig aus 2026-05-21 00:19:05 +02:00
DragonSlayer_14 d2579c8f45 Fix: Behebt Fehler 2026-05-21 00:16:29 +02:00
DragonSlayer_14 70d6d09c65 Feat: Passt Default-Config an 2026-05-21 00:13:11 +02:00
DragonSlayer_14 23494013c8 Feat: Entfernt gelöschte Zeile 2026-05-20 23:10:36 +02:00
DragonSlayer_14 173f9ecbe4 Feat: Passt Paketursprünge an 2026-05-20 22:49:49 +02:00
DragonSlayer_14 2c70d0a709 Feat: Fügt imagemagick hinzu 2026-05-20 22:24:08 +02:00
DragonSlayer_14 0cf512fc4f Feat: Passt Installation an 2026-05-20 22:10:54 +02:00
DragonSlayer_14 7f7431029f Verschiebt einzelne Pakete wieder zurück 2026-05-20 21:16:29 +02:00
DragonSlayer_14 cef7039f29 Lagert Stable-Pakete in 00 aus 2026-05-20 19:47:26 +02:00
DragonSlayer_14 338393580a Feat: Installiert und nutzt aptitude 2026-05-20 19:42:08 +02:00
DragonSlayer_14 60191445bc Feat: Schiebt rsync in der Installation weiter nach vorne 2026-05-20 19:30:31 +02:00
DragonSlayer_14 9c1e62dfe8 Feat: Passt Hyprland-Install-Skript URL an 2026-05-20 19:08:52 +02:00
DragonSlayer_14 6fbc98bc98 Feat: Passt Branch-URL an 2026-05-20 19:07:51 +02:00
DragonSlayer_14 f9c892baee Feat: Passt README an 2026-05-20 19:06:27 +02:00
DragonSlayer_14 51a7a9a927 Feat: Fügt neue Version ein 2026-05-20 19:05:33 +02:00
52 changed files with 4134 additions and 21 deletions
+15
View File
@@ -77,3 +77,18 @@ fabric.properties
# Android studio 3.1+ serialized cache file # Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser .idea/caches/build_file_checksums.ser
# ---> VisualStudioCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
.junie/plans
+1
View File
@@ -0,0 +1 @@
{}
+226
View File
@@ -0,0 +1,226 @@
# 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
```
.
├── install.sh # Web-Installer & Bootstrap-Skript (curl | bash, klont nach /tmp)
├── 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
│ ├── btrfs.sh # Btrfs Root- & Subvolume-Erkennung, Migration (@, @home), fstab-Verwaltung
│ ├── network.sh # Loopback- & LAN-Schnittstellenkonfiguration (Debian Installer Standard)
│ └── 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, Heroic, 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 10)
│ ├── 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, Ollama
│ ├── 07-skel-and-user.sh # /etc/skel Vorlagen, ZSH-Shell-Setzen, Dotfiles-Sync
│ ├── 08-flatpaks.sh # Flathub Setup, Flatpak-Paketlisten-Installation
│ ├── 09-apps.sh # Spotify, Waydroid, OpenDeck, Desktop-Starter, MIME-Types
│ └── 10-hyprland.sh # LinuxBeginnings Debian-Hyprland Auto-Installer & Desktop-Setup
├── 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 "<befehl>"` 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 `<datei>.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.
- `prompt_ollama_models_path`: Fragt interaktiv nach dem Speicherort für Ollama KI-Modelle oder nutzt Standardpfad.
- `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/<name>.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/btrfs.sh`
- `is_root_btrfs`: Prüft, ob das Root-Dateisystem auf Btrfs liegt.
- `is_root_subvolume_configured`: Prüft, ob Root bereits in einem Subvolume (`@`) läuft.
- `update_btrfs_fstab "fstab_file" "root_id"`: Aktualisiert Mount-Optionen in `/etc/fstab` für `@` und `@home`.
- `check_and_setup_btrfs_subvolumes`: Erkennt flache Btrfs-Root-Volumes und migriert `/` und `/home` transparent in Subvolumes `@` und `@home`.
- `ensure_timeshift_btrfs_config`: Erstellt bzw. initialisiert die Timeshift-Btrfs-Konfiguration (`/etc/timeshift/timeshift.json`, automatische Boot-Snapshots, Retention auf 5 Snapshots) für die Root-UUID.
- `ensure_timeshift_boot_service`: Richtet den `timeshift-boot.service` und Cron-Einträge für automatische Boot-Snapshots ein.
- `ensure_timeshift_apt_hook`: Richtet einen DPkg/APT-Hook (`/etc/apt/apt.conf.d/80timeshift-auto-snapshot` und `/usr/local/bin/timeshift-apt-hook`) für automatische Snapshots vor System-Updates ein.
- `ensure_grub_btrfs`: Installiert und konfiguriert `grub-btrfs` sowie den `grub-btrfsd`-Dienst für die automatische Generierung von Snapshot-Bootmenüeinträgen in GRUB.
- `create_timeshift_snapshot "comment" [tags]`: Erstellt einen Timeshift-Btrfs-Snapshot an kritischen Setup-Meilensteinen (idempotent, steuerbar über `ENABLE_TIMESHIFT_SNAPSHOTS` in `config/setup.conf`).
### `lib/network.sh`
- `get_lan_interfaces`: Erkennt alle physischen LAN/Ethernet-Schnittstellen dynamisch auf jedem System (unter Ausschluss von Loopback, Wi-Fi, Bridges und virtuellen Containern).
- `is_interface_configured "iface"`: Prüft, ob eine Schnittstelle bereits in `/etc/network/interfaces` oder `/etc/network/interfaces.d/` konfiguriert ist.
- `configure_loopback_interface`: Richtet das Loopback-Interface `lo` in `/etc/network/interfaces` (`auto lo`, `iface lo inet loopback`) sowie `/etc/hosts` ein und aktiviert es.
- `configure_lan_interfaces`: Richtet alle erkannten physischen LAN-Schnittstellen im Debian-Installer-Standard (`allow-hotplug <iface>`, `iface <iface> inet dhcp`, `iface <iface> inet6 auto`) ein und aktiviert diese.
- `configure_network_manager`: Konfiguriert `/etc/NetworkManager/NetworkManager.conf` mit `[ifupdown] managed=true` für nahtlose Desktop- und Waybar-Integration.
- `enable_network_services`: Aktiviert und startet `networking.service` und `NetworkManager.service`.
- `configure_network_all`: Zentraler Orchestrator zur vollständigen Netzwerkeinrichtung.
### `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-<name>.sh` (nummeriert nach Reihenfolge, mit `chmod +x`).
2. Nutze das Standard-Template:
```bash
#!/usr/bin/env bash
# ==============================================================================
# stages/XX-<name>.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: <Name der Phase>"
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/<kategorie>.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.
+153 -21
View File
@@ -1,32 +1,164 @@
# 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.
## Anforderungen ## 🚀 Schnellstart
Um die Skripte in diesem Repository auszuführen, stelle sicher, dass die folgenden Voraussetzungen erfüllt sind: ### 1. Web-Installer (Curl One-Liner)
Das Setup kann direkt ohne vorheriges manuelles Klonen via `curl` gestartet werden. Das Installationsskript (`install.sh`) installiert bei Bedarf `git`, klont das Repository automatisch in ein temporäres Verzeichnis (`/tmp`), startet den Orchestrator und räumt nach Abschluss sauber auf:
- Die Skripte sind als bash-Skripte konzipiert. ```bash
- Für die Skripte muss der richtige Branch der jewiligen Distribution ausgewählt werden. # Interaktiver Modus (whiptail Menü)
- Daten werden vor der Ausführung nicht gesichert. Datenverlust möglich! curl -fsSL https://gitea.creative-dragonslayer.de/Scripts/Setup/raw/branch/main/install.sh | bash
## Nutzung # Vollautomatischer Modus (alle Stages 00 bis 10)
curl -fsSL https://gitea.creative-dragonslayer.de/Scripts/Setup/raw/branch/main/install.sh | bash -s -- --all
1. Klone das Repository: # Gezielte Modulauswahl (z. B. Paketlisten und Schriften)
```bash curl -fsSL https://gitea.creative-dragonslayer.de/Scripts/Setup/raw/branch/main/install.sh | bash -s -- --stages 04,05
git clone https://gitea.creative-dragonslayer.de/DragonSlayer_14/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.
## Lizenz ### 2. Manuelles Klonen & Starten
Alternativ kann das Repository manuell geklont und ausgeführt werden:
```bash
git clone https://gitea.creative-dragonslayer.de/Scripts/Setup.git && cd Setup && sudo ./setup.sh
```
Oder direkt vollautomatisch alle Stages (`00` bis `10`) ausführen:
```bash
git clone https://gitea.creative-dragonslayer.de/Scripts/Setup.git && cd Setup && sudo ./setup.sh --all
```
Dieses Projekt steht unter einer Open-Source-Lizenz. Weitere Informationen findest du in der Datei `LICENSE`. ### 3. Interaktiver TUI-Modus
Starte das grafische Terminal-Menü (`whiptail`) zur flexiblen Auswahl einzelner Module:
```bash
sudo ./setup.sh
```
## Autor ### 4. Vollautomatischer CLI-Modus
Führe alle Phasen (`00` bis `10`) ohne Interaktion aus:
```bash
sudo ./setup.sh --all
```
Erstellt und gepflegt von DragonSlayer_14. ### 5. Gezielte Modulauswahl
Installiere nur bestimmte Phasen (z. B. nur Paketlisten und Schriften):
```bash
sudo ./setup.sh --stages 04,05
```
### 6. 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 `10`) sequenziell aus |
| `-s`, `--stages` | `<01,02,...>` | Kommagetrennte Liste der auszuführenden Phasen |
| `-u`, `--user` | `<username>` | 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
```
.
├── install.sh # Web-Installer & Bootstrap-Skript (curl | bash, klont nach /tmp)
├── 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
│ ├── btrfs.sh # Btrfs Root- & Subvolume-Erkennung, Migration (@, @home), Timeshift-Snapshots
│ ├── network.sh # Loopback- & LAN-Schnittstellenkonfiguration (Debian Installer Standard)
│ └── 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, Heroic, 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, Ollama
│ ├── 07-skel-and-user.sh # /etc/skel Vorlagen, ZSH-Shell-Setzen, Dotfiles-Sync
│ ├── 08-flatpaks.sh # Flathub Setup, Flatpak-Paketlisten-Installation
│ ├── 09-apps.sh # Spotify, Waydroid, OpenDeck, Desktop-Starter, MIME-Types
│ └── 10-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, .config/hypr, 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 & Timeshift Btrfs-Snapshots**:
- 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.
- Auf Btrfs-Systemen werden mit Timeshift automatisch Rollback-Punkte vor und nach kritischen Operationen (Dist-Upgrade, Kernel-Installation, Paketinstallation, Desktop-Setup), bei jedem System-Update (automatischer APT/DPkg-Pre-Invoke-Hook) sowie bei jedem Systemstart (`timeshift-boot.service`) erstellt, wobei standardmäßig die letzten 5 Snapshots vorgehalten werden.
- Mittels `grub-btrfs` und dem Hintergrunddienst `grub-btrfsd` werden Btrfs-Snapshots automatisch in das GRUB-Bootmenü integriert, sodass direkt beim Systemstart in beliebige Snapshots gebootet werden kann.
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.
6. **Netzwerk- & Schnittstellenkonfiguration (Debian Installer Standard)**:
- Automatische Erkennung und Konfiguration aller physischen LAN-Netzwerkschnittstellen via DHCP und IPv6 SLAAC (`allow-hotplug <iface>`, `iface <iface> inet dhcp`, `iface <iface> inet6 auto`).
- Standardkonforme Einrichtung des Loopback-Interfaces (`auto lo`, `iface lo inet loopback`) in `/etc/network/interfaces` und `/etc/hosts`.
- Nahtlose NetworkManager-Integration (`managed=true`) und Berechtigung des Zielbenutzers via `netdev`-Gruppe.
---
## 🎮 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%
```
---
## 📜 Lizenz & Autor
- **Lizenz**: MIT License (siehe `LICENSE`)
- **Autor**: DragonSlayer_14
+86
View File
@@ -0,0 +1,86 @@
# ==============================================================================
# config/packages/01-base.list - Base system utilities, firmware, shell & diagnostics
# ==============================================================================
7zip
adb
apparmor
apparmor-notify
apparmor-profiles
apparmor-profiles-extra
apparmor-utils
apt-listbugs
apt-listchanges
aptitude
baobab
bat
bleachbit
bluetooth
blueman
bluez
bruno
btop
ca-certificates
clamav
clamav-daemon
clamav-docs
clamav-freshclam
command-not-found
cpupower-gui
cryptomator
curl
dconf-editor
debian-goodies
ethtool
fastfetch
file-roller
firmware-linux
firmware-linux-nonfree
firmware-misc-nonfree
flatpak
flatseal
fzf
git
glances
gnome-disk-utility
gnome-firmware
gnome-logs
gnome-system-monitor
gparted
htop
hunspell
hunspell-de-de-frami
ifupdown
inotify-tools
iproute2
irqbalance
isc-dhcp-client
keepassxc
lsd
man
net-tools
network-manager
network-manager-gnome
plymouth
plymouth-themes
resources
rfkill
ripgrep
rpi-imager
shellcheck
sl
systemd-timesyncd
tar
tealdeer
timeshift
topgrade
tree
unrar
unzip
wireless-regdb
wpasupplicant
zram-tools
zsh
zsh-autosuggestions
zsh-doc
zsh-syntax-highlighting
+40
View File
@@ -0,0 +1,40 @@
# ==============================================================================
# config/packages/02-desktop.list - Wayland/Hyprland desktop, display manager & tools
# ==============================================================================
cava
codium
dconf-editor
flameshot
floorp
fragments
gnome-calculator
gnome-decoder
gnome-font-viewer
gnome-keyring
gnome-snapshot
gnome-text-editor
grim
impression
input-remapper
kitty
localsend
nodejs
nwg-displays
nwg-look
obfuscate
pipewire
pipewire-pulse
remmina
sddm
slurp
speech-dispatcher
swappy
swaybg
thunar
vesktop
wayland-utils
wireplumber
wl-clipboard
xdg-user-dirs
yazi
+22
View File
@@ -0,0 +1,22 @@
# ==============================================================================
# config/packages/03-gaming.list - Gaming tools, Vulkan drivers, Wine & Emulation
# ==============================================================================
gameconqueror
gamemode
gamescope
heroic
lutris
mangohud
mangoapp
mesa-utils
mesa-vulkan-drivers
openrgb
prismlauncher
protontricks
radeontop
steam-installer
steam-devices
vulkan-tools
wine
winetricks
+10
View File
@@ -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
+22
View File
@@ -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
+17
View File
@@ -0,0 +1,17 @@
# ==============================================================================
# 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
net.davidotek.pupgui2
io.github.rfrench3.scopebuddy-gui
+33
View File
@@ -0,0 +1,33 @@
# ==============================================================================
# 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
# Backup & System Snapshots (Timeshift Btrfs)
ENABLE_TIMESHIFT_SNAPSHOTS=1
TIMESHIFT_COUNT_BOOT=5
TIMESHIFT_SCHEDULE_BOOT="true"
TIMESHIFT_SNAPSHOT_ON_UPDATE="true"
ENABLE_GRUB_BTRFS=1
# Bootloader & Appearance
GRUB_THEME="vimix"
PLYMOUTH_THEME="solar"
GRUB_TIMEOUT=5
GRUB_TIMEOUT_STYLE="menu"
# Shell & Userland
DEFAULT_SHELL="zsh"
# Ollama AI Configuration
OLLAMA_MODELS_DEFAULT="/mnt/Data/Software/ollama/models"
OLLAMA_FLASH_ATTENTION="1"
OLLAMA_KV_CACHE_TYPE="q8_0"
OLLAMA_KEEP_ALIVE="30m"
# Default Stages (if --all is passed or in default batch mode)
ALL_STAGES="00 01 02 03 04 05 06 07 08 09 10"
+7
View File
@@ -0,0 +1,7 @@
Package: *
Pin: release a=unstable
Pin-Priority: 900
Package: *
Pin: release a=experimental
Pin-Priority: 100
+3
View File
@@ -0,0 +1,3 @@
Package: *
Pin: origin deb.xanmod.org
Pin-Priority: 900
+5
View File
@@ -0,0 +1,5 @@
Types: deb deb-src
URIs: http://deb.debian.org/debian/
Suites: unstable
Components: main non-free-firmware non-free contrib
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
@@ -0,0 +1,5 @@
Types: deb
URIs: https://gitea.creative-dragonslayer.de/api/packages/Linuxapps/debian/
Suites: stable
Components: main
Signed-By: /etc/apt/keyrings/gitea-Linuxapps.asc
@@ -0,0 +1,6 @@
Types: deb
URIs: https://gitea.creative-dragonslayer.de/api/packages/Mirror/debian/
Suites: stable
Components: main
Architectures: amd64
Signed-By: /etc/apt/keyrings/gitea-Mirror.asc
+5
View File
@@ -0,0 +1,5 @@
Types: deb
URIs: http://deb.xanmod.org
Suites: releases
Components: main
Signed-By: /etc/apt/keyrings/xanmod-archive-keyring.gpg
@@ -0,0 +1,3 @@
# Raytracing support environment flags for RADV / Mesa
VKD3D_CONFIG=dxr11,dxr
RADV_PERFTEST=rt
+3
View File
@@ -0,0 +1,3 @@
# Upscaling and gaming enhancement variables
WINE_FULLSCREEN_FSR=1
WINE_FULLSCREEN_FSR_STRENGTH=2
+5
View File
@@ -0,0 +1,5 @@
#!/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
+10
View File
@@ -0,0 +1,10 @@
#!/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
+12
View File
@@ -0,0 +1,12 @@
#!/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
+23
View File
@@ -0,0 +1,23 @@
#!/bin/sh
# Display sudo reminder for administrative users once after initial setup
SUDO_FILE="$HOME/.sudo_as_admin_successful"
HUSH_FILE="$HOME/.hushlogin"
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 2>/dev/null) " in
*\ admin\ *|*\ sudo\ *)
if [ -x /usr/bin/sudo ]; then
echo 'To run a command as administrator (user "root"), use "sudo <command>".'
echo 'See "man sudo_root" for details.'
fi
;;
esac
fi
+26
View File
@@ -0,0 +1,26 @@
#!/bin/sh
# /etc/profile.d/desktop_session_xdg_dirs.sh - Prepend a $DESKTOP_SESSION-named directory to $XDG_CONFIG_DIRS and $XDG_DATA_DIRS
DEFAULT_XDG_CONFIG_DIRS="/etc/xdg"
DEFAULT_XDG_DATA_DIRS="/usr/local/share/:/usr/share/"
if [ -n "$DESKTOP_SESSION" ]; then
# readd default if was empty
if [ -z "$XDG_CONFIG_DIRS" ]; then
XDG_CONFIG_DIRS="$DEFAULT_XDG_CONFIG_DIRS"
fi
if [ -n "${XDG_CONFIG_DIRS##*"$DEFAULT_XDG_CONFIG_DIRS"/xdg-"$DESKTOP_SESSION"*}" ]; then
XDG_CONFIG_DIRS="$DEFAULT_XDG_CONFIG_DIRS"/xdg-"$DESKTOP_SESSION":"$XDG_CONFIG_DIRS"
fi
export XDG_CONFIG_DIRS
# gnome is already added if gnome-session installed
if [ "$DESKTOP_SESSION" != "gnome" ]; then
if [ -z "$XDG_DATA_DIRS" ]; then
XDG_DATA_DIRS="$DEFAULT_XDG_DATA_DIRS"
fi
if [ -n "${XDG_DATA_DIRS##*/usr/share/"$DESKTOP_SESSION"*}" ]; then
XDG_DATA_DIRS=/usr/share/"$DESKTOP_SESSION":"$XDG_DATA_DIRS"
fi
export XDG_DATA_DIRS
fi
fi
+97
View File
@@ -0,0 +1,97 @@
# ==============================================================================
# Rudimentäre Hyprland-Konfiguration (Standard für neue Benutzer)
# ==============================================================================
# Monitor Setup (Standard: Automatische Auflösung & Positionierung)
monitor = , preferred, auto, 1
# Modifikator-Taste: SUPER (Windows-Taste)
$mainMod = SUPER
# Standard-Terminal
$terminal = kitty
# ------------------------------------------------------------------------------
# Tastenbelegungen (Keybindings)
# ------------------------------------------------------------------------------
# SUPER + ENTER: Kitty Terminal öffnen
bind = $mainMod, RETURN, exec, $terminal
bind = $mainMod, Return, exec, $terminal
# SUPER + Q: Aktives Fenster schließen
bind = $mainMod, Q, killactive,
# Grundlegende Navigation & Fensterverwaltung
bind = $mainMod, M, exit,
bind = $mainMod, E, exec, thunar
bind = $mainMod, V, togglefloating,
bind = $mainMod, F, fullscreen,
# Fokus mit Pfeiltasten wechseln
bind = $mainMod, left, movefocus, l
bind = $mainMod, right, movefocus, r
bind = $mainMod, up, movefocus, u
bind = $mainMod, down, movefocus, d
# Workspaces 1-10 wechseln
bind = $mainMod, 1, workspace, 1
bind = $mainMod, 2, workspace, 2
bind = $mainMod, 3, workspace, 3
bind = $mainMod, 4, workspace, 4
bind = $mainMod, 5, workspace, 5
bind = $mainMod, 6, workspace, 6
bind = $mainMod, 7, workspace, 7
bind = $mainMod, 8, workspace, 8
bind = $mainMod, 9, workspace, 9
bind = $mainMod, 0, workspace, 10
# Aktives Fenster auf Workspace 1-10 verschieben
bind = $mainMod SHIFT, 1, movetoworkspace, 1
bind = $mainMod SHIFT, 2, movetoworkspace, 2
bind = $mainMod SHIFT, 3, movetoworkspace, 3
bind = $mainMod SHIFT, 4, movetoworkspace, 4
bind = $mainMod SHIFT, 5, movetoworkspace, 5
bind = $mainMod SHIFT, 6, movetoworkspace, 6
bind = $mainMod SHIFT, 7, movetoworkspace, 7
bind = $mainMod SHIFT, 8, movetoworkspace, 8
bind = $mainMod SHIFT, 9, movetoworkspace, 9
bind = $mainMod SHIFT, 0, movetoworkspace, 10
# Fenster mit Maus bewegen und vergrößern/verkleinern
bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow
# ------------------------------------------------------------------------------
# Erscheinungsbild & Verhalten
# ------------------------------------------------------------------------------
general {
gaps_in = 4
gaps_out = 8
border_size = 2
col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
col.inactive_border = rgba(595959aa)
layout = dwindle
}
decoration {
rounding = 8
}
animations {
enabled = yes
}
input {
kb_layout = de
follow_mouse = 1
touchpad {
natural_scroll = yes
}
}
# ------------------------------------------------------------------------------
# Autostart nach der Anmeldung
# ------------------------------------------------------------------------------
# Fragt nach der ersten Anmeldung nach der gewünschten Dotfiles-Konfiguration
# (LinuxBeginnings Hyprland-Dots oder eigenes Git-Repository für ~/.config)
exec-once = ~/.config/hypr/scripts/install-dots-prompt.sh
+357
View File
@@ -0,0 +1,357 @@
#!/usr/bin/env bash
# ==============================================================================
# ~/.config/hypr/scripts/install-dots-prompt.sh
# Ersteinrichtung beim ersten Login:
# 1) Desktop-Konfiguration (LinuxBeginnings Hyprland-Dots oder eigenes Git-Repo)
# 2) Installation der JetBrains Junie CLI & AwesomeJunieSkills
# ==============================================================================
set -euo pipefail
MARKER_FILE="$HOME/.config/hypr/.dots_prompted"
FORCE=0
for arg in "$@"; do
case "$arg" in
-f|--force)
FORCE=1
;;
esac
done
# Wenn bereits abgefragt und kein --force übergeben wurde, beenden
if [[ "$FORCE" -eq 0 && -f "$MARKER_FILE" ]]; then
exit 0
fi
# Wenn nicht in einem interaktiven Terminal ausgeführt (z. B. via Hyprland exec-once),
# starte das Skript in einem Kitty-Fenster:
if [[ ! -t 0 || ! -t 1 ]]; then
if command -v kitty >/dev/null 2>&1; then
exec kitty --title "System-Ersteinrichtung & Dotfiles" bash -c "$0 --in-terminal; echo; read -r -p 'Drücke Enter zum Schließen...' || true"
else
exit 0
fi
fi
# ANSI Farben
CLR_RESET='\033[0m'
CLR_BOLD='\033[1m'
CLR_CYAN='\033[0;36m'
CLR_GREEN='\033[0;32m'
CLR_YELLOW='\033[0;33m'
CLR_RED='\033[0;31m'
CLR_BLUE='\033[0;34m'
CLR_MAGENTA='\033[0;35m'
mark_as_prompted() {
mkdir -p "$(dirname "$MARKER_FILE")" 2>/dev/null || true
touch "$MARKER_FILE" 2>/dev/null || true
}
install_oh_my_zsh() {
local zsh_dir="$HOME/.oh-my-zsh"
printf "\n"
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}==============================================================================${CLR_RESET}"
printf "%b\n" "${CLR_BOLD}${CLR_CYAN} Oh-My-Zsh & Shell-Konfiguration ${CLR_RESET}"
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}==============================================================================${CLR_RESET}"
printf "\n"
if [[ ! -d "$zsh_dir" ]]; then
printf "%b\n" "${CLR_CYAN}[INFO] Richte Oh-My-Zsh für $USER ein...${CLR_RESET}"
if command -v git >/dev/null 2>&1; then
if git clone --depth=1 https://github.com/ohmyzsh/ohmyzsh.git "$zsh_dir"; then
mkdir -p "$zsh_dir/custom/plugins"
git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions "$zsh_dir/custom/plugins/zsh-autosuggestions" 2>/dev/null || true
git clone --depth=1 https://github.com/zsh-users/zsh-syntax-highlighting "$zsh_dir/custom/plugins/zsh-syntax-highlighting" 2>/dev/null || true
printf "%b\n" "${CLR_GREEN}[✓] Oh-My-Zsh erfolgreich eingerichtet.${CLR_RESET}"
else
printf "%b\n" "${CLR_YELLOW}[WARNUNG] Oh-My-Zsh konnte nicht geklont werden.${CLR_RESET}"
fi
else
printf "%b\n" "${CLR_RED}[FEHLER] 'git' ist nicht installiert. Oh-My-Zsh konnte nicht eingerichtet werden.${CLR_RESET}"
fi
else
# Plugins sicherstellen
if [[ ! -d "$zsh_dir/custom/plugins/zsh-autosuggestions" ]] && command -v git >/dev/null 2>&1; then
git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions "$zsh_dir/custom/plugins/zsh-autosuggestions" 2>/dev/null || true
fi
if [[ ! -d "$zsh_dir/custom/plugins/zsh-syntax-highlighting" ]] && command -v git >/dev/null 2>&1; then
git clone --depth=1 https://github.com/zsh-users/zsh-syntax-highlighting "$zsh_dir/custom/plugins/zsh-syntax-highlighting" 2>/dev/null || true
fi
printf "%b\n" "${CLR_GREEN}[✓] Oh-My-Zsh ist bereits vorhanden und konfiguriert.${CLR_RESET}"
fi
}
install_junie_cli_and_skills() {
printf "\n"
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}==============================================================================${CLR_RESET}"
printf "%b\n" "${CLR_BOLD}${CLR_CYAN} JetBrains Junie CLI & AwesomeJunieSkills Installation ${CLR_RESET}"
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}==============================================================================${CLR_RESET}"
printf "\n"
# 1. JetBrains Junie CLI installieren
printf "%b\n" "${CLR_CYAN}[1/2] Installiere JetBrains Junie CLI...${CLR_RESET}"
if command -v curl >/dev/null 2>&1; then
if curl -fsSL https://junie.jetbrains.com/install.sh | bash; then
printf "%b\n" "${CLR_GREEN}[✓] JetBrains Junie CLI erfolgreich installiert.${CLR_RESET}"
else
printf "%b\n" "${CLR_YELLOW}[WARNUNG] Installation von JetBrains Junie CLI fehlgeschlagen oder unterbrochen.${CLR_RESET}"
fi
else
printf "%b\n" "${CLR_RED}[FEHLER] 'curl' ist nicht installiert. Junie CLI konnte nicht geladen werden.${CLR_RESET}"
fi
# 2. AwesomeJunieSkills im Benutzer-Skillverzeichnis (~/.junie/skills) klonen / aktualisieren
printf "\n"
printf "%b\n" "${CLR_CYAN}[2/2] Installiere AwesomeJunieSkills im Benutzer-Skillverzeichnis (~/.junie/skills)...${CLR_RESET}"
local skills_dir="$HOME/.junie/skills"
local repo_dir="$skills_dir/awesome-junie-skills"
mkdir -p "$skills_dir"
if command -v git >/dev/null 2>&1; then
if [[ -d "$repo_dir/.git" ]]; then
printf "%b\n" "${CLR_BLUE}[INFO] Repository existiert bereits in $repo_dir. Führe 'git pull' aus...${CLR_RESET}"
if git -C "$repo_dir" pull --ff-only 2>/dev/null; then
printf "%b\n" "${CLR_GREEN}[✓] AwesomeJunieSkills erfolgreich aktualisiert.${CLR_RESET}"
else
printf "%b\n" "${CLR_YELLOW}[WARNUNG] 'git pull' in $repo_dir fehlgeschlagen.${CLR_RESET}"
fi
else
printf "%b\n" "${CLR_BLUE}[INFO] Klone AwesomeJunieSkills nach $repo_dir...${CLR_RESET}"
rm -rf "$repo_dir" 2>/dev/null || true
if git clone https://github.com/alebaffa/awesome-junie-skills.git "$repo_dir"; then
printf "%b\n" "${CLR_GREEN}[✓] AwesomeJunieSkills erfolgreich nach $repo_dir geklont.${CLR_RESET}"
else
printf "%b\n" "${CLR_YELLOW}[WARNUNG] Klonen von AwesomeJunieSkills fehlgeschlagen.${CLR_RESET}"
fi
fi
# Symlinks für alle Skills im Skill-Hauptordner erstellen
if [[ -d "$repo_dir" ]]; then
local count=0
for skill_path in "$repo_dir"/*; do
if [[ -d "$skill_path" && -f "$skill_path/SKILL.md" ]]; then
local s_name
s_name="$(basename "$skill_path")"
ln -sfn "$skill_path" "$skills_dir/$s_name"
((count++)) || true
fi
done
printf "%b\n" "${CLR_GREEN}[✓] $count Skills verknüpft in '$skills_dir' (kann via 'git pull' in '$repo_dir' aktualisiert werden).${CLR_RESET}"
fi
# Junie config.json konfigurieren (skill-locations)
mkdir -p "$HOME/.junie"
local config_file="$HOME/.junie/config.json"
if command -v python3 >/dev/null 2>&1; then
python3 -c "
import json, os
cfg_path = os.path.expanduser('$config_file')
repo_path = os.path.expanduser('$repo_dir')
data = {}
if os.path.exists(cfg_path):
try:
with open(cfg_path, 'r', encoding='utf-8') as f:
data = json.load(f)
except Exception:
data = {}
locs = data.get('skill-locations', [])
if repo_path not in locs:
locs.append(repo_path)
data['skill-locations'] = locs
with open(cfg_path, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2)
" 2>/dev/null || true
fi
else
printf "%b\n" "${CLR_RED}[FEHLER] 'git' ist nicht installiert. AwesomeJunieSkills konnte nicht eingerichtet werden.${CLR_RESET}"
fi
}
install_linuxbeginnings() {
printf "\n"
printf "%b\n" "${CLR_GREEN}${CLR_BOLD}[INFO] Starte Installation der LinuxBeginnings Hyprland-Dotfiles...${CLR_RESET}"
printf "\n"
if command -v curl >/dev/null 2>&1; then
sh <(curl -fsSL https://raw.githubusercontent.com/LinuxBeginnings/Hyprland-Dots/main/Distro-Hyprland.sh)
else
printf "%b\n" "${CLR_RED}[FEHLER] 'curl' ist nicht installiert. Bitte installieren Sie curl und wiederholen Sie den Vorgang.${CLR_RESET}"
fi
}
clone_custom_repo() {
if ! command -v git >/dev/null 2>&1; then
printf "\n%b\n" "${CLR_RED}[FEHLER] 'git' ist nicht installiert. Bitte installieren Sie git zuerst.${CLR_RESET}"
return 1
fi
while true; do
printf "\n"
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}--- Eigenes Git-Repository für ~/.config klonen ---${CLR_RESET}"
printf "%b\n" "Geben Sie die Git-URL Ihres Dotfiles-/Config-Repositories an."
printf "%b\n" "Beispiele:"
printf "%b\n" " HTTPS : ${CLR_BLUE}https://github.com/Benutzername/mein-config-repo.git${CLR_RESET}"
printf "%b\n" " SSH : ${CLR_BLUE}git@github.com:Benutzername/mein-config-repo.git${CLR_RESET}"
printf "\n"
printf "%b\n" "${CLR_YELLOW}Hinweise zur Authentifizierung:${CLR_RESET}"
printf "%b\n" " - ${CLR_BOLD}HTTPS:${CLR_RESET} Bei privaten Repositories fragt Git nach Benutzername & Personal Access Token (PAT)."
printf "%b\n" " - ${CLR_BOLD}SSH:${CLR_RESET} Erfordert einen hinterlegten SSH-Schlüssel (z. B. in ~/.ssh/ oder via ssh-agent)."
printf "\n"
read -r -p "Git-Repository-URL (oder 'q' zum Abbrechen): " repo_url
repo_url="$(echo "$repo_url" | xargs)"
if [[ "$repo_url" == "q" || "$repo_url" == "Q" || -z "$repo_url" ]]; then
printf "%b\n" "${CLR_YELLOW}[INFO] Vorgang abgebrochen. Kehre zum Hauptmenü zurück.${CLR_RESET}"
return 0
fi
# SSH-Prüfung und Hilfestellung
if [[ "$repo_url" =~ ^git@ || "$repo_url" =~ ^ssh:// ]]; then
local ssh_keys_found=0
if [[ -d "$HOME/.ssh" ]]; then
for k in "$HOME/.ssh"/id_*; do
if [[ -f "$k" && ! "$k" =~ \.pub$ ]]; then
ssh_keys_found=1
break
fi
done
fi
if [[ "$ssh_keys_found" -eq 0 ]]; then
printf "\n"
printf "%b\n" "${CLR_YELLOW}[WARNUNG] Es wurde kein lokaler SSH-Privatschlüssel in ~/.ssh/ gefunden.${CLR_RESET}"
read -r -p "Möchten Sie vor dem Klonen ein neues SSH-Schlüsselpaar (ed25519) generieren? [j/N]: " gen_ssh || gen_ssh="n"
if [[ "$gen_ssh" =~ ^[JjYy] ]]; then
mkdir -p "$HOME/.ssh"
chmod 700 "$HOME/.ssh"
ssh-keygen -t ed25519 -f "$HOME/.ssh/id_ed25519" -C "$USER@$(hostname)"
printf "\n%b\n" "${CLR_GREEN}Neuer öffentlicher SSH-Schlüssel (~/.ssh/id_ed25519.pub):${CLR_RESET}"
cat "$HOME/.ssh/id_ed25519.pub"
printf "\n%b\n" "Bitte fügen Sie diesen Schlüssel bei GitHub/GitLab zu Ihrem Account hinzu."
if command -v wl-copy >/dev/null 2>&1; then
if wl-copy < "$HOME/.ssh/id_ed25519.pub" 2>/dev/null; then
printf "%b\n" "${CLR_GREEN}(In die Zwischenablage kopiert!)${CLR_RESET}"
fi
fi
read -r -p "Drücken Sie Enter, sobald der SSH-Key hinterlegt wurde..."
fi
fi
fi
# Backup und Klon-Vorgang vorbereiten
local timestamp
timestamp="$(date +%Y%m%d_%H%M%S)"
local backup_dir="$HOME/.config.backup_$timestamp"
printf "\n"
printf "%b\n" "${CLR_CYAN}[1/3] Sichere bestehendes ~/.config-Verzeichnis nach ${backup_dir}...${CLR_RESET}"
if [[ -d "$HOME/.config" ]]; then
mv "$HOME/.config" "$backup_dir"
fi
printf "%b\n" "${CLR_CYAN}[2/3] Klone Repository direkt nach ~/.config...${CLR_RESET}"
# Git ausführen mit aktivierter Terminal-Eingabeaufforderung für Authentifizierung
if env GIT_TERMINAL_PROMPT=1 git clone --recurse-submodules "$repo_url" "$HOME/.config"; then
printf "\n"
printf "%b\n" "${CLR_GREEN}${CLR_BOLD}[ERFOLG] Repository wurde erfolgreich nach ~/.config geklont!${CLR_RESET}"
printf "%b\n" " - Ihr gesamter ${CLR_BOLD}~/.config${CLR_RESET}-Ordner ist nun das Git-Repository."
printf "%b\n" " - Vorherige Konfigurationen wurden gesichert in: ${CLR_BOLD}${backup_dir}${CLR_RESET}"
# Hyprland-Konfiguration neu laden falls aktiv
if command -v hyprctl >/dev/null 2>&1; then
printf "\n"
printf "%b\n" "${CLR_CYAN}[3/3] Lade Hyprland-Konfiguration neu...${CLR_RESET}"
hyprctl reload 2>/dev/null || true
printf "%b\n" "${CLR_GREEN}[✓] Hyprland erfolgreich aktualisiert.${CLR_RESET}"
fi
printf "\n"
printf "%b\n" "${CLR_GREEN}Dotfiles-Einrichtung abgeschlossen!${CLR_RESET}"
return 0
else
printf "\n"
printf "%b\n" "${CLR_RED}${CLR_BOLD}[FEHLER] Git Clone ist fehlgeschlagen (Authentifizierungsfehler, falsche URL oder Netzwerkproblem).${CLR_RESET}"
printf "%b\n" "${CLR_YELLOW}[ROLLBACK] Stelle vorheriges ~/.config-Verzeichnis aus dem Backup wieder her...${CLR_RESET}"
rm -rf "$HOME/.config" 2>/dev/null || true
if [[ -d "$backup_dir" ]]; then
mv "$backup_dir" "$HOME/.config"
printf "%b\n" "${CLR_GREEN}[✓] Ursprüngliches ~/.config-Verzeichnis wurde vollständig wiederhergestellt.${CLR_RESET}"
fi
printf "\n"
read -r -p "Möchten Sie es erneut versuchen? [J/n]: " retry || retry="n"
if [[ ! "$retry" =~ ^[JjYy] && -n "$retry" ]]; then
return 0
fi
fi
done
}
clear 2>/dev/null || true
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}==============================================================================${CLR_RESET}"
printf "%b\n" "${CLR_BOLD}${CLR_CYAN} Hyprland Desktop - Dotfiles Setup & Konfiguration ${CLR_RESET}"
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}==============================================================================${CLR_RESET}"
printf "\n"
printf "%b\n" "Willkommen auf Ihrem neuen Debian Unstable Hyprland-System!"
printf "\n"
printf "%b\n" "Aktuell ist eine rudimentäre Basiskonfiguration aktiv:"
printf "%b\n" " - ${CLR_BOLD}SUPER + ENTER${CLR_RESET} : Terminal (Kitty) öffnen"
printf "%b\n" " - ${CLR_BOLD}SUPER + Q${CLR_RESET} : Aktives Fenster schließen"
printf "\n"
printf "%b\n" "Wie möchten Sie Ihre Desktop-Konfiguration (Dotfiles) einrichten?"
printf "\n"
printf "%b\n" " ${CLR_BOLD}[1]${CLR_RESET} ${CLR_GREEN}LinuxBeginnings Hyprland-Dotfiles installieren${CLR_RESET}"
printf "%b\n" " Vollständig vorkonfiguriertes Setup (Waybar, Rofi, Animationen, Themes)"
printf "%b\n" " URL: https://github.com/LinuxBeginnings/Hyprland-Dots"
printf "\n"
printf "%b\n" " ${CLR_BOLD}[2]${CLR_RESET} ${CLR_MAGENTA}Eigenes Git-Repository als ~/.config klonen${CLR_RESET}"
printf "%b\n" " Klont Ihr eigenes Git-Repository direkt als vollständigen ~/.config-Ordner."
printf "%b\n" " (Unterstützt HTTPS & SSH inkl. Authentifizierung)"
printf "\n"
printf "%b\n" " ${CLR_BOLD}[3]${CLR_RESET} ${CLR_YELLOW}Überspringen / Basiskonfiguration beibehalten${CLR_RESET}"
printf "%b\n" " Keine Änderungen vornehmen (kann später manuell eingerichtet werden)."
printf "\n"
printf "%b\n" "${CLR_BOLD}${CLR_CYAN}------------------------------------------------------------------------------${CLR_RESET}"
while true; do
read -r -p "Bitte wählen Sie eine Option [1-3] (Standard: 1): " choice || choice="1"
choice="$(echo "$choice" | xargs)"
[[ -z "$choice" ]] && choice="1"
case "$choice" in
1)
install_linuxbeginnings
break
;;
2)
clone_custom_repo
break
;;
3)
printf "\n"
printf "%b\n" "${CLR_YELLOW}[INFO] Dotfiles-Einrichtung übersprungen. Die Basiskonfiguration bleibt aktiv.${CLR_RESET}"
break
;;
*)
printf "%b\n" "${CLR_RED}Ungültige Eingabe. Bitte 1, 2 oder 3 wählen.${CLR_RESET}"
;;
esac
done
# Oh-My-Zsh & Plugins einrichten
install_oh_my_zsh
# JetBrains Junie CLI & AwesomeJunieSkills installieren
install_junie_cli_and_skills
# Marker-Datei setzen
mark_as_prompted
printf "\n"
printf "%b\n" "${CLR_GREEN}${CLR_BOLD}[✓] Ersteinrichtung vollständig abgeschlossen!${CLR_RESET}"
printf "%b\n" "Sie können dieses Menü jederzeit erneut aufrufen mit:"
printf "%b\n" " ${CLR_BOLD}~/.config/hypr/scripts/install-dots-prompt.sh --force${CLR_RESET}"
+75
View File
@@ -0,0 +1,75 @@
# 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"
# Automatic Oh-My-Zsh installation on login / shell startup if not yet installed
if [[ ! -d "$ZSH" ]]; then
if command -v git >/dev/null 2>&1; then
echo "Oh-My-Zsh ist nicht eingerichtet. Installiere Oh-My-Zsh für $USER..."
if git clone --depth=1 https://github.com/ohmyzsh/ohmyzsh.git "$ZSH" 2>/dev/null; then
mkdir -p "${ZSH_CUSTOM:-$ZSH/custom}/plugins"
git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions "${ZSH_CUSTOM:-$ZSH/custom}/plugins/zsh-autosuggestions" 2>/dev/null || true
git clone --depth=1 https://github.com/zsh-users/zsh-syntax-highlighting "${ZSH_CUSTOM:-$ZSH/custom}/plugins/zsh-syntax-highlighting" 2>/dev/null || true
echo "Oh-My-Zsh erfolgreich eingerichtet."
fi
fi
else
# Plugins sicherstellen, falls Oh-My-Zsh existiert aber Custom-Plugins fehlen
if [[ ! -d "${ZSH_CUSTOM:-$ZSH/custom}/plugins/zsh-autosuggestions" ]] && command -v git >/dev/null 2>&1; then
git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions "${ZSH_CUSTOM:-$ZSH/custom}/plugins/zsh-autosuggestions" 2>/dev/null || true
fi
if [[ ! -d "${ZSH_CUSTOM:-$ZSH/custom}/plugins/zsh-syntax-highlighting" ]] && command -v git >/dev/null 2>&1; then
git clone --depth=1 https://github.com/zsh-users/zsh-syntax-highlighting "${ZSH_CUSTOM:-$ZSH/custom}/plugins/zsh-syntax-highlighting" 2>/dev/null || true
fi
fi
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
+2
View File
@@ -0,0 +1,2 @@
#!/bin/bash
BIN
View File
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
+2
View File
@@ -0,0 +1,2 @@
#!/usr/bin/env python3
+1
View File
@@ -0,0 +1 @@
BIN
View File
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
[Desktop Entry]
Name=Spotify
Exec=/usr/bin/spotify
Icon=spotify-client
Terminal=false
Type=Application
Categories=Audio;Music;
Executable
+141
View File
@@ -0,0 +1,141 @@
#!/usr/bin/env bash
# ==============================================================================
# install.sh - Web installer and bootstrap script for Debian Setup Framework
# ==============================================================================
# Usage:
# curl -fsSL https://gitea.creative-dragonslayer.de/Scripts/Setup/raw/branch/main/install.sh | bash
# curl -fsSL https://gitea.creative-dragonslayer.de/Scripts/Setup/raw/branch/main/install.sh | bash -s -- --all
# ==============================================================================
set -euo pipefail
# ANSI Color Codes
CLR_RESET='\033[0m'
CLR_BOLD='\033[1m'
CLR_RED='\033[0;31m'
CLR_GREEN='\033[0;32m'
CLR_YELLOW='\033[0;33m'
CLR_BLUE='\033[0;34m'
CLR_CYAN='\033[0;36m'
if [[ ! -t 1 ]]; then
CLR_RESET=""
CLR_BOLD=""
CLR_RED=""
CLR_GREEN=""
CLR_YELLOW=""
CLR_BLUE=""
CLR_CYAN=""
fi
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" "$*"
}
TMP_DIR=""
cleanup() {
if [[ -n "${TMP_DIR:-}" && -d "$TMP_DIR" ]]; then
log_info "Cleaning up temporary installation files..."
rm -rf "$TMP_DIR"
fi
}
trap cleanup EXIT INT TERM
main() {
local repo_url="${REPO_URL:-https://gitea.creative-dragonslayer.de/Scripts/Setup.git}"
local repo_branch="${REPO_BRANCH:-}"
log_step "Debian Unstable & Hyprland Setup Framework Installer"
log_info "Repository: $repo_url ${repo_branch:+(Branch: $repo_branch)}"
# Ensure git is available
if ! command -v git >/dev/null 2>&1; then
log_info "Installing git..."
if [[ "$(id -u)" -eq 0 ]]; then
DEBIAN_FRONTEND=noninteractive apt-get update -y
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends git ca-certificates
else
if ! command -v sudo >/dev/null 2>&1; then
log_error "sudo is required to install prerequisites. Please run as root or install sudo."
exit 1
fi
sudo DEBIAN_FRONTEND=noninteractive apt-get update -y
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends git ca-certificates
fi
fi
# Create temporary directory
TMP_DIR="$(mktemp -d /tmp/debian-setup-XXXXXX)"
log_info "Cloning repository into temporary directory: $TMP_DIR..."
local clone_success=0
if [[ -n "$repo_branch" ]]; then
if git clone --depth 1 -b "$repo_branch" "$repo_url" "$TMP_DIR" 2>/dev/null; then
clone_success=1
else
log_warn "Failed to clone branch '$repo_branch', falling back to default branch..."
rm -rf "${TMP_DIR:?}"/* "${TMP_DIR:?}"/.* 2>/dev/null || true
fi
fi
if [[ "$clone_success" -eq 0 ]]; then
if git clone --depth 1 "$repo_url" "$TMP_DIR"; then
clone_success=1
fi
fi
if [[ "$clone_success" -eq 0 ]]; then
log_error "Failed to clone repository from $repo_url"
exit 1
fi
cd "$TMP_DIR"
chmod +x setup.sh
log_success "Repository cloned successfully. Starting setup orchestrator..."
# Check if dry-run flag is requested
local is_dry_run=0
for arg in "$@"; do
if [[ "$arg" == "-d" || "$arg" == "--dry-run" ]]; then
is_dry_run=1
break
fi
done
# Prepare command to execute setup.sh
local -a setup_cmd=()
if [[ "$(id -u)" -ne 0 ]] && [[ "$is_dry_run" -eq 0 ]]; then
if ! command -v sudo >/dev/null 2>&1; then
log_error "sudo is required to run setup.sh. Please install sudo or run as root."
exit 1
fi
setup_cmd+=(sudo)
fi
setup_cmd+=(./setup.sh "$@")
# Reconnect stdin to /dev/tty if stdin is currently piped and /dev/tty is accessible (for interactive prompts/TUI)
if [[ ! -t 0 ]] && [[ -e /dev/tty ]] && ( : < /dev/tty ) 2>/dev/null; then
"${setup_cmd[@]}" < /dev/tty
else
"${setup_cmd[@]}"
fi
}
main "$@"
Executable
+151
View File
@@ -0,0 +1,151 @@
#!/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
}
# Enable i386 (32-bit) multiarch architecture
apt_enable_i386() {
if ! dpkg --print-foreign-architectures | grep -q "^i386$"; then
log_info "Enabling 32-bit (i386) multiarch architecture..."
dpkg --add-architecture i386
log_success "32-bit (i386) architecture enabled."
else
log_info "32-bit (i386) architecture is already enabled."
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 grep -q "BEGIN PGP PUBLIC KEY BLOCK" "$tmp_key"; then
gpg --dearmor --yes --batch -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")"
}
+619
View File
@@ -0,0 +1,619 @@
#!/usr/bin/env bash
# ==============================================================================
# lib/btrfs.sh - Btrfs root volume detection, subvolume management & migration
# ==============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# shellcheck source=lib/utils.sh
source "$SCRIPT_DIR/lib/utils.sh"
# Check if the root filesystem is Btrfs
is_root_btrfs() {
local fstype
fstype="$(findmnt -n -o FSTYPE / 2>/dev/null || true)"
[[ "$fstype" == "btrfs" ]]
}
# Resolve the root block device (stripping any subvolume bracket suffix)
get_root_btrfs_device() {
local dev
dev="$(findmnt -n -o SOURCE --canonical / 2>/dev/null || findmnt -n -o SOURCE / 2>/dev/null || true)"
dev="${dev%%\[*}"
echo "$dev"
}
# Resolve UUID of root filesystem
get_root_btrfs_uuid() {
local uuid dev
uuid="$(findmnt -n -o UUID / 2>/dev/null || true)"
if [[ -z "$uuid" ]]; then
dev="$(get_root_btrfs_device)"
if [[ -n "$dev" && -b "$dev" ]]; then
uuid="$(blkid -s UUID -o value "$dev" 2>/dev/null || true)"
fi
fi
echo "$uuid"
}
# Check if /home is mounted on a separate filesystem / partition from /
is_home_separate_filesystem() {
local root_dev home_dev
root_dev="$(get_root_btrfs_device)"
home_dev="$(findmnt -n -o SOURCE --canonical /home 2>/dev/null || findmnt -n -o SOURCE /home 2>/dev/null || true)"
home_dev="${home_dev%%\[*}"
if [[ -n "$home_dev" && -n "$root_dev" && "$home_dev" != "$root_dev" ]]; then
return 0
fi
return 1
}
# Check if root is already running from a dedicated subvolume (@ or @rootfs)
is_root_subvolume_configured() {
local fsroot opts
fsroot="$(findmnt -n -o FSROOT / 2>/dev/null || true)"
opts="$(findmnt -n -o OPTIONS / 2>/dev/null || true)"
if [[ "$fsroot" == "/@" || "$fsroot" == "/@rootfs" ]] || \
[[ "$opts" =~ subvol=@ || "$opts" =~ subvol=/@ ]]; then
return 0
fi
return 1
}
# Update /etc/fstab to mount / with subvol=@ and /home with subvol=@home
update_btrfs_fstab() {
local fstab_file="$1"
local root_id="$2"
[[ -f "$fstab_file" ]] || return 0
backup_file_or_dir "$fstab_file"
local tmp_fstab
tmp_fstab="$(mktemp)"
local found_root=0
local found_home=0
local root_spec="${root_id:-}"
local root_opts="defaults,subvol=@"
while IFS= read -r line || [[ -n "$line" ]]; do
# Retain comments and blank lines
if [[ "$line" =~ ^[[:space:]]*# || -z "${line// /}" ]]; then
echo "$line" >> "$tmp_fstab"
continue
fi
# Parse fields
local spec mnt type opts freq pass
read -r spec mnt type opts freq pass <<< "$line"
if [[ "$mnt" == "/" && "$type" == "btrfs" ]]; then
found_root=1
root_spec="${root_id:-$spec}"
local new_opts="$opts"
if [[ "$new_opts" =~ subvol= ]] || [[ "$new_opts" =~ subvolid= ]]; then
new_opts="$(echo "$new_opts" | sed -E 's/(subvol|subvolid)=[^,]*/subvol=@/g')"
else
new_opts="${new_opts},subvol=@"
fi
new_opts="$(echo "$new_opts" | sed -E -e 's/,,+/,/g' -e 's/^,//' -e 's/,$//')"
root_opts="$new_opts"
spec="$root_spec"
printf "%s\t%s\t%s\t%s\t%s\t%s\n" "$spec" "$mnt" "$type" "$new_opts" "${freq:-0}" "${pass:-0}" >> "$tmp_fstab"
elif [[ "$mnt" == "/home" && "$type" == "btrfs" ]]; then
found_home=1
local new_opts="$opts"
if [[ "$new_opts" =~ subvol= ]] || [[ "$new_opts" =~ subvolid= ]]; then
new_opts="$(echo "$new_opts" | sed -E 's/(subvol|subvolid)=[^,]*/subvol=@home/g')"
else
new_opts="${new_opts},subvol=@home"
fi
new_opts="$(echo "$new_opts" | sed -E -e 's/,,+/,/g' -e 's/^,//' -e 's/,$//')"
spec="${root_id:-$spec}"
printf "%s\t%s\t%s\t%s\t%s\t%s\n" "$spec" "$mnt" "$type" "$new_opts" "${freq:-0}" "${pass:-0}" >> "$tmp_fstab"
else
echo "$line" >> "$tmp_fstab"
fi
done < "$fstab_file"
# If home was not present in fstab and root was found/specified, add /home entry
if [[ "$found_home" -eq 0 && ( "$found_root" -eq 1 || -n "$root_spec" ) ]]; then
local home_opts="${root_opts/subvol=@/subvol=@home}"
if [[ "$home_opts" == "$root_opts" ]]; then
home_opts="defaults,subvol=@home"
fi
printf "%s\t%s\t%s\t%s\t%s\t%s\n" "$root_spec" "/home" "btrfs" "$home_opts" "0" "0" >> "$tmp_fstab"
fi
if ! cat "$tmp_fstab" > "$fstab_file" 2>/dev/null; then
log_warn "Could not write to $fstab_file (permission denied)."
fi
rm -f "$tmp_fstab"
}
# Main function to check and configure Btrfs subvolumes for root and home
check_and_setup_btrfs_subvolumes() {
if ! is_root_btrfs; then
local fstype
fstype="$(findmnt -n -o FSTYPE / 2>/dev/null || echo "unknown")"
log_info "Root filesystem is not Btrfs ($fstype). Skipping Btrfs subvolume migration."
return 0
fi
log_info "Btrfs root filesystem detected."
if is_root_subvolume_configured; then
local fsroot
fsroot="$(findmnt -n -o FSROOT / 2>/dev/null || true)"
log_success "Root filesystem is already running inside subvolume '$fsroot'."
return 0
fi
# Ensure btrfs utility is available
if ! command_exists btrfs; then
log_info "Installing btrfs-progs..."
DEBIAN_FRONTEND=noninteractive apt-get update -y >/dev/null 2>&1 || true
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends btrfs-progs || {
log_error "btrfs-progs could not be installed."
return 1
}
fi
local root_dev root_uuid
root_dev="$(get_root_btrfs_device)"
root_uuid="$(get_root_btrfs_uuid)"
if [[ -z "$root_dev" ]]; then
log_warn "Could not determine root block device for Btrfs. Skipping migration."
return 0
fi
local root_fstab_id
if [[ -n "$root_uuid" ]]; then
root_fstab_id="UUID=$root_uuid"
else
root_fstab_id="$root_dev"
fi
log_step "Btrfs Migration: Creating subvolumes '@' and '@home'..."
local tmp_mnt
tmp_mnt="$(mktemp -d /tmp/btrfs-toplevel.XXXXXX)"
# Trap to safely unmount and remove temporary mountpoint
cleanup_tmp_mnt() {
if [[ -d "$tmp_mnt" ]]; then
if mountpoint -q "$tmp_mnt"; then
umount "$tmp_mnt" 2>/dev/null || true
fi
rm -rf "$tmp_mnt"
fi
}
# Mount top-level btrfs root (subvolid=5)
if ! mount -t btrfs -o subvolid=5 "$root_dev" "$tmp_mnt"; then
log_error "Failed to mount top-level Btrfs volume on $tmp_mnt."
rm -rf "$tmp_mnt"
return 1
fi
# 1. Create or snapshot '@' subvolume for root
if [[ ! -d "$tmp_mnt/@" ]]; then
log_info "Creating snapshot of top-level filesystem into '@' subvolume..."
btrfs subvolume snapshot "$tmp_mnt" "$tmp_mnt/@"
log_success "Created '@' subvolume snapshot."
else
log_info "'@' subvolume already exists in top-level Btrfs tree."
fi
# 2. Create '@home' subvolume if /home is on the same volume
if ! is_home_separate_filesystem; then
if [[ ! -d "$tmp_mnt/@home" ]]; then
log_info "Creating '@home' subvolume..."
btrfs subvolume create "$tmp_mnt/@home"
log_success "Created '@home' subvolume."
# Move existing home data into @home
if [[ -d "$tmp_mnt/@/home" && "$(ls -A "$tmp_mnt/@/home" 2>/dev/null)" ]]; then
log_info "Moving existing /home data to '@home' subvolume..."
cp -a --reflink=auto "$tmp_mnt/@/home/." "$tmp_mnt/@home/"
# Clean up the directory inside @/home so it acts as an empty mountpoint
rm -rf "$tmp_mnt/@/home"/* "$tmp_mnt/@/home"/.[!.]* "$tmp_mnt/@/home"/..?* 2>/dev/null || true
chmod 755 "$tmp_mnt/@/home" 2>/dev/null || true
chown root:root "$tmp_mnt/@/home" 2>/dev/null || true
log_success "Moved /home data to '@home' subvolume."
fi
else
log_info "'@home' subvolume already exists in top-level Btrfs tree."
fi
else
log_info "/home is mounted on a separate filesystem. Skipping '@home' subvolume creation."
fi
# 3. Set default subvolume to '@'
local subvol_at_id
subvol_at_id="$(btrfs subvolume list "$tmp_mnt" 2>/dev/null | awk '$NF == "@" {print $2}' | tail -n1)"
if [[ -n "$subvol_at_id" ]]; then
btrfs subvolume set-default "$subvol_at_id" "$tmp_mnt"
log_success "Set default Btrfs subvolume to '@' (ID: $subvol_at_id)."
fi
# 4. Update /etc/fstab (and the snapshotted @/etc/fstab)
log_info "Updating /etc/fstab entries for '@' and '@home'..."
update_btrfs_fstab "/etc/fstab" "$root_fstab_id"
if [[ -f "$tmp_mnt/@/etc/fstab" ]]; then
update_btrfs_fstab "$tmp_mnt/@/etc/fstab" "$root_fstab_id"
fi
log_success "Updated /etc/fstab with subvolume mount options."
# 5. Mount '@home' at /home for the current live session if not already mounted
if ! is_home_separate_filesystem; then
if ! findmnt /home >/dev/null 2>&1; then
log_info "Mounting '@home' subvolume at /home for current setup session..."
mount -t btrfs -o subvol=@home "$root_dev" /home || log_warn "Could not mount @home at /home live."
fi
fi
# Clean up temporary top-level mount
cleanup_tmp_mnt
log_success "Btrfs subvolume setup and migration completed successfully."
}
# Ensure Timeshift APT hook is configured for automatic snapshots on system updates
ensure_timeshift_apt_hook() {
local root_prefix="${ROOT_PREFIX:-}"
local snapshot_on_update="${TIMESHIFT_SNAPSHOT_ON_UPDATE:-true}"
local apt_conf_file="${root_prefix}/etc/apt/apt.conf.d/80timeshift-auto-snapshot"
local hook_script="${root_prefix}/usr/local/bin/timeshift-apt-hook"
# If disabled in configuration, remove hook if present
if [[ "$snapshot_on_update" != "1" && "$snapshot_on_update" != "true" ]]; then
if [[ -f "$apt_conf_file" || -f "$hook_script" ]]; then
log_info "Disabling Timeshift APT update snapshot hook..."
rm -f "$apt_conf_file" "$hook_script"
fi
return 0
fi
mkdir -p "${root_prefix}/usr/local/bin" "${root_prefix}/etc/apt/apt.conf.d"
# Create hook script
log_info "Configuring Timeshift APT update hook ($hook_script)..."
cat > "$hook_script" <<'EOF'
#!/usr/bin/env bash
# ==============================================================================
# /usr/local/bin/timeshift-apt-hook - Automatic Timeshift Snapshot on APT updates
# ==============================================================================
set -euo pipefail
# Check if timeshift binary is available
if ! command -v timeshift >/dev/null 2>&1; then
exit 0
fi
# Check if timeshift configuration exists
if [[ ! -f /etc/timeshift/timeshift.json && ! -f /etc/timeshift.json ]]; then
exit 0
fi
# Check if root filesystem is Btrfs
if command -v findmnt >/dev/null 2>&1; then
if [[ "$(findmnt -n -o FSTYPE / 2>/dev/null || true)" != "btrfs" ]]; then
exit 0
fi
fi
# Prevent duplicate snapshots within 60 seconds (rate limiting)
STAMP_FILE="/run/timeshift-apt-hook.stamp"
if [[ -f "$STAMP_FILE" ]]; then
LAST_RUN="$(stat -c %Y "$STAMP_FILE" 2>/dev/null || stat -f %m "$STAMP_FILE" 2>/dev/null || echo 0)"
CURRENT_TIME="$(date +%s)"
if (( CURRENT_TIME - LAST_RUN < 60 )); then
exit 0
fi
fi
echo ">> [Timeshift] Creating automatic pre-update system snapshot..."
if timeshift --create --scripted --tags O --comments "Automatic snapshot before system update (APT)" 2>&1; then
touch "$STAMP_FILE" 2>/dev/null || true
echo ">> [Timeshift] Pre-update snapshot created successfully."
else
echo ">> [Timeshift] Warning: Automatic snapshot could not be created (continuing update)."
fi
exit 0
EOF
chmod 755 "$hook_script"
# Create APT configuration hook
cat > "$apt_conf_file" <<'EOF'
// Automatic Timeshift snapshot before APT package operations / updates
DPkg::Pre-Invoke { "[ -x /usr/local/bin/timeshift-apt-hook ] && /usr/local/bin/timeshift-apt-hook || true"; };
EOF
chmod 644 "$apt_conf_file"
log_success "Timeshift APT update hook configured: $apt_conf_file"
}
# Ensure Timeshift systemd boot service and cron jobs are configured and enabled
ensure_timeshift_boot_service() {
local root_prefix="${ROOT_PREFIX:-}"
local service_file="${root_prefix}/etc/systemd/system/timeshift-boot.service"
local timeshift_bin
timeshift_bin="$(command -v timeshift || echo "/usr/bin/timeshift")"
mkdir -p "${root_prefix}/etc/systemd/system"
local needs_service_update=0
if [[ ! -f "$service_file" ]]; then
needs_service_update=1
fi
if [[ "$needs_service_update" -eq 1 ]]; then
log_info "Creating Timeshift boot snapshot service ($service_file)..."
cat > "$service_file" <<EOF
[Unit]
Description=Timeshift Boot Snapshot Service
Documentation=man:timeshift(1)
After=local-fs.target
ConditionPathExists=/etc/timeshift/timeshift.json
[Service]
Type=oneshot
ExecStart=${timeshift_bin} --check --scripted
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
chmod 644 "$service_file"
fi
if [[ -z "$root_prefix" ]] && command_exists systemctl; then
systemctl daemon-reload 2>/dev/null || true
systemctl enable timeshift-boot.service 2>/dev/null || true
fi
# Also install cron entries if cron directory exists
if [[ -d "${root_prefix}/etc/cron.d" ]]; then
local cron_boot="${root_prefix}/etc/cron.d/timeshift-boot"
local cron_hourly="${root_prefix}/etc/cron.d/timeshift-hourly"
if [[ ! -f "$cron_boot" ]]; then
cat > "$cron_boot" <<EOF
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=""
@reboot root sleep 10m && ${timeshift_bin} --create --scripted --tags B
EOF
chmod 644 "$cron_boot"
fi
if [[ ! -f "$cron_hourly" ]]; then
cat > "$cron_hourly" <<EOF
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=""
0 * * * * root ${timeshift_bin} --check --scripted
EOF
chmod 644 "$cron_hourly"
fi
fi
}
# Ensure Timeshift is configured for Btrfs mode on the root filesystem
ensure_timeshift_btrfs_config() {
local root_prefix="${ROOT_PREFIX:-}"
local root_uuid
root_uuid="$(get_root_btrfs_uuid)"
mkdir -p "${root_prefix}/etc/timeshift"
local config_file="${root_prefix}/etc/timeshift/timeshift.json"
local count_boot="${TIMESHIFT_COUNT_BOOT:-5}"
local schedule_boot="${TIMESHIFT_SCHEDULE_BOOT:-true}"
local needs_update=0
if [[ ! -f "$config_file" ]]; then
needs_update=1
elif grep -q '"btrfs_mode"[[:space:]]*:[[:space:]]*"false"' "$config_file" 2>/dev/null; then
needs_update=1
elif grep -q '"backup_device_uuid"[[:space:]]*:[[:space:]]*""' "$config_file" 2>/dev/null && [[ -n "$root_uuid" ]]; then
needs_update=1
elif ! grep -q "\"schedule_boot\"[[:space:]]*:[[:space:]]*\"${schedule_boot}\"" "$config_file" 2>/dev/null; then
needs_update=1
elif ! grep -q "\"count_boot\"[[:space:]]*:[[:space:]]*\"${count_boot}\"" "$config_file" 2>/dev/null; then
needs_update=1
fi
if [[ "$needs_update" -eq 1 ]]; then
log_info "Initializing Timeshift Btrfs configuration ($config_file)..."
backup_file_or_dir "$config_file"
cat > "$config_file" <<EOF
{
"backup_device_uuid" : "${root_uuid}",
"parent_device_uuid" : "",
"do_first_run" : "false",
"btrfs_mode" : "true",
"include_btrfs_home_for_backup" : "false",
"include_btrfs_home_for_restore" : "false",
"stop_cron_emails" : "true",
"schedule_monthly" : "false",
"schedule_weekly" : "false",
"schedule_daily" : "false",
"schedule_hourly" : "false",
"schedule_boot" : "${schedule_boot}",
"count_monthly" : "2",
"count_weekly" : "3",
"count_daily" : "5",
"count_hourly" : "6",
"count_boot" : "${count_boot}",
"snapshot_size" : "0",
"snapshot_count" : "0",
"exclude" : [
],
"exclude-apps" : [
]
}
EOF
chmod 644 "$config_file"
if [[ ! -e "${root_prefix}/etc/timeshift.json" ]]; then
ln -sf /etc/timeshift/timeshift.json "${root_prefix}/etc/timeshift.json" 2>/dev/null || true
fi
fi
ensure_timeshift_boot_service
ensure_timeshift_apt_hook
ensure_grub_btrfs
}
# Ensure grub-btrfs is installed and configured to generate GRUB snapshot boot entries
ensure_grub_btrfs() {
local root_prefix="${ROOT_PREFIX:-}"
local enable_grub_btrfs="${ENABLE_GRUB_BTRFS:-1}"
# Check if disabled in configuration
if [[ "$enable_grub_btrfs" != "1" && "$enable_grub_btrfs" != "true" ]]; then
log_info "GRUB Btrfs snapshot booting disabled in configuration."
return 0
fi
# Dry-run check
if [[ "${FLAG_DRY_RUN:-0}" -eq 1 ]]; then
log_info "[DRY-RUN] Would install and configure grub-btrfs for GRUB snapshot booting."
return 0
fi
# Check if root is on Btrfs
if ! is_root_btrfs; then
log_info "Root filesystem is not Btrfs. Skipping grub-btrfs setup."
return 0
fi
log_info "Configuring GRUB Btrfs snapshot support (grub-btrfs)..."
# Ensure required dependencies are installed
if ! command_exists inotifywait || ! command_exists git || ! command_exists make; then
log_info "Installing dependencies for grub-btrfs (inotify-tools, git, make)..."
DEBIAN_FRONTEND=noninteractive apt-get update -y >/dev/null 2>&1 || true
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends inotify-tools git make 2>/dev/null || true
fi
local repo_dir="${root_prefix}/usr/share/debian-gaming/grub/grub-btrfs"
mkdir -p "$(dirname "$repo_dir")"
if [[ ! -d "$repo_dir/.git" ]]; then
log_info "Cloning grub-btrfs repository..."
if ! git clone --depth 1 https://github.com/Antynea/grub-btrfs.git "$repo_dir" 2>/dev/null; then
log_warn "Failed to clone grub-btrfs repository. Snapshot boot menu may not be available."
return 0
fi
else
log_info "grub-btrfs repository already cloned; pulling latest updates..."
(cd "$repo_dir" && git pull 2>/dev/null) || log_warn "grub-btrfs git pull skipped."
fi
# Install grub.d script
mkdir -p "${root_prefix}/etc/grub.d"
if [[ -f "$repo_dir/41_snapshots-btrfs" ]]; then
cp -f "$repo_dir/41_snapshots-btrfs" "${root_prefix}/etc/grub.d/41_snapshots-btrfs"
chmod 755 "${root_prefix}/etc/grub.d/41_snapshots-btrfs"
fi
# Install default config
mkdir -p "${root_prefix}/etc/default/grub-btrfs"
if [[ -f "$repo_dir/config" && ! -f "${root_prefix}/etc/default/grub-btrfs/config" ]]; then
cp -f "$repo_dir/config" "${root_prefix}/etc/default/grub-btrfs/config"
chmod 644 "${root_prefix}/etc/default/grub-btrfs/config"
fi
# Install grub-btrfsd binary
mkdir -p "${root_prefix}/usr/bin"
if [[ -f "$repo_dir/grub-btrfsd" ]]; then
cp -f "$repo_dir/grub-btrfsd" "${root_prefix}/usr/bin/grub-btrfsd"
chmod 755 "${root_prefix}/usr/bin/grub-btrfsd"
fi
# Install and configure systemd service for automatic snapshot tracking with Timeshift
mkdir -p "${root_prefix}/etc/systemd/system"
local service_file="${root_prefix}/etc/systemd/system/grub-btrfsd.service"
cat > "$service_file" <<'EOF'
[Unit]
Description=Regenerate grub-btrfs.cfg on snapshot changes
After=local-fs.target
ConditionPathExists=/etc/default/grub-btrfs/config
[Service]
Type=simple
LogLevelMax=notice
Environment="PATH=/sbin:/bin:/usr/sbin:/usr/bin"
EnvironmentFile=-/etc/default/grub-btrfs/config
ExecStart=/usr/bin/grub-btrfsd --syslog --timeshift-auto
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
chmod 644 "$service_file"
if [[ -z "$root_prefix" ]] && command_exists systemctl; then
systemctl daemon-reload 2>/dev/null || true
systemctl enable grub-btrfsd.service 2>/dev/null || true
systemctl restart grub-btrfsd.service 2>/dev/null || true
fi
log_success "grub-btrfs installed and configured successfully."
}
# Create a Btrfs snapshot using Timeshift
create_timeshift_snapshot() {
local comment="${1:-Setup Snapshot}"
local tags="${2:-O}"
# Check if disabled via configuration
if [[ "${ENABLE_TIMESHIFT_SNAPSHOTS:-1}" != "1" && "${ENABLE_TIMESHIFT_SNAPSHOTS:-1}" != "true" ]]; then
log_info "Timeshift snapshots disabled in configuration. Skipping: '$comment'"
return 0
fi
# Dry-run check
if [[ "${FLAG_DRY_RUN:-0}" -eq 1 ]]; then
log_info "[DRY-RUN] Would create Timeshift Btrfs snapshot: '$comment' (Tag: $tags)"
return 0
fi
# Check if root is on Btrfs
if ! is_root_btrfs; then
log_info "Root filesystem is not Btrfs. Skipping Timeshift snapshot: '$comment'"
return 0
fi
# Ensure timeshift is installed
if ! command_exists timeshift; then
log_info "Timeshift not found. Attempting to install timeshift..."
DEBIAN_FRONTEND=noninteractive apt-get update -y >/dev/null 2>&1 || true
if ! DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends timeshift 2>/dev/null; then
log_warn "Timeshift is not available and could not be installed. Skipping snapshot: '$comment'"
return 0
fi
fi
# Ensure Timeshift configuration for Btrfs
ensure_timeshift_btrfs_config
log_substep "Creating Timeshift Btrfs snapshot: '$comment' (Tag: $tags)..."
local root_dev
root_dev="$(get_root_btrfs_device)"
if timeshift --create --scripted --comments "$comment" --tags "$tags" 2>/dev/null || \
([[ -n "$root_dev" ]] && timeshift --create --scripted --snapshot-device "$root_dev" --btrfs --comments "$comment" --tags "$tags" 2>/dev/null); then
log_success "Timeshift Btrfs snapshot created: '$comment'"
else
log_warn "Timeshift snapshot could not be created for '$comment' (non-fatal)."
fi
}
+273
View File
@@ -0,0 +1,273 @@
#!/usr/bin/env bash
# ==============================================================================
# lib/network.sh - Network interface configuration (Debian Installer style & Loopback)
# ==============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# shellcheck source=lib/utils.sh
source "$SCRIPT_DIR/lib/utils.sh"
# Get a list of all physical LAN / Ethernet network interfaces on the system
get_lan_interfaces() {
local -a lan_ifaces=()
if [[ -d /sys/class/net ]]; then
for iface_path in /sys/class/net/*; do
[[ -e "$iface_path" ]] || continue
local iface
iface="$(basename "$iface_path")"
# Skip loopback interface
[[ "$iface" == "lo" ]] && continue
# Skip known virtual, bridge, container, tunnel and VPN interfaces
if [[ "$iface" =~ ^(docker[0-9]*|veth.*|virbr[0-9]*|br.*|bridge.*|tun[0-9]*|tap[0-9]*|wg[0-9]*|dummy[0-9]*|waydroid.*|tailscale.*|zt.*|bond.*|sit[0-9]*|ip6tnl.*|gre.*|erspan.*|vboxnet.*|vmnet.*)$ ]]; then
continue
fi
# Skip wireless / Wi-Fi interfaces
if [[ -e "$iface_path/wireless" || -e "$iface_path/phy80211" || "$iface" =~ ^(wl.*|wlan.*|wifi.*|ath.*)$ ]]; then
continue
fi
# Check if it is a physical device (has device link) or standard Ethernet type (type == 1)
local is_lan=0
local dev_type=""
if [[ -f "$iface_path/type" ]]; then
dev_type="$(cat "$iface_path/type" 2>/dev/null || echo "")"
fi
if [[ -e "$iface_path/device" && "$dev_type" == "1" ]]; then
is_lan=1
elif [[ "$iface" =~ ^(eth[0-9]+|en[a-zA-Z0-9]+)$ ]] && [[ "$dev_type" == "1" || -z "$dev_type" ]]; then
is_lan=1
elif [[ -e "$iface_path/device" ]]; then
is_lan=1
fi
if [[ "$is_lan" -eq 1 ]]; then
lan_ifaces+=("$iface")
fi
done
elif command_exists ip; then
# Fallback to ip link parsing if /sys/class/net is not directly readable
while IFS= read -r line; do
local iface
iface="$(echo "$line" | awk -F': ' '{print $2}' | cut -d'@' -f1)"
[[ -z "$iface" || "$iface" == "lo" ]] && continue
if [[ "$iface" =~ ^(eth[0-9]+|en[a-zA-Z0-9]+)$ ]]; then
lan_ifaces+=("$iface")
fi
done < <(ip -o link show 2>/dev/null || true)
fi
echo "${lan_ifaces[@]:-}"
}
# Check if a specific interface is already configured in /etc/network/interfaces or interfaces.d
is_interface_configured() {
local iface="$1"
local interfaces_file="/etc/network/interfaces"
local interfaces_dir="/etc/network/interfaces.d"
if [[ -f "$interfaces_file" ]]; then
if grep -E -q "^[[:space:]]*(iface|auto|allow-hotplug)[[:space:]]+${iface}([[:space:]]|$)" "$interfaces_file" 2>/dev/null; then
return 0
fi
fi
if [[ -d "$interfaces_dir" ]]; then
if grep -E -q -r "^[[:space:]]*(iface|auto|allow-hotplug)[[:space:]]+${iface}([[:space:]]|$)" "$interfaces_dir" 2>/dev/null; then
return 0
fi
fi
return 1
}
# Configure loopback interface in /etc/network/interfaces and /etc/hosts
configure_loopback_interface() {
local interfaces_file="/etc/network/interfaces"
local interfaces_dir="/etc/network/interfaces.d"
mkdir -p "/etc/network" "$interfaces_dir"
log_substep "Configuring loopback network interface (lo)..."
if [[ ! -f "$interfaces_file" ]]; then
cat <<EOF > "$interfaces_file"
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
EOF
chmod 0644 "$interfaces_file"
log_success "Created $interfaces_file with loopback configuration."
else
backup_file_or_dir "$interfaces_file"
# Ensure source /etc/network/interfaces.d/* is present
if ! grep -E -q "^[[:space:]]*source[[:space:]]+/etc/network/interfaces\.d/\*" "$interfaces_file"; then
sed -i '1i # The loopback network interface\nsource /etc/network/interfaces.d/*\n' "$interfaces_file"
fi
# Ensure auto lo and iface lo inet loopback are configured
if ! grep -E -q "^[[:space:]]*iface[[:space:]]+lo[[:space:]]+inet[[:space:]]+loopback" "$interfaces_file"; then
cat <<EOF >> "$interfaces_file"
# The loopback network interface
auto lo
iface lo inet loopback
EOF
log_success "Added loopback configuration to $interfaces_file."
fi
fi
# Ensure /etc/hosts has standard loopback mappings
if [[ -f /etc/hosts ]]; then
local host_name
host_name="$(hostname 2>/dev/null || cat /etc/hostname 2>/dev/null || echo "debian")"
if ! grep -q "127.0.0.1[[:space:]]\+localhost" /etc/hosts; then
echo "127.0.0.1 localhost" >> /etc/hosts
fi
if ! grep -q "::1[[:space:]]\+localhost" /etc/hosts; then
echo "::1 localhost ip6-localhost ip6-loopback" >> /etc/hosts
fi
if [[ -n "$host_name" ]] && ! grep -E -q "(127\.0\.1\.1|127\.0\.0\.1)[[:space:]]+.*$host_name" /etc/hosts; then
echo "127.0.1.1 $host_name" >> /etc/hosts
fi
fi
# Bring up loopback interface immediately
if command_exists ip; then
ip link set lo up 2>/dev/null || true
fi
if command_exists ifup; then
ifup lo 2>/dev/null || true
fi
log_success "Loopback interface (lo) configured and activated."
}
# Configure all detected physical LAN interfaces (Debian installer standard)
configure_lan_interfaces() {
local interfaces_file="/etc/network/interfaces"
local interfaces_dir="/etc/network/interfaces.d"
mkdir -p "/etc/network" "$interfaces_dir"
local -a lan_ifaces
read -r -a lan_ifaces <<< "$(get_lan_interfaces)"
if [[ ${#lan_ifaces[@]} -eq 0 ]]; then
log_info "No physical LAN interfaces detected at this time."
return 0
fi
log_substep "Found physical LAN interface(s): ${lan_ifaces[*]}"
# Backup interfaces file before modifications
if [[ -f "$interfaces_file" ]]; then
backup_file_or_dir "$interfaces_file"
fi
for iface in "${lan_ifaces[@]}"; do
[[ -z "$iface" ]] && continue
if is_interface_configured "$iface"; then
log_info "LAN interface '$iface' is already configured."
else
log_info "Configuring LAN interface '$iface' (Debian Installer style: DHCP & IPv6 Auto)..."
cat <<EOF >> "$interfaces_file"
# LAN network interface: $iface
allow-hotplug $iface
iface $iface inet dhcp
iface $iface inet6 auto
EOF
log_success "Added LAN interface '$iface' to $interfaces_file."
fi
# Ensure the interface is brought UP and usable
if command_exists ip; then
ip link set "$iface" up 2>/dev/null || true
fi
if command_exists ifup; then
ifup "$iface" 2>/dev/null || true
fi
done
log_success "All LAN network interfaces configured and activated."
}
# Configure NetworkManager to manage interfaces and work seamlessly with ifupdown
configure_network_manager() {
local nm_conf="/etc/NetworkManager/NetworkManager.conf"
local nm_dir="/etc/NetworkManager"
if [[ -d "$nm_dir" ]] || command_exists NetworkManager || command_exists nmcli; then
log_substep "Configuring NetworkManager integration (managed=true)..."
mkdir -p "$nm_dir"
if [[ ! -f "$nm_conf" ]]; then
cat <<EOF > "$nm_conf"
[main]
plugins=ifupdown,keyfile
[ifupdown]
managed=true
EOF
chmod 0644 "$nm_conf"
log_success "Created $nm_conf with managed=true."
else
backup_file_or_dir "$nm_conf"
# Set managed=true in [ifupdown] section
if grep -q "\[ifupdown\]" "$nm_conf"; then
sed -i '/\[ifupdown\]/,/^\[/{s/managed=false/managed=true/}' "$nm_conf"
if ! grep -A2 "\[ifupdown\]" "$nm_conf" | grep -q "managed="; then
sed -i '/\[ifupdown\]/a managed=true' "$nm_conf"
fi
else
cat <<EOF >> "$nm_conf"
[ifupdown]
managed=true
EOF
fi
log_success "Updated $nm_conf to managed=true."
fi
fi
}
# Enable networking and NetworkManager services
enable_network_services() {
if command_exists systemctl; then
log_substep "Enabling and activating network services..."
# Enable networking service (ifupdown)
systemctl enable networking.service 2>/dev/null || true
# Enable & start NetworkManager if available
if systemctl list-unit-files NetworkManager.service >/dev/null 2>&1 || [[ -f /lib/systemd/system/NetworkManager.service ]]; then
systemctl enable NetworkManager.service 2>/dev/null || true
systemctl start NetworkManager.service 2>/dev/null || true
log_success "NetworkManager service enabled and started."
fi
fi
}
# Central orchestration function for network configuration
configure_network_all() {
log_substep "Configuring complete network subsystem (Loopback, all LAN interfaces, NetworkManager)..."
configure_loopback_interface
configure_lan_interfaces
configure_network_manager
enable_network_services
log_success "Network configuration completed successfully."
}
Executable
+99
View File
@@ -0,0 +1,99 @@
#!/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:" \
23 78 10 \
"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, Ollama)" ON \
"07" "Userland & Skel (Zsh, Skel-Templates, Dotfiles)" ON \
"08" "Flatpaks (Flathub Repository & Flatpaks)" ON \
"09" "Zusatz-Apps & MIME (Spotify, Waydroid, OpenDeck, MIME)" ON \
"10" "Hyprland Desktop (LinuxBeginnings Debian-Hyprland 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
}
Executable
+282
View File
@@ -0,0 +1,282 @@
#!/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%bTarget User Detection:%b\n" "${CLR_CYAN}" "${CLR_RESET}" > "$tty_out"
printf "Detected target user: %b%s%b\n" "${CLR_BOLD}" "$candidate" "${CLR_RESET}" > "$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 "%bUsername cannot be empty.%b\n" "${CLR_YELLOW}" "${CLR_RESET}" > "$tty_out"
continue
fi
if [[ "$input_user" == "root" ]]; then
printf "%bRoot cannot be used as target desktop user.%b\n" "${CLR_YELLOW}" "${CLR_RESET}" > "$tty_out"
continue
fi
if ! id "$input_user" >/dev/null 2>&1; then
printf "%bUser '%s' does not exist on this system.%b\n" "${CLR_YELLOW}" "$input_user" "${CLR_RESET}" > "$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"
}
# Prompt for Ollama AI models storage path
prompt_ollama_models_path() {
if [[ -n "${OLLAMA_MODELS:-}" ]]; then
echo "$OLLAMA_MODELS"
return 0
fi
local default_path="${OLLAMA_MODELS_DEFAULT:-/mnt/Data/Software/ollama/models}"
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 whiptail is available and running on an active terminal, use whiptail dialog
if command_exists whiptail && [[ -t 1 || -c /dev/tty ]]; then
local tui_input
if tui_input=$(whiptail --title "Ollama KI-Modelle Speicherort" \
--inputbox "Bitte gib den Speicherort für die Ollama KI-Modelle an:" \
10 70 "$default_path" \
3>&1 1>&2 2>&3); then
tui_input="$(echo "$tui_input" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
if [[ -n "$tui_input" ]]; then
chosen="$tui_input"
else
chosen="$default_path"
fi
fi
fi
# CLI fallback if whiptail was not used or failed
if [[ -z "$chosen" ]]; then
printf "\n%bOllama KI-Modelle Speicherort:%b\n" "${CLR_CYAN}" "${CLR_RESET}" > "$tty_out"
printf "Standard-Pfad: %b%s%b\n" "${CLR_BOLD}" "$default_path" "${CLR_RESET}" > "$tty_out"
local input_path=""
read -r -p "Speicherort für Ollama-Modelle eingeben [$default_path]: " input_path < "$tty_in" > "$tty_out" 2>&1 || true
input_path="$(echo "$input_path" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
if [[ -n "$input_path" ]]; then
chosen="$input_path"
else
chosen="$default_path"
fi
fi
else
chosen="$default_path"
fi
export OLLAMA_MODELS="$chosen"
echo "$chosen"
}
# 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
}
run_as_user() {
run_as_target_user "$@"
}
# 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}"
if cp -r "$target" "$backup_path" 2>/dev/null; then
log_info "Created backup: $backup_path"
else
log_warn "Could not create backup of $target (permission denied)."
fi
fi
}
backup_file() {
backup_file_or_dir "$@"
}
Executable
+219
View File
@@ -0,0 +1,219 @@
#!/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/btrfs.sh"
source "$SCRIPT_DIR/lib/network.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 <<EOF
Usage: sudo ./setup.sh [OPTIONS]
Debian Unstable Setup & Desktop Customization Framework
Options:
-a, --all Run all setup stages sequentially (00 through 10)
-s, --stages <list> Comma-separated list of stages to run (e.g. --stages 01,02,04)
-u, --user <username> 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, Ollama)
07: Skel & User Environment (Zsh, Templates, Dotfiles Sync)
08: Flatpak Applications (Flathub, Flatpak package list)
09: Standalone Applications & MIME (Spotify, Waydroid, OpenDeck, MIME types)
10: 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
export FLAG_DRY_RUN
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 10)
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 10)
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
# Create pre-setup baseline Timeshift snapshot if on Btrfs
create_timeshift_snapshot "Pre-Setup Baseline: Before executing stages (${SELECTED_STAGES[*]})" "B"
# 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
# Create final completion Timeshift snapshot if on Btrfs
create_timeshift_snapshot "Post-Setup Final: All stages completed successfully (${SELECTED_STAGES[*]})" "O"
log_step "All selected setup stages completed successfully!"
+89
View File
@@ -0,0 +1,89 @@
#!/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"
source "$SCRIPT_DIR/lib/btrfs.sh"
source "$SCRIPT_DIR/lib/network.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 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=<user>."
exit 1
fi
log_success "Target user identified: $TARGET_USER (Home: $TARGET_HOME)"
# 3. Configure and Activate Network Interfaces (Loopback & LAN)
log_substep "Initializing and activating network interfaces (Loopback & LAN)..."
configure_loopback_interface
configure_lan_interfaces
# 4. 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."
# 5. 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
# 6. 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
# 7. Check & Setup Btrfs Subvolumes (@, @home)
log_substep "Checking Btrfs root volume & subvolume layout..."
check_and_setup_btrfs_subvolumes
# 8. Create Timeshift Btrfs Snapshot after preflight & subvolume setup
create_timeshift_snapshot "Stage 00: Pre-flight checks & Btrfs baseline" "B"
log_success "Stage 00: Pre-flight checks passed successfully."
+83
View File
@@ -0,0 +1,83 @@
#!/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"
source "$SCRIPT_DIR/lib/btrfs.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 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. Enable 32-bit (i386) Multiarch Architecture
log_substep "Enabling 32-bit (i386) multiarch architecture..."
apt_enable_i386
# 3. Ensure Keyrings directory exists and install repository keyrings
apt_ensure_keyrings_dir
log_substep "Installing custom repository keyrings..."
apt_add_keyring_from_url "https://gitea.creative-dragonslayer.de/api/packages/Linuxapps/debian/repository.key" "gitea-Linuxapps.asc" || log_warn "Could not fetch gitea-Linuxapps.asc keyring."
apt_add_keyring_from_url "https://gitea.creative-dragonslayer.de/api/packages/Mirror/debian/repository.key" "gitea-Mirror.asc" || log_warn "Could not fetch gitea-Mirror.asc keyring."
# 4. 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 Deb822 sources
log_substep "Deploying Deb822 APT sources..."
if compgen -G "$SCRIPT_DIR/data/apt/sources.list.d/*.sources" > /dev/null; then
for src_file in "$SCRIPT_DIR"/data/apt/sources.list.d/*.sources; do
if [[ "$(basename "$src_file")" != "xanmod.sources" ]]; then
apt_install_sources_file "$src_file" "$(basename "$src_file")"
fi
done
fi
# 5. 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
# 6. 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
# 7. Perform Full Dist-Upgrade
log_substep "Performing full distribution upgrade to Debian Sid..."
create_timeshift_snapshot "Stage 01: Pre-dist-upgrade to Debian Sid" "B"
apt_dist_upgrade
create_timeshift_snapshot "Stage 01: Post-dist-upgrade to Debian Sid" "O"
log_success "Stage 01: Debian Unstable migration and upgrade completed successfully!"
+125
View File
@@ -0,0 +1,125 @@
#!/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"
source "$SCRIPT_DIR/lib/btrfs.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..."
create_timeshift_snapshot "Stage 02: Pre-XanMod kernel installation" "B"
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
create_timeshift_snapshot "Stage 02: Post-kernel and hardware tuning" "O"
log_success "Stage 02: Kernel and Hardware Tuning completed successfully!"
+122
View File
@@ -0,0 +1,122 @@
#!/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"
source "$SCRIPT_DIR/lib/btrfs.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:-5}"
GRUB_TIMEOUT_STYLE="${GRUB_TIMEOUT_STYLE:-menu}"
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. Configure GRUB Btrfs Snapshot Booting (grub-btrfs)
log_substep "Configuring GRUB Btrfs snapshot booting support..."
if is_root_btrfs; then
ensure_grub_btrfs
log_success "GRUB Btrfs snapshot booting configured."
else
log_info "Root filesystem is not Btrfs. Skipping grub-btrfs setup."
fi
# 6. 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!"
+60
View File
@@ -0,0 +1,60 @@
#!/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"
source "$SCRIPT_DIR/lib/btrfs.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 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
create_timeshift_snapshot "Stage 04: Pre-thematic package installation" "B"
# 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 "Ensuring 32-bit (i386) multiarch architecture is enabled..."
apt_enable_i386
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
create_timeshift_snapshot "Stage 04: Post-thematic package installation" "O"
log_success "Stage 04: Thematic package installation completed successfully!"
+74
View File
@@ -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
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!"
+167
View File
@@ -0,0 +1,167 @@
#!/usr/bin/env bash
# ==============================================================================
# stages/06-services.sh - System services activation (AppArmor, Docker, Libvirt, zram, Ollama)
# ==============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "$SCRIPT_DIR/lib/utils.sh"
source "$SCRIPT_DIR/lib/apt.sh"
source "$SCRIPT_DIR/lib/btrfs.sh"
source "$SCRIPT_DIR/lib/network.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 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="trixie"
if [[ -f /etc/os-release ]]; then
# shellcheck source=/dev/null
source /etc/os-release
DEBIAN_CODENAME="${VERSION_CODENAME:-trixie}"
# 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 <<EOF > /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. Ollama AI Service & Configuration
log_substep "Configuring Ollama AI Service..."
OLLAMA_MODELS_DIR="$(prompt_ollama_models_path)"
log_info "Ollama models directory set to: $OLLAMA_MODELS_DIR"
mkdir -p "$OLLAMA_MODELS_DIR"
log_substep "Installing / Updating Ollama..."
if curl -fsSL https://ollama.com/install.sh | sh; then
log_success "Ollama installation completed."
else
log_warn "Ollama installation script returned a non-zero exit code."
fi
# Ensure permissions on models directory for ollama user
if id ollama >/dev/null 2>&1; then
chown -R ollama:ollama "$OLLAMA_MODELS_DIR" 2>/dev/null || true
chmod -R 775 "$OLLAMA_MODELS_DIR" 2>/dev/null || true
fi
# Configure systemd drop-in override for Ollama service
log_substep "Configuring systemd override for Ollama service..."
mkdir -p /etc/systemd/system/ollama.service.d
cat <<EOF > /etc/systemd/system/ollama.service.d/override.conf
[Service]
Environment="OLLAMA_MODELS=$OLLAMA_MODELS_DIR"
Environment="OLLAMA_FLASH_ATTENTION=${OLLAMA_FLASH_ATTENTION:-1}"
Environment="OLLAMA_KV_CACHE_TYPE=${OLLAMA_KV_CACHE_TYPE:-q8_0}"
Environment="OLLAMA_KEEP_ALIVE=${OLLAMA_KEEP_ALIVE:-30m}"
EOF
chmod 0644 /etc/systemd/system/ollama.service.d/override.conf
if command_exists systemctl; then
systemctl daemon-reload 2>/dev/null || true
systemctl enable --now ollama.service 2>/dev/null || true
systemctl restart ollama.service 2>/dev/null || true
log_success "Ollama systemd service configured and enabled."
fi
# 6. Timeshift Boot Snapshot Service, APT Update Hook & GRUB Btrfs Daemon (if on Btrfs)
log_substep "Configuring Timeshift Boot Snapshot Service, APT Update Hook and GRUB Btrfs Snapshot Daemon..."
if command_exists timeshift && is_root_btrfs; then
ensure_timeshift_btrfs_config
ensure_grub_btrfs
log_success "Timeshift and GRUB Btrfs snapshot services configured and enabled."
elif is_root_btrfs; then
ensure_grub_btrfs
log_info "Timeshift will be configured when installed; grub-btrfs configured."
fi
# 7. Network Configuration & Services (Loopback, LAN, NetworkManager)
log_substep "Configuring and activating network interfaces (Loopback, all LAN interfaces, NetworkManager)..."
configure_network_all
# 8. User Group Memberships
log_substep "Updating user group memberships for $TARGET_USER..."
groupadd -f sudo
groupadd -f docker
groupadd -f netdev
groupadd -f ollama 2>/dev/null || true
usermod -aG sudo,docker,netdev "$TARGET_USER"
if getent group ollama >/dev/null 2>&1; then
usermod -aG ollama "$TARGET_USER" 2>/dev/null || true
fi
log_success "Target user $TARGET_USER added to sudo, docker, netdev and ollama groups."
log_success "Stage 06: System services configuration completed successfully!"
+152
View File
@@ -0,0 +1,152 @@
#!/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 /etc/skel/.junie/skills
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
if [[ -d "$SCRIPT_DIR/data/skel/.config" ]]; then
mkdir -p /etc/skel/.config
cp -r "$SCRIPT_DIR"/data/skel/.config/* /etc/skel/.config/ 2>/dev/null || true
if [[ -d /etc/skel/.config/hypr/scripts ]]; then
chmod 0755 /etc/skel/.config/hypr/scripts/*.sh 2>/dev/null || true
fi
fi
# Provision Oh-My-Zsh template in /etc/skel so newly created users receive it automatically
if command_exists git; then
if [[ ! -d /etc/skel/.oh-my-zsh ]]; then
log_info "Provisioning Oh-My-Zsh template in /etc/skel/.oh-my-zsh..."
git clone --depth=1 https://github.com/ohmyzsh/ohmyzsh.git /etc/skel/.oh-my-zsh 2>/dev/null || log_warn "Could not clone Oh-My-Zsh into /etc/skel."
fi
if [[ -d /etc/skel/.oh-my-zsh ]]; then
mkdir -p /etc/skel/.oh-my-zsh/custom/plugins
[[ -d /etc/skel/.oh-my-zsh/custom/plugins/zsh-autosuggestions ]] || \
git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions /etc/skel/.oh-my-zsh/custom/plugins/zsh-autosuggestions 2>/dev/null || true
[[ -d /etc/skel/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting ]] || \
git clone --depth=1 https://github.com/zsh-users/zsh-syntax-highlighting /etc/skel/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting 2>/dev/null || true
fi
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" "$TARGET_HOME/.config" "$TARGET_HOME/.junie/skills"
# 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
# Backup existing Hyprland config if present
if [[ -f "$TARGET_HOME/.config/hypr/hyprland.conf" ]]; then
backup_file_or_dir "$TARGET_HOME/.config/hypr/hyprland.conf"
fi
if [[ -d "$SCRIPT_DIR/data/skel/.config" ]]; then
cp -r "$SCRIPT_DIR"/data/skel/.config/* "$TARGET_HOME/.config/" 2>/dev/null || true
if [[ -d "$TARGET_HOME/.config/hypr/scripts" ]]; then
chmod 0755 "$TARGET_HOME"/.config/hypr/scripts/*.sh 2>/dev/null || true
fi
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 [[ -d /etc/skel/.oh-my-zsh ]]; then
cp -r /etc/skel/.oh-my-zsh "$TARGET_HOME/.oh-my-zsh"
elif 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
if [[ -d "$TARGET_HOME/.oh-my-zsh" ]]; then
mkdir -p "$TARGET_HOME/.oh-my-zsh/custom/plugins"
if [[ ! -d "$TARGET_HOME/.oh-my-zsh/custom/plugins/zsh-autosuggestions" ]] && command_exists git; then
run_as_target_user git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions "$TARGET_HOME/.oh-my-zsh/custom/plugins/zsh-autosuggestions" 2>/dev/null || true
fi
if [[ ! -d "$TARGET_HOME/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting" ]] && command_exists git; then
run_as_target_user git clone --depth=1 https://github.com/zsh-users/zsh-syntax-highlighting "$TARGET_HOME/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting" 2>/dev/null || true
fi
fi
# Fix ownership
chown -R "$TARGET_USER:$TARGET_USER" "$TARGET_HOME/.zshrc" "$TARGET_HOME/Templates" "$TARGET_HOME/.config" "$TARGET_HOME/.junie"
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
# Configure default shell for newly created users
if command_exists useradd; then
useradd -D -s "$ZSH_BIN" 2>/dev/null || true
fi
if [[ -f /etc/adduser.conf ]]; then
sed -i -E 's|^#?\s*DSHELL=.*|DSHELL='"$ZSH_BIN"'|' /etc/adduser.conf 2>/dev/null || true
fi
else
log_warn "Zsh binary not found at $ZSH_BIN. Skipping chsh."
fi
log_success "Stage 07: Skel & userland configuration completed successfully!"
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env bash
# ==============================================================================
# stages/08-flatpaks.sh - Flathub repository setup & Flatpak package installation
# ==============================================================================
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 & Flathub Repository Setup"
require_root
TARGET_USER="$(get_target_user)"
# 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
log_success "Stage 08: Flatpaks and Flathub repository setup completed successfully!"
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env bash
# ==============================================================================
# stages/09-apps.sh - Spotify, Waydroid, OpenDeck, custom desktop apps & 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 09: Standalone Applications, Integrations & MIME Associations"
require_root
TARGET_USER="$(get_target_user)"
# 1. Spotify Client Installation (Debian APT repo)
log_substep "Configuring Spotify repository and client..."
if apt_add_keyring_from_url "https://download.spotify.com/debian/pubkey_5384CE82BA52C83A.asc" "spotify.gpg"; then
cat <<EOF > /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
# 2. 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
# 3. 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
# 4. OpenDeck Installation
log_substep "Installing / Updating OpenDeck..."
if curl -sSL https://raw.githubusercontent.com/nekename/OpenDeck/main/install_opendeck.sh | bash; then
log_success "OpenDeck installation completed."
else
log_warn "OpenDeck installation script returned a non-zero exit code."
fi
# 5. 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 09: Standalone Applications, Integrations and MIME associations completed successfully!"
+81
View File
@@ -0,0 +1,81 @@
#!/usr/bin/env bash
# ==============================================================================
# stages/10-hyprland.sh - LinuxBeginnings Debian-Hyprland auto-installer & desktop setup
# ==============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# shellcheck source=lib/utils.sh
source "$SCRIPT_DIR/lib/utils.sh"
source "$SCRIPT_DIR/lib/btrfs.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 10: Hyprland Desktop (LinuxBeginnings Debian-Hyprland 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)"
# 1. Execute LinuxBeginnings Debian-Hyprland installer
log_substep "Downloading and executing LinuxBeginnings Debian-Hyprland installer..."
create_timeshift_snapshot "Stage 10: Pre-Hyprland desktop installation" "B"
if command_exists curl; then
log_info "Running Debian-Hyprland installer as target user '$TARGET_USER'..."
if run_as_target_user bash -c 'sh <(curl -L https://raw.githubusercontent.com/LinuxBeginnings/Debian-Hyprland/main/auto-install.sh)'; then
log_success "LinuxBeginnings Debian-Hyprland installation completed successfully."
else
log_warn "LinuxBeginnings installer exited with non-zero status. Check logs if needed."
fi
else
log_error "curl is required to download Debian-Hyprland installer."
exit 1
fi
# 2. Ensure rudimentary Hyprland config is deployed to /etc/skel
log_substep "Deploying rudimentary Hyprland configuration to /etc/skel..."
mkdir -p /etc/skel/.config/hypr/scripts
if [[ -f "$SCRIPT_DIR/data/skel/.config/hypr/hyprland.conf" ]]; then
cp "$SCRIPT_DIR/data/skel/.config/hypr/hyprland.conf" /etc/skel/.config/hypr/hyprland.conf
fi
if [[ -f "$SCRIPT_DIR/data/skel/.config/hypr/scripts/install-dots-prompt.sh" ]]; then
cp "$SCRIPT_DIR/data/skel/.config/hypr/scripts/install-dots-prompt.sh" /etc/skel/.config/hypr/scripts/install-dots-prompt.sh
chmod 0755 /etc/skel/.config/hypr/scripts/install-dots-prompt.sh
fi
chown -R root:root /etc/skel/.config
# 3. Deploy rudimentary Hyprland config to target user
log_substep "Deploying rudimentary Hyprland configuration to $TARGET_HOME/.config/hypr..."
mkdir -p "$TARGET_HOME/.config/hypr/scripts"
if [[ -f "$TARGET_HOME/.config/hypr/hyprland.conf" ]]; then
backup_file_or_dir "$TARGET_HOME/.config/hypr/hyprland.conf"
fi
if [[ -f "$SCRIPT_DIR/data/skel/.config/hypr/hyprland.conf" ]]; then
cp "$SCRIPT_DIR/data/skel/.config/hypr/hyprland.conf" "$TARGET_HOME/.config/hypr/hyprland.conf"
fi
if [[ -f "$SCRIPT_DIR/data/skel/.config/hypr/scripts/install-dots-prompt.sh" ]]; then
cp "$SCRIPT_DIR/data/skel/.config/hypr/scripts/install-dots-prompt.sh" "$TARGET_HOME/.config/hypr/scripts/install-dots-prompt.sh"
chmod 0755 "$TARGET_HOME/.config/hypr/scripts/install-dots-prompt.sh"
fi
chown -R "$TARGET_USER:$TARGET_USER" "$TARGET_HOME/.config/hypr"
log_success "Rudimentary Hyprland configuration deployed:"
log_info " - SUPER+ENTER: Kitty Terminal"
log_info " - SUPER+Q: Close Active Window"
log_info " - Login Prompt: Asks user after login to choose Dotfiles setup & installs JetBrains Junie CLI + AwesomeJunieSkills"
create_timeshift_snapshot "Stage 10: Post-Hyprland desktop setup" "O"
log_success "Stage 10: Hyprland Desktop installation & configuration completed successfully!"