395 lines
11 KiB
Bash
Executable file
395 lines
11 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
REPO_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
CONFIG_DIR="$HOME/.config"
|
|
APP_DIR="$CONFIG_DIR/hypr-nepharius"
|
|
|
|
log() {
|
|
printf '\n==> %s\n' "$1"
|
|
}
|
|
|
|
warn_overwrite() {
|
|
cat <<'MSG'
|
|
Achtung: Dieses Setup überschreibt bestehende Desktop-Konfigurationen in ~/.config.
|
|
Aktuell ist das bewusst so, damit unser Stand auf dem Testsystem sauber und reproduzierbar landet.
|
|
Bitte starte das Script normal als User, nicht mit sudo. Einzelne Root-Schritte werden intern per sudo ausgeführt.
|
|
|
|
Temporär enthält der Installer auch einen Cleanup-Block für alte Caelestia-/Quickshell-Reste.
|
|
Den räumen wir wieder raus, sobald unsere Middleware-/Shell-Entscheidung final ist.
|
|
MSG
|
|
}
|
|
|
|
require_cmd() {
|
|
command -v "$1" >/dev/null 2>&1 || {
|
|
echo "Fehlt: $1" >&2
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
ensure_not_root() {
|
|
if [[ ${EUID:-$(id -u)} -eq 0 ]]; then
|
|
echo "Bitte ./install.sh nicht als root ausführen. Starte es als normaler User, sudo wird intern verwendet." >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
ensure_core_dependencies() {
|
|
log "[1/7] Prüfe Basis-Abhängigkeiten"
|
|
|
|
if ! command -v pacman >/dev/null 2>&1; then
|
|
echo "Dieses Install-Script ist aktuell für Arch Linux / pacman gedacht." >&2
|
|
exit 1
|
|
fi
|
|
|
|
local missing=()
|
|
for cmd in git curl bash; do
|
|
if ! command -v "$cmd" >/dev/null 2>&1; then
|
|
missing+=("$cmd")
|
|
fi
|
|
done
|
|
|
|
if (( ${#missing[@]} > 0 )); then
|
|
log "Installiere fehlende Basis-Abhängigkeiten: ${missing[*]}"
|
|
sudo pacman -Sy --needed --noconfirm "${missing[@]}"
|
|
else
|
|
log "Keine fehlenden Basis-Abhängigkeiten"
|
|
fi
|
|
}
|
|
|
|
ensure_yay() {
|
|
log "[2/7] Prüfe yay"
|
|
|
|
if command -v yay >/dev/null 2>&1; then
|
|
log "yay bereits vorhanden"
|
|
return
|
|
fi
|
|
|
|
log "yay fehlt, installiere yay"
|
|
sudo pacman -Sy --needed --noconfirm base-devel
|
|
|
|
local tmpdir
|
|
tmpdir="$(mktemp -d)"
|
|
trap 'rm -rf "$tmpdir"' RETURN
|
|
|
|
git clone https://aur.archlinux.org/yay.git "$tmpdir/yay"
|
|
cd "$tmpdir/yay"
|
|
makepkg -si --noconfirm
|
|
cd "$REPO_DIR"
|
|
log "yay wurde installiert"
|
|
}
|
|
|
|
install_arch_packages() {
|
|
require_cmd pacman
|
|
log "[3/10] Installiere Arch-Pakete"
|
|
|
|
if [[ ! -f "$REPO_DIR/packages/arch.txt" ]]; then
|
|
log "Keine arch.txt gefunden, überspringe"
|
|
return
|
|
fi
|
|
|
|
mapfile -t packages < <(grep -v '^\s*$' "$REPO_DIR/packages/arch.txt")
|
|
|
|
if (( ${#packages[@]} == 0 )); then
|
|
log "Keine Arch-Pakete definiert, überspringe"
|
|
return
|
|
fi
|
|
|
|
local kernel_headers=()
|
|
if pacman -Qq linux >/dev/null 2>&1; then
|
|
kernel_headers+=(linux-headers)
|
|
fi
|
|
if pacman -Qq linux-lts >/dev/null 2>&1; then
|
|
kernel_headers+=(linux-lts-headers)
|
|
fi
|
|
if pacman -Qq linux-zen >/dev/null 2>&1; then
|
|
kernel_headers+=(linux-zen-headers)
|
|
fi
|
|
if pacman -Qq linux-hardened >/dev/null 2>&1; then
|
|
kernel_headers+=(linux-hardened-headers)
|
|
fi
|
|
|
|
if (( ${#kernel_headers[@]} > 0 )); then
|
|
log "Erkannte Kernel-Header: ${kernel_headers[*]}"
|
|
packages+=("${kernel_headers[@]}")
|
|
else
|
|
log "Keine bekannten Arch-Kernel erkannt, Header-Ergänzung übersprungen"
|
|
fi
|
|
|
|
log "Arch-Pakete: ${#packages[@]} Einträge"
|
|
if sudo pacman -S --needed --noconfirm "${packages[@]}"; then
|
|
log "Arch-Pakete fertig"
|
|
else
|
|
status=$?
|
|
echo "pacman Exit-Code: $status" >&2
|
|
exit "$status"
|
|
fi
|
|
}
|
|
|
|
install_aur_packages() {
|
|
log "[4/10] Installiere AUR-Pakete"
|
|
|
|
if [[ ! -f "$REPO_DIR/packages/aur.txt" ]]; then
|
|
log "Keine aur.txt gefunden, überspringe"
|
|
return
|
|
fi
|
|
|
|
mapfile -t aur_packages < <(grep -v '^\s*$' "$REPO_DIR/packages/aur.txt")
|
|
|
|
if (( ${#aur_packages[@]} == 0 )); then
|
|
log "Keine AUR-Pakete definiert, überspringe"
|
|
return
|
|
fi
|
|
|
|
if [[ ${EUID:-$(id -u)} -eq 0 ]]; then
|
|
echo "AUR-Pakete dürfen nicht als root gebaut werden." >&2
|
|
exit 1
|
|
fi
|
|
|
|
log "AUR-Pakete: ${#aur_packages[@]} Einträge"
|
|
if yay -S --needed --noconfirm --answerclean None --answerdiff None --removemake "${aur_packages[@]}"; then
|
|
log "AUR-Pakete fertig"
|
|
else
|
|
status=$?
|
|
echo "yay Exit-Code: $status" >&2
|
|
if [[ $status -eq 10 ]]; then
|
|
echo "Hinweis: Exit-Code 10 bedeutet hier sehr wahrscheinlich, dass ein AUR-Build als root lief oder makepkg aus einem sudo/root-Kontext gestartet wurde." >&2
|
|
echo "Bitte install.sh als normaler User starten, nicht mit sudo." >&2
|
|
fi
|
|
exit "$status"
|
|
fi
|
|
}
|
|
|
|
prompt_yes_no() {
|
|
local prompt="$1"
|
|
local reply
|
|
read -r -p "$prompt [y/N]: " reply || true
|
|
[[ "$reply" =~ ^([yY][eE][sS]|[yY])$ ]]
|
|
}
|
|
|
|
install_optional_pacman_group() {
|
|
local label="$1"
|
|
local file="$2"
|
|
|
|
if [[ ! -f "$file" ]]; then
|
|
return 1
|
|
fi
|
|
|
|
mapfile -t packages < <(grep -v '^\s*$' "$file")
|
|
if (( ${#packages[@]} == 0 )); then
|
|
return 1
|
|
fi
|
|
|
|
if prompt_yes_no "Optionale Pacman-Gruppe installieren: ${label}?"; then
|
|
log "Installiere optionale Pacman-Gruppe: ${label}"
|
|
sudo pacman -S --needed --noconfirm "${packages[@]}"
|
|
return 0
|
|
else
|
|
log "Überspringe optionale Pacman-Gruppe: ${label}"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
install_optional_aur_group() {
|
|
local label="$1"
|
|
local file="$2"
|
|
|
|
if [[ ! -f "$file" ]]; then
|
|
return 1
|
|
fi
|
|
|
|
mapfile -t packages < <(grep -v '^\s*$' "$file")
|
|
if (( ${#packages[@]} == 0 )); then
|
|
return 1
|
|
fi
|
|
|
|
if prompt_yes_no "Optionale AUR-Gruppe installieren: ${label}?"; then
|
|
log "Installiere optionale AUR-Gruppe: ${label}"
|
|
yay -S --needed --noconfirm --answerclean None --answerdiff None --removemake "${packages[@]}"
|
|
return 0
|
|
else
|
|
log "Überspringe optionale AUR-Gruppe: ${label}"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
setup_optional_dev_ai() {
|
|
if ! prompt_yes_no "Optionales Dev/AI Bundle (OpenCode + Ollama) installieren?"; then
|
|
log "Überspringe optionales Dev-AI Setup"
|
|
return
|
|
fi
|
|
|
|
if ! install_optional_pacman_group "Dev/AI" "$REPO_DIR/packages/optional-arch-dev-ai.txt"; then
|
|
log "Pacman-Dev/AI nicht installiert oder fehlgeschlagen, versuche AUR-Fallback falls konfiguriert"
|
|
install_optional_aur_group "Dev/AI Fallback" "$REPO_DIR/packages/optional-aur-dev-ai.txt" || true
|
|
fi
|
|
|
|
if command -v systemctl >/dev/null 2>&1; then
|
|
sudo systemctl enable --now ollama.service >/dev/null 2>&1 || true
|
|
fi
|
|
|
|
if [ -x "$REPO_DIR/scripts/setup-opencode-ollama.sh" ]; then
|
|
"$REPO_DIR/scripts/setup-opencode-ollama.sh" || true
|
|
fi
|
|
|
|
if command -v ollama >/dev/null 2>&1; then
|
|
if prompt_yes_no "Ollama Cloud Login jetzt ausführen?"; then
|
|
ollama signin || true
|
|
fi
|
|
|
|
if prompt_yes_no "Empfohlene Coding-Modelle jetzt per ollama pull laden?"; then
|
|
ollama pull qwen2.5-coder:14b || true
|
|
ollama pull qwen2.5-coder:32b || true
|
|
ollama pull qwen2.5:14b-instruct || true
|
|
fi
|
|
fi
|
|
}
|
|
|
|
install_optional_packages() {
|
|
log "[5/10] Optionale Softwarepakete"
|
|
install_optional_pacman_group "Gaming" "$REPO_DIR/packages/optional-arch-gaming.txt"
|
|
install_optional_pacman_group "Apps" "$REPO_DIR/packages/optional-arch-apps.txt"
|
|
install_optional_aur_group "Gaming" "$REPO_DIR/packages/optional-aur-gaming.txt"
|
|
install_optional_aur_group "Apps" "$REPO_DIR/packages/optional-aur-apps.txt"
|
|
setup_optional_dev_ai
|
|
}
|
|
|
|
copy_dir() {
|
|
local src="$1"
|
|
local dest="$2"
|
|
mkdir -p "$(dirname "$dest")"
|
|
rm -rf "$dest"
|
|
cp -r "$src" "$dest"
|
|
}
|
|
|
|
ensure_icon_theme_available() {
|
|
log "[5/10] Prüfe GTK/Icon-Theme-Verfügbarkeit"
|
|
|
|
local icon_themes=("Tela-circle-green-dark" "Tela-circle-green" "Tela-green-dark" "Papirus-Dark" "Adwaita")
|
|
local icon_theme
|
|
for icon_theme in "${icon_themes[@]}"; do
|
|
if find /usr/share/icons "$HOME/.local/share/icons" -maxdepth 1 -mindepth 1 -type d 2>/dev/null | grep -q "/${icon_theme}$"; then
|
|
log "Icon-Theme gefunden: ${icon_theme}"
|
|
return
|
|
fi
|
|
done
|
|
|
|
echo "Fehler: Keines der erwarteten Icon-Themes wurde nach der Paketinstallation gefunden." >&2
|
|
echo "Geprüft: ${icon_themes[*]}" >&2
|
|
echo "Bitte prüfe, ob das gewünschte Tela/Papirus-Theme auf dem Zielsystem wirklich verfügbar/installierbar ist." >&2
|
|
exit 1
|
|
}
|
|
|
|
cleanup_old_shells() {
|
|
log "[6/10] Räume alte Shell-/Middleware-Reste weg (temporär)"
|
|
sudo pacman -Rns --noconfirm caelestia-shell caelestia-cli quickshell-git >/dev/null 2>&1 || true
|
|
rm -rf "$HOME/.config/caelestia" "$HOME/.local/state/caelestia"
|
|
log "Temporärer Cleanup fertig"
|
|
}
|
|
|
|
install_configs() {
|
|
log "[7/10] Kopiere Konfigurationen frisch nach ~/.config"
|
|
for dir in hypr hyprmod caelestia kitty mako launcher waybar kanshi; do
|
|
if [ -d "$REPO_DIR/config/$dir" ]; then
|
|
copy_dir "$REPO_DIR/config/$dir" "$CONFIG_DIR/$dir"
|
|
echo " copied: ~/.config/$dir"
|
|
else
|
|
echo " missing in repo: config/$dir"
|
|
fi
|
|
done
|
|
|
|
if [ -d "$REPO_DIR/config/gtk-3.0" ]; then
|
|
copy_dir "$REPO_DIR/config/gtk-3.0" "$CONFIG_DIR/gtk-3.0"
|
|
echo " copied: ~/.config/gtk-3.0"
|
|
else
|
|
echo " missing in repo: config/gtk-3.0"
|
|
fi
|
|
|
|
if [ -d "$REPO_DIR/config/gtk-4.0" ]; then
|
|
copy_dir "$REPO_DIR/config/gtk-4.0" "$CONFIG_DIR/gtk-4.0"
|
|
echo " copied: ~/.config/gtk-4.0"
|
|
else
|
|
echo " missing in repo: config/gtk-4.0"
|
|
fi
|
|
|
|
if [ -d "$REPO_DIR/config/sddm/theme/forest-cyber" ]; then
|
|
sudo mkdir -p /usr/share/sddm/themes/forest-cyber
|
|
sudo cp -r "$REPO_DIR/config/sddm/theme/forest-cyber/." /usr/share/sddm/themes/forest-cyber/
|
|
echo " copied: /usr/share/sddm/themes/forest-cyber"
|
|
else
|
|
echo " missing in repo: config/sddm/theme/forest-cyber"
|
|
fi
|
|
|
|
if [ -f "$REPO_DIR/config/sddm.conf" ]; then
|
|
sudo mkdir -p /etc
|
|
sudo cp "$REPO_DIR/config/sddm.conf" /etc/sddm.conf
|
|
echo " copied: /etc/sddm.conf"
|
|
else
|
|
echo " missing in repo: config/sddm.conf"
|
|
fi
|
|
|
|
mkdir -p "$APP_DIR"
|
|
copy_dir "$REPO_DIR/scripts" "$APP_DIR/scripts"
|
|
copy_dir "$REPO_DIR/wallpapers" "$APP_DIR/wallpapers"
|
|
if [ -f "$REPO_DIR/config/.gtkrc-2.0" ]; then
|
|
cp "$REPO_DIR/config/.gtkrc-2.0" "$HOME/.gtkrc-2.0"
|
|
echo " copied: ~/.gtkrc-2.0"
|
|
fi
|
|
echo " copied: ~/.config/hypr-nepharius/scripts"
|
|
echo " copied: ~/.config/hypr-nepharius/wallpapers"
|
|
|
|
if [ -x "$APP_DIR/scripts/apply-gtk-theme.sh" ]; then
|
|
"$APP_DIR/scripts/apply-gtk-theme.sh"
|
|
echo " applied: GTK theme settings"
|
|
else
|
|
echo " skipped: GTK theme apply script missing or not executable"
|
|
fi
|
|
|
|
log "Config-Copy fertig"
|
|
}
|
|
|
|
enable_services() {
|
|
log "[8/10] Aktiviere wichtige Services"
|
|
sudo systemctl enable "hhd@${USER}.service" || true
|
|
sudo systemctl enable sddm.service || true
|
|
log "Service-Aktivierung fertig"
|
|
}
|
|
|
|
print_summary() {
|
|
log "[9/10] Installationszusammenfassung"
|
|
echo "- Pakete installiert: arch + aur"
|
|
echo "- Configs kopiert nach ~/.config"
|
|
echo "- Scripts/Wallpapers kopiert nach ~/.config/hypr-nepharius"
|
|
echo "- SDDM und hhd@${USER}.service aktiviert"
|
|
echo "- Sichtbare Module aktuell: Hyprland, Kitty, Mako, Rofi, Hyprlock, Wallpaper-Menü, Waybar"
|
|
echo "- Temporärer Cleanup aktiv: Caelestia/Quickshell-Reste werden entfernt"
|
|
echo "- Vorbereitete Module: Hyprmod, forest-cyber SDDM Theme, Plymouth Theme"
|
|
}
|
|
|
|
reload_hyprland() {
|
|
log "[10/10] Lade Hyprland neu, falls aktiv"
|
|
if command -v hyprctl >/dev/null 2>&1 && [[ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]]; then
|
|
hyprctl reload && log "Hyprland wurde neu geladen"
|
|
else
|
|
log "Hyprland läuft gerade nicht in dieser Shell, Reload übersprungen"
|
|
fi
|
|
}
|
|
|
|
main() {
|
|
warn_overwrite
|
|
ensure_not_root
|
|
ensure_core_dependencies
|
|
ensure_yay
|
|
install_arch_packages
|
|
install_aur_packages
|
|
install_optional_packages
|
|
ensure_icon_theme_available
|
|
cleanup_old_shells
|
|
install_configs
|
|
enable_services
|
|
print_summary
|
|
reload_hyprland
|
|
log "Fertig. Falls nötig bitte Session einmal neu starten."
|
|
}
|
|
|
|
main "$@"
|