From 3d5e464392d4dc00480332df56a811ab6026b428 Mon Sep 17 00:00:00 2001 From: mboehmlaender Date: Sat, 14 Mar 2026 08:46:45 +0000 Subject: [PATCH] chore: remove local installer scripts from repo --- install-dev.sh | 960 ------------------------------------------------- install.sh | 761 --------------------------------------- setup.sh | 154 -------- 3 files changed, 1875 deletions(-) delete mode 100755 install-dev.sh delete mode 100755 install.sh delete mode 100755 setup.sh diff --git a/install-dev.sh b/install-dev.sh deleted file mode 100755 index 4de8f13..0000000 --- a/install-dev.sh +++ /dev/null @@ -1,960 +0,0 @@ -#!/usr/bin/env bash -# ============================================================================= -# Ripster – Installationsskript -# Unterstützt: Debian 11/12, Ubuntu 22.04/24.04 -# Benötigt: sudo / root -# -# Verwendung: -# chmod +x install.sh -# sudo ./install.sh [Optionen] -# -# Optionen: -# --dir Installationsverzeichnis (Standard: /opt/ripster) -# --user Systembenutzer für den Dienst (Standard: ripster) -# --port Backend-Port (Standard: 3001) -# --host Hostname/IP für die Weboberfläche (Standard: Maschinen-IP) -# --no-makemkv MakeMKV-Installation überspringen -# --no-handbrake HandBrake-Installation überspringen -# --build-handbrake HandBrake aus Quellcode mit NVDEC-Unterstützung bauen -# --handbrake-version HandBrake-Version für Source-Build (Standard: 1.9.0) -# --handbrake-update-policy -# Bei NVDEC-Self-Build: bei neuer Git-Release behalten, -# nachfragen oder direkt neu bauen (Standard: keep) -# --no-nginx Nginx-Einrichtung überspringen (Frontend läuft dann auf Port 5173) -# --reinstall Vorhandene Installation ersetzen (Daten bleiben erhalten) -# -h, --help Diese Hilfe anzeigen -# ============================================================================= -set -euo pipefail - -# --- Farben ------------------------------------------------------------------- -RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' -BLUE='\033[0;34m'; BOLD='\033[1m'; RESET='\033[0m' - -info() { echo -e "${BLUE}[INFO]${RESET} $*"; } -ok() { echo -e "${GREEN}[OK]${RESET} $*"; } -warn() { echo -e "${YELLOW}[WARN]${RESET} $*"; } -error() { echo -e "${RED}[FEHLER]${RESET} $*" >&2; } -header() { echo -e "\n${BOLD}${BLUE}══════════════════════════════════════════${RESET}"; \ - echo -e "${BOLD} $*${RESET}"; \ - echo -e "${BOLD}${BLUE}══════════════════════════════════════════${RESET}"; } -fatal() { error "$*"; exit 1; } - -# --- Standard-Optionen -------------------------------------------------------- -INSTALL_DIR="/opt/ripster" -SERVICE_USER="ripster" -BACKEND_PORT="3001" -FRONTEND_HOST="" # wird automatisch ermittelt, wenn leer -SKIP_MAKEMKV=false -SKIP_HANDBRAKE=false -BUILD_HANDBRAKE_NVDEC=false -HANDBRAKE_MODE_SELECTED=false -HANDBRAKE_VERSION="1.9.0" -HANDBRAKE_UPDATE_POLICY="keep" -HANDBRAKE_UPDATE_POLICY_SELECTED=false -SKIP_NGINX=false -REINSTALL=false -SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -HANDBRAKE_SELFBUILD_MARKER="/usr/local/share/ripster/handbrake-selfbuild.env" - -# --- Argumente parsen --------------------------------------------------------- -while [[ $# -gt 0 ]]; do - case "$1" in - --dir) INSTALL_DIR="$2"; shift 2 ;; - --user) SERVICE_USER="$2"; shift 2 ;; - --port) BACKEND_PORT="$2"; shift 2 ;; - --host) FRONTEND_HOST="$2"; shift 2 ;; - --no-makemkv) SKIP_MAKEMKV=true; shift ;; - --no-handbrake) SKIP_HANDBRAKE=true; shift ;; - --build-handbrake) BUILD_HANDBRAKE_NVDEC=true; HANDBRAKE_MODE_SELECTED=true; shift ;; - --handbrake-version) HANDBRAKE_VERSION="$2"; shift 2 ;; - --handbrake-update-policy) - case "$2" in - keep|prompt|build) HANDBRAKE_UPDATE_POLICY="$2"; HANDBRAKE_UPDATE_POLICY_SELECTED=true ;; - *) fatal "Ungültige --handbrake-update-policy: $2 (erlaubt: keep|prompt|build)" ;; - esac - shift 2 ;; - --no-nginx) SKIP_NGINX=true; shift ;; - --reinstall) REINSTALL=true; shift ;; - -h|--help) - sed -n '/^# Verwendung/,/^# ====/p' "$0" | head -n -1 | sed 's/^# \?//' - exit 0 ;; - *) fatal "Unbekannte Option: $1" ;; - esac -done - -# --- Voraussetzungen prüfen --------------------------------------------------- -header "Ripster Installationsskript" - -if [[ $EUID -ne 0 ]]; then - fatal "Dieses Skript muss als root ausgeführt werden (sudo ./install.sh)" -fi - -# OS-Erkennung -if [[ ! -f /etc/os-release ]]; then - fatal "Betriebssystem nicht erkennbar. Nur Debian/Ubuntu wird unterstützt." -fi -. /etc/os-release -case "$ID" in - debian|ubuntu|linuxmint|pop) ok "Betriebssystem: $PRETTY_NAME" ;; - *) fatal "Nicht unterstütztes OS: $ID. Nur Debian/Ubuntu unterstützt." ;; -esac - -# Host-IP ermitteln -if [[ -z "$FRONTEND_HOST" ]]; then - FRONTEND_HOST=$(hostname -I | awk '{print $1}') - info "Erkannte IP: $FRONTEND_HOST" -fi - -# Quelldirectory prüfen -[[ -f "$SOURCE_DIR/backend/package.json" ]] || \ - fatal "Ripster-Quellen nicht gefunden in: $SOURCE_DIR" - -info "Quellverzeichnis: $SOURCE_DIR" -info "Installationsverzeichnis: $INSTALL_DIR" -info "Systembenutzer: $SERVICE_USER" -info "Backend-Port: $BACKEND_PORT" -info "Frontend-Host: $FRONTEND_HOST" - -# --- Hilfsfunktionen ---------------------------------------------------------- - -command_exists() { command -v "$1" &>/dev/null; } - -install_node() { - header "Node.js installieren" - local required_major=20 - - if command_exists node; then - local current_major - current_major=$(node -e "process.stdout.write(String(process.version.split('.')[0].replace('v','')))") - if [[ "$current_major" -ge "$required_major" ]]; then - ok "Node.js $(node --version) bereits installiert" - return - fi - warn "Node.js $(node --version) zu alt – Node.js 20 wird installiert" - fi - - info "Installiere Node.js 20.x über NodeSource..." - curl -fsSL https://deb.nodesource.com/setup_20.x | bash - - apt-get install -y nodejs - ok "Node.js $(node --version) installiert" -} - -install_makemkv() { - header "MakeMKV installieren" - - if command_exists makemkvcon; then - local mk_version_line - mk_version_line="$(makemkvcon --version 2>&1 | head -1 || true)" - if [[ -z "$mk_version_line" || "$mk_version_line" == *"unrecognized option"* ]]; then - mk_version_line="$(makemkvcon 2>&1 | head -1 || true)" - fi - ok "makemkvcon bereits installiert (${mk_version_line:-Version unbekannt})" - return - fi - - info "Installiere Build-Abhängigkeiten für MakeMKV..." - apt-get install -y \ - build-essential pkg-config libc6-dev libssl-dev \ - libexpat1-dev libavcodec-dev libgl1-mesa-dev \ - qtbase5-dev zlib1g-dev wget - - local makemkv_fallback="1.18.3" - info "Ermittle aktuelle MakeMKV-Version (forum.makemkv.com)..." - local makemkv_version - makemkv_version=$(curl -s --max-time 15 \ - "https://forum.makemkv.com/forum/viewtopic.php?f=3&t=224" \ - | grep -oP 'MakeMKV \K[0-9]+\.[0-9]+\.[0-9]+(?= for Linux)' | head -1 || true) - - if [[ -z "$makemkv_version" ]]; then - warn "MakeMKV-Version konnte nicht ermittelt werden – verwende Fallback $makemkv_fallback" - makemkv_version="$makemkv_fallback" - else - info "Gefundene Version: $makemkv_version" - fi - - info "Baue MakeMKV $makemkv_version..." - local tmp_dir - tmp_dir=$(mktemp -d) - cd "$tmp_dir" - - local base_url="https://www.makemkv.com/download" - wget -q "${base_url}/makemkv-bin-${makemkv_version}.tar.gz" - wget -q "${base_url}/makemkv-oss-${makemkv_version}.tar.gz" - - tar xf "makemkv-oss-${makemkv_version}.tar.gz" - cd "makemkv-oss-${makemkv_version}" - ./configure - make -j"$(nproc)" - make install - - cd "$tmp_dir" - tar xf "makemkv-bin-${makemkv_version}.tar.gz" - cd "makemkv-bin-${makemkv_version}" - mkdir -p tmp && echo "accepted" > tmp/eula_accepted - make -j"$(nproc)" - make install - - cd / - rm -rf "$tmp_dir" - ok "MakeMKV $makemkv_version installiert" - warn "Hinweis: MakeMKV benötigt eine Lizenz oder den Beta-Key." - warn "Beta-Key: https://www.makemkv.com/forum/viewtopic.php?t=1053" -} - -handbrake_has_nvdec() { - command_exists HandBrakeCLI || return 1 - HandBrakeCLI --help 2>&1 | grep -qi "nvdec" -} - -handbrake_installed_version() { - command_exists HandBrakeCLI || return 1 - HandBrakeCLI --version 2>/dev/null | grep -oE '[0-9]+(\.[0-9]+){1,3}' | head -1 -} - -handbrake_latest_git_version() { - local latest="" - latest=$(curl -fsSL --max-time 10 "https://api.github.com/repos/HandBrake/HandBrake/releases/latest" 2>/dev/null \ - | grep -oE '"tag_name"[[:space:]]*:[[:space:]]*"[^"]+"' \ - | head -1 \ - | sed -E 's/.*"([^"]+)".*/\1/' \ - | sed 's/^v//') - [[ -n "$latest" ]] || return 1 - [[ "$latest" =~ ^[0-9]+(\.[0-9]+){1,3}$ ]] || return 1 - printf '%s\n' "$latest" -} - -handbrake_is_self_built() { - local hb_path="${1:-$(command -v HandBrakeCLI 2>/dev/null || true)}" - local resolved_path="" - [[ -n "$hb_path" ]] || return 1 - [[ "$hb_path" == "/usr/local/bin/HandBrakeCLI" ]] || return 1 - [[ -f "$HANDBRAKE_SELFBUILD_MARKER" ]] && return 0 - resolved_path=$(readlink -f "$hb_path" 2>/dev/null || true) - dpkg -S "$hb_path" >/dev/null 2>&1 && return 1 - [[ -n "$resolved_path" ]] && dpkg -S "$resolved_path" >/dev/null 2>&1 && return 1 - return 0 -} - -remove_non_selfbuilt_handbrake() { - info "Entferne nicht-selbst-gebaute HandBrake-Installationen..." - apt-get remove -y handbrake-cli handbrake 2>/dev/null || true - snap remove handbrake-cli 2>/dev/null || true - - rm -f /usr/bin/HandBrakeCLI \ - /snap/bin/handbrake-cli \ - /snap/bin/HandBrakeCLI - - if [[ -e /usr/local/bin/HandBrakeCLI ]] && ! handbrake_is_self_built "/usr/local/bin/HandBrakeCLI"; then - warn "Entferne fremdes /usr/local/bin/HandBrakeCLI" - rm -f /usr/local/bin/HandBrakeCLI - fi - - hash -r 2>/dev/null || true - ok "Bereinigung abgeschlossen" -} - -remove_selfbuilt_handbrake() { - if [[ -e /usr/local/bin/HandBrakeCLI ]] && handbrake_is_self_built "/usr/local/bin/HandBrakeCLI"; then - warn "Entferne selbst gebautes /usr/local/bin/HandBrakeCLI" - rm -f /usr/local/bin/HandBrakeCLI - fi - rm -f "$HANDBRAKE_SELFBUILD_MARKER" - hash -r 2>/dev/null || true -} - -build_handbrake_nvdec() { - header "HandBrake ${HANDBRAKE_VERSION} mit NVDEC aus Quellcode bauen" - - local cache_dir="/var/cache/ripster/handbrake" - local src_url="https://github.com/HandBrake/HandBrake/releases/download/${HANDBRAKE_VERSION}/HandBrake-${HANDBRAKE_VERSION}-source.tar.bz2" - local tarball="${cache_dir}/HandBrake-${HANDBRAKE_VERSION}-source.tar.bz2" - local src_dir="${cache_dir}/HandBrake-${HANDBRAKE_VERSION}" - - if [[ -t 0 && -d "$cache_dir" ]]; then - local clear_cache_answer="" - warn "Build-Cache gefunden: $cache_dir" - warn "Wenn du ihn löschst, startet der Source-Build wieder komplett von vorne." - read -r -p "Build-Cache jetzt löschen (sudo rm -rf $cache_dir)? [y/N] " clear_cache_answer - case "${clear_cache_answer,,}" in - y|yes|j|ja) - rm -rf "$cache_dir" - info "Build-Cache gelöscht." - ;; - esac - fi - mkdir -p "$cache_dir" - - # Build-Abhängigkeiten - info "Installiere Build-Abhängigkeiten..." - apt-get install -y \ - autoconf automake build-essential clang cmake git \ - libass-dev libbz2-dev libdvdnav-dev libdvdread-dev \ - libfontconfig-dev libfreetype-dev libfribidi-dev libharfbuzz-dev \ - libjansson-dev liblzma-dev libmp3lame-dev libnuma-dev libogg-dev \ - libopus-dev libsamplerate0-dev libspeex-dev libtheora-dev libtool libtool-bin libva-dev \ - libturbojpeg0-dev libvorbis-dev libvpx-dev libx264-dev libxml2-dev \ - m4 meson nasm ninja-build patch pkg-config python3 tar yasm zlib1g-dev \ - >/dev/null - - # CUDA Toolkit für NVDEC-Header - info "Installiere CUDA Toolkit (für NVDEC-Header)..." - if ! dpkg -l 2>/dev/null | grep -q '^ii.*nvidia-cuda-toolkit'; then - apt-get install -y nvidia-cuda-toolkit >/dev/null 2>&1 || { - warn "nvidia-cuda-toolkit nicht verfügbar – versuche Fallback-Header..." - local cuda_keyring="/tmp/cuda-keyring.deb" - local ubuntu_ver="${VERSION_ID//./}" - curl -fsSL "https://developer.download.nvidia.com/compute/cuda/repos/ubuntu${ubuntu_ver}/x86_64/cuda-keyring_1.1-1_all.deb" \ - -o "$cuda_keyring" 2>/dev/null && \ - dpkg -i "$cuda_keyring" 2>/dev/null && \ - apt-get update -qq && \ - apt-get install -y cuda-cudart-dev-12-8 >/dev/null 2>&1 || \ - warn "CUDA-Header konnten nicht installiert werden – NVDEC wird möglicherweise nicht verfügbar sein." - } - fi - ok "Build-Abhängigkeiten installiert" - - if [[ ! -d "$src_dir" ]]; then - if [[ ! -f "$tarball" ]]; then - info "Lade HandBrake ${HANDBRAKE_VERSION} herunter..." - curl -fsSL "$src_url" -o "$tarball" 2>/dev/null || \ - wget -q "$src_url" -O "$tarball" || \ - fatal "HandBrake-Quellcode konnte nicht heruntergeladen werden (${src_url})" - else - info "Nutze vorhandenes HandBrake-Source-Archiv: $tarball" - fi - - info "Entpacke Quellcode..." - tar xjf "$tarball" -C "$cache_dir" - [[ -d "$src_dir" ]] || src_dir=$(find "$cache_dir" -maxdepth 1 -type d -name "HandBrake*" | head -1) - [[ -d "$src_dir" ]] || fatal "HandBrake-Quellverzeichnis nicht gefunden in $cache_dir" - else - info "Nutze vorhandenen HandBrake-Source-Baum: $src_dir" - fi - - cd "$src_dir" - - local configure_log="${src_dir}/build/configure-ripster.log" - local configure_stamp="${src_dir}/build/.ripster-config" - local configure_args="--enable-nvdec --disable-gtk --prefix=/usr/local" - local need_configure="false" - local configure_cmd=( - ./configure - --launch-jobs="$(nproc)" - --enable-nvdec - --disable-gtk - --prefix=/usr/local - ) - - if [[ ! -f "$src_dir/build/GNUmakefile" ]]; then - need_configure="true" - elif [[ ! -f "$configure_stamp" ]]; then - need_configure="true" - elif ! grep -qx "args=${configure_args}" "$configure_stamp"; then - need_configure="true" - fi - - if [[ "$need_configure" == "true" ]]; then - if [[ -d "$src_dir/build" ]]; then - configure_cmd=(./configure --force "${configure_cmd[@]:1}") - fi - - if [[ -f "$src_dir/build/GNUmakefile" ]]; then - info "Vorhandener Build gefunden – aktualisiere Konfiguration (CLI-only)." - else - info "Konfiguriere HandBrake mit NVDEC (CLI-only)..." - fi - - if ! "${configure_cmd[@]}" >"$configure_log" 2>&1; then - tail -n 50 "$configure_log" >&2 || true - fatal "HandBrake-Konfiguration fehlgeschlagen. Vollständiges Log: $configure_log" - fi - tail -n 10 "$configure_log" - - mkdir -p "${src_dir}/build" - cat > "$configure_stamp" </dev/null || true - if ! command_exists HandBrakeCLI; then - warn "HandBrakeCLI nach direkter Installation nicht gefunden – setze Build fort." - make --directory=build -j"$(nproc)" - make --directory=build install - fi - else - info "Baue HandBrake ($(nproc) Threads – bitte warten)..." - make --directory=build -j"$(nproc)" - info "Installiere HandBrake nach /usr/local/bin..." - make --directory=build install - fi - - cd / - hash -r 2>/dev/null || true - - if command_exists HandBrakeCLI; then - local ver - ver=$(HandBrakeCLI --version 2>&1 | head -1) - handbrake_has_nvdec || fatal "HandBrakeCLI ist installiert, aber ohne NVDEC-Unterstützung." - - mkdir -p "$(dirname "$HANDBRAKE_SELFBUILD_MARKER")" - cat > "$HANDBRAKE_SELFBUILD_MARKER" </dev/null | grep -q libnvcuvid; then - ok "libnvcuvid gefunden – NVDEC ist zur Laufzeit verfügbar." - else - warn "libnvcuvid NICHT gefunden. NVDEC benötigt den installierten NVIDIA-Treiber." - fi - else - fatal "HandBrakeCLI nach dem Build nicht gefunden – Build fehlgeschlagen." - fi -} - -has_nvidia_gpu() { - [[ -e /dev/nvidia0 ]] && return 0 - command_exists nvidia-smi && nvidia-smi &>/dev/null && return 0 - command_exists lspci && lspci 2>/dev/null | grep -qi "nvidia" && return 0 - return 1 -} - -install_handbrake() { - header "HandBrake CLI installieren" - - local hb_path - local current_mode="none" - hb_path=$(command -v HandBrakeCLI 2>/dev/null || true) - if [[ -n "$hb_path" ]]; then - if handbrake_has_nvdec; then - current_mode="nvdec" - else - current_mode="standard" - fi - fi - - if [[ "$BUILD_HANDBRAKE_NVDEC" == true ]]; then - info "Installmodus: Source-Build mit NVDEC-Support" - if has_nvidia_gpu; then - info "NVIDIA-GPU erkannt – NVDEC-Build wird verwendet." - fi - - if handbrake_has_nvdec; then - if handbrake_is_self_built "$hb_path"; then - local installed_ver latest_ver answer - installed_ver=$(handbrake_installed_version || true) - latest_ver=$(handbrake_latest_git_version || true) - - if [[ -n "$installed_ver" && -n "$latest_ver" ]] && dpkg --compare-versions "$latest_ver" gt "$installed_ver"; then - case "$HANDBRAKE_UPDATE_POLICY" in - keep) - warn "Neuere HandBrake-Version verfügbar (${latest_ver}, installiert: ${installed_ver}) – behalte aktuelle Installation." - return - ;; - prompt) - if [[ -t 0 ]]; then - read -r -p "Neue HandBrake-Version ${latest_ver} verfügbar (installiert ${installed_ver}). Neu bauen? [y/N] " answer - case "${answer,,}" in - y|yes|j|ja) - info "Aktualisiere auf HandBrake ${latest_ver}." - HANDBRAKE_VERSION="$latest_ver" - ;; - *) - info "Behalte bestehende Installation (${installed_ver})." - return - ;; - esac - else - warn "Neuere HandBrake-Version verfügbar (${latest_ver}), aber kein TTY für Rückfrage – behalte aktuelle Installation." - return - fi - ;; - build) - info "Neuere HandBrake-Version verfügbar (${latest_ver}, installiert: ${installed_ver}) – aktualisiere." - HANDBRAKE_VERSION="$latest_ver" - ;; - esac - else - ok "Selbst gebautes HandBrakeCLI mit NVDEC bereits installiert: $(HandBrakeCLI --version 2>&1 | head -1)" - return - fi - fi - warn "HandBrakeCLI mit NVDEC gefunden (${hb_path}), aber nicht als Selbst-Build erkannt." - fi - - if [[ -n "$hb_path" ]] && ! handbrake_has_nvdec; then - warn "HandBrakeCLI ohne NVDEC gefunden (${hb_path}) – wird ersetzt durch Selbst-Build." - elif [[ -z "$hb_path" ]]; then - info "Kein HandBrakeCLI gefunden – baue aus Quellcode." - fi - - remove_non_selfbuilt_handbrake - build_handbrake_nvdec - return - fi - - info "Installmodus: Standard (APT, ohne NVDEC-Zwang)" - if [[ "$current_mode" == "standard" ]] && ! handbrake_is_self_built "$hb_path"; then - ok "HandBrakeCLI bereits installiert: $(HandBrakeCLI --version 2>&1 | head -1)" - return - fi - - if [[ "$current_mode" == "nvdec" ]]; then - warn "Umschalten von NVDEC-Build auf Standard-Installation." - fi - - remove_selfbuilt_handbrake - remove_non_selfbuilt_handbrake - - info "Installiere HandBrakeCLI aus den Standard-Repositories..." - apt_update - apt-get install -y handbrake-cli >/dev/null - hash -r 2>/dev/null || true - - if command_exists HandBrakeCLI; then - ok "HandBrakeCLI installiert: $(HandBrakeCLI --version 2>&1 | head -1)" - return - fi - - if command_exists handbrake-cli; then - ln -sf "$(command -v handbrake-cli)" /usr/local/bin/HandBrakeCLI - hash -r 2>/dev/null || true - ok "HandBrakeCLI Alias angelegt auf: $(command -v handbrake-cli)" - return - fi - - fatal "HandBrake wurde installiert, aber kein CLI-Befehl wurde gefunden." -} - -# --- apt-Hilfsfunktionen ------------------------------------------------------ - -apt_update() { - local output - if output=$(apt-get update 2>&1); then - return 0 - fi - - if echo "$output" | grep -q "no longer has a Release file\|does not have a Release file"; then - warn "apt-Sources fehlerhaft. Versuche Reparatur..." - - if apt-get update --allow-releaseinfo-change -qq 2>/dev/null; then - ok "apt-Update mit --allow-releaseinfo-change erfolgreich" - return 0 - fi - - if [[ -n "${VERSION_CODENAME:-}" ]]; then - warn "Schreibe minimale sources.list für $VERSION_CODENAME..." - local main_list=/etc/apt/sources.list - cp "$main_list" "${main_list}.bak-$(date +%Y%m%d%H%M%S)" 2>/dev/null || true - - case "$ID" in - ubuntu) - cat > "$main_list" < "$main_list" </dev/null; then - ok "apt-Update nach Sources-Reparatur erfolgreich" - return 0 - fi - fi - - warn "Deaktiviere fehlerhafte Eintraege in /etc/apt/sources.list.d/ ..." - local broken_files - broken_files=$(apt-get update 2>&1 | grep -oP "(?<=The repository ').*?(?=' )" | \ - xargs -I{} grep -rl "{}" /etc/apt/sources.list.d/ 2>/dev/null || true) - if [[ -n "$broken_files" ]]; then - echo "$broken_files" | while read -r f; do - warn "Deaktiviere: $f" - mv "$f" "${f}.disabled" 2>/dev/null || true - done - if apt-get update -qq 2>/dev/null; then - ok "apt-Update nach Deaktivierung fehlerhafter Sources erfolgreich" - return 0 - fi - fi - - error "apt-Update fehlgeschlagen. Bitte Sources manuell pruefen:" - echo "$output" - fatal "Installation abgebrochen. Repariere /etc/apt/sources.list und starte erneut." - else - error "apt-Update fehlgeschlagen:" - echo "$output" - fatal "Installation abgebrochen." - fi -} - -# --- Systemabhängigkeiten ----------------------------------------------------- -header "Systemabhängigkeiten installieren" - -info "Paketlisten aktualisieren..." -apt_update - -info "Installiere Basispakete..." -apt-get install -y \ - curl wget git \ - mediainfo \ - util-linux udev \ - ca-certificates gnupg \ - lsb-release - -ok "Basispakete installiert" - -# Node.js -install_node - -# MakeMKV -if [[ "$SKIP_MAKEMKV" == false ]]; then - install_makemkv -else - warn "MakeMKV-Installation übersprungen (--no-makemkv)" -fi - -# HandBrake -if [[ "$SKIP_HANDBRAKE" == false ]]; then - install_handbrake -else - warn "HandBrake-Installation übersprungen (--no-handbrake)" -fi - -# Nginx -if [[ "$SKIP_NGINX" == false ]]; then - if ! command_exists nginx; then - info "Installiere nginx..." - apt-get install -y nginx - fi - ok "nginx installiert" -fi - -# --- Systembenutzer anlegen --------------------------------------------------- -header "Systembenutzer anlegen" - -if id "$SERVICE_USER" &>/dev/null; then - ok "Benutzer '$SERVICE_USER' existiert bereits" -else - info "Lege Systembenutzer '$SERVICE_USER' an..." - useradd --system --no-create-home --shell /usr/sbin/nologin "$SERVICE_USER" - ok "Benutzer '$SERVICE_USER' angelegt" -fi - -SERVICE_HOME="$(getent passwd "$SERVICE_USER" | cut -d: -f6)" -if [[ -z "$SERVICE_HOME" || "$SERVICE_HOME" == "/" || "$SERVICE_HOME" == "/nonexistent" ]]; then - SERVICE_HOME="/home/$SERVICE_USER" -fi -mkdir -p "$SERVICE_HOME" -chown "$SERVICE_USER:$SERVICE_USER" "$SERVICE_HOME" 2>/dev/null || true -chmod 755 "$SERVICE_HOME" 2>/dev/null || true -info "Service-Home für '$SERVICE_USER': $SERVICE_HOME" - -# Optisches Laufwerk: Benutzer zur cdrom/optical-Gruppe hinzufügen -for grp in cdrom optical disk; do - if getent group "$grp" &>/dev/null; then - usermod -aG "$grp" "$SERVICE_USER" 2>/dev/null || true - info "Benutzer '$SERVICE_USER' zur Gruppe '$grp' hinzugefügt" - fi -done - -# --- Dateien kopieren --------------------------------------------------------- -header "Ripster-Dateien installieren" - -if [[ -d "$INSTALL_DIR" && "$REINSTALL" == false ]]; then - fatal "Verzeichnis $INSTALL_DIR existiert bereits.\nVerwende --reinstall um zu überschreiben (Daten bleiben erhalten)." -fi - -# Bei Reinstall: Daten sichern -if [[ -d "$INSTALL_DIR/backend/data" ]]; then - info "Sichere vorhandene Datenbank..." - cp -a "$INSTALL_DIR/backend/data" "/tmp/ripster-data-backup-$(date +%Y%m%d%H%M%S)" - ok "Datenbank gesichert" -fi - -info "Kopiere Quellen nach $INSTALL_DIR..." -mkdir -p "$INSTALL_DIR" - -rsync -a --delete \ - --exclude='.git' \ - --exclude='node_modules' \ - --exclude='backend/node_modules' \ - --exclude='frontend/node_modules' \ - --exclude='backend/data' \ - --exclude='backend/logs' \ - --exclude='frontend/dist' \ - --exclude='*.sh' \ - --exclude='deploy-ripster.sh' \ - --exclude='debug/' \ - --exclude='site/' \ - --exclude='docs/' \ - "$SOURCE_DIR/" "$INSTALL_DIR/" - -# Datenbank-/Log-Verzeichnisse anlegen -mkdir -p "$INSTALL_DIR/backend/data" -mkdir -p "$INSTALL_DIR/backend/logs" - -# Bei Reinstall: Daten wiederherstellen -if [[ -d "$INSTALL_DIR/../ripster-data-backup" ]]; then - cp -a /tmp/ripster-data-backup-*/ "$INSTALL_DIR/backend/data/" 2>/dev/null || true -fi - -ok "Dateien kopiert" - -# --- npm-Abhängigkeiten installieren ----------------------------------------- -header "npm-Abhängigkeiten installieren" - -info "Installiere Root-Abhängigkeiten..." -npm install --prefix "$INSTALL_DIR" --omit=dev --silent - -info "Installiere Backend-Abhängigkeiten..." -npm install --prefix "$INSTALL_DIR/backend" --omit=dev --silent - -info "Installiere Frontend-Abhängigkeiten..." -npm install --prefix "$INSTALL_DIR/frontend" --silent - -ok "npm-Abhängigkeiten installiert" - -# --- Frontend bauen ----------------------------------------------------------- -header "Frontend bauen" - -info "Baue Frontend für $FRONTEND_HOST..." - -# Relative URLs verwenden – funktioniert mit jedem Hostnamen/Domain, da nginx -# /api/ und /ws auf dem selben Host proxied. Absolute IP-URLs würden Chromes -# Private Network Access (PNA) Policy verletzen, wenn das Frontend über einen -# Domainnamen aufgerufen wird. -rm -f "$INSTALL_DIR/frontend/.env.production.local" - -npm run build --prefix "$INSTALL_DIR/frontend" --silent -ok "Frontend gebaut: $INSTALL_DIR/frontend/dist" - -# --- Backend-Konfiguration --------------------------------------------------- -header "Backend konfigurieren" - -ENV_FILE="$INSTALL_DIR/backend/.env" - -if [[ -f "$ENV_FILE" && "$REINSTALL" == false ]]; then - warn "Backend .env existiert bereits – wird nicht überschrieben" -else - info "Erstelle Backend .env..." - cat > "$ENV_FILE" </dev/null || true -chmod 700 "$MAKEMKV_SERVICE_DIR" 2>/dev/null || true - -# --- Systemd-Dienst: Backend ------------------------------------------------- -header "Systemd-Dienst (Backend) erstellen" - -cat > /etc/systemd/system/ripster-backend.service < /etc/nginx/sites-available/ripster < Git-Branch (Standard: main) -# --dir Installationsverzeichnis (Standard: /opt/ripster) -# --user Systembenutzer für den Dienst (Standard: ripster) -# --port Backend-Port (Standard: 3001) -# --host Hostname/IP für die Weboberfläche (Standard: Maschinen-IP) -# --no-makemkv MakeMKV-Installation überspringen -# --no-handbrake HandBrake-Installation überspringen -# --no-nginx Nginx-Einrichtung überspringen -# --reinstall Vorhandene Installation aktualisieren (Daten bleiben erhalten) -# -h, --help Diese Hilfe anzeigen -# ============================================================================= -set -euo pipefail - -REPO_URL="https://github.com/Mboehmlaender/ripster.git" -REPO_RAW_BASE="https://raw.githubusercontent.com/Mboehmlaender/ripster" -SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd -P)" -BUNDLED_HANDBRAKE_CLI="${SCRIPT_DIR}/bin/HandBrakeCLI" - -# --- Farben ------------------------------------------------------------------- -RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' -BLUE='\033[0;34m'; BOLD='\033[1m'; RESET='\033[0m' - -info() { echo -e "${BLUE}[INFO]${RESET} $*"; } -ok() { echo -e "${GREEN}[OK]${RESET} $*"; } -warn() { echo -e "${YELLOW}[WARN]${RESET} $*"; } -error() { echo -e "${RED}[FEHLER]${RESET} $*" >&2; } -header() { echo -e "\n${BOLD}${BLUE}══════════════════════════════════════════${RESET}"; \ - echo -e "${BOLD} $*${RESET}"; \ - echo -e "${BOLD}${BLUE}══════════════════════════════════════════${RESET}"; } -fatal() { error "$*"; exit 1; } - -# --- Standard-Optionen -------------------------------------------------------- -GIT_BRANCH="dev" -INSTALL_DIR="/opt/ripster" -SERVICE_USER="ripster" -BACKEND_PORT="3001" -FRONTEND_HOST="" -SKIP_MAKEMKV=false -SKIP_HANDBRAKE=false -HANDBRAKE_INSTALL_MODE="" -SKIP_NGINX=false -REINSTALL=false - -# --- Argumente parsen --------------------------------------------------------- -while [[ $# -gt 0 ]]; do - case "$1" in - --branch) GIT_BRANCH="$2"; shift 2 ;; - --dir) INSTALL_DIR="$2"; shift 2 ;; - --user) SERVICE_USER="$2"; shift 2 ;; - --port) BACKEND_PORT="$2"; shift 2 ;; - --host) FRONTEND_HOST="$2"; shift 2 ;; - --no-makemkv) SKIP_MAKEMKV=true; shift ;; - --no-handbrake) SKIP_HANDBRAKE=true; shift ;; - --no-nginx) SKIP_NGINX=true; shift ;; - --reinstall) REINSTALL=true; shift ;; - -h|--help) - sed -n '/^# Verwendung/,/^# ====/p' "$0" | head -n -1 | sed 's/^# \?//' - exit 0 ;; - *) fatal "Unbekannte Option: $1" ;; - esac -done - -# --- Voraussetzungen prüfen --------------------------------------------------- -header "Ripster Installationsskript (Git)" - -if [[ $EUID -ne 0 ]]; then - fatal "Dieses Skript muss als root ausgeführt werden (sudo bash install.sh)" -fi - -if [[ ! -f /etc/os-release ]]; then - fatal "Betriebssystem nicht erkennbar. Nur Debian/Ubuntu wird unterstützt." -fi -. /etc/os-release -case "$ID" in - debian|ubuntu|linuxmint|pop) ok "Betriebssystem: $PRETTY_NAME" ;; - *) fatal "Nicht unterstütztes OS: $ID. Nur Debian/Ubuntu unterstützt." ;; -esac - -if [[ -z "$FRONTEND_HOST" ]]; then - FRONTEND_HOST=$(hostname -I | awk '{print $1}') - info "Erkannte IP: $FRONTEND_HOST" -fi - -info "Repository: $REPO_URL" -info "Branch: $GIT_BRANCH" -info "Installationsverzeichnis: $INSTALL_DIR" -info "Systembenutzer: $SERVICE_USER" -info "Backend-Port: $BACKEND_PORT" -info "Frontend-Host: $FRONTEND_HOST" - -# --- Hilfsfunktionen ---------------------------------------------------------- - -command_exists() { command -v "$1" &>/dev/null; } - -download_file() { - local url="$1" - local target="$2" - - if command_exists curl; then - curl -fsSL "$url" -o "$target" - return 0 - fi - - if command_exists wget; then - wget -q "$url" -O "$target" - return 0 - fi - - return 1 -} - -install_node() { - header "Node.js installieren" - local required_major=20 - - if command_exists node; then - local current_major - current_major=$(node -e "process.stdout.write(String(process.version.split('.')[0].replace('v','')))") - if [[ "$current_major" -ge "$required_major" ]]; then - ok "Node.js $(node --version) bereits installiert" - return - fi - warn "Node.js $(node --version) zu alt – Node.js 20 wird installiert" - fi - - info "Installiere Node.js 20.x über NodeSource..." - curl -fsSL https://deb.nodesource.com/setup_20.x | bash - - apt-get install -y nodejs - ok "Node.js $(node --version) installiert" -} - -install_makemkv() { - header "MakeMKV installieren" - - if command_exists makemkvcon; then - ok "makemkvcon bereits installiert ($(makemkvcon --version 2>&1 | head -1))" - return - fi - - info "Installiere Build-Abhängigkeiten für MakeMKV..." - apt-get install -y \ - build-essential pkg-config libc6-dev libssl-dev \ - libexpat1-dev libavcodec-dev libgl1-mesa-dev \ - qtbase5-dev zlib1g-dev wget - - # Aktuelle Version aus dem offiziellen Linux-Forum-Thread ermitteln. - # Der Titel lautet immer: "MakeMKV X.Y.Z for Linux is available" - local makemkv_fallback="1.18.3" - info "Ermittle aktuelle MakeMKV-Version (forum.makemkv.com)..." - local makemkv_version - makemkv_version=$(curl -s --max-time 15 \ - "https://forum.makemkv.com/forum/viewtopic.php?f=3&t=224" \ - | grep -oP 'MakeMKV \K[0-9]+\.[0-9]+\.[0-9]+(?= for Linux)' | head -1 || true) - - if [[ -z "$makemkv_version" ]]; then - warn "MakeMKV-Version konnte nicht ermittelt werden – verwende Fallback $makemkv_fallback" - makemkv_version="$makemkv_fallback" - else - info "Aktuelle Version: $makemkv_version" - fi - - info "Baue MakeMKV $makemkv_version..." - local tmp_dir - tmp_dir=$(mktemp -d) - cd "$tmp_dir" - - local base_url="https://www.makemkv.com/download" - wget -q "${base_url}/makemkv-bin-${makemkv_version}.tar.gz" - wget -q "${base_url}/makemkv-oss-${makemkv_version}.tar.gz" - - tar xf "makemkv-oss-${makemkv_version}.tar.gz" - cd "makemkv-oss-${makemkv_version}" - ./configure - make -j"$(nproc)" - make install - - cd "$tmp_dir" - tar xf "makemkv-bin-${makemkv_version}.tar.gz" - cd "makemkv-bin-${makemkv_version}" - mkdir -p tmp && echo "accepted" > tmp/eula_accepted - make -j"$(nproc)" - make install - - cd / - rm -rf "$tmp_dir" - ok "MakeMKV $makemkv_version installiert" - warn "Hinweis: MakeMKV benötigt eine Lizenz oder den Beta-Key." - warn "Beta-Key: https://www.makemkv.com/forum/viewtopic.php?t=1053" -} - -select_handbrake_mode() { - [[ "$SKIP_HANDBRAKE" == true ]] && return - - local mode_answer="" - echo "" - echo "Install HandBrake:" - echo "" - echo "1. Standard version (apt install handbrake-cli)" - echo "2. GPU version with NVDEC (use bundled binary)" - - if [[ -t 0 ]]; then - read -r -p "Select option [1/2]: " mode_answer - elif [[ -r /dev/tty ]]; then - read -r -p "Select option [1/2]: " mode_answer /dev/null || true - - if command_exists HandBrakeCLI; then - ok "HandBrakeCLI installiert: $(HandBrakeCLI --version 2>&1 | head -1)" - return - fi - - if command_exists handbrake-cli; then - ok "handbrake-cli installiert: $(handbrake-cli --version 2>&1 | head -1)" - return - fi - - fatal "HandBrake wurde installiert, aber kein CLI-Befehl wurde gefunden." -} - -install_handbrake_gpu_bundled() { - info "Installiere gebündeltes HandBrakeCLI mit NVDEC..." - local bundled_source="$BUNDLED_HANDBRAKE_CLI" - local downloaded_tmp="" - - if [[ ! -f "$bundled_source" ]]; then - local remote_url="${REPO_RAW_BASE}/${GIT_BRANCH}/bin/HandBrakeCLI" - downloaded_tmp=$(mktemp) - info "Lokale Binary fehlt – lade aus Branch '$GIT_BRANCH' nach..." - if download_file "$remote_url" "$downloaded_tmp"; then - chmod 0755 "$downloaded_tmp" - bundled_source="$downloaded_tmp" - ok "Bundled HandBrakeCLI temporär heruntergeladen" - else - rm -f "$downloaded_tmp" 2>/dev/null || true - fatal "Bundled Binary fehlt lokal ($BUNDLED_HANDBRAKE_CLI) und Download schlug fehl: $remote_url" - fi - fi - - install -m 0755 "$bundled_source" /usr/local/bin/HandBrakeCLI - hash -r 2>/dev/null || true - if [[ -n "$downloaded_tmp" ]]; then - rm -f "$downloaded_tmp" 2>/dev/null || true - fi - - ok "Bundled HandBrakeCLI installiert nach /usr/local/bin/HandBrakeCLI" - if command_exists HandBrakeCLI; then - ok "HandBrakeCLI Version: $(HandBrakeCLI --version 2>&1 | head -1)" - fi -} - -install_handbrake() { - header "HandBrake CLI installieren" - - if [[ -z "$HANDBRAKE_INSTALL_MODE" ]]; then - HANDBRAKE_INSTALL_MODE="standard" - fi - - case "$HANDBRAKE_INSTALL_MODE" in - standard) install_handbrake_standard ;; - gpu) install_handbrake_gpu_bundled ;; - *) fatal "Unbekannter HandBrake-Modus: $HANDBRAKE_INSTALL_MODE" ;; - esac -} - -# --- apt-Hilfsfunktionen ------------------------------------------------------ - -# Führt apt-get update aus. Bei Release-Fehlern wird versucht, die Sources zu -# reparieren (Proxmox-Container, veraltete Spiegelserver, etc.). -apt_update() { - local output - if output=$(apt-get update 2>&1); then - return 0 - fi - - # Release-Datei fehlt → versuche Repair - if echo "$output" | grep -q "no longer has a Release file\|does not have a Release file"; then - warn "apt-Sources fehlerhaft. Versuche Reparatur..." - - # Strategie 1: --allow-releaseinfo-change - if apt-get update --allow-releaseinfo-change -qq 2>/dev/null; then - ok "apt-Update mit --allow-releaseinfo-change erfolgreich" - return 0 - fi - - # Strategie 2: Kaputte Einträge aus sources.list.d entfernen und Fallback - # auf offizielle Spiegel schreiben - if [[ -n "${VERSION_CODENAME:-}" ]]; then - warn "Schreibe minimale sources.list für $VERSION_CODENAME..." - local main_list=/etc/apt/sources.list - - # Backup - cp "$main_list" "${main_list}.bak-$(date +%Y%m%d%H%M%S)" 2>/dev/null || true - - case "$ID" in - ubuntu) - cat > "$main_list" < "$main_list" </dev/null; then - ok "apt-Update nach Sources-Reparatur erfolgreich" - return 0 - fi - fi - - # Strategie 3: Kaputte .list-Dateien in sources.list.d deaktivieren - warn "Deaktiviere fehlerhafte Eintraege in /etc/apt/sources.list.d/ ..." - local broken_files - broken_files=$(apt-get update 2>&1 | grep -oP "(?<=The repository ').*?(?=' )" | \ - xargs -I{} grep -rl "{}" /etc/apt/sources.list.d/ 2>/dev/null || true) - if [[ -n "$broken_files" ]]; then - echo "$broken_files" | while read -r f; do - warn "Deaktiviere: $f" - mv "$f" "${f}.disabled" 2>/dev/null || true - done - if apt-get update -qq 2>/dev/null; then - ok "apt-Update nach Deaktivierung fehlerhafter Sources erfolgreich" - return 0 - fi - fi - - error "apt-Update fehlgeschlagen. Bitte Sources manuell pruefen:" - echo "$output" - fatal "Installation abgebrochen. Repariere /etc/apt/sources.list und starte erneut." - else - error "apt-Update fehlgeschlagen:" - echo "$output" - fatal "Installation abgebrochen." - fi -} - -# --- HandBrake-Installmodus auswählen ---------------------------------------- -select_handbrake_mode - -# --- Systemabhängigkeiten ----------------------------------------------------- -header "Systemabhängigkeiten installieren" - -info "Paketlisten aktualisieren..." -apt_update - -info "Installiere Basispakete..." -apt-get install -y \ - curl wget git jq \ - mediainfo \ - util-linux udev \ - ca-certificates gnupg \ - lsb-release - -ok "Basispakete installiert" - -info "Installiere CD-Ripping-Tools..." -apt-get install -y \ - cdparanoia \ - flac \ - lame \ - opus-tools \ - vorbis-tools - -ok "CD-Ripping-Tools installiert (cdparanoia, flac, lame, opus-tools, vorbis-tools)" - -install_node - -if [[ "$SKIP_MAKEMKV" == false ]]; then - install_makemkv -else - warn "MakeMKV-Installation übersprungen (--no-makemkv)" -fi - -if [[ "$SKIP_HANDBRAKE" == false ]]; then - install_handbrake -else - warn "HandBrake-Installation übersprungen (--no-handbrake)" -fi - -if [[ "$SKIP_NGINX" == false ]]; then - if ! command_exists nginx; then - info "Installiere nginx..." - apt-get install -y nginx - fi - ok "nginx installiert" -fi - -# --- Systembenutzer anlegen --------------------------------------------------- -header "Systembenutzer anlegen" - -if id "$SERVICE_USER" &>/dev/null; then - ok "Benutzer '$SERVICE_USER' existiert bereits" -else - info "Lege Systembenutzer '$SERVICE_USER' an..." - useradd --system --no-create-home --shell /usr/sbin/nologin "$SERVICE_USER" - ok "Benutzer '$SERVICE_USER' angelegt" -fi - -SERVICE_HOME="$(getent passwd "$SERVICE_USER" | cut -d: -f6)" -if [[ -z "$SERVICE_HOME" || "$SERVICE_HOME" == "/" || "$SERVICE_HOME" == "/nonexistent" ]]; then - SERVICE_HOME="/home/$SERVICE_USER" -fi -mkdir -p "$SERVICE_HOME" -chown "$SERVICE_USER:$SERVICE_USER" "$SERVICE_HOME" 2>/dev/null || true -chmod 755 "$SERVICE_HOME" 2>/dev/null || true -info "Service-Home für '$SERVICE_USER': $SERVICE_HOME" - -for grp in cdrom optical disk video render; do - if getent group "$grp" &>/dev/null; then - usermod -aG "$grp" "$SERVICE_USER" 2>/dev/null || true - info "Benutzer '$SERVICE_USER' zur Gruppe '$grp' hinzugefügt" - fi -done - -# --- Repository klonen / aktualisieren ---------------------------------------- -header "Repository holen (Git)" - -# Prüfen ob der gewünschte Branch auf dem Remote existiert -info "Prüfe Branch '$GIT_BRANCH' auf Remote..." -if ! git ls-remote --exit-code --heads "$REPO_URL" "$GIT_BRANCH" &>/dev/null; then - fatal "Branch '$GIT_BRANCH' existiert nicht im Repository $REPO_URL.\nVerfügbare Branches: $(git ls-remote --heads "$REPO_URL" | awk '{print $2}' | sed 's|refs/heads/||' | tr '\n' ' ')" -fi -ok "Branch '$GIT_BRANCH' gefunden" - -if [[ -d "$INSTALL_DIR/.git" ]]; then - if [[ "$REINSTALL" == true ]]; then - info "Aktualisiere bestehendes Repository..." - # Daten sichern - if [[ -d "$INSTALL_DIR/backend/data" ]]; then - DATA_BACKUP="/tmp/ripster-data-backup-$(date +%Y%m%d%H%M%S)" - cp -a "$INSTALL_DIR/backend/data" "$DATA_BACKUP" - info "Datenbank gesichert nach: $DATA_BACKUP" - fi - # safe.directory nötig wenn das Verzeichnis einem anderen User gehört - # (z.B. ripster-Serviceuser nach erstem Install) - git config --global --add safe.directory "$INSTALL_DIR" 2>/dev/null || true - git -C "$INSTALL_DIR" remote set-branches origin '*' - git -C "$INSTALL_DIR" fetch --quiet origin - git -C "$INSTALL_DIR" reset --hard HEAD - git -C "$INSTALL_DIR" checkout --quiet -B "$GIT_BRANCH" "origin/$GIT_BRANCH" - git -C "$INSTALL_DIR" reset --hard "origin/$GIT_BRANCH" - ok "Repository aktualisiert auf Branch '$GIT_BRANCH'" - else - fatal "$INSTALL_DIR enthält bereits ein Git-Repository.\nVerwende --reinstall um zu aktualisieren." - fi -elif [[ -d "$INSTALL_DIR" && "$REINSTALL" == false ]]; then - fatal "Verzeichnis $INSTALL_DIR existiert bereits (kein Git-Repo).\nBitte manuell entfernen oder --reinstall verwenden." -else - info "Klone $REPO_URL (Branch: $GIT_BRANCH)..." - git clone --quiet --branch "$GIT_BRANCH" --depth 1 "$REPO_URL" "$INSTALL_DIR" - ok "Repository geklont nach $INSTALL_DIR" -fi - -# Daten- und Log-Verzeichnisse sicherstellen -mkdir -p "$INSTALL_DIR/backend/data" -mkdir -p "$INSTALL_DIR/backend/logs" -mkdir -p "$INSTALL_DIR/backend/data/output/raw" -mkdir -p "$INSTALL_DIR/backend/data/output/movies" -mkdir -p "$INSTALL_DIR/backend/data/output/cd" -mkdir -p "$INSTALL_DIR/backend/data/logs" - -# Gesicherte Daten zurückspielen -if [[ -n "${DATA_BACKUP:-}" && -d "$DATA_BACKUP" ]]; then - cp -a "$DATA_BACKUP/." "$INSTALL_DIR/backend/data/" - ok "Datenbank wiederhergestellt" -fi - -# --- npm-Abhängigkeiten installieren ----------------------------------------- -header "npm-Abhängigkeiten installieren" - -info "Root-Abhängigkeiten..." -npm install --prefix "$INSTALL_DIR" --omit=dev --silent - -info "Backend-Abhängigkeiten..." -npm install --prefix "$INSTALL_DIR/backend" --omit=dev --silent - -info "Frontend-Abhängigkeiten..." -npm install --prefix "$INSTALL_DIR/frontend" --silent - -ok "npm-Abhängigkeiten installiert" - -# --- Frontend bauen ----------------------------------------------------------- -header "Frontend bauen" - -info "Baue Frontend für $FRONTEND_HOST..." - -# Relative URLs verwenden – funktioniert mit jedem Hostnamen/Domain, da nginx -# /api/ und /ws auf dem selben Host proxied. Absolute IP-URLs würden Chromes -# Private Network Access (PNA) Policy verletzen, wenn das Frontend über einen -# Domainnamen aufgerufen wird. -rm -f "$INSTALL_DIR/frontend/.env.production.local" - -npm run build --prefix "$INSTALL_DIR/frontend" --silent -ok "Frontend gebaut: $INSTALL_DIR/frontend/dist" - -# --- Backend-Konfiguration --------------------------------------------------- -header "Backend konfigurieren" - -ENV_FILE="$INSTALL_DIR/backend/.env" - -if [[ -f "$ENV_FILE" && "$REINSTALL" == true ]]; then - warn "Bestehende .env bleibt erhalten (--reinstall)" -else - info "Erstelle Backend .env..." - cat > "$ENV_FILE" </dev/null || true -chmod 700 "$MAKEMKV_SERVICE_DIR" 2>/dev/null || true - -# --- Systemd-Dienst: Backend ------------------------------------------------- -header "Systemd-Dienst (Backend) erstellen" - -cat > /etc/systemd/system/ripster-backend.service < /etc/nginx/sites-available/ripster < Branch direkt setzen (ohne Auswahlmenue) - --dir Installationsverzeichnis - --user Systembenutzer fuer den Dienst - --port Backend-Port - --host Hostname/IP fuer die Weboberflaeche - --no-makemkv MakeMKV-Installation ueberspringen - --no-handbrake HandBrake-Installation ueberspringen - --no-nginx Nginx-Einrichtung ueberspringen - --reinstall Vorhandene Installation aktualisieren - -h, --help Hilfe anzeigen -EOF -} - -SELECTED_BRANCH="" -FORWARDED_ARGS=() - -while [[ $# -gt 0 ]]; do - case "$1" in - --branch) - [[ $# -ge 2 ]] || { echo "Fehlender Wert fuer --branch" >&2; exit 1; } - SELECTED_BRANCH="$2" - shift 2 - ;; - --dir|--user|--port|--host) - [[ $# -ge 2 ]] || { echo "Fehlender Wert fuer $1" >&2; exit 1; } - FORWARDED_ARGS+=("$1" "$2") - shift 2 - ;; - --no-makemkv|--no-handbrake|--no-nginx|--reinstall) - FORWARDED_ARGS+=("$1") - shift - ;; - -h|--help) - usage - exit 0 - ;; - *) - echo "Unbekannter Parameter: $1" >&2 - usage >&2 - exit 1 - ;; - esac -done - -fetch_url() { - local url="$1" - - if command -v curl >/dev/null 2>&1; then - curl -fsSL "$url" - return - fi - - if command -v wget >/dev/null 2>&1; then - wget -qO- "$url" - return - fi - - echo "Weder curl noch wget gefunden. Bitte eines davon installieren." >&2 - exit 1 -} - -download_file() { - local url="$1" - local target="$2" - fetch_url "$url" > "$target" -} - -select_branch() { - local branches_json - local -a branches - local selection - - branches_json="$(fetch_url "$BRANCHES_API_URL")" - mapfile -t branches < <( - printf '%s\n' "$branches_json" \ - | grep -oE '"name"[[:space:]]*:[[:space:]]*"[^"]+"' \ - | sed -E 's/"name"[[:space:]]*:[[:space:]]*"([^"]+)"/\1/' - ) - - if [[ ${#branches[@]} -eq 0 ]]; then - echo "Keine Branches gefunden oder API-Antwort ungültig." >&2 - exit 1 - fi - - if [[ -n "$SELECTED_BRANCH" ]]; then - local found=false - for branch in "${branches[@]}"; do - if [[ "$branch" == "$SELECTED_BRANCH" ]]; then - found=true - break - fi - done - if [[ "$found" == false ]]; then - echo "Branch '$SELECTED_BRANCH' nicht gefunden." >&2 - exit 1 - fi - return - fi - - if [[ ! -t 0 ]]; then - echo "Kein interaktives Terminal für die Branch-Auswahl verfügbar." >&2 - exit 1 - fi - - echo "Verfügbare Branches:" - for i in "${!branches[@]}"; do - printf " %2d) %s\n" "$((i + 1))" "${branches[$i]}" - done - - while true; do - read -r -p "Bitte Branch auswählen [1-${#branches[@]}]: " selection - if [[ "$selection" =~ ^[0-9]+$ ]] && (( selection >= 1 && selection <= ${#branches[@]} )); then - SELECTED_BRANCH="${branches[$((selection - 1))]}" - return - fi - echo "Ungültige Auswahl." - done -} - -TMP_DIR="$(mktemp -d)" -trap 'rm -rf "$TMP_DIR"' EXIT - -select_branch - -INSTALL_SCRIPT="${TMP_DIR}/install.sh" -INSTALL_URL="${REPO_RAW_BASE}/${SELECTED_BRANCH}/install.sh" - -echo "Lade install.sh aus Branch '${SELECTED_BRANCH}'..." -download_file "$INSTALL_URL" "$INSTALL_SCRIPT" -chmod +x "$INSTALL_SCRIPT" - -if [[ $EUID -eq 0 ]]; then - bash "$INSTALL_SCRIPT" --branch "$SELECTED_BRANCH" "${FORWARDED_ARGS[@]}" -else - if ! command -v sudo >/dev/null 2>&1; then - echo "sudo nicht gefunden. Bitte als root ausführen." >&2 - exit 1 - fi - sudo bash "$INSTALL_SCRIPT" --branch "$SELECTED_BRANCH" "${FORWARDED_ARGS[@]}" -fi