6335 lines
218 KiB
Bash
Executable File
6335 lines
218 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# ===================================================================
|
||
# MYP Druckerverwaltung - VOLLAUTOMATISCHES SETUP-SKRIPT (OPTIMIERT)
|
||
# Intelligente Installation ohne Benutzerinteraktion
|
||
# Erkennt automatisch den Systemzustand und installiert entsprechend
|
||
# Optimiert für Debian/Linux (Raspberry Pi OS) - KEIN Windows-Support
|
||
# HTTPS auf Port 443 mit automatischer SSL-Zertifikat-Generierung
|
||
# Kiosk-Modus mit Chromium-Autostart ohne Desktop-Environment
|
||
# Version: 5.0.0 - Vollautomatische Installation
|
||
# ===================================================================
|
||
|
||
set -euo pipefail
|
||
|
||
# =========================== GLOBALE KONFIGURATION ===========================
|
||
readonly APP_NAME="MYP Druckerverwaltung"
|
||
readonly APP_VERSION="5.0.0"
|
||
readonly APP_DIR="/opt/myp"
|
||
readonly HTTP_SERVICE_NAME="myp-https"
|
||
readonly KIOSK_SERVICE_NAME="myp-kiosk"
|
||
readonly WATCHDOG_SERVICE_NAME="kiosk-watchdog"
|
||
readonly WATCHDOG_PYTHON_SERVICE_NAME="kiosk-watchdog-python"
|
||
readonly FIREWALL_SERVICE_NAME="myp-firewall"
|
||
readonly KIOSK_USER="kiosk"
|
||
readonly CURRENT_DIR="$(pwd)"
|
||
|
||
# Automatische Installationsmodus-Erkennung
|
||
AUTO_INSTALL_MODE=""
|
||
FORCE_PRODUCTION=false
|
||
FORCE_DEVELOPMENT=false
|
||
|
||
# =========================== DYNAMISCHE CREDENTIALS KONFIGURATION ===========================
|
||
# Zentrale Credentials-Verwaltung mit dynamischen Override-Möglichkeiten
|
||
|
||
# Standard-Credentials (werden ggf. überschrieben)
|
||
MYP_SECRET_KEY="7445630171969DFAC92C53CEC92E67A9CB2E00B3CB2F"
|
||
MYP_MAIN_PASSWORD="744563017196A"
|
||
MYP_SSH_PASSWORD="raspberry"
|
||
MYP_ADMIN_EMAIL="admin@mercedes-benz.com"
|
||
MYP_TAPO_EMAIL="till.tomczak@mercedes-benz.com"
|
||
MYP_TAPO_PASSWORD="744563017196A"
|
||
MYP_ROUTER_USER="admin"
|
||
MYP_ROUTER_PASSWORD="vT6Vsd^p"
|
||
MYP_GITHUB_CLIENT_ID="7c5d8bef1a5519ec1fdc"
|
||
MYP_GITHUB_CLIENT_SECRET="5f1e586204358fbd53cf5fb7d418b3f06ccab8fd"
|
||
|
||
# Funktion: Dynamische Credentials laden/ändern
|
||
load_dynamic_credentials() {
|
||
log "🔑 LADE DYNAMISCHE CREDENTIALS..."
|
||
|
||
# Credentials aus Umgebungsvariablen überschreiben (falls gesetzt)
|
||
MYP_SECRET_KEY="${MYP_SECRET_KEY_OVERRIDE:-$MYP_SECRET_KEY}"
|
||
MYP_MAIN_PASSWORD="${MYP_MAIN_PASSWORD_OVERRIDE:-$MYP_MAIN_PASSWORD}"
|
||
MYP_SSH_PASSWORD="${MYP_SSH_PASSWORD_OVERRIDE:-$MYP_SSH_PASSWORD}"
|
||
MYP_ADMIN_EMAIL="${MYP_ADMIN_EMAIL_OVERRIDE:-$MYP_ADMIN_EMAIL}"
|
||
MYP_TAPO_EMAIL="${MYP_TAPO_EMAIL_OVERRIDE:-$MYP_TAPO_EMAIL}"
|
||
MYP_TAPO_PASSWORD="${MYP_TAPO_PASSWORD_OVERRIDE:-$MYP_TAPO_PASSWORD}"
|
||
MYP_ROUTER_USER="${MYP_ROUTER_USER_OVERRIDE:-$MYP_ROUTER_USER}"
|
||
MYP_ROUTER_PASSWORD="${MYP_ROUTER_PASSWORD_OVERRIDE:-$MYP_ROUTER_PASSWORD}"
|
||
MYP_GITHUB_CLIENT_ID="${MYP_GITHUB_CLIENT_ID_OVERRIDE:-$MYP_GITHUB_CLIENT_ID}"
|
||
MYP_GITHUB_CLIENT_SECRET="${MYP_GITHUB_CLIENT_SECRET_OVERRIDE:-$MYP_GITHUB_CLIENT_SECRET}"
|
||
|
||
# Credentials aus externer Datei laden (falls vorhanden)
|
||
local credentials_file="$CURRENT_DIR/CREDENTIALS_OVERRIDE.env"
|
||
if [ -f "$credentials_file" ]; then
|
||
progress "Lade Credentials aus: $credentials_file"
|
||
source "$credentials_file"
|
||
info "✅ Externe Credentials-Datei geladen"
|
||
fi
|
||
|
||
# Interaktive Credentials-Änderung (falls gewünscht)
|
||
if [ "${INTERACTIVE_CREDENTIALS:-0}" = "1" ]; then
|
||
interactive_credentials_setup
|
||
fi
|
||
|
||
# Credentials als readonly setzen
|
||
readonly MYP_SECRET_KEY MYP_MAIN_PASSWORD MYP_SSH_PASSWORD MYP_ADMIN_EMAIL
|
||
readonly MYP_TAPO_EMAIL MYP_TAPO_PASSWORD MYP_ROUTER_USER MYP_ROUTER_PASSWORD
|
||
readonly MYP_GITHUB_CLIENT_ID MYP_GITHUB_CLIENT_SECRET
|
||
|
||
success "✅ Dynamische Credentials geladen und fixiert"
|
||
}
|
||
|
||
# Funktion: Interaktive Credentials-Einrichtung
|
||
interactive_credentials_setup() {
|
||
log "🔧 INTERAKTIVE CREDENTIALS-EINRICHTUNG"
|
||
|
||
echo ""
|
||
echo "🔑 CREDENTIALS ANPASSEN (Enter = Standard beibehalten)"
|
||
echo "====================================================="
|
||
|
||
# Secret Key
|
||
echo -n "MYP Secret Key [${MYP_SECRET_KEY:0:8}...]: "
|
||
read input_secret_key
|
||
if [ -n "$input_secret_key" ]; then
|
||
MYP_SECRET_KEY="$input_secret_key"
|
||
fi
|
||
|
||
# Main Password
|
||
echo -n "MYP Main Password [***]: "
|
||
read -s input_main_password
|
||
echo ""
|
||
if [ -n "$input_main_password" ]; then
|
||
MYP_MAIN_PASSWORD="$input_main_password"
|
||
fi
|
||
|
||
# SSH Password
|
||
echo -n "SSH Password [***]: "
|
||
read -s input_ssh_password
|
||
echo ""
|
||
if [ -n "$input_ssh_password" ]; then
|
||
MYP_SSH_PASSWORD="$input_ssh_password"
|
||
fi
|
||
|
||
# Admin Email
|
||
echo -n "Admin Email [$MYP_ADMIN_EMAIL]: "
|
||
read input_admin_email
|
||
if [ -n "$input_admin_email" ]; then
|
||
MYP_ADMIN_EMAIL="$input_admin_email"
|
||
fi
|
||
|
||
# TAPO Email
|
||
echo -n "TAPO Email [$MYP_TAPO_EMAIL]: "
|
||
read input_tapo_email
|
||
if [ -n "$input_tapo_email" ]; then
|
||
MYP_TAPO_EMAIL="$input_tapo_email"
|
||
fi
|
||
|
||
# TAPO Password
|
||
echo -n "TAPO Password [***]: "
|
||
read -s input_tapo_password
|
||
echo ""
|
||
if [ -n "$input_tapo_password" ]; then
|
||
MYP_TAPO_PASSWORD="$input_tapo_password"
|
||
fi
|
||
|
||
# Router Credentials
|
||
echo -n "Router User [$MYP_ROUTER_USER]: "
|
||
read input_router_user
|
||
if [ -n "$input_router_user" ]; then
|
||
MYP_ROUTER_USER="$input_router_user"
|
||
fi
|
||
|
||
echo -n "Router Password [***]: "
|
||
read -s input_router_password
|
||
echo ""
|
||
if [ -n "$input_router_password" ]; then
|
||
MYP_ROUTER_PASSWORD="$input_router_password"
|
||
fi
|
||
|
||
# GitHub Credentials
|
||
echo -n "GitHub Client ID [${MYP_GITHUB_CLIENT_ID:0:8}...]: "
|
||
read input_github_id
|
||
if [ -n "$input_github_id" ]; then
|
||
MYP_GITHUB_CLIENT_ID="$input_github_id"
|
||
fi
|
||
|
||
echo -n "GitHub Client Secret [***]: "
|
||
read -s input_github_secret
|
||
echo ""
|
||
if [ -n "$input_github_secret" ]; then
|
||
MYP_GITHUB_CLIENT_SECRET="$input_github_secret"
|
||
fi
|
||
|
||
echo ""
|
||
info "✅ Interaktive Credentials-Einrichtung abgeschlossen"
|
||
|
||
# Optional: Credentials in Override-Datei speichern
|
||
echo -n "Sollen die neuen Credentials gespeichert werden? (j/N): "
|
||
read save_credentials
|
||
if [[ "$save_credentials" =~ ^[jJ]$ ]]; then
|
||
save_credentials_override
|
||
fi
|
||
}
|
||
|
||
# Funktion: Credentials in Override-Datei speichern
|
||
save_credentials_override() {
|
||
local override_file="$CURRENT_DIR/CREDENTIALS_OVERRIDE.env"
|
||
|
||
progress "Speichere Credentials-Override in: $override_file"
|
||
cat > "$override_file" << EOF
|
||
# MYP Credentials Override
|
||
# Diese Datei überschreibt die Standard-Credentials
|
||
# Generiert: $(date '+%Y-%m-%d %H:%M:%S')
|
||
|
||
export MYP_SECRET_KEY_OVERRIDE="$MYP_SECRET_KEY"
|
||
export MYP_MAIN_PASSWORD_OVERRIDE="$MYP_MAIN_PASSWORD"
|
||
export MYP_SSH_PASSWORD_OVERRIDE="$MYP_SSH_PASSWORD"
|
||
export MYP_ADMIN_EMAIL_OVERRIDE="$MYP_ADMIN_EMAIL"
|
||
export MYP_TAPO_EMAIL_OVERRIDE="$MYP_TAPO_EMAIL"
|
||
export MYP_TAPO_PASSWORD_OVERRIDE="$MYP_TAPO_PASSWORD"
|
||
export MYP_ROUTER_USER_OVERRIDE="$MYP_ROUTER_USER"
|
||
export MYP_ROUTER_PASSWORD_OVERRIDE="$MYP_ROUTER_PASSWORD"
|
||
export MYP_GITHUB_CLIENT_ID_OVERRIDE="$MYP_GITHUB_CLIENT_ID"
|
||
export MYP_GITHUB_CLIENT_SECRET_OVERRIDE="$MYP_GITHUB_CLIENT_SECRET"
|
||
|
||
# Verwendung:
|
||
# source CREDENTIALS_OVERRIDE.env && sudo ./setup.sh
|
||
# oder
|
||
# MYP_SECRET_KEY_OVERRIDE="neuer_key" sudo ./setup.sh
|
||
EOF
|
||
|
||
chmod 600 "$override_file"
|
||
success "✅ Credentials-Override gespeichert: $override_file"
|
||
info " Verwendung: source $override_file && sudo ./setup.sh"
|
||
}
|
||
|
||
# Log-Dateien - verwende relatives logs-Verzeichnis
|
||
mkdir -p "$CURRENT_DIR/logs" 2>/dev/null || true
|
||
INSTALL_LOG="$CURRENT_DIR/logs/install.log"
|
||
ERROR_LOG="$CURRENT_DIR/logs/errors.log"
|
||
WARNING_LOG="$CURRENT_DIR/logs/warnings.log"
|
||
DEBUG_LOG="$CURRENT_DIR/logs/debug.log"
|
||
readonly HTTP_PORT="5000"
|
||
readonly HTTP_URL="http://localhost:${HTTP_PORT}"
|
||
readonly SYSTEMD_DIR="$CURRENT_DIR/systemd"
|
||
readonly SYSTEM_SYSTEMD_DIR="/etc/systemd/system"
|
||
|
||
# Retry-Konfiguration
|
||
readonly MAX_RETRIES=3
|
||
readonly RETRY_DELAY=5
|
||
|
||
# Farben für Ausgabe
|
||
readonly RED='\033[0;31m'
|
||
readonly GREEN='\033[0;32m'
|
||
readonly YELLOW='\033[1;33m'
|
||
readonly BLUE='\033[0;34m'
|
||
readonly PURPLE='\033[0;35m'
|
||
readonly CYAN='\033[0;36m'
|
||
readonly NC='\033[0m'
|
||
|
||
# =========================== AUTOMATISCHE MODUS-ERKENNUNG ===========================
|
||
detect_installation_mode() {
|
||
log "=== AUTOMATISCHE INSTALLATIONSMODUS-ERKENNUNG ==="
|
||
|
||
# Prüfe Kommandozeilen-Parameter
|
||
for arg in "$@"; do
|
||
case $arg in
|
||
--production|--prod|-p)
|
||
FORCE_PRODUCTION=true
|
||
log "🎯 Produktionsmodus durch Parameter erzwungen"
|
||
;;
|
||
--development|--dev|-d)
|
||
FORCE_DEVELOPMENT=true
|
||
log "🔧 Entwicklungsmodus durch Parameter erzwungen"
|
||
;;
|
||
--help|-h)
|
||
show_help
|
||
exit 0
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# Wenn explizit gesetzt, verwende das
|
||
if [ "$FORCE_PRODUCTION" = true ]; then
|
||
AUTO_INSTALL_MODE="production"
|
||
log "✅ Installationsmodus: PRODUKTION (erzwungen)"
|
||
return
|
||
elif [ "$FORCE_DEVELOPMENT" = true ]; then
|
||
AUTO_INSTALL_MODE="development"
|
||
log "✅ Installationsmodus: ENTWICKLUNG (erzwungen)"
|
||
return
|
||
fi
|
||
|
||
# Automatische Erkennung basierend auf Systemzustand
|
||
local indicators_production=0
|
||
local indicators_development=0
|
||
|
||
# Prüfe Hardware-Indikatoren
|
||
if grep -q "Raspberry Pi" /proc/cpuinfo 2>/dev/null; then
|
||
indicators_production=$((indicators_production + 2))
|
||
log "🔍 Raspberry Pi Hardware erkannt (+2 Punkte für Produktion)"
|
||
fi
|
||
|
||
# Prüfe RAM (weniger RAM = eher Produktion/Kiosk)
|
||
local ram_mb=$(free -m 2>/dev/null | awk '/^Mem:/{print $2}' 2>/dev/null || echo "0")
|
||
if [ "$ram_mb" -lt 2048 ] 2>/dev/null; then
|
||
indicators_production=$((indicators_production + 1))
|
||
log "🔍 Wenig RAM ($ram_mb MB) erkannt (+1 Punkt für Produktion)"
|
||
else
|
||
indicators_development=$((indicators_development + 1))
|
||
log "🔍 Viel RAM ($ram_mb MB) erkannt (+1 Punkt für Entwicklung)"
|
||
fi
|
||
|
||
# Prüfe ob Desktop-Environment vorhanden ist
|
||
if command -v gnome-session >/dev/null 2>&1 || command -v kde-session >/dev/null 2>&1 || command -v xfce4-session >/dev/null 2>&1; then
|
||
indicators_development=$((indicators_development + 2))
|
||
log "🔍 Desktop-Environment erkannt (+2 Punkte für Entwicklung)"
|
||
else
|
||
indicators_production=$((indicators_production + 1))
|
||
log "🔍 Kein Desktop-Environment erkannt (+1 Punkt für Produktion)"
|
||
fi
|
||
|
||
# Prüfe ob bereits Kiosk-User existiert
|
||
if id "$KIOSK_USER" >/dev/null 2>&1; then
|
||
indicators_production=$((indicators_production + 2))
|
||
log "🔍 Kiosk-User bereits vorhanden (+2 Punkte für Produktion)"
|
||
fi
|
||
|
||
# Prüfe ob bereits Services installiert sind
|
||
if systemctl list-unit-files | grep -q "$HTTP_SERVICE_NAME"; then
|
||
indicators_production=$((indicators_production + 1))
|
||
log "🔍 MYP-Services bereits installiert (+1 Punkt für Produktion)"
|
||
fi
|
||
|
||
# Prüfe SSH-Konfiguration (Remote-Zugang deutet auf Produktion hin)
|
||
if systemctl is-active ssh >/dev/null 2>&1; then
|
||
indicators_production=$((indicators_production + 1))
|
||
log "🔍 SSH-Service aktiv (+1 Punkt für Produktion)"
|
||
fi
|
||
|
||
# Prüfe ob Entwicklungstools vorhanden sind
|
||
if command -v git >/dev/null 2>&1 && command -v code >/dev/null 2>&1; then
|
||
indicators_development=$((indicators_development + 2))
|
||
log "🔍 Entwicklungstools erkannt (+2 Punkte für Entwicklung)"
|
||
fi
|
||
|
||
# Prüfe Hostname
|
||
local hostname=$(hostname 2>/dev/null || echo "")
|
||
if [[ "$hostname" == *"kiosk"* ]] || [[ "$hostname" == *"display"* ]] || [[ "$hostname" == *"terminal"* ]]; then
|
||
indicators_production=$((indicators_production + 2))
|
||
log "🔍 Kiosk-Hostname erkannt: $hostname (+2 Punkte für Produktion)"
|
||
elif [[ "$hostname" == *"dev"* ]] || [[ "$hostname" == *"development"* ]]; then
|
||
indicators_development=$((indicators_development + 2))
|
||
log "🔍 Entwicklungs-Hostname erkannt: $hostname (+2 Punkte für Entwicklung)"
|
||
fi
|
||
|
||
# Entscheidung treffen
|
||
log "📊 Bewertung: Produktion=$indicators_production, Entwicklung=$indicators_development"
|
||
|
||
if [ $indicators_production -gt $indicators_development ]; then
|
||
AUTO_INSTALL_MODE="production"
|
||
log "✅ Automatisch erkannt: PRODUKTIONS-INSTALLATION"
|
||
log " → Vollständige Kiosk-Installation mit Remote-Zugang"
|
||
elif [ $indicators_development -gt $indicators_production ]; then
|
||
AUTO_INSTALL_MODE="development"
|
||
log "✅ Automatisch erkannt: ENTWICKLUNGS-INSTALLATION"
|
||
log " → Abhängigkeiten und System für manuelles Testen"
|
||
else
|
||
# Bei Gleichstand: Default zu Entwicklung (sicherer)
|
||
AUTO_INSTALL_MODE="development"
|
||
log "⚖️ Unentschieden - Standard: ENTWICKLUNGS-INSTALLATION"
|
||
log " → Verwenden Sie --production für Kiosk-Installation"
|
||
fi
|
||
}
|
||
|
||
show_help() {
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo -e "${CYAN} $APP_NAME - Automatisches Setup-Skript v$APP_VERSION${NC}"
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo ""
|
||
echo -e "${YELLOW}VERWENDUNG:${NC}"
|
||
echo -e " sudo $0 [OPTIONEN]"
|
||
echo ""
|
||
echo -e "${YELLOW}OPTIONEN:${NC}"
|
||
echo -e " ${GREEN}--production, --prod, -p${NC} Erzwinge Produktions-Installation"
|
||
echo -e " → Vollständige Kiosk-Installation"
|
||
echo -e " → Remote-Zugang (RDP/SSH)"
|
||
echo -e " → Automatischer Kiosk-Start"
|
||
echo ""
|
||
echo -e " ${GREEN}--development, --dev, -d${NC} Erzwinge Entwicklungs-Installation"
|
||
echo -e " → Nur Abhängigkeiten und Basis-System"
|
||
echo -e " → Für manuelle Tests und Entwicklung"
|
||
echo ""
|
||
echo -e " ${GREEN}--help, -h${NC} Zeige diese Hilfe"
|
||
echo ""
|
||
echo -e "${YELLOW}AUTOMATISCHE ERKENNUNG:${NC}"
|
||
echo -e " Ohne Parameter erkennt das Skript automatisch den besten Modus:"
|
||
echo -e " • Raspberry Pi Hardware → Produktion"
|
||
echo -e " • Wenig RAM (< 2GB) → Produktion"
|
||
echo -e " • Kein Desktop-Environment → Produktion"
|
||
echo -e " • Entwicklungstools vorhanden → Entwicklung"
|
||
echo -e " • Viel RAM (≥ 2GB) → Entwicklung"
|
||
echo ""
|
||
echo -e "${YELLOW}BEISPIELE:${NC}"
|
||
echo -e " ${CYAN}sudo $0${NC} # Automatische Erkennung"
|
||
echo -e " ${CYAN}sudo $0 --production${NC} # Erzwinge Kiosk-Installation"
|
||
echo -e " ${CYAN}sudo $0 --development${NC} # Erzwinge Entwicklungs-Setup"
|
||
echo ""
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
}
|
||
|
||
# =========================== UMFASSENDE CREDENTIALS VALIDIERUNG ===========================
|
||
validate_credentials_comprehensive() {
|
||
log "=== VALIDIERE CREDENTIALS KONFIGURATION ==="
|
||
|
||
local validation_errors=0
|
||
|
||
# Prüfe ob alle wichtigen Credentials gesetzt sind
|
||
if [ -z "$MYP_SECRET_KEY" ] || [ ${#MYP_SECRET_KEY} -lt 32 ]; then
|
||
error "MYP_SECRET_KEY ist nicht gesetzt oder zu kurz"
|
||
((validation_errors++))
|
||
fi
|
||
|
||
if [ -z "$MYP_MAIN_PASSWORD" ] || [ ${#MYP_MAIN_PASSWORD} -lt 8 ]; then
|
||
error "MYP_MAIN_PASSWORD ist nicht gesetzt oder zu kurz"
|
||
((validation_errors++))
|
||
fi
|
||
|
||
if [ -z "$MYP_SSH_PASSWORD" ] || [ ${#MYP_SSH_PASSWORD} -lt 4 ]; then
|
||
error "MYP_SSH_PASSWORD ist nicht gesetzt oder zu kurz"
|
||
((validation_errors++))
|
||
fi
|
||
|
||
if [ -z "$MYP_ADMIN_EMAIL" ] || [[ ! "$MYP_ADMIN_EMAIL" =~ @.*\. ]]; then
|
||
error "MYP_ADMIN_EMAIL ist nicht gesetzt oder ungültig"
|
||
((validation_errors++))
|
||
fi
|
||
|
||
if [ -z "$MYP_TAPO_EMAIL" ] || [[ ! "$MYP_TAPO_EMAIL" =~ @.*\. ]]; then
|
||
error "MYP_TAPO_EMAIL ist nicht gesetzt oder ungültig"
|
||
((validation_errors++))
|
||
fi
|
||
|
||
if [ -z "$MYP_GITHUB_CLIENT_ID" ] || [ ${#MYP_GITHUB_CLIENT_ID} -lt 16 ]; then
|
||
error "MYP_GITHUB_CLIENT_ID ist nicht gesetzt oder zu kurz"
|
||
((validation_errors++))
|
||
fi
|
||
|
||
if [ -z "$MYP_GITHUB_CLIENT_SECRET" ] || [ ${#MYP_GITHUB_CLIENT_SECRET} -lt 32 ]; then
|
||
error "MYP_GITHUB_CLIENT_SECRET ist nicht gesetzt oder zu kurz"
|
||
((validation_errors++))
|
||
fi
|
||
|
||
if [ $validation_errors -eq 0 ]; then
|
||
success "✅ Alle Credentials korrekt konfiguriert"
|
||
log " 🔑 SECRET_KEY: ${MYP_SECRET_KEY:0:8}... (${#MYP_SECRET_KEY} Zeichen)"
|
||
log " 🔒 MAIN_PASSWORD: ${MYP_MAIN_PASSWORD:0:4}... (${#MYP_MAIN_PASSWORD} Zeichen)"
|
||
log " 📧 ADMIN_EMAIL: $MYP_ADMIN_EMAIL"
|
||
log " 📧 TAPO_EMAIL: $MYP_TAPO_EMAIL"
|
||
log " 🐙 GITHUB_CLIENT_ID: ${MYP_GITHUB_CLIENT_ID:0:8}..."
|
||
else
|
||
error "❌ $validation_errors Credentials-Fehler gefunden - Installation abgebrochen"
|
||
fi
|
||
}
|
||
|
||
# =========================== LOG-DATEIEN INITIALISIERUNG ===========================
|
||
# Log-Dateien - verwende relatives logs-Verzeichnis (falls noch nicht definiert)
|
||
if [ -z "$INSTALL_LOG" ]; then
|
||
mkdir -p "$CURRENT_DIR/logs" 2>/dev/null || true
|
||
INSTALL_LOG="$CURRENT_DIR/logs/install.log"
|
||
ERROR_LOG="$CURRENT_DIR/logs/errors.log"
|
||
WARNING_LOG="$CURRENT_DIR/logs/warnings.log"
|
||
DEBUG_LOG="$CURRENT_DIR/logs/debug.log"
|
||
fi
|
||
|
||
# =========================== VERBESSERTE LOGGING-FUNKTIONEN ===========================
|
||
# Globale Variablen für Fehler-Tracking
|
||
ERROR_COUNT=0
|
||
WARNING_COUNT=0
|
||
|
||
# Log-Dateien initialisieren
|
||
init_logging() {
|
||
# Sichere Log-Verzeichnis-Erstellung
|
||
if ! mkdir -p "$CURRENT_DIR/logs" 2>/dev/null; then
|
||
echo "FEHLER: Kann logs-Verzeichnis nicht erstellen - verwende /tmp" >&2
|
||
INSTALL_LOG="/tmp/myp-install.log"
|
||
ERROR_LOG="/tmp/myp-install-errors.log"
|
||
WARNING_LOG="/tmp/myp-install-warnings.log"
|
||
DEBUG_LOG="/tmp/myp-install-debug.log"
|
||
fi
|
||
|
||
# Überschreibe bestehende Log-Dateien
|
||
{
|
||
echo "================================================================="
|
||
echo "MYP Installation Log - $(date '+%Y-%m-%d %H:%M:%S')"
|
||
echo "Script Version: $APP_VERSION"
|
||
echo "System: $(timeout 5 uname -a 2>/dev/null || echo 'System-Info nicht verfügbar')"
|
||
echo "Arbeitsverzeichnis: $CURRENT_DIR"
|
||
echo "Log-Verzeichnis: $(dirname "$INSTALL_LOG")"
|
||
echo "================================================================="
|
||
echo ""
|
||
} > "$INSTALL_LOG" 2>/dev/null || {
|
||
echo "KRITISCH: Kann Haupt-Log nicht schreiben!" >&2
|
||
exit 1
|
||
}
|
||
|
||
{
|
||
echo "================================================================="
|
||
echo "MYP Installation FEHLER Log - $(date '+%Y-%m-%d %H:%M:%S')"
|
||
echo "================================================================="
|
||
echo ""
|
||
} > "$ERROR_LOG"
|
||
|
||
{
|
||
echo "================================================================="
|
||
echo "MYP Installation WARNUNGEN Log - $(date '+%Y-%m-%d %H:%M:%S')"
|
||
echo "================================================================="
|
||
echo ""
|
||
} > "$WARNING_LOG"
|
||
|
||
{
|
||
echo "================================================================="
|
||
echo "MYP Installation DEBUG Log - $(date '+%Y-%m-%d %H:%M:%S')"
|
||
echo "================================================================="
|
||
echo ""
|
||
} > "$DEBUG_LOG"
|
||
}
|
||
|
||
log() {
|
||
local message="[$(date '+%Y-%m-%d %H:%M:%S')] $1"
|
||
echo -e "${GREEN}${message}${NC}" | tee -a "$INSTALL_LOG"
|
||
}
|
||
|
||
error() {
|
||
local timestamp="$(date '+%Y-%m-%d %H:%M:%S')"
|
||
local caller="${BASH_SOURCE[1]##*/}:${BASH_LINENO[0]}"
|
||
local message="[FEHLER] $1"
|
||
|
||
# Erhöhe Fehler-Zähler
|
||
((ERROR_COUNT++))
|
||
|
||
# Ausgabe auf Konsole
|
||
echo -e "${RED}${message}${NC}" | tee -a "$INSTALL_LOG"
|
||
|
||
# Detaillierte Fehler-Information in Fehler-Log
|
||
{
|
||
echo "[$timestamp] FEHLER #$ERROR_COUNT"
|
||
echo "Quelle: $caller"
|
||
echo "Nachricht: $1"
|
||
echo "Arbeitsverzeichnis: $(pwd)"
|
||
echo "Benutzer: $(whoami)"
|
||
echo "---"
|
||
echo ""
|
||
} >> "$ERROR_LOG"
|
||
|
||
# Debug-Informationen sammeln
|
||
{
|
||
echo "[$timestamp] FEHLER AUFGETRETEN - Debug-Info:"
|
||
echo "Caller: $caller"
|
||
echo "PWD: $(pwd)"
|
||
echo "User: $(whoami)"
|
||
echo "Disk Space: $(df -h / | tail -1)"
|
||
echo "Memory: $(free -m | grep '^Mem:' | awk '{print $3"/"$2" MB"}')"
|
||
echo "Load Average: $(uptime | awk -F'load average:' '{print $2}')"
|
||
echo "Recent commands from history:"
|
||
history | tail -5 2>/dev/null || echo "History nicht verfügbar"
|
||
echo "==============================================="
|
||
echo ""
|
||
} >> "$DEBUG_LOG"
|
||
|
||
exit 1
|
||
}
|
||
|
||
warning() {
|
||
local timestamp="$(date '+%Y-%m-%d %H:%M:%S')"
|
||
local caller="${BASH_SOURCE[1]##*/}:${BASH_LINENO[0]}"
|
||
local message="[WARNUNG] $1"
|
||
|
||
# Erhöhe Warnungs-Zähler
|
||
((WARNING_COUNT++))
|
||
|
||
# Ausgabe auf Konsole
|
||
echo -e "${YELLOW}${message}${NC}" | tee -a "$INSTALL_LOG"
|
||
|
||
# Detaillierte Warnungs-Information in Warnungs-Log
|
||
{
|
||
echo "[$timestamp] WARNUNG #$WARNING_COUNT"
|
||
echo "Quelle: $caller"
|
||
echo "Nachricht: $1"
|
||
echo "---"
|
||
echo ""
|
||
} >> "$WARNING_LOG"
|
||
}
|
||
|
||
info() {
|
||
echo -e "${BLUE}[INFO] $1${NC}" | tee -a "$INSTALL_LOG"
|
||
}
|
||
|
||
progress() {
|
||
echo -e "${PURPLE}[FORTSCHRITT] $1${NC}" | tee -a "$INSTALL_LOG"
|
||
}
|
||
|
||
success() {
|
||
echo -e "${CYAN}[ERFOLG] $1${NC}" | tee -a "$INSTALL_LOG"
|
||
}
|
||
|
||
debug() {
|
||
local timestamp="$(date '+%Y-%m-%d %H:%M:%S')"
|
||
local caller="${BASH_SOURCE[1]##*/}:${BASH_LINENO[0]}"
|
||
|
||
# Debug sowohl in normales Log als auch Debug-Log
|
||
echo -e "${BLUE}[DEBUG] $1${NC}" >> "$INSTALL_LOG"
|
||
|
||
{
|
||
echo "[$timestamp] DEBUG von $caller"
|
||
echo "$1"
|
||
echo "---"
|
||
echo ""
|
||
} >> "$DEBUG_LOG"
|
||
}
|
||
|
||
# Fehler-Zusammenfassung anzeigen
|
||
show_error_summary() {
|
||
echo ""
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo -e "${CYAN} INSTALLATION ABGESCHLOSSEN - FEHLER-ZUSAMMENFASSUNG${NC}"
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo ""
|
||
|
||
echo -e "${BLUE}📊 Statistiken:${NC}"
|
||
echo -e " ${RED}❌ Fehler: $ERROR_COUNT${NC}"
|
||
echo -e " ${YELLOW}⚠️ Warnungen: $WARNING_COUNT${NC}"
|
||
echo ""
|
||
|
||
echo -e "${BLUE}📁 Log-Dateien:${NC}"
|
||
echo -e " 📄 Vollständiges Log: $INSTALL_LOG"
|
||
echo -e " 🚨 Fehler-Log: $ERROR_LOG"
|
||
echo -e " ⚠️ Warnungs-Log: $WARNING_LOG"
|
||
echo -e " 🔍 Debug-Log: $DEBUG_LOG"
|
||
echo ""
|
||
|
||
if [ $ERROR_COUNT -gt 0 ]; then
|
||
echo -e "${RED}⚠️ Es sind $ERROR_COUNT Fehler aufgetreten!${NC}"
|
||
echo -e "${RED} Bitte prüfen Sie: $ERROR_LOG${NC}"
|
||
echo ""
|
||
|
||
# Zeige die letzten 3 Fehler an
|
||
if [ -f "$ERROR_LOG" ] && [ -s "$ERROR_LOG" ]; then
|
||
echo -e "${RED}🔍 Letzte Fehler:${NC}"
|
||
tail -n 20 "$ERROR_LOG" | head -n 15
|
||
echo ""
|
||
fi
|
||
fi
|
||
|
||
if [ $WARNING_COUNT -gt 0 ]; then
|
||
echo -e "${YELLOW}⚠️ Es sind $WARNING_COUNT Warnungen aufgetreten${NC}"
|
||
echo -e "${YELLOW} Bitte prüfen Sie: $WARNING_LOG${NC}"
|
||
echo ""
|
||
fi
|
||
|
||
if [ $ERROR_COUNT -eq 0 ] && [ $WARNING_COUNT -eq 0 ]; then
|
||
echo -e "${GREEN}✅ Installation ohne Fehler oder Warnungen abgeschlossen!${NC}"
|
||
elif [ $ERROR_COUNT -eq 0 ]; then
|
||
echo -e "${GREEN}✅ Installation erfolgreich mit $WARNING_COUNT Warnungen${NC}"
|
||
fi
|
||
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
|
||
# Erstelle automatische Log-Zusammenfassung
|
||
create_log_summary
|
||
}
|
||
|
||
# Automatische Log-Zusammenfassung erstellen
|
||
create_log_summary() {
|
||
local summary_file="$CURRENT_DIR/logs/install-summary.txt"
|
||
|
||
{
|
||
echo "================================================================="
|
||
echo "MYP INSTALLATION ZUSAMMENFASSUNG"
|
||
echo "Erstellt: $(date '+%Y-%m-%d %H:%M:%S')"
|
||
echo "================================================================="
|
||
echo ""
|
||
echo "STATISTIKEN:"
|
||
echo "- Fehler: $ERROR_COUNT"
|
||
echo "- Warnungen: $WARNING_COUNT"
|
||
echo "- Script Version: $APP_VERSION"
|
||
echo "- System: $(uname -a 2>/dev/null || echo 'Unbekannt')"
|
||
echo "- Hostname: $(hostname 2>/dev/null || echo 'Unbekannt')"
|
||
echo "- User: $(whoami 2>/dev/null || echo 'Unbekannt')"
|
||
echo ""
|
||
echo "SYSTEM-INFORMATIONEN:"
|
||
echo "- Festplattenspeicher: $(df -h / | tail -1 2>/dev/null || echo 'Nicht verfügbar')"
|
||
echo "- Arbeitsspeicher: $(free -m | grep '^Mem:' | awk '{print $3"/"$2" MB"}' 2>/dev/null || echo 'Nicht verfügbar')"
|
||
echo "- Python Version: $(python3 --version 2>&1 || echo 'Nicht installiert')"
|
||
echo "- Node.js Version: $(node --version 2>&1 || echo 'Nicht installiert')"
|
||
echo ""
|
||
echo "LOG-DATEIEN:"
|
||
echo "- Vollständiges Log: $INSTALL_LOG"
|
||
echo "- Fehler-Log: $ERROR_LOG"
|
||
echo "- Warnungs-Log: $WARNING_LOG"
|
||
echo "- Debug-Log: $DEBUG_LOG"
|
||
echo ""
|
||
|
||
if [ $ERROR_COUNT -gt 0 ] && [ -f "$ERROR_LOG" ] && [ -s "$ERROR_LOG" ]; then
|
||
echo "FEHLER-ÜBERSICHT:"
|
||
echo "================="
|
||
tail -n 50 "$ERROR_LOG"
|
||
echo ""
|
||
fi
|
||
|
||
if [ $WARNING_COUNT -gt 0 ] && [ -f "$WARNING_LOG" ] && [ -s "$WARNING_LOG" ]; then
|
||
echo "WARNUNGS-ÜBERSICHT:"
|
||
echo "==================="
|
||
tail -n 30 "$WARNING_LOG"
|
||
echo ""
|
||
fi
|
||
|
||
echo "INSTALLATION ABGESCHLOSSEN: $(date '+%Y-%m-%d %H:%M:%S')"
|
||
echo "================================================================="
|
||
|
||
} > "$summary_file"
|
||
|
||
# Berechtigung für Zusammenfassungs-Datei setzen
|
||
chmod 644 "$summary_file" 2>/dev/null || true
|
||
|
||
debug "Log-Zusammenfassung erstellt: $summary_file"
|
||
}
|
||
|
||
# =========================== RETRY-MECHANISMEN ===========================
|
||
retry_command() {
|
||
local cmd="$1"
|
||
local description="$2"
|
||
local attempts=0
|
||
|
||
while [ $attempts -lt $MAX_RETRIES ]; do
|
||
if eval "$cmd"; then
|
||
return 0
|
||
fi
|
||
|
||
attempts=$((attempts + 1))
|
||
if [ $attempts -lt $MAX_RETRIES ]; then
|
||
warning "$description fehlgeschlagen (Versuch $attempts/$MAX_RETRIES) - wiederhole in ${RETRY_DELAY}s..."
|
||
|
||
# Debug-Information für jeden fehlgeschlagenen Versuch
|
||
debug "Retry-Versuch für '$description': $attempts/$MAX_RETRIES"
|
||
debug "Fehlgeschlagener Befehl: $cmd"
|
||
debug "Aktuelles Arbeitsverzeichnis: $(pwd)"
|
||
debug "Verfügbarer Speicher: $(free -m | grep '^Mem:' | awk '{print $3"/"$2" MB"}' 2>/dev/null || echo 'Unbekannt')"
|
||
debug "Exit-Code des letzten Befehls: $?"
|
||
|
||
sleep $RETRY_DELAY
|
||
fi
|
||
done
|
||
|
||
# Detaillierte Fehler-Information vor dem Beenden
|
||
debug "CRITICAL: Retry-Mechanismus erschöpft für '$description'"
|
||
debug "Letzter Befehl: $cmd"
|
||
debug "Versuche: $MAX_RETRIES"
|
||
debug "System-Status zum Zeitpunkt des kritischen Fehlers:"
|
||
debug " - Disk Usage: $(df -h / | tail -1 2>/dev/null || echo 'Nicht verfügbar')"
|
||
debug " - Memory Usage: $(free -m 2>/dev/null || echo 'Nicht verfügbar')"
|
||
debug " - Load Average: $(uptime 2>/dev/null | awk -F'load average:' '{print $2}' || echo 'Nicht verfügbar')"
|
||
debug " - Network Status: $(ip addr show 2>/dev/null | grep 'inet ' | grep -v '127.0.0.1' || echo 'Nicht verfügbar')"
|
||
debug " - APT Status: $(ps aux | grep -i apt | grep -v grep || echo 'Keine APT-Prozesse')"
|
||
debug " - Python Status: $(python3 --version 2>&1 || echo 'Python nicht verfügbar')"
|
||
|
||
error "$description nach $MAX_RETRIES Versuchen fehlgeschlagen!"
|
||
}
|
||
|
||
# APT-Pakete mit Retry installieren
|
||
apt_install_retry() {
|
||
local packages="$*"
|
||
local cmd="DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $packages"
|
||
|
||
progress "Installiere Pakete: $packages"
|
||
retry_command "$cmd" "APT Installation für: $packages"
|
||
}
|
||
|
||
# =========================== ERWEITERTE SYSTEM-VALIDIERUNG ===========================
|
||
check_root() {
|
||
if [ "$EUID" -ne 0 ]; then
|
||
error "Dieses Skript muss als Root ausgeführt werden: sudo $0"
|
||
fi
|
||
export PATH="/usr/sbin:/sbin:/usr/bin:/bin:/usr/local/bin:$PATH"
|
||
log "✅ Root-Berechtigung bestätigt"
|
||
}
|
||
|
||
check_system_resources() {
|
||
log "=== SYSTEM-RESSOURCEN PRÜFUNG ==="
|
||
|
||
# RAM prüfen (robuster)
|
||
progress "Prüfe RAM..."
|
||
local ram_mb=""
|
||
|
||
# Verschiedene Methoden zur RAM-Ermittlung
|
||
if command -v free >/dev/null 2>&1; then
|
||
ram_mb=$(free -m 2>/dev/null | awk '/^Mem:/{print $2}' 2>/dev/null || echo "")
|
||
fi
|
||
|
||
# Fallback über /proc/meminfo
|
||
if [ -z "$ram_mb" ] && [ -f "/proc/meminfo" ]; then
|
||
ram_mb=$(grep '^MemTotal:' /proc/meminfo 2>/dev/null | awk '{print int($2/1024)}' 2>/dev/null || echo "")
|
||
fi
|
||
|
||
if [ -n "$ram_mb" ] && [ "$ram_mb" -gt 0 ] 2>/dev/null; then
|
||
progress "Verfügbarer RAM: ${ram_mb}MB"
|
||
|
||
if [ "$ram_mb" -lt 512 ] 2>/dev/null; then
|
||
warning "⚠️ Wenig RAM verfügbar (${ram_mb}MB) - Installation könnte langsam sein"
|
||
else
|
||
success "✅ Ausreichend RAM verfügbar (${ram_mb}MB)"
|
||
fi
|
||
else
|
||
warning "⚠️ RAM-Größe konnte nicht ermittelt werden"
|
||
debug "RAM-Ermittlung fehlgeschlagen: free-Output: $(free -m 2>&1 || echo 'Befehl nicht verfügbar')"
|
||
fi
|
||
|
||
# Festplattenplatz prüfen (robuster ohne bc)
|
||
progress "Prüfe Festplattenplatz..."
|
||
local disk_free_gb=""
|
||
local disk_free_mb=""
|
||
|
||
if command -v df >/dev/null 2>&1; then
|
||
# Hole Festplattenplatz in MB
|
||
disk_free_mb=$(df / 2>/dev/null | awk 'NR==2{print int($4/1024)}' 2>/dev/null || echo "")
|
||
|
||
if [ -n "$disk_free_mb" ] && [ "$disk_free_mb" -gt 0 ] 2>/dev/null; then
|
||
# Berechne GB ohne bc (einfache Division)
|
||
disk_free_gb=$(awk -v mb="$disk_free_mb" 'BEGIN{printf "%.1f", mb/1024}' 2>/dev/null || echo "$((disk_free_mb/1024))")
|
||
|
||
progress "Verfügbarer Festplattenplatz: ${disk_free_gb}GB (${disk_free_mb}MB)"
|
||
|
||
# Prüfe ob mindestens 2GB verfügbar (2048 MB)
|
||
if [ "$disk_free_mb" -lt 2048 ] 2>/dev/null; then
|
||
warning "⚠️ Wenig Festplattenplatz verfügbar (${disk_free_gb}GB)"
|
||
else
|
||
success "✅ Ausreichend Festplattenplatz verfügbar (${disk_free_gb}GB)"
|
||
fi
|
||
else
|
||
warning "⚠️ Festplattenplatz konnte nicht ermittelt werden"
|
||
debug "Disk-Ermittlung fehlgeschlagen: df-Output: $(df / 2>&1 || echo 'Befehl nicht verfügbar')"
|
||
fi
|
||
else
|
||
warning "⚠️ df-Befehl nicht verfügbar - kann Festplattenplatz nicht prüfen"
|
||
fi
|
||
|
||
# CPU prüfen (robuster)
|
||
progress "Prüfe CPU..."
|
||
local cpu_count=""
|
||
local cpu_model=""
|
||
|
||
# CPU-Anzahl ermitteln
|
||
if command -v nproc >/dev/null 2>&1; then
|
||
cpu_count=$(nproc 2>/dev/null || echo "")
|
||
fi
|
||
|
||
if [ -z "$cpu_count" ] && [ -f "/proc/cpuinfo" ]; then
|
||
cpu_count=$(grep -c '^processor' /proc/cpuinfo 2>/dev/null || echo "")
|
||
fi
|
||
|
||
# CPU-Modell ermitteln
|
||
if [ -f "/proc/cpuinfo" ]; then
|
||
cpu_model=$(grep "model name" /proc/cpuinfo 2>/dev/null | head -1 | cut -d: -f2 2>/dev/null | sed 's/^[[:space:]]*//' 2>/dev/null || echo "Unbekannt")
|
||
fi
|
||
|
||
if [ -n "$cpu_count" ] && [ "$cpu_count" -gt 0 ] 2>/dev/null; then
|
||
progress "CPU: $cpu_count Kern(e) - $cpu_model"
|
||
success "✅ CPU-Information erfolgreich ermittelt"
|
||
else
|
||
progress "CPU: Unbekannte Anzahl Kerne - $cpu_model"
|
||
warning "⚠️ CPU-Kern-Anzahl konnte nicht ermittelt werden"
|
||
debug "CPU-Ermittlung fehlgeschlagen: nproc-Output: $(nproc 2>&1 || echo 'Befehl nicht verfügbar')"
|
||
fi
|
||
|
||
log "✅ System-Ressourcen-Prüfung abgeschlossen"
|
||
}
|
||
|
||
check_debian_system() {
|
||
progress "Prüfe Debian/Raspbian-System..."
|
||
|
||
# Robuste Debian-Erkennung
|
||
local is_debian=false
|
||
local debian_version="Unbekannt"
|
||
|
||
# Verschiedene Methoden zur Debian-Erkennung
|
||
if [ -f /etc/debian_version ]; then
|
||
debian_version=$(cat /etc/debian_version 2>/dev/null | head -1 | tr -d '\n\r' || echo "Unbekannt")
|
||
is_debian=true
|
||
debug "Debian erkannt über /etc/debian_version: $debian_version"
|
||
fi
|
||
|
||
# Fallback über os-release
|
||
if [ "$is_debian" = false ] && [ -f /etc/os-release ]; then
|
||
local os_id=$(grep '^ID=' /etc/os-release 2>/dev/null | cut -d= -f2 | tr -d '"' || echo "")
|
||
if [[ "$os_id" =~ ^(debian|raspbian|ubuntu)$ ]]; then
|
||
is_debian=true
|
||
local os_version=$(grep '^VERSION=' /etc/os-release 2>/dev/null | cut -d= -f2 | tr -d '"' || echo "Unbekannt")
|
||
debian_version="$os_id $os_version"
|
||
debug "Debian-basiertes System erkannt über os-release: $debian_version"
|
||
fi
|
||
fi
|
||
|
||
# Fallback über lsb_release
|
||
if [ "$is_debian" = false ] && command -v lsb_release >/dev/null 2>&1; then
|
||
local lsb_id=$(lsb_release -si 2>/dev/null | tr '[:upper:]' '[:lower:]' || echo "")
|
||
if [[ "$lsb_id" =~ ^(debian|raspbian|ubuntu)$ ]]; then
|
||
is_debian=true
|
||
debian_version="$lsb_id $(lsb_release -sr 2>/dev/null || echo 'Unbekannt')"
|
||
debug "Debian-basiertes System erkannt über lsb_release: $debian_version"
|
||
fi
|
||
fi
|
||
|
||
if [ "$is_debian" = false ]; then
|
||
warning "⚠️ System ist möglicherweise nicht Debian/Raspbian-basiert!"
|
||
warning "⚠️ Installation wird fortgesetzt, könnte aber fehlschlagen"
|
||
debug "System-Erkennung fehlgeschlagen. Verfügbare Info:"
|
||
debug " - /etc/debian_version: $([ -f /etc/debian_version ] && echo 'vorhanden' || echo 'nicht vorhanden')"
|
||
debug " - /etc/os-release: $([ -f /etc/os-release ] && grep '^ID=' /etc/os-release 2>/dev/null || echo 'nicht verfügbar')"
|
||
debug " - lsb_release: $(command -v lsb_release >/dev/null 2>&1 && lsb_release -si 2>/dev/null || echo 'nicht verfügbar')"
|
||
else
|
||
log "✅ Debian/Raspbian-basiertes System erkannt (Version: $debian_version)"
|
||
fi
|
||
|
||
# Prüfe auf Raspberry Pi (robuster)
|
||
progress "Prüfe Raspberry Pi Hardware..."
|
||
local is_raspberry_pi=false
|
||
local pi_model="Unbekannt"
|
||
|
||
# Methode 1: Device Tree Model
|
||
if [ -f /proc/device-tree/model ]; then
|
||
pi_model=$(cat /proc/device-tree/model 2>/dev/null | tr -d '\0\n\r' | head -c 100 || echo "")
|
||
if [[ "$pi_model" =~ [Rr]aspberry.*[Pp]i ]]; then
|
||
is_raspberry_pi=true
|
||
debug "Raspberry Pi erkannt über device-tree: $pi_model"
|
||
fi
|
||
fi
|
||
|
||
# Methode 2: CPU Info
|
||
if [ "$is_raspberry_pi" = false ] && [ -f /proc/cpuinfo ]; then
|
||
local cpu_hardware=$(grep '^Hardware' /proc/cpuinfo 2>/dev/null | cut -d: -f2 | sed 's/^[[:space:]]*//' | head -1 || echo "")
|
||
local cpu_model=$(grep '^Model' /proc/cpuinfo 2>/dev/null | cut -d: -f2 | sed 's/^[[:space:]]*//' | head -1 || echo "")
|
||
|
||
if [[ "$cpu_hardware" =~ [Bb][Cc][Mm] ]] || [[ "$cpu_model" =~ [Rr]aspberry.*[Pp]i ]]; then
|
||
is_raspberry_pi=true
|
||
pi_model="$cpu_model ($cpu_hardware)"
|
||
debug "Raspberry Pi erkannt über cpuinfo: $pi_model"
|
||
fi
|
||
fi
|
||
|
||
if [ "$is_raspberry_pi" = true ]; then
|
||
info "🍓 Raspberry Pi erkannt: $pi_model"
|
||
progress "Aktiviere Raspberry Pi spezifische Optimierungen..."
|
||
export RASPBERRY_PI_DETECTED=1
|
||
debug "Raspberry Pi Optimierungen aktiviert"
|
||
else
|
||
info "💻 Standard-PC/Server System (kein Raspberry Pi)"
|
||
debug "Kein Raspberry Pi erkannt. Hardware-Info:"
|
||
debug " - Device Tree: $([ -f /proc/device-tree/model ] && cat /proc/device-tree/model 2>/dev/null | tr -d '\0' || echo 'nicht verfügbar')"
|
||
debug " - CPU Hardware: $(grep '^Hardware' /proc/cpuinfo 2>/dev/null | cut -d: -f2 | sed 's/^[[:space:]]*//' || echo 'nicht verfügbar')"
|
||
fi
|
||
|
||
# System-Architektur prüfen (robuster)
|
||
progress "Prüfe System-Architektur..."
|
||
local arch=""
|
||
|
||
if command -v uname >/dev/null 2>&1; then
|
||
arch=$(uname -m 2>/dev/null || echo "Unbekannt")
|
||
info "📐 System-Architektur: $arch"
|
||
|
||
# Architektur-spezifische Hinweise
|
||
case "$arch" in
|
||
"aarch64"|"arm64")
|
||
info " → 64-Bit ARM Architektur erkannt"
|
||
;;
|
||
"armv7l"|"armv6l")
|
||
info " → 32-Bit ARM Architektur erkannt"
|
||
;;
|
||
"x86_64"|"amd64")
|
||
info " → 64-Bit x86 Architektur erkannt"
|
||
;;
|
||
"i386"|"i686")
|
||
info " → 32-Bit x86 Architektur erkannt"
|
||
;;
|
||
*)
|
||
warning "⚠️ Unbekannte Architektur: $arch"
|
||
;;
|
||
esac
|
||
else
|
||
warning "⚠️ uname-Befehl nicht verfügbar - kann Architektur nicht ermitteln"
|
||
fi
|
||
|
||
# Kernel-Version prüfen (robuster)
|
||
progress "Prüfe Kernel-Version..."
|
||
local kernel=""
|
||
|
||
if command -v uname >/dev/null 2>&1; then
|
||
kernel=$(uname -r 2>/dev/null || echo "Unbekannt")
|
||
info "🐧 Kernel-Version: $kernel"
|
||
debug "Vollständige Kernel-Info: $(uname -a 2>/dev/null || echo 'Nicht verfügbar')"
|
||
else
|
||
warning "⚠️ Kernel-Version konnte nicht ermittelt werden"
|
||
fi
|
||
|
||
log "✅ System-Analyse abgeschlossen"
|
||
}
|
||
|
||
check_internet_connection() {
|
||
progress "Prüfe Internetverbindung (erweiterte Methoden)..."
|
||
|
||
local connection_ok=false
|
||
local test_method=""
|
||
local debug_info=""
|
||
|
||
# Methode 1: DNS-Auflösung (robuster)
|
||
progress "Teste DNS-Auflösung..."
|
||
local dns_hosts=("8.8.8.8" "1.1.1.1" "google.com" "cloudflare.com")
|
||
|
||
for host in "${dns_hosts[@]}"; do
|
||
debug_info="${debug_info}Teste DNS für $host: "
|
||
|
||
# Teste nslookup
|
||
if command -v nslookup >/dev/null 2>&1; then
|
||
if timeout 10 nslookup "$host" >/dev/null 2>&1; then
|
||
connection_ok=true
|
||
test_method="DNS-Auflösung (nslookup: $host)"
|
||
debug_info="${debug_info}Erfolg mit nslookup. "
|
||
break
|
||
fi
|
||
debug_info="${debug_info}nslookup fehlgeschlagen. "
|
||
fi
|
||
|
||
# Teste getent hosts
|
||
if [ "$connection_ok" = false ] && command -v getent >/dev/null 2>&1; then
|
||
if timeout 8 getent hosts "$host" >/dev/null 2>&1; then
|
||
connection_ok=true
|
||
test_method="DNS-Auflösung (getent: $host)"
|
||
debug_info="${debug_info}Erfolg mit getent. "
|
||
break
|
||
fi
|
||
debug_info="${debug_info}getent fehlgeschlagen. "
|
||
fi
|
||
|
||
# Teste ping als Fallback
|
||
if [ "$connection_ok" = false ] && command -v ping >/dev/null 2>&1; then
|
||
if timeout 5 ping -c 1 "$host" >/dev/null 2>&1; then
|
||
connection_ok=true
|
||
test_method="Netzwerk-Verbindung (ping: $host)"
|
||
debug_info="${debug_info}Erfolg mit ping. "
|
||
break
|
||
fi
|
||
debug_info="${debug_info}ping fehlgeschlagen. "
|
||
fi
|
||
done
|
||
|
||
debug "DNS-Test Details: $debug_info"
|
||
|
||
# Methode 2: HTTP/HTTPS-Tests (robuster)
|
||
if [ "$connection_ok" = false ]; then
|
||
progress "Teste HTTP/HTTPS-Verbindungen..."
|
||
local http_urls=("http://connectivitycheck.gstatic.com/generate_204" "http://detectportal.firefox.com/success.txt" "https://www.google.com")
|
||
|
||
for url in "${http_urls[@]}"; do
|
||
debug_info="Teste HTTP für $url: "
|
||
|
||
# Teste curl
|
||
if command -v curl >/dev/null 2>&1; then
|
||
if timeout 15 curl -s --connect-timeout 8 --max-time 12 --fail "$url" >/dev/null 2>&1; then
|
||
connection_ok=true
|
||
test_method="HTTP/HTTPS (curl: $url)"
|
||
debug_info="${debug_info}Erfolg mit curl. "
|
||
break
|
||
fi
|
||
debug_info="${debug_info}curl fehlgeschlagen. "
|
||
fi
|
||
|
||
# Teste wget
|
||
if [ "$connection_ok" = false ] && command -v wget >/dev/null 2>&1; then
|
||
if timeout 15 wget -q --timeout=8 --tries=1 --spider "$url" 2>/dev/null; then
|
||
connection_ok=true
|
||
test_method="HTTP/HTTPS (wget: $url)"
|
||
debug_info="${debug_info}Erfolg mit wget. "
|
||
break
|
||
fi
|
||
debug_info="${debug_info}wget fehlgeschlagen. "
|
||
fi
|
||
|
||
debug "HTTP-Test Details: $debug_info"
|
||
done
|
||
fi
|
||
|
||
# Methode 3: Lokale Netzwerk-Interface Prüfung
|
||
if [ "$connection_ok" = false ]; then
|
||
progress "Prüfe lokale Netzwerk-Interfaces..."
|
||
|
||
local has_network_interface=false
|
||
|
||
# Prüfe ob aktive Netzwerk-Interfaces vorhanden sind
|
||
if command -v ip >/dev/null 2>&1; then
|
||
local active_interfaces=$(ip route show default 2>/dev/null | awk '{print $5}' | head -1)
|
||
if [ -n "$active_interfaces" ]; then
|
||
has_network_interface=true
|
||
local interface_ip=$(ip route get 1.1.1.1 2>/dev/null | awk '{print $7}' | head -1 || echo "Unbekannt")
|
||
info " 📡 Aktives Interface: $active_interfaces (IP: $interface_ip)"
|
||
debug "Netzwerk-Interface gefunden: $active_interfaces mit IP $interface_ip"
|
||
fi
|
||
fi
|
||
|
||
# Fallback über ifconfig
|
||
if [ "$has_network_interface" = false ] && command -v ifconfig >/dev/null 2>&1; then
|
||
local active_interfaces=$(ifconfig 2>/dev/null | grep -E '^[a-zA-Z]' | grep -v '^lo' | head -1 | cut -d: -f1)
|
||
if [ -n "$active_interfaces" ]; then
|
||
has_network_interface=true
|
||
info " 📡 Interface erkannt: $active_interfaces"
|
||
debug "Netzwerk-Interface über ifconfig gefunden: $active_interfaces"
|
||
fi
|
||
fi
|
||
|
||
if [ "$has_network_interface" = true ]; then
|
||
warning "⚠️ Netzwerk-Interface aktiv, aber Internet nicht erreichbar"
|
||
warning " → Möglicherweise Firewall, Proxy oder DNS-Problem"
|
||
else
|
||
warning "⚠️ Keine aktiven Netzwerk-Interfaces gefunden"
|
||
warning " → Bitte prüfen Sie die Netzwerk-Konfiguration"
|
||
fi
|
||
fi
|
||
|
||
# Methode 4: APT-Repository-Test (nur als letzter Test)
|
||
if [ "$connection_ok" = false ]; then
|
||
progress "Teste APT-Repository-Zugang (kann länger dauern)..."
|
||
|
||
# Sehr kurzer APT-Test ohne Update
|
||
if timeout 30 apt-get -qq --print-uris update 2>/dev/null | grep -q 'http'; then
|
||
connection_ok=true
|
||
test_method="APT-Repository-Konfiguration"
|
||
debug "APT-Repositories scheinen konfiguriert zu sein"
|
||
else
|
||
debug "APT-Repository-Test fehlgeschlagen"
|
||
fi
|
||
fi
|
||
|
||
# Ergebnis-Bewertung
|
||
if [ "$connection_ok" = true ]; then
|
||
success "✅ Internetverbindung verfügbar"
|
||
info " 🔍 Erkannt via: $test_method"
|
||
|
||
# Zusätzliche Informationen (robust)
|
||
if command -v curl >/dev/null 2>&1; then
|
||
progress "Ermittle externe IP-Adresse..."
|
||
local external_ip=""
|
||
local ip_services=("ifconfig.me" "ipinfo.io/ip" "icanhazip.com")
|
||
|
||
for service in "${ip_services[@]}"; do
|
||
external_ip=$(timeout 8 curl -s --connect-timeout 5 "$service" 2>/dev/null | head -1 | tr -d '\n\r' || echo "")
|
||
if [ -n "$external_ip" ] && [[ "$external_ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||
info " 🌐 Externe IP: $external_ip"
|
||
debug "Externe IP ermittelt über $service: $external_ip"
|
||
break
|
||
fi
|
||
done
|
||
|
||
if [ -z "$external_ip" ]; then
|
||
debug "Externe IP konnte nicht ermittelt werden"
|
||
fi
|
||
fi
|
||
else
|
||
warning "⚠️ Keine Internetverbindung erkannt"
|
||
info " → Installation wird fortgesetzt, aber Downloads könnten fehlschlagen"
|
||
warning " → Bitte prüfen Sie die Netzwerkverbindung!"
|
||
|
||
# Debug-Informationen bei fehlgeschlagener Verbindung
|
||
debug "Internet-Verbindungstest fehlgeschlagen. System-Info:"
|
||
debug " - DNS-Server: $(cat /etc/resolv.conf 2>/dev/null | grep nameserver | head -3 || echo 'Nicht verfügbar')"
|
||
debug " - Default Route: $(ip route show default 2>/dev/null || echo 'Nicht verfügbar')"
|
||
debug " - Network Interfaces: $(ip addr show 2>/dev/null | grep -E '^[0-9]+:' | cut -d: -f2 | tr -d ' ' | grep -v lo | head -3 || echo 'Nicht verfügbar')"
|
||
fi
|
||
}
|
||
|
||
# =========================== ROBUSTE SYSTEM-VORBEREITUNG ===========================
|
||
update_system() {
|
||
log "=== ANTI-HÄNGE SYSTEM-UPDATE MIT TIMEOUTS ==="
|
||
|
||
progress "Konfiguriere APT für bessere Zuverlässigkeit (timeout-gesichert)..."
|
||
|
||
# APT-Konfiguration optimieren (aggressivere Timeouts)
|
||
timeout 10 bash -c 'cat > /etc/apt/apt.conf.d/99myp-optimized << "EOF"
|
||
APT::Acquire::Retries "2";
|
||
APT::Acquire::http::Timeout "15";
|
||
APT::Acquire::https::Timeout "15";
|
||
APT::Acquire::ftp::Timeout "15";
|
||
APT::Install-Recommends "false";
|
||
APT::Install-Suggests "false";
|
||
Dpkg::Options {
|
||
"--force-confdef";
|
||
"--force-confold";
|
||
}
|
||
APT::Get::Assume-Yes "true";
|
||
APT::Get::Fix-Broken "true";
|
||
EOF' || warning "APT-Konfiguration timeout - verwende Defaults"
|
||
|
||
# Repository-Listen korrigieren (timeout-gesichert)
|
||
progress "Validiere APT-Repositories (timeout-gesichert)..."
|
||
timeout 20 bash -c '
|
||
if [ -f /etc/apt/sources.list ]; then
|
||
cp /etc/apt/sources.list /etc/apt/sources.list.backup 2>/dev/null || true
|
||
if grep -q "deb-src" /etc/apt/sources.list 2>/dev/null; then
|
||
sed -i "s/^deb-src/#deb-src/g" /etc/apt/sources.list 2>/dev/null || true
|
||
echo "Source-Repositories deaktiviert"
|
||
fi
|
||
fi
|
||
' || warning "Repository-Validierung timeout - fahre fort"
|
||
|
||
# APT-Lock-Dateien bereinigen (falls hängend)
|
||
progress "Bereinige APT-Lock-Dateien..."
|
||
timeout 10 bash -c '
|
||
rm -f /var/lib/dpkg/lock-frontend 2>/dev/null || true
|
||
rm -f /var/lib/dpkg/lock 2>/dev/null || true
|
||
rm -f /var/cache/apt/archives/lock 2>/dev/null || true
|
||
rm -f /var/lib/apt/lists/lock 2>/dev/null || true
|
||
' || true
|
||
|
||
progress "Aktualisiere Paketlisten (max 60s timeout)..."
|
||
if timeout 60 apt-get update 2>/dev/null; then
|
||
success "✅ APT Update erfolgreich"
|
||
else
|
||
warning "⚠️ APT Update timeout - fahre ohne Update fort"
|
||
fi
|
||
|
||
progress "Führe System-Upgrade durch (max 120s timeout)..."
|
||
if timeout 120 bash -c 'DEBIAN_FRONTEND=noninteractive apt-get upgrade -y 2>/dev/null'; then
|
||
success "✅ System Upgrade erfolgreich"
|
||
else
|
||
warning "⚠️ System Upgrade timeout - fahre ohne Upgrade fort"
|
||
fi
|
||
|
||
progress "Installiere essenzielle System-Tools..."
|
||
|
||
# Grundlegende Tools in optimierter Reihenfolge
|
||
local essential_packages=(
|
||
"ca-certificates"
|
||
"gnupg"
|
||
"curl"
|
||
"wget"
|
||
"git"
|
||
"nano"
|
||
"htop"
|
||
"rsync"
|
||
"unzip"
|
||
"sudo"
|
||
"systemd"
|
||
"lsb-release"
|
||
"apt-transport-https"
|
||
"software-properties-common"
|
||
"bc"
|
||
"dbus"
|
||
"systemd-timesyncd"
|
||
)
|
||
|
||
for package in "${essential_packages[@]}"; do
|
||
apt_install_retry "$package"
|
||
done
|
||
|
||
# Zeitserver synchronisieren
|
||
progress "Synchronisiere Systemzeit..."
|
||
systemctl enable systemd-timesyncd 2>/dev/null || true
|
||
systemctl start systemd-timesyncd 2>/dev/null || true
|
||
|
||
log "✅ Robustes System-Update abgeschlossen"
|
||
}
|
||
|
||
# =========================== VERBESSERTE PYTHON-INSTALLATION ===========================
|
||
install_python_dependencies() {
|
||
log "=== ROBUSTE PYTHON-INSTALLATION ==="
|
||
|
||
progress "Installiere Python 3 und Build-Abhängigkeiten..."
|
||
|
||
local python_packages=(
|
||
"python3"
|
||
"python3-pip"
|
||
"python3-dev"
|
||
"python3-setuptools"
|
||
"python3-venv"
|
||
"python3-wheel"
|
||
"build-essential"
|
||
"libssl-dev"
|
||
"libffi-dev"
|
||
"libbz2-dev"
|
||
"libreadline-dev"
|
||
"libsqlite3-dev"
|
||
"libncurses5-dev"
|
||
"libncursesw5-dev"
|
||
"zlib1g-dev"
|
||
"sqlite3"
|
||
)
|
||
|
||
for package in "${python_packages[@]}"; do
|
||
apt_install_retry "$package"
|
||
done
|
||
|
||
# Python-Version validieren
|
||
progress "Validiere Python-Installation..."
|
||
local python_version=$(python3 --version 2>&1 | cut -d' ' -f2)
|
||
log "✅ Python Version: $python_version"
|
||
|
||
# pip konfigurieren und aktualisieren
|
||
progress "Konfiguriere pip für bessere Zuverlässigkeit..."
|
||
|
||
# Root pip-Konfiguration
|
||
mkdir -p /root/.pip
|
||
cat > /root/.pip/pip.conf << 'EOF'
|
||
[global]
|
||
trusted-host = pypi.org
|
||
pypi.python.org
|
||
files.pythonhosted.org
|
||
cert = /etc/ssl/certs/ca-certificates.crt
|
||
timeout = 120
|
||
retries = 5
|
||
no-cache-dir = false
|
||
disable-pip-version-check = true
|
||
no-warn-script-location = true
|
||
break-system-packages = true
|
||
|
||
[install]
|
||
trusted-host = pypi.org
|
||
pypi.python.org
|
||
files.pythonhosted.org
|
||
user = false
|
||
break-system-packages = true
|
||
EOF
|
||
|
||
# Systemweite pip-Konfiguration für alle Benutzer
|
||
progress "Erstelle systemweite pip-Konfiguration..."
|
||
mkdir -p /etc/pip
|
||
cat > /etc/pip/pip.conf << 'EOF'
|
||
[global]
|
||
break-system-packages = true
|
||
trusted-host = pypi.org
|
||
pypi.python.org
|
||
files.pythonhosted.org
|
||
timeout = 120
|
||
retries = 5
|
||
disable-pip-version-check = true
|
||
|
||
[install]
|
||
break-system-packages = true
|
||
trusted-host = pypi.org
|
||
pypi.python.org
|
||
files.pythonhosted.org
|
||
user = false
|
||
EOF
|
||
|
||
# pip-Konfiguration für existierende Benutzer erstellen
|
||
progress "Konfiguriere pip für alle Benutzer..."
|
||
for user_home in "/home/"*; do
|
||
if [ -d "$user_home" ] && [ "$user_home" != "/home/lost+found" ]; then
|
||
local username=$(basename "$user_home")
|
||
if id "$username" &>/dev/null; then
|
||
mkdir -p "$user_home/.pip" 2>/dev/null || true
|
||
cat > "$user_home/.pip/pip.conf" << 'EOF'
|
||
[global]
|
||
break-system-packages = true
|
||
trusted-host = pypi.org
|
||
pypi.python.org
|
||
files.pythonhosted.org
|
||
timeout = 60
|
||
retries = 3
|
||
|
||
[install]
|
||
break-system-packages = true
|
||
trusted-host = pypi.org
|
||
pypi.python.org
|
||
files.pythonhosted.org
|
||
EOF
|
||
chown "$username:$username" "$user_home/.pip/pip.conf" 2>/dev/null || true
|
||
log "✅ pip konfiguriert für Benutzer: $username"
|
||
fi
|
||
fi
|
||
done
|
||
|
||
# pip selbst aktualisieren
|
||
progress "Aktualisiere pip mit Retry..."
|
||
retry_command "python3 -m pip install --break-system-packages --upgrade pip setuptools wheel" "pip Upgrade"
|
||
|
||
# pip-Version validieren
|
||
local pip_version=$(python3 -m pip --version | cut -d' ' -f2)
|
||
log "✅ pip Version: $pip_version"
|
||
|
||
log "✅ Robuste Python-Umgebung installiert"
|
||
}
|
||
|
||
install_python_packages() {
|
||
log "=== PYTHON-PAKETE INSTALLATION ==="
|
||
|
||
progress "Installiere Python-Pakete..."
|
||
|
||
if [ ! -f "$CURRENT_DIR/requirements.txt" ]; then
|
||
error "requirements.txt nicht gefunden: $CURRENT_DIR/requirements.txt"
|
||
fi
|
||
|
||
# Kopiere requirements.txt
|
||
cp "$CURRENT_DIR/requirements.txt" "$APP_DIR/" 2>/dev/null || true
|
||
|
||
# Installiere alle Pakete aus requirements.txt
|
||
progress "Installiere requirements.txt..."
|
||
|
||
if python3 -m pip install -r "$CURRENT_DIR/requirements.txt" --break-system-packages; then
|
||
success "✅ requirements.txt erfolgreich installiert"
|
||
else
|
||
error "❌ requirements.txt Installation fehlgeschlagen"
|
||
return 1
|
||
fi
|
||
|
||
# Validiere essenzielle Module
|
||
progress "Validiere essenzielle Python-Module..."
|
||
|
||
local essential_modules=("flask" "requests")
|
||
local validation_success=true
|
||
|
||
for module in "${essential_modules[@]}"; do
|
||
if python3 -c "import $module; print(f'✅ $module verfügbar')" 2>/dev/null; then
|
||
debug "$module erfolgreich importiert"
|
||
else
|
||
warning "⚠️ $module nicht verfügbar"
|
||
validation_success=false
|
||
fi
|
||
done
|
||
|
||
if [ "$validation_success" = true ]; then
|
||
success "✅ Essenzielle Python-Module verfügbar"
|
||
else
|
||
warning "⚠️ Einige essenzielle Module fehlen"
|
||
fi
|
||
|
||
log "✅ Python-Pakete Installation abgeschlossen"
|
||
|
||
# Zeige installierte Pakete
|
||
progress "Zeige installierte Python-Pakete..."
|
||
echo ""
|
||
echo "📦 Installierte Python-Pakete:"
|
||
python3 -m pip list 2>/dev/null | grep -E "(Flask|requests|Werkzeug|Jinja2)" | head -10 || echo " Keine relevanten Pakete gefunden"
|
||
echo ""
|
||
}
|
||
|
||
# =========================== PYTHON-PAKETE MIT BREAK-SYSTEM-PACKAGES ===========================
|
||
install_python_packages_with_break_system() {
|
||
log "🐍 PYTHON-PAKETE MIT BREAK-SYSTEM-PACKAGES INSTALLATION"
|
||
|
||
progress "Installiere Python-Pakete mit --break-system-packages..."
|
||
|
||
if [ ! -f "$CURRENT_DIR/requirements.txt" ]; then
|
||
error "requirements.txt nicht gefunden: $CURRENT_DIR/requirements.txt"
|
||
return 1
|
||
fi
|
||
|
||
# Kopiere requirements.txt
|
||
cp "$CURRENT_DIR/requirements.txt" "$APP_DIR/" 2>/dev/null || true
|
||
|
||
# Installiere alle Pakete aus requirements.txt mit --break-system-packages
|
||
progress "Installiere requirements.txt mit --break-system-packages..."
|
||
|
||
# Mehrere Installationsversuche mit verschiedenen Strategien
|
||
local install_success=false
|
||
|
||
# Strategie 1: Mit --break-system-packages und --force-reinstall
|
||
if python3.11 -m pip install -r "$CURRENT_DIR/requirements.txt" --break-system-packages --force-reinstall --no-cache-dir; then
|
||
install_success=true
|
||
success "✅ requirements.txt mit --break-system-packages erfolgreich installiert"
|
||
else
|
||
warning "⚠️ Strategie 1 fehlgeschlagen, versuche Alternative..."
|
||
|
||
# Strategie 2: Einzelne Pakete installieren
|
||
progress "Installiere Pakete einzeln..."
|
||
while IFS= read -r package || [ -n "$package" ]; do
|
||
# Überspringe Kommentare und leere Zeilen
|
||
if [[ "$package" =~ ^[[:space:]]*# ]] || [[ -z "${package// }" ]]; then
|
||
continue
|
||
fi
|
||
|
||
# Entferne Whitespace
|
||
package=$(echo "$package" | xargs)
|
||
|
||
if [ -n "$package" ]; then
|
||
progress "Installiere: $package"
|
||
if python3.11 -m pip install "$package" --break-system-packages --no-cache-dir; then
|
||
debug "✅ $package erfolgreich installiert"
|
||
else
|
||
warning "⚠️ $package Installation fehlgeschlagen"
|
||
fi
|
||
fi
|
||
done < "$CURRENT_DIR/requirements.txt"
|
||
install_success=true
|
||
fi
|
||
|
||
if [ "$install_success" = false ]; then
|
||
error "❌ Python-Pakete Installation komplett fehlgeschlagen"
|
||
return 1
|
||
fi
|
||
|
||
# Validiere essenzielle Module mit Python 3.11
|
||
progress "Validiere essenzielle Python-Module mit Python 3.11..."
|
||
|
||
local essential_modules=("flask" "requests" "werkzeug" "jinja2")
|
||
local validation_success=true
|
||
|
||
for module in "${essential_modules[@]}"; do
|
||
if python3.11 -c "import $module; print(f'✅ $module verfügbar')" 2>/dev/null; then
|
||
debug "$module erfolgreich importiert"
|
||
else
|
||
warning "⚠️ $module nicht verfügbar - versuche Installation..."
|
||
python3.11 -m pip install "$module" --break-system-packages --no-cache-dir 2>/dev/null || true
|
||
fi
|
||
done
|
||
|
||
# Finale Validierung
|
||
progress "Finale Modul-Validierung..."
|
||
for module in "${essential_modules[@]}"; do
|
||
if python3.11 -c "import $module" 2>/dev/null; then
|
||
success "✅ $module verfügbar"
|
||
else
|
||
warning "⚠️ $module immer noch nicht verfügbar"
|
||
validation_success=false
|
||
fi
|
||
done
|
||
|
||
if [ "$validation_success" = true ]; then
|
||
success "✅ Alle essentiellen Python-Module verfügbar"
|
||
else
|
||
warning "⚠️ Einige essenzielle Module fehlen - Installation kann trotzdem funktionieren"
|
||
fi
|
||
|
||
# Zeige installierte Pakete mit Python 3.11
|
||
progress "Zeige installierte Python-Pakete (Python 3.11)..."
|
||
echo ""
|
||
echo "📦 Installierte Python-Pakete (Python 3.11):"
|
||
python3.11 -m pip list 2>/dev/null | grep -E "(Flask|requests|Werkzeug|Jinja2|gunicorn|psutil)" | head -15 || echo " Keine relevanten Pakete gefunden"
|
||
echo ""
|
||
|
||
success "✅ Python-Pakete mit --break-system-packages Installation abgeschlossen"
|
||
}
|
||
|
||
# =========================== ROBUSTE NODE.JS INSTALLATION ===========================
|
||
install_nodejs_npm() {
|
||
log "=== ROBUSTE NODE.JS UND NPM INSTALLATION ==="
|
||
|
||
# Alte Installationen entfernen
|
||
progress "Bereinige alte Node.js-Installationen..."
|
||
apt-get remove --purge -y nodejs npm 2>/dev/null || true
|
||
apt-get autoremove -y 2>/dev/null || true
|
||
rm -rf /usr/local/bin/node /usr/local/bin/npm 2>/dev/null || true
|
||
|
||
# NodeSource Repository mit Fallback
|
||
progress "Installiere Node.js mit Fallback-Strategie..."
|
||
|
||
local nodejs_installed=false
|
||
|
||
# Strategie 1: NodeSource Repository
|
||
if curl -fsSL https://deb.nodesource.com/setup_lts.x 2>/dev/null | bash - 2>/dev/null; then
|
||
if apt-get update -y && apt_install_retry nodejs; then
|
||
nodejs_installed=true
|
||
log "✅ Node.js via NodeSource Repository installiert"
|
||
fi
|
||
fi
|
||
|
||
# Strategie 2: Snap (falls verfügbar)
|
||
if [ "$nodejs_installed" = false ] && command -v snap >/dev/null 2>&1; then
|
||
progress "Versuche Node.js Installation via Snap..."
|
||
if snap install node --classic 2>/dev/null; then
|
||
nodejs_installed=true
|
||
log "✅ Node.js via Snap installiert"
|
||
fi
|
||
fi
|
||
|
||
# Strategie 3: Debian Repository (Fallback)
|
||
if [ "$nodejs_installed" = false ]; then
|
||
progress "Verwende Debian Repository als Fallback..."
|
||
apt_install_retry nodejs npm
|
||
nodejs_installed=true
|
||
log "✅ Node.js via Debian Repository installiert"
|
||
fi
|
||
|
||
# Validierung
|
||
progress "Validiere Node.js Installation..."
|
||
if command -v node >/dev/null 2>&1; then
|
||
local node_version=$(node --version)
|
||
log "✅ Node.js Version: $node_version"
|
||
else
|
||
error "❌ Node.js nicht verfügbar nach Installation"
|
||
fi
|
||
|
||
if command -v npm >/dev/null 2>&1; then
|
||
local npm_version=$(npm --version)
|
||
log "✅ npm Version: $npm_version"
|
||
|
||
# npm optimieren
|
||
progress "Optimiere npm-Konfiguration..."
|
||
npm config set fund false 2>/dev/null || true
|
||
npm config set audit-level moderate 2>/dev/null || true
|
||
npm config set progress false 2>/dev/null || true
|
||
npm config set loglevel warn 2>/dev/null || true
|
||
else
|
||
# Versuche npm separat zu installieren
|
||
progress "Installiere npm separat..."
|
||
apt_install_retry npm
|
||
fi
|
||
|
||
log "✅ Node.js und npm erfolgreich installiert"
|
||
}
|
||
|
||
# =========================== NETZWERK-SICHERHEIT ===========================
|
||
configure_network_security() {
|
||
log "=== SIMPLE NETZWERK-SICHERHEIT (ANTI-HÄNGE VERSION) ==="
|
||
|
||
# Standardmäßig überspringen um Hänger zu vermeiden
|
||
if [ "${SKIP_NETWORK_SECURITY:-1}" = "1" ]; then
|
||
info "🚀 Netzwerk-Sicherheit übersprungen für schnellere Installation"
|
||
info "📝 Kann später manuell aktiviert werden mit: SKIP_NETWORK_SECURITY=0"
|
||
return
|
||
fi
|
||
|
||
# Komplette Funktion mit aggressivem Timeout
|
||
if ! timeout 30 bash -c '
|
||
# Nur essenzielle IPv6-Deaktivierung
|
||
progress() { echo "[FORTSCHRITT] $1"; }
|
||
warning() { echo "[WARNUNG] $1"; }
|
||
success() { echo "[ERFOLG] $1"; }
|
||
|
||
progress "Deaktiviere IPv6 (essentiell, max 30s)..."
|
||
|
||
# 1. Einfache sysctl IPv6-Deaktivierung (schnell)
|
||
echo "net.ipv6.conf.all.disable_ipv6=1" > /etc/sysctl.d/99-myp-ipv6.conf 2>/dev/null || true
|
||
echo "net.ipv6.conf.default.disable_ipv6=1" >> /etc/sysctl.d/99-myp-ipv6.conf 2>/dev/null || true
|
||
|
||
# 2. IPv6 in /etc/hosts auskommentieren (schnell)
|
||
if [ -f /etc/hosts ]; then
|
||
sed -i.backup "s/^::1/#::1/" /etc/hosts 2>/dev/null || true
|
||
fi
|
||
|
||
# 3. GRUB nur wenn schnell verfügbar
|
||
if [ -f /etc/default/grub ] && command -v update-grub >/dev/null 2>&1; then
|
||
if ! grep -q "ipv6.disable=1" /etc/default/grub 2>/dev/null; then
|
||
cp /etc/default/grub /etc/default/grub.backup 2>/dev/null || true
|
||
sed -i "s/GRUB_CMDLINE_LINUX_DEFAULT=\"/&ipv6.disable=1 /" /etc/default/grub 2>/dev/null || true
|
||
# update-grub nur mit 10s timeout
|
||
if timeout 10 update-grub >/dev/null 2>&1; then
|
||
success "GRUB IPv6 deaktiviert"
|
||
else
|
||
warning "GRUB-Update timeout - wird beim nächsten Boot aktiv"
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
success "IPv6-Deaktivierung abgeschlossen"
|
||
'; then
|
||
warning "⚠️ Netzwerk-Sicherheit timeout (30s) - überspringe"
|
||
info " → System funktioniert trotzdem normal"
|
||
info " → IPv6-Deaktivierung kann später manuell durchgeführt werden"
|
||
else
|
||
log "✅ Basis-Netzwerk-Sicherheit konfiguriert:"
|
||
log " 🚫 IPv6 deaktiviert"
|
||
log " 📝 Konfiguration in /etc/sysctl.d/99-myp-ipv6.conf"
|
||
log " 🔄 Wird beim nächsten Boot vollständig aktiv"
|
||
fi
|
||
}
|
||
|
||
# =========================== DESKTOP-ENVIRONMENT ENTFERNUNG ===========================
|
||
remove_desktop_environments() {
|
||
log "=== ENTFERNE DESKTOP ENVIRONMENTS FÜR KIOSK-MODUS ==="
|
||
|
||
progress "Stoppe alle Desktop-Services..."
|
||
local desktop_services=("lightdm" "gdm3" "sddm" "xdm" "nodm")
|
||
|
||
for service in "${desktop_services[@]}"; do
|
||
systemctl stop "$service" 2>/dev/null || true
|
||
systemctl disable "$service" 2>/dev/null || true
|
||
done
|
||
|
||
progress "Entferne Desktop-Pakete vollständig..."
|
||
|
||
# Raspberry Pi OS Desktop-Pakete
|
||
apt-get remove --purge -y \
|
||
raspberrypi-ui-mods \
|
||
pi-package \
|
||
desktop-base \
|
||
lxde* \
|
||
xfce4* \
|
||
gnome* \
|
||
kde* \
|
||
mate* \
|
||
cinnamon* \
|
||
openbox \
|
||
pcmanfm \
|
||
file-manager* \
|
||
task-lxde-desktop \
|
||
task-xfce-desktop \
|
||
task-gnome-desktop \
|
||
task-kde-desktop \
|
||
2>/dev/null || true
|
||
|
||
# Display Manager entfernen
|
||
apt-get remove --purge -y \
|
||
lightdm* \
|
||
gdm3* \
|
||
sddm* \
|
||
xdm* \
|
||
nodm* \
|
||
2>/dev/null || true
|
||
|
||
# Unnötige Anwendungen entfernen
|
||
apt-get remove --purge -y \
|
||
libreoffice* \
|
||
thunderbird* \
|
||
firefox* \
|
||
vlc* \
|
||
gimp* \
|
||
scratch* \
|
||
minecraft-pi \
|
||
sonic-pi \
|
||
2>/dev/null || true
|
||
|
||
# Aufräumen
|
||
apt-get autoremove --purge -y
|
||
apt-get autoclean
|
||
|
||
log "✅ Desktop Environments vollständig entfernt"
|
||
}
|
||
|
||
# =========================== AGGRESSIVE VOLLSTÄNDIGE UMGEBUNGSBEREINIGUNG ===========================
|
||
complete_environment_cleanup() {
|
||
log "🧹 AGGRESSIVE VOLLSTÄNDIGE UMGEBUNGSBEREINIGUNG..."
|
||
|
||
# SCHRITT 1: Alle laufenden Desktop-Services sofort stoppen und MASKIEREN
|
||
progress "Stoppe und maskiere ALLE Desktop-Services aggressiv..."
|
||
local desktop_services=(
|
||
"gdm3" "gdm" "lightdm" "sddm" "xdm" "nodm" "wdm" "kdm" "lxdm"
|
||
"display-manager" "graphical-session.target"
|
||
"gnome-session-manager" "kde-session" "xfce4-session" "lxsession"
|
||
"desktop-session" "x11-session" "wayland-session"
|
||
)
|
||
|
||
for service in "${desktop_services[@]}"; do
|
||
systemctl stop "$service" 2>/dev/null || true
|
||
systemctl disable "$service" 2>/dev/null || true
|
||
systemctl mask "$service" 2>/dev/null || true
|
||
progress "Service $service: gestoppt, deaktiviert, MASKIERT"
|
||
done
|
||
|
||
# SCHRITT 2: Boot-Target auf multi-user setzen (KEIN automatisches GUI)
|
||
progress "🚫 Setze Boot-Target auf multi-user - KEIN automatisches GUI mehr!"
|
||
systemctl set-default multi-user.target
|
||
systemctl disable graphical.target 2>/dev/null || true
|
||
systemctl mask graphical.target 2>/dev/null || true
|
||
systemctl disable graphical-session.target 2>/dev/null || true
|
||
systemctl mask graphical-session.target 2>/dev/null || true
|
||
|
||
warning "⚠️ WICHTIG: Kein Desktop-Environment startet mehr automatisch nach Reboot!"
|
||
|
||
# SCHRITT 3: Alle Desktop-Prozesse brutal beenden
|
||
progress "💀 Beende alle laufenden Desktop-Prozesse brutal..."
|
||
local desktop_processes=(
|
||
"gnome-session" "kde-session" "xfce4-session" "lxsession" "mate-session"
|
||
"cinnamon-session" "unity" "compiz" "metacity" "kwin" "mutter"
|
||
"X :0" "Xorg" "xfce4-panel" "gnome-panel" "kde-panel" "lxpanel"
|
||
"nautilus" "dolphin" "thunar" "pcmanfm" "caja"
|
||
)
|
||
|
||
for process in "${desktop_processes[@]}"; do
|
||
pkill -f "$process" 2>/dev/null || true
|
||
progress "Prozess $process: beendet"
|
||
done
|
||
|
||
# SCHRITT 4: Display Manager KOMPLETT deinstallieren
|
||
progress "🗑️ Entferne ALLE Display Manager komplett..."
|
||
apt-get remove --purge -y \
|
||
gdm3* gdm* lightdm* sddm* xdm* nodm* wdm* kdm* lxdm* \
|
||
display-manager-service* slim* entrance* \
|
||
2>/dev/null || true
|
||
|
||
# SCHRITT 5: Desktop-Environments AGGRESSIV entfernen
|
||
progress "🔥 Entferne ALLE Desktop-Environments AGGRESSIV..."
|
||
|
||
# GNOME - komplett vernichten
|
||
progress "Vernichte GNOME komplett..."
|
||
apt-get remove --purge -y \
|
||
gnome* gdm3* ubuntu-desktop* ubuntu-session* \
|
||
gnome-shell* gnome-desktop* gnome-session* gnome-control-center* \
|
||
nautilus* gedit* evince* totem* rhythmbox* \
|
||
gnome-calculator* gnome-calendar* gnome-contacts* \
|
||
2>/dev/null || true
|
||
|
||
# KDE - komplett vernichten
|
||
progress "Vernichte KDE komplett..."
|
||
apt-get remove --purge -y \
|
||
kde* plasma* kubuntu-desktop* kdebase* kdelibs* \
|
||
dolphin* konqueror* kate* okular* \
|
||
2>/dev/null || true
|
||
|
||
# XFCE - komplett vernichten
|
||
progress "Vernichte XFCE komplett..."
|
||
apt-get remove --purge -y \
|
||
xfce4* xubuntu-desktop* thunar* xfce4-panel* \
|
||
xfce4-terminal* xfce4-appfinder* \
|
||
2>/dev/null || true
|
||
|
||
# LXDE/LXQt - komplett vernichten
|
||
progress "Vernichte LXDE/LXQt komplett..."
|
||
apt-get remove --purge -y \
|
||
lxde* lxqt* lubuntu-desktop* pcmanfm* lxpanel* \
|
||
lxterminal* lxsession* \
|
||
2>/dev/null || true
|
||
|
||
# MATE - komplett vernichten
|
||
progress "Vernichte MATE komplett..."
|
||
apt-get remove --purge -y \
|
||
mate* ubuntu-mate-desktop* caja* pluma* \
|
||
mate-panel* mate-desktop* \
|
||
2>/dev/null || true
|
||
|
||
# Cinnamon - komplett vernichten
|
||
progress "Vernichte Cinnamon komplett..."
|
||
apt-get remove --purge -y \
|
||
cinnamon* nemo* \
|
||
2>/dev/null || true
|
||
|
||
# Unity (falls noch vorhanden)
|
||
progress "Vernichte Unity..."
|
||
apt-get remove --purge -y \
|
||
unity* ubuntu-unity-desktop* \
|
||
2>/dev/null || true
|
||
|
||
# SCHRITT 6: Desktop-Meta-Pakete entfernen
|
||
progress "🗑️ Entferne Desktop-Meta-Pakete..."
|
||
apt-get remove --purge -y \
|
||
ubuntu-desktop* kubuntu-desktop* xubuntu-desktop* \
|
||
lubuntu-desktop* ubuntu-mate-desktop* ubuntu-unity-desktop* \
|
||
desktop-base* tasksel* task-desktop* \
|
||
2>/dev/null || true
|
||
|
||
# SCHRITT 7: Autostart-Verzeichnisse bereinigen
|
||
progress "🧹 Bereinige Autostart-Verzeichnisse..."
|
||
rm -rf /etc/xdg/autostart/* 2>/dev/null || true
|
||
rm -rf /usr/share/xsessions/* 2>/dev/null || true
|
||
rm -rf /usr/share/wayland-sessions/* 2>/dev/null || true
|
||
rm -rf ~/.config/autostart/* 2>/dev/null || true
|
||
|
||
# SCHRITT 8: Python-Installationen bereinigen
|
||
progress "🐍 Bereinige alte Python-Installationen..."
|
||
apt-get remove --purge -y python3-pip python3-venv python3-virtualenv
|
||
rm -rf /usr/local/lib/python3.*/dist-packages/* 2>/dev/null || true
|
||
rm -rf ~/.local/lib/python3.*/site-packages/* 2>/dev/null || true
|
||
rm -rf /home/*/.local/lib/python3.*/site-packages/* 2>/dev/null || true
|
||
|
||
# SCHRITT 9: Snap-Pakete komplett entfernen
|
||
if command -v snap >/dev/null 2>&1; then
|
||
progress "📦 Entferne alle Snap-Pakete..."
|
||
snap list 2>/dev/null | awk 'NR>1 {print $1}' | while read snapname; do
|
||
snap remove "$snapname" --purge 2>/dev/null || true
|
||
done
|
||
apt-get remove --purge -y snapd 2>/dev/null || true
|
||
fi
|
||
|
||
# SCHRITT 10: Flatpak-Pakete komplett entfernen
|
||
if command -v flatpak >/dev/null 2>&1; then
|
||
progress "📦 Entferne alle Flatpak-Pakete..."
|
||
flatpak uninstall --all -y 2>/dev/null || true
|
||
apt-get remove --purge -y flatpak* 2>/dev/null || true
|
||
fi
|
||
|
||
# SCHRITT 11: AGGRESSIVE Bereinigung
|
||
progress "🧽 Führe aggressive System-Bereinigung durch..."
|
||
apt-get autoremove --purge -y
|
||
apt-get autoclean
|
||
apt-get clean
|
||
|
||
# Alle Caches leeren
|
||
rm -rf /var/cache/apt/archives/*
|
||
rm -rf /tmp/*
|
||
rm -rf /var/tmp/*
|
||
rm -rf /var/cache/fontconfig/*
|
||
rm -rf /home/*/.cache/* 2>/dev/null || true
|
||
rm -rf /root/.cache/* 2>/dev/null || true
|
||
|
||
# SCHRITT 12: Desktop-Konfigurationen entfernen
|
||
progress "🗑️ Entferne Desktop-Konfigurationen..."
|
||
rm -rf /etc/gdm3/ 2>/dev/null || true
|
||
rm -rf /etc/lightdm/ 2>/dev/null || true
|
||
rm -rf /etc/sddm/ 2>/dev/null || true
|
||
rm -rf /etc/xdg/ 2>/dev/null || true
|
||
rm -rf /home/*/.config/autostart/ 2>/dev/null || true
|
||
rm -rf /home/*/.config/xfce4/ 2>/dev/null || true
|
||
rm -rf /home/*/.config/lxsession/ 2>/dev/null || true
|
||
rm -rf /home/*/.gnome/ 2>/dev/null || true
|
||
rm -rf /home/*/.kde/ 2>/dev/null || true
|
||
|
||
success "✅ AGGRESSIVE Umgebungsbereinigung abgeschlossen!"
|
||
warning "⚠️ WICHTIG: Nach Reboot startet KEIN Desktop automatisch mehr!"
|
||
warning "⚠️ Nur noch Kiosk-Modus wird automatisch gestartet!"
|
||
}
|
||
|
||
# =========================== SAUBERE PYTHON-UMGEBUNG ===========================
|
||
setup_clean_python_environment() {
|
||
log "🐍 PYTHON-UMGEBUNG NEU EINRICHTEN..."
|
||
|
||
# Python 3.11 Repository hinzufügen (falls nicht vorhanden)
|
||
progress "Füge Python 3.11 Repository hinzu..."
|
||
if ! grep -q "deadsnakes" /etc/apt/sources.list.d/* 2>/dev/null; then
|
||
add-apt-repository ppa:deadsnakes/ppa -y
|
||
apt-get update
|
||
fi
|
||
|
||
# Python 3.11 und essenzielle Pakete installieren
|
||
progress "Installiere Python 3.11 und essenzielle Pakete..."
|
||
apt-get install -y \
|
||
python3.11 \
|
||
python3.11-dev \
|
||
python3.11-venv \
|
||
python3.11-distutils \
|
||
python3-pip \
|
||
build-essential \
|
||
pkg-config \
|
||
libffi-dev \
|
||
libssl-dev \
|
||
libxml2-dev \
|
||
libxslt1-dev \
|
||
libjpeg-dev \
|
||
libpng-dev \
|
||
zlib1g-dev
|
||
|
||
# Python 3.11 als Standard setzen
|
||
progress "Setze Python 3.11 als Standard..."
|
||
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1
|
||
update-alternatives --set python3 /usr/bin/python3.11
|
||
|
||
# pip für Python 3.11 aktualisieren
|
||
progress "Aktualisiere pip für Python 3.11..."
|
||
python3.11 -m pip install --upgrade pip setuptools wheel
|
||
|
||
# pip-Konfiguration für --break-system-packages erstellen
|
||
progress "Konfiguriere pip für System-Pakete..."
|
||
mkdir -p /etc/pip
|
||
cat > /etc/pip/pip.conf << 'EOF'
|
||
[global]
|
||
break-system-packages = true
|
||
trusted-host = pypi.org
|
||
pypi.python.org
|
||
files.pythonhosted.org
|
||
timeout = 60
|
||
retries = 3
|
||
EOF
|
||
|
||
# Benutzer-spezifische pip-Konfiguration
|
||
mkdir -p ~/.config/pip
|
||
cp /etc/pip/pip.conf ~/.config/pip/pip.conf
|
||
|
||
# Python-Version validieren
|
||
local python_version=$(python3.11 --version 2>&1)
|
||
if [[ "$python_version" == *"3.11"* ]]; then
|
||
success "✅ Python 3.11 erfolgreich installiert: $python_version"
|
||
else
|
||
error "❌ Python 3.11 Installation fehlgeschlagen"
|
||
return 1
|
||
fi
|
||
|
||
success "✅ Saubere Python-Umgebung eingerichtet"
|
||
}
|
||
|
||
# =========================== MINIMALES DESKTOP-ENVIRONMENT ===========================
|
||
install_minimal_desktop_environment() {
|
||
log "🖥️ MINIMALES DESKTOP-ENVIRONMENT INSTALLIEREN..."
|
||
|
||
# Basis X11 und Window Manager
|
||
progress "Installiere X11 und minimalen Window Manager..."
|
||
apt-get install -y \
|
||
xorg \
|
||
xserver-xorg \
|
||
xserver-xorg-video-fbdev \
|
||
xinit \
|
||
x11-xserver-utils \
|
||
openbox \
|
||
lightdm \
|
||
lightdm-gtk-greeter \
|
||
lightdm-gtk-greeter-settings
|
||
|
||
# Chromium für Kiosk-Modus
|
||
progress "Installiere Chromium Browser..."
|
||
apt-get install -y \
|
||
chromium-browser \
|
||
chromium-codecs-ffmpeg-extra
|
||
|
||
# Essenzielle Desktop-Tools
|
||
progress "Installiere essenzielle Desktop-Tools..."
|
||
apt-get install -y \
|
||
pcmanfm \
|
||
lxterminal \
|
||
leafpad \
|
||
gvfs \
|
||
gvfs-backends \
|
||
udisks2 \
|
||
policykit-1 \
|
||
network-manager \
|
||
network-manager-gnome
|
||
|
||
# Audio-Support
|
||
progress "Installiere Audio-Support..."
|
||
apt-get install -y \
|
||
pulseaudio \
|
||
pulseaudio-utils \
|
||
alsa-utils \
|
||
pavucontrol
|
||
|
||
# Schriftarten
|
||
progress "Installiere Schriftarten..."
|
||
apt-get install -y \
|
||
fonts-dejavu \
|
||
fonts-liberation \
|
||
fonts-noto \
|
||
ttf-mscorefonts-installer
|
||
|
||
# LightDM konfigurieren
|
||
progress "Konfiguriere LightDM..."
|
||
cat > /etc/lightdm/lightdm.conf << 'EOF'
|
||
[Seat:*]
|
||
autologin-user=kiosk
|
||
autologin-user-timeout=0
|
||
user-session=openbox
|
||
greeter-session=lightdm-gtk-greeter
|
||
greeter-hide-users=false
|
||
greeter-allow-guest=false
|
||
greeter-show-manual-login=true
|
||
EOF
|
||
|
||
# LightDM GTK Greeter konfigurieren
|
||
cat > /etc/lightdm/lightdm-gtk-greeter.conf << 'EOF'
|
||
[greeter]
|
||
background=/usr/share/pixmaps/debian-logo.png
|
||
theme-name=Adwaita
|
||
icon-theme-name=Adwaita
|
||
font-name=Sans 11
|
||
xft-antialias=true
|
||
xft-dpi=96
|
||
xft-hintstyle=slight
|
||
xft-rgba=rgb
|
||
show-indicators=~host;~spacer;~clock;~spacer;~session;~language;~a11y;~power
|
||
show-clock=true
|
||
clock-format=%H:%M
|
||
EOF
|
||
|
||
success "✅ Minimales Desktop-Environment installiert"
|
||
}
|
||
|
||
# =========================== MINIMALE X11-UMGEBUNG ===========================
|
||
install_minimal_x11() {
|
||
log "=== INSTALLIERE MINIMALE X11-UMGEBUNG FÜR KIOSK ==="
|
||
|
||
progress "Installiere minimale X11-Pakete..."
|
||
apt-get install -y \
|
||
xserver-xorg-core \
|
||
xserver-xorg-input-all \
|
||
xserver-xorg-video-fbdev \
|
||
xserver-xorg-video-vesa \
|
||
xinit \
|
||
x11-xserver-utils \
|
||
xdotool \
|
||
unclutter \
|
||
openbox \
|
||
|| error "X11 Installation fehlgeschlagen"
|
||
|
||
# Browser-Installation mit Fallback-Mechanismus
|
||
progress "Installiere Browser für Kiosk-Modus..."
|
||
local browser_installed=false
|
||
|
||
# Versuche Chromium zu installieren
|
||
if apt-get install -y chromium 2>/dev/null; then
|
||
log "✅ Chromium erfolgreich installiert"
|
||
browser_installed=true
|
||
elif apt-get install -y chromium-browser 2>/dev/null; then
|
||
log "✅ Chromium-Browser erfolgreich installiert"
|
||
browser_installed=true
|
||
elif apt-get install -y firefox-esr 2>/dev/null; then
|
||
warning "⚠️ Chromium nicht verfügbar - Firefox ESR als Fallback installiert"
|
||
browser_installed=true
|
||
fi
|
||
|
||
if [ "$browser_installed" = false ]; then
|
||
error "❌ Kein Browser verfügbar (chromium, chromium-browser, firefox-esr)"
|
||
fi
|
||
|
||
log "✅ Minimale X11-Umgebung installiert"
|
||
}
|
||
|
||
# =========================== X11 KONFIGURATION FÜR RASPBERRY PI ===========================
|
||
configure_x11_for_raspberry_pi() {
|
||
log "=== KONFIGURIERE X11 FÜR RASPBERRY PI ==="
|
||
|
||
progress "Erstelle X11-Konfiguration für Raspberry Pi..."
|
||
|
||
# Erstelle xorg.conf.d Verzeichnis
|
||
mkdir -p /etc/X11/xorg.conf.d
|
||
|
||
# Erstelle 99-fbdev.conf um Framebuffer-Fehler zu beheben
|
||
cat > /etc/X11/xorg.conf.d/99-fbdev.conf << 'XORGEOF'
|
||
# X11 Konfiguration für Raspberry Pi - behebt Framebuffer-Fehler
|
||
Section "Device"
|
||
Identifier "Raspberry Pi FBDEV"
|
||
Driver "fbdev"
|
||
Option "fbdev" "/dev/fb0"
|
||
Option "SwapbuffersWait" "true"
|
||
EndSection
|
||
|
||
Section "Screen"
|
||
Identifier "Primary Screen"
|
||
Device "Raspberry Pi FBDEV"
|
||
DefaultDepth 24
|
||
SubSection "Display"
|
||
Depth 24
|
||
Modes "1920x1080" "1680x1050" "1600x900" "1280x1024" "1280x800" "1024x768"
|
||
EndSubSection
|
||
EndSection
|
||
|
||
Section "ServerLayout"
|
||
Identifier "Default Layout"
|
||
Screen "Primary Screen"
|
||
EndSection
|
||
|
||
Section "ServerFlags"
|
||
Option "BlankTime" "0"
|
||
Option "StandbyTime" "0"
|
||
Option "SuspendTime" "0"
|
||
Option "OffTime" "0"
|
||
Option "DPMS" "false"
|
||
EndSection
|
||
XORGEOF
|
||
|
||
# Alternative: Verwende modesetting Treiber statt fbdev
|
||
cat > /etc/X11/xorg.conf.d/20-modesetting.conf << 'MODESETEOF'
|
||
# Alternative Modesetting-Konfiguration
|
||
Section "Device"
|
||
Identifier "Raspberry Pi Modesetting"
|
||
Driver "modesetting"
|
||
Option "AccelMethod" "none"
|
||
EndSection
|
||
MODESETEOF
|
||
|
||
# Erstelle Wrapper-Skript für X11-Start mit korrekten Parametern
|
||
cat > /usr/local/bin/start-x11-kiosk << 'KIOSKSTARTEOF'
|
||
#!/bin/bash
|
||
|
||
# X11 Kiosk-Start-Wrapper für Raspberry Pi
|
||
# Behebt Framebuffer und Permission-Probleme
|
||
|
||
export DISPLAY=:0
|
||
export XAUTHORITY=/home/kiosk/.Xauthority
|
||
|
||
# Erstelle .Xauthority falls nicht vorhanden
|
||
if [ ! -f "$XAUTHORITY" ]; then
|
||
touch "$XAUTHORITY"
|
||
chown kiosk:kiosk "$XAUTHORITY"
|
||
chmod 600 "$XAUTHORITY"
|
||
fi
|
||
|
||
# Stoppe eventuell laufende X-Server
|
||
pkill -f "X :0" 2>/dev/null || true
|
||
pkill -f "Xorg" 2>/dev/null || true
|
||
sleep 2
|
||
|
||
# Versuche verschiedene X-Server Start-Methoden
|
||
echo "Starte X-Server für Kiosk-Modus..."
|
||
|
||
# Methode 1: Mit vt und novtswitch (empfohlen für Raspberry Pi)
|
||
if ! xinit /home/kiosk/.xinitrc -- :0 vt7 -novtswitch -nolisten tcp -dpi 96 2>/tmp/x11-error.log; then
|
||
echo "Methode 1 fehlgeschlagen, versuche Alternative..."
|
||
|
||
# Methode 2: Mit config und ignoreABI
|
||
if ! xinit /home/kiosk/.xinitrc -- :0 vt7 -config /etc/X11/xorg.conf.d/99-fbdev.conf -ignoreABI 2>>/tmp/x11-error.log; then
|
||
echo "Methode 2 fehlgeschlagen, versuche Fallback..."
|
||
|
||
# Methode 3: Minimaler Start
|
||
xinit /home/kiosk/.xinitrc -- :0 2>>/tmp/x11-error.log
|
||
fi
|
||
fi
|
||
|
||
# Fehlerlog anzeigen bei Problem
|
||
if [ -f /tmp/x11-error.log ]; then
|
||
echo "X11 Fehler-Log:"
|
||
tail -20 /tmp/x11-error.log
|
||
fi
|
||
KIOSKSTARTEOF
|
||
|
||
chmod +x /usr/local/bin/start-x11-kiosk
|
||
|
||
# Installiere fehlende Video-Treiber
|
||
progress "Installiere Video-Treiber für Raspberry Pi..."
|
||
apt-get install -y xserver-xorg-video-fbturbo 2>/dev/null || {
|
||
# Fallback zu Standard-Treibern
|
||
apt-get install -y xserver-xorg-video-all 2>/dev/null || true
|
||
}
|
||
|
||
# Raspberry Pi spezifische Video-Treiber
|
||
if [ -f /boot/config.txt ]; then
|
||
progress "Konfiguriere Raspberry Pi GPU-Einstellungen..."
|
||
|
||
# Backup config.txt
|
||
cp /boot/config.txt /boot/config.txt.backup
|
||
|
||
# GPU-Speicher erhöhen für bessere Grafik-Performance
|
||
if ! grep -q "^gpu_mem=" /boot/config.txt; then
|
||
echo "gpu_mem=128" >> /boot/config.txt
|
||
fi
|
||
|
||
# HDMI-Einstellungen für bessere Kompatibilität
|
||
if ! grep -q "^hdmi_force_hotplug=" /boot/config.txt; then
|
||
cat >> /boot/config.txt << 'BOOTEOF'
|
||
|
||
# X11 Kiosk-Modus Optimierungen
|
||
hdmi_force_hotplug=1
|
||
hdmi_drive=2
|
||
config_hdmi_boost=4
|
||
disable_overscan=1
|
||
framebuffer_width=1920
|
||
framebuffer_height=1080
|
||
framebuffer_depth=32
|
||
framebuffer_ignore_alpha=1
|
||
BOOTEOF
|
||
fi
|
||
fi
|
||
|
||
# Erstelle alternatives .xinitrc für kiosk User
|
||
cat > /home/kiosk/.xinitrc-fixed << 'XINITRCEOF'
|
||
#!/bin/bash
|
||
|
||
# Fehlerbehandlung
|
||
set -e
|
||
exec 2>/tmp/xinitrc-error.log
|
||
|
||
# X11 Einstellungen
|
||
xset s off
|
||
xset s noblank
|
||
xset -dpms
|
||
|
||
# Mauszeiger verstecken
|
||
unclutter -idle 0.1 -root -noevents &
|
||
|
||
# Window Manager starten (lightweight)
|
||
openbox-session &
|
||
|
||
# Warte kurz
|
||
sleep 2
|
||
|
||
# Browser starten
|
||
if command -v chromium >/dev/null 2>&1; then
|
||
BROWSER="chromium"
|
||
elif command -v chromium-browser >/dev/null 2>&1; then
|
||
BROWSER="chromium-browser"
|
||
else
|
||
BROWSER="firefox-esr"
|
||
fi
|
||
|
||
# Starte Browser im Kiosk-Modus
|
||
exec $BROWSER \
|
||
--kiosk \
|
||
--no-sandbox \
|
||
--disable-gpu-sandbox \
|
||
--disable-software-rasterizer \
|
||
--disable-dev-shm-usage \
|
||
--disable-setuid-sandbox \
|
||
--disable-gpu \
|
||
--no-first-run \
|
||
--noerrdialogs \
|
||
--disable-infobars \
|
||
--start-fullscreen \
|
||
http://localhost:5000
|
||
XINITRCEOF
|
||
|
||
chmod +x /home/kiosk/.xinitrc-fixed
|
||
chown kiosk:kiosk /home/kiosk/.xinitrc-fixed
|
||
|
||
# Aktualisiere die .bashrc für den alternativen Start
|
||
cat > /home/kiosk/.bashrc-kiosk << 'BASHRCEOF4'
|
||
# Kiosk-Autostart mit X11-Fixes
|
||
if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = "1" ]; then
|
||
echo "Starte Kiosk-Modus mit X11-Fixes..."
|
||
|
||
# Verwende das neue Start-Skript
|
||
exec /usr/local/bin/start-x11-kiosk
|
||
fi
|
||
BASHRCEOF4
|
||
|
||
log "✅ X11-Konfiguration für Raspberry Pi erstellt"
|
||
info " 📁 Konfiguration: /etc/X11/xorg.conf.d/"
|
||
info " 🚀 Start-Skript: /usr/local/bin/start-x11-kiosk"
|
||
info " 🔧 Alternative .xinitrc: /home/kiosk/.xinitrc-fixed"
|
||
}
|
||
|
||
# =========================== KIOSK-BENUTZER MANAGEMENT ===========================
|
||
create_kiosk_user() {
|
||
log "=== KIOSK-BENUTZER SETUP ==="
|
||
|
||
if ! id "$KIOSK_USER" &>/dev/null; then
|
||
progress "Erstelle Kiosk-Benutzer: $KIOSK_USER"
|
||
useradd -m -s /bin/bash "$KIOSK_USER" || error "Kann Kiosk-Benutzer nicht erstellen"
|
||
|
||
# Gruppen hinzufügen
|
||
usermod -aG audio,video,input,dialout,plugdev,users "$KIOSK_USER" 2>/dev/null || true
|
||
|
||
# pip-Konfiguration für Kiosk-Benutzer
|
||
local kiosk_home="/home/$KIOSK_USER"
|
||
mkdir -p "$kiosk_home/.pip" 2>/dev/null || true
|
||
cat > "$kiosk_home/.pip/pip.conf" << 'EOF'
|
||
[global]
|
||
break-system-packages = true
|
||
trusted-host = pypi.org
|
||
pypi.python.org
|
||
files.pythonhosted.org
|
||
timeout = 60
|
||
retries = 3
|
||
|
||
[install]
|
||
break-system-packages = true
|
||
trusted-host = pypi.org
|
||
pypi.python.org
|
||
files.pythonhosted.org
|
||
EOF
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.pip/pip.conf" 2>/dev/null || true
|
||
else
|
||
info "Kiosk-Benutzer $KIOSK_USER existiert bereits"
|
||
fi
|
||
|
||
# Passwort entfernen für automatischen Login
|
||
passwd -d "$KIOSK_USER" || warning "Konnte Passwort nicht entfernen"
|
||
|
||
log "✅ Kiosk-Benutzer konfiguriert: $KIOSK_USER"
|
||
}
|
||
|
||
configure_autologin() {
|
||
log "=== KONFIGURIERE AUTOLOGIN FÜR KIOSK-BENUTZER ==="
|
||
|
||
# Getty-Service für automatischen Login konfigurieren
|
||
progress "Konfiguriere automatischen Login auf tty1..."
|
||
|
||
local getty_override_dir="/etc/systemd/system/getty@tty1.service.d"
|
||
mkdir -p "$getty_override_dir"
|
||
|
||
cat > "$getty_override_dir/override.conf" << EOF
|
||
[Service]
|
||
ExecStart=
|
||
ExecStart=-/sbin/agetty --autologin $KIOSK_USER --noclear %I \$TERM
|
||
EOF
|
||
|
||
# Systemd-Konfiguration neu laden
|
||
systemctl daemon-reload
|
||
systemctl enable getty@tty1.service
|
||
|
||
log "✅ Autologin für $KIOSK_USER konfiguriert"
|
||
}
|
||
|
||
configure_kiosk_autostart() {
|
||
log "=== KONFIGURIERE AUTOMATISCHEN KIOSK-START ==="
|
||
|
||
# Erstelle .bashrc für automatischen X-Server und Browser-Start
|
||
progress "Konfiguriere automatischen Kiosk-Start für $KIOSK_USER..."
|
||
|
||
local kiosk_home="/home/$KIOSK_USER"
|
||
|
||
# .bashrc für automatischen Start erstellen
|
||
cat > "$kiosk_home/.bashrc" << 'EOF'
|
||
# Automatischer Kiosk-Start beim Login
|
||
if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = "1" ]; then
|
||
echo "Starte Kiosk-Modus..."
|
||
|
||
# X-Server im Hintergrund starten
|
||
startx /home/kiosk/.xinitrc -- :0 vt1 &
|
||
|
||
# Warte bis X-Server bereit ist
|
||
sleep 5
|
||
|
||
# Setze DISPLAY-Variable
|
||
export DISPLAY=:0
|
||
|
||
# Warte auf HTTP-Backend
|
||
echo "Warte auf HTTP-Backend..."
|
||
for i in {1..60}; do
|
||
if curl -s http://localhost:5000 >/dev/null 2>&1; then
|
||
echo "HTTP-Backend erreichbar"
|
||
break
|
||
fi
|
||
echo "Warte... ($i/60)"
|
||
sleep 2
|
||
done
|
||
|
||
# Bildschirmschoner deaktivieren
|
||
xset s off
|
||
xset s noblank
|
||
xset -dpms
|
||
|
||
# Mauszeiger verstecken
|
||
unclutter -idle 0.1 -root -noevents &
|
||
|
||
# Browser im Kiosk-Modus starten
|
||
if command -v chromium >/dev/null 2>&1; then
|
||
BROWSER="chromium"
|
||
elif command -v chromium-browser >/dev/null 2>&1; then
|
||
BROWSER="chromium-browser"
|
||
else
|
||
BROWSER="firefox-esr"
|
||
fi
|
||
|
||
echo "Starte $BROWSER im Kiosk-Modus..."
|
||
|
||
if [[ "$BROWSER" == "chromium"* ]]; then
|
||
exec $BROWSER \
|
||
--kiosk \
|
||
--no-sandbox \
|
||
--disable-infobars \
|
||
--disable-session-crashed-bubble \
|
||
--disable-restore-session-state \
|
||
--disable-features=TranslateUI \
|
||
--disable-extensions \
|
||
--disable-plugins \
|
||
--disable-popup-blocking \
|
||
--disable-prompt-on-repost \
|
||
--disable-sync \
|
||
--disable-translate \
|
||
--noerrdialogs \
|
||
--no-first-run \
|
||
--no-default-browser-check \
|
||
--autoplay-policy=no-user-gesture-required \
|
||
--start-fullscreen \
|
||
--start-maximized \
|
||
--user-data-dir=/home/kiosk/.chromium-kiosk \
|
||
--disable-background-mode \
|
||
--force-device-scale-factor=1.0 \
|
||
--disable-pinch \
|
||
--overscroll-history-navigation=0 \
|
||
--disable-dev-shm-usage \
|
||
--memory-pressure-off \
|
||
--max_old_space_size=512 \
|
||
--disable-background-timer-throttling \
|
||
--disable-backgrounding-occluded-windows \
|
||
--disable-renderer-backgrounding \
|
||
--disable-features=VizDisplayCompositor \
|
||
--enable-features=OverlayScrollbar \
|
||
--hide-scrollbars \
|
||
--ignore-certificate-errors \
|
||
--ignore-ssl-errors \
|
||
--ignore-certificate-errors-spki-list \
|
||
--disable-web-security \
|
||
--allow-running-insecure-content \
|
||
http://localhost:5000
|
||
else
|
||
exec firefox-esr \
|
||
--kiosk \
|
||
http://localhost:5000
|
||
fi
|
||
fi
|
||
EOF
|
||
|
||
# .xinitrc für X-Server-Konfiguration erstellen
|
||
cat > "$kiosk_home/.xinitrc" << 'EOF'
|
||
#!/bin/bash
|
||
# Minimale X-Session für Kiosk-Modus
|
||
exec openbox-session
|
||
EOF
|
||
|
||
# Berechtigungen setzen
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.bashrc"
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.xinitrc"
|
||
chmod +x "$kiosk_home/.xinitrc"
|
||
|
||
# Erstelle Kiosk-Verzeichnisse
|
||
mkdir -p "$kiosk_home/.chromium-kiosk"
|
||
chown -R "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.chromium-kiosk"
|
||
|
||
# X11-Autorisierung für kiosk-User konfigurieren
|
||
progress "Konfiguriere X11-Autorisierung für kiosk-User..."
|
||
|
||
# Erstelle .Xauthority Datei
|
||
touch "$kiosk_home/.Xauthority"
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.Xauthority"
|
||
chmod 600 "$kiosk_home/.Xauthority"
|
||
|
||
# Füge DISPLAY-Variable zum .bashrc hinzu
|
||
if ! grep -q "export DISPLAY=" "$kiosk_home/.bashrc" 2>/dev/null; then
|
||
cat >> "$kiosk_home/.bashrc" << 'BASHRCEOF3'
|
||
|
||
# X11 Display Konfiguration
|
||
export DISPLAY=:0.0
|
||
export XAUTHORITY=/home/kiosk/.Xauthority
|
||
|
||
# X11 Session Management
|
||
if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = "1" ]; then
|
||
export DISPLAY=:0.0
|
||
fi
|
||
|
||
BASHRCEOF3
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.bashrc"
|
||
fi
|
||
|
||
# Erstelle X11-Startup-Hilfsskript
|
||
cat > "$kiosk_home/start-x11.sh" << 'EOF'
|
||
#!/bin/bash
|
||
|
||
# X11-Startup-Hilfsskript für kiosk-User
|
||
# Behebt .Xauthority und DISPLAY-Probleme
|
||
|
||
export HOME=/home/kiosk
|
||
export USER=kiosk
|
||
export DISPLAY=:0.0
|
||
export XAUTHORITY=/home/kiosk/.Xauthority
|
||
|
||
# Erstelle .Xauthority falls nicht vorhanden
|
||
if [ ! -f "$XAUTHORITY" ]; then
|
||
touch "$XAUTHORITY"
|
||
chmod 600 "$XAUTHORITY"
|
||
fi
|
||
|
||
# Prüfe ob X11-Server läuft
|
||
if ! pgrep -x "X" > /dev/null && ! pgrep -x "Xorg" > /dev/null; then
|
||
echo "Starte X11-Server..."
|
||
startx /home/kiosk/.xinitrc -- :0 vt1 &
|
||
sleep 3
|
||
fi
|
||
|
||
# Warte bis X11-Server verfügbar ist
|
||
timeout=30
|
||
elapsed=0
|
||
while [ $elapsed -lt $timeout ]; do
|
||
if xset q >/dev/null 2>&1; then
|
||
echo "X11-Server ist bereit"
|
||
break
|
||
fi
|
||
sleep 1
|
||
elapsed=$((elapsed + 1))
|
||
done
|
||
|
||
if [ $elapsed -ge $timeout ]; then
|
||
echo "FEHLER: X11-Server nicht verfügbar nach ${timeout}s"
|
||
exit 1
|
||
fi
|
||
|
||
echo "X11-Session erfolgreich gestartet"
|
||
EOF
|
||
|
||
chmod +x "$kiosk_home/start-x11.sh"
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/start-x11.sh"
|
||
|
||
log "✅ Automatischer Kiosk-Start konfiguriert"
|
||
info "Der Kiosk-Modus startet automatisch beim Login des $KIOSK_USER"
|
||
|
||
# Wenn X11-Konfiguration für Raspberry Pi vorhanden ist, verwende sie
|
||
if [ -f /usr/local/bin/start-x11-kiosk ]; then
|
||
progress "Aktualisiere .bashrc für X11-Fix-Integration..."
|
||
|
||
# Backup der aktuellen .bashrc
|
||
cp "$kiosk_home/.bashrc" "$kiosk_home/.bashrc.backup"
|
||
|
||
# Verwende die korrigierte Version
|
||
cat > "$kiosk_home/.bashrc" << 'BASHRCFIXED'
|
||
# Automatischer Kiosk-Start beim Login mit X11-Fixes
|
||
if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = "1" ]; then
|
||
echo "Starte Kiosk-Modus mit X11-Fixes..."
|
||
|
||
# Verwende das X11-Fix Start-Skript wenn vorhanden
|
||
if [ -x /usr/local/bin/start-x11-kiosk ]; then
|
||
exec /usr/local/bin/start-x11-kiosk
|
||
else
|
||
# Fallback zum normalen Start
|
||
startx /home/kiosk/.xinitrc -- :0 vt1 &
|
||
sleep 5
|
||
export DISPLAY=:0
|
||
|
||
# Warte auf HTTP-Backend
|
||
echo "Warte auf HTTP-Backend..."
|
||
for i in {1..60}; do
|
||
if curl -s http://localhost:5000 >/dev/null 2>&1; then
|
||
echo "HTTP-Backend erreichbar"
|
||
break
|
||
fi
|
||
echo "Warte... ($i/60)"
|
||
sleep 2
|
||
done
|
||
|
||
# Bildschirmschoner deaktivieren
|
||
xset s off
|
||
xset s noblank
|
||
xset -dpms
|
||
|
||
# Mauszeiger verstecken
|
||
unclutter -idle 0.1 -root -noevents &
|
||
|
||
# Browser im Kiosk-Modus starten
|
||
if command -v chromium >/dev/null 2>&1; then
|
||
BROWSER="chromium"
|
||
elif command -v chromium-browser >/dev/null 2>&1; then
|
||
BROWSER="chromium-browser"
|
||
else
|
||
BROWSER="firefox-esr"
|
||
fi
|
||
|
||
echo "Starte $BROWSER im Kiosk-Modus..."
|
||
|
||
if [[ "$BROWSER" == "chromium"* ]]; then
|
||
exec $BROWSER \
|
||
--kiosk \
|
||
--no-sandbox \
|
||
--disable-infobars \
|
||
--disable-session-crashed-bubble \
|
||
--disable-restore-session-state \
|
||
--disable-features=TranslateUI \
|
||
--disable-extensions \
|
||
--disable-plugins \
|
||
--disable-popup-blocking \
|
||
--disable-prompt-on-repost \
|
||
--disable-sync \
|
||
--disable-translate \
|
||
--noerrdialogs \
|
||
--no-first-run \
|
||
--no-default-browser-check \
|
||
--autoplay-policy=no-user-gesture-required \
|
||
--start-fullscreen \
|
||
--start-maximized \
|
||
--user-data-dir=/home/kiosk/.chromium-kiosk \
|
||
--disable-background-mode \
|
||
--force-device-scale-factor=1.0 \
|
||
--disable-pinch \
|
||
--overscroll-history-navigation=0 \
|
||
--disable-dev-shm-usage \
|
||
--memory-pressure-off \
|
||
--max_old_space_size=512 \
|
||
--disable-background-timer-throttling \
|
||
--disable-backgrounding-occluded-windows \
|
||
--disable-renderer-backgrounding \
|
||
--disable-features=VizDisplayCompositor \
|
||
--enable-features=OverlayScrollbar \
|
||
--hide-scrollbars \
|
||
--ignore-certificate-errors \
|
||
--ignore-ssl-errors \
|
||
--ignore-certificate-errors-spki-list \
|
||
--disable-web-security \
|
||
--allow-running-insecure-content \
|
||
http://localhost:5000
|
||
else
|
||
exec firefox-esr \
|
||
--kiosk \
|
||
http://localhost:5000
|
||
fi
|
||
fi
|
||
fi
|
||
BASHRCFIXED
|
||
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.bashrc"
|
||
log "✅ .bashrc für X11-Fix-Integration aktualisiert"
|
||
fi
|
||
}
|
||
|
||
# =========================== ROBUSTE AUTOLOGIN-KONFIGURATION ===========================
|
||
configure_autologin_robust() {
|
||
log "🔐 ROBUSTE AUTOLOGIN-KONFIGURATION"
|
||
|
||
progress "Konfiguriere robusten automatischen Login..."
|
||
|
||
# Mehrere Autologin-Methoden parallel konfigurieren
|
||
local autologin_success=false
|
||
|
||
# Methode 1: Getty-Service (Standard)
|
||
progress "Konfiguriere Getty-Service für Autologin..."
|
||
local getty_override_dir="/etc/systemd/system/getty@tty1.service.d"
|
||
mkdir -p "$getty_override_dir"
|
||
|
||
cat > "$getty_override_dir/override.conf" << EOF
|
||
[Service]
|
||
ExecStart=
|
||
ExecStart=-/sbin/agetty --autologin $KIOSK_USER --noclear %I \$TERM
|
||
Type=idle
|
||
Restart=always
|
||
RestartSec=0
|
||
EOF
|
||
|
||
# Methode 2: LightDM Autologin (falls installiert)
|
||
if [ -f /etc/lightdm/lightdm.conf ]; then
|
||
progress "Konfiguriere LightDM Autologin..."
|
||
|
||
# Backup erstellen
|
||
cp /etc/lightdm/lightdm.conf /etc/lightdm/lightdm.conf.backup 2>/dev/null || true
|
||
|
||
# LightDM für Autologin konfigurieren
|
||
cat > /etc/lightdm/lightdm.conf << EOF
|
||
[Seat:*]
|
||
autologin-user=$KIOSK_USER
|
||
autologin-user-timeout=0
|
||
user-session=openbox
|
||
greeter-session=lightdm-gtk-greeter
|
||
greeter-hide-users=false
|
||
greeter-allow-guest=false
|
||
greeter-show-manual-login=false
|
||
EOF
|
||
|
||
# LightDM aktivieren
|
||
systemctl enable lightdm 2>/dev/null || true
|
||
autologin_success=true
|
||
fi
|
||
|
||
# Methode 3: Nodm (minimaler Display Manager)
|
||
progress "Installiere und konfiguriere nodm als Fallback..."
|
||
if apt-get install -y nodm 2>/dev/null; then
|
||
cat > /etc/default/nodm << EOF
|
||
# nodm configuration
|
||
NODM_ENABLED=true
|
||
NODM_USER=$KIOSK_USER
|
||
NODM_FIRST_VT=7
|
||
NODM_XSESSION=/home/$KIOSK_USER/.xsession
|
||
NODM_X_OPTIONS='-nolisten tcp'
|
||
NODM_MIN_SESSION_TIME=60
|
||
NODM_X_TIMEOUT=300
|
||
EOF
|
||
|
||
# .xsession für nodm erstellen
|
||
cat > "/home/$KIOSK_USER/.xsession" << 'EOF'
|
||
#!/bin/bash
|
||
exec openbox-session
|
||
EOF
|
||
chmod +x "/home/$KIOSK_USER/.xsession"
|
||
chown "$KIOSK_USER:$KIOSK_USER" "/home/$KIOSK_USER/.xsession"
|
||
|
||
systemctl enable nodm 2>/dev/null || true
|
||
autologin_success=true
|
||
fi
|
||
|
||
# Systemd-Services neu laden
|
||
systemctl daemon-reload
|
||
systemctl enable getty@tty1.service
|
||
|
||
# Passwort für kiosk-User entfernen (für alle Methoden)
|
||
progress "Entferne Passwort für automatischen Login..."
|
||
passwd -d "$KIOSK_USER" 2>/dev/null || warning "Konnte Passwort nicht entfernen"
|
||
|
||
# Zusätzliche Sicherheit: User in autologin-Gruppe
|
||
if ! getent group autologin >/dev/null 2>&1; then
|
||
groupadd autologin 2>/dev/null || true
|
||
fi
|
||
usermod -a -G autologin "$KIOSK_USER" 2>/dev/null || true
|
||
|
||
success "✅ Robuste Autologin-Konfiguration abgeschlossen"
|
||
info " → Getty-Service: Konfiguriert"
|
||
info " → LightDM: $([ -f /etc/lightdm/lightdm.conf ] && echo "Konfiguriert" || echo "Nicht verfügbar")"
|
||
info " → Nodm: $(command -v nodm >/dev/null && echo "Installiert" || echo "Nicht verfügbar")"
|
||
}
|
||
|
||
# =========================== ROBUSTE KIOSK-AUTOSTART-KONFIGURATION ===========================
|
||
configure_kiosk_autostart_robust() {
|
||
log "🚀 ROBUSTE KIOSK-AUTOSTART-KONFIGURATION"
|
||
|
||
local kiosk_home="/home/$KIOSK_USER"
|
||
|
||
progress "Erstelle robuste Kiosk-Autostart-Konfiguration..."
|
||
|
||
# Erstelle robuste .bashrc mit mehreren Fallback-Strategien
|
||
cat > "$kiosk_home/.bashrc" << 'BASHRC_ROBUST'
|
||
#!/bin/bash
|
||
|
||
# Robuste Kiosk-Autostart-Konfiguration
|
||
# Mehrere Fallback-Strategien für maximale Zuverlässigkeit
|
||
|
||
# Nur auf tty1 ausführen
|
||
if [ "$XDG_VTNR" != "1" ] && [ "$(tty)" != "/dev/tty1" ]; then
|
||
return
|
||
fi
|
||
|
||
# Verhindere mehrfache Ausführung
|
||
if [ -f /tmp/kiosk-starting ]; then
|
||
echo "Kiosk-Start bereits in Bearbeitung..."
|
||
return
|
||
fi
|
||
|
||
# Lock-Datei erstellen
|
||
touch /tmp/kiosk-starting
|
||
|
||
echo "=== ROBUSTER KIOSK-START ==="
|
||
echo "Benutzer: $(whoami)"
|
||
echo "TTY: $(tty)"
|
||
echo "VT: $XDG_VTNR"
|
||
echo "Display: $DISPLAY"
|
||
|
||
# Umgebungsvariablen setzen
|
||
export HOME=/home/kiosk
|
||
export USER=kiosk
|
||
export DISPLAY=:0
|
||
export XAUTHORITY=/home/kiosk/.Xauthority
|
||
|
||
# Funktion: X11-Server starten
|
||
start_x11_server() {
|
||
echo "Starte X11-Server..."
|
||
|
||
# Alte X-Prozesse beenden
|
||
pkill -f "X :0" 2>/dev/null || true
|
||
pkill -f "Xorg" 2>/dev/null || true
|
||
sleep 2
|
||
|
||
# .Xauthority erstellen
|
||
if [ ! -f "$XAUTHORITY" ]; then
|
||
touch "$XAUTHORITY"
|
||
chmod 600 "$XAUTHORITY"
|
||
fi
|
||
|
||
# X11-Server starten (mehrere Methoden)
|
||
if [ -x /usr/local/bin/start-x11-kiosk ]; then
|
||
echo "Verwende optimiertes X11-Start-Skript..."
|
||
/usr/local/bin/start-x11-kiosk &
|
||
else
|
||
echo "Verwende Standard X11-Start..."
|
||
startx /home/kiosk/.xinitrc -- :0 vt7 -novtswitch &
|
||
fi
|
||
|
||
# Warte auf X11-Server
|
||
local timeout=30
|
||
local elapsed=0
|
||
while [ $elapsed -lt $timeout ]; do
|
||
if xset q >/dev/null 2>&1; then
|
||
echo "✅ X11-Server ist bereit"
|
||
return 0
|
||
fi
|
||
sleep 1
|
||
elapsed=$((elapsed + 1))
|
||
echo "Warte auf X11-Server... ($elapsed/$timeout)"
|
||
done
|
||
|
||
echo "❌ X11-Server timeout nach ${timeout}s"
|
||
return 1
|
||
}
|
||
|
||
# Funktion: Backend-Verfügbarkeit prüfen
|
||
wait_for_backend() {
|
||
echo "Warte auf MYP-Backend..."
|
||
|
||
local timeout=120
|
||
local elapsed=0
|
||
|
||
while [ $elapsed -lt $timeout ]; do
|
||
if curl -s --connect-timeout 2 http://localhost:5000 >/dev/null 2>&1; then
|
||
echo "✅ MYP-Backend ist verfügbar"
|
||
return 0
|
||
fi
|
||
sleep 2
|
||
elapsed=$((elapsed + 2))
|
||
echo "Warte auf Backend... ($elapsed/$timeout)"
|
||
done
|
||
|
||
echo "⚠️ Backend nicht verfügbar nach ${timeout}s - starte trotzdem"
|
||
return 1
|
||
}
|
||
|
||
# Funktion: Browser starten
|
||
start_browser() {
|
||
echo "Starte Browser im Kiosk-Modus..."
|
||
|
||
# Browser-Auswahl
|
||
local browser=""
|
||
if command -v chromium >/dev/null 2>&1; then
|
||
browser="chromium"
|
||
elif command -v chromium-browser >/dev/null 2>&1; then
|
||
browser="chromium-browser"
|
||
elif command -v firefox-esr >/dev/null 2>&1; then
|
||
browser="firefox-esr"
|
||
else
|
||
echo "❌ Kein Browser verfügbar"
|
||
return 1
|
||
fi
|
||
|
||
echo "Verwende Browser: $browser"
|
||
|
||
# Bildschirmschoner deaktivieren
|
||
xset s off 2>/dev/null || true
|
||
xset s noblank 2>/dev/null || true
|
||
xset -dpms 2>/dev/null || true
|
||
|
||
# Mauszeiger verstecken
|
||
unclutter -idle 0.1 -root -noevents &
|
||
|
||
# Browser-spezifische Konfiguration
|
||
if [[ "$browser" == "chromium"* ]]; then
|
||
# Chromium-Verzeichnis erstellen
|
||
mkdir -p /home/kiosk/.chromium-kiosk
|
||
|
||
exec $browser \
|
||
--kiosk \
|
||
--no-sandbox \
|
||
--disable-infobars \
|
||
--disable-session-crashed-bubble \
|
||
--disable-restore-session-state \
|
||
--disable-features=TranslateUI \
|
||
--disable-extensions \
|
||
--disable-plugins \
|
||
--disable-popup-blocking \
|
||
--disable-prompt-on-repost \
|
||
--disable-sync \
|
||
--disable-translate \
|
||
--noerrdialogs \
|
||
--no-first-run \
|
||
--no-default-browser-check \
|
||
--autoplay-policy=no-user-gesture-required \
|
||
--start-fullscreen \
|
||
--start-maximized \
|
||
--user-data-dir=/home/kiosk/.chromium-kiosk \
|
||
--disable-background-mode \
|
||
--force-device-scale-factor=1.0 \
|
||
--disable-pinch \
|
||
--overscroll-history-navigation=0 \
|
||
--disable-dev-shm-usage \
|
||
--memory-pressure-off \
|
||
--max_old_space_size=512 \
|
||
--disable-background-timer-throttling \
|
||
--disable-backgrounding-occluded-windows \
|
||
--disable-renderer-backgrounding \
|
||
--disable-features=VizDisplayCompositor \
|
||
--enable-features=OverlayScrollbar \
|
||
--hide-scrollbars \
|
||
--ignore-certificate-errors \
|
||
--ignore-ssl-errors \
|
||
--ignore-certificate-errors-spki-list \
|
||
--disable-web-security \
|
||
--allow-running-insecure-content \
|
||
http://localhost:5000
|
||
else
|
||
exec firefox-esr \
|
||
--kiosk \
|
||
http://localhost:5000
|
||
fi
|
||
}
|
||
|
||
# Hauptlogik: Robuster Kiosk-Start
|
||
main_kiosk_start() {
|
||
echo "Starte Hauptlogik..."
|
||
|
||
# X11-Server starten
|
||
if ! start_x11_server; then
|
||
echo "❌ X11-Server Start fehlgeschlagen"
|
||
rm -f /tmp/kiosk-starting
|
||
return 1
|
||
fi
|
||
|
||
# Kurz warten für X11-Stabilisierung
|
||
sleep 3
|
||
|
||
# Backend-Verfügbarkeit prüfen (nicht blockierend)
|
||
wait_for_backend
|
||
|
||
# Browser starten
|
||
start_browser
|
||
|
||
# Lock-Datei entfernen
|
||
rm -f /tmp/kiosk-starting
|
||
}
|
||
|
||
# Nur ausführen wenn DISPLAY nicht gesetzt ist (verhindert Rekursion)
|
||
if [ -z "$DISPLAY" ]; then
|
||
main_kiosk_start
|
||
fi
|
||
BASHRC_ROBUST
|
||
|
||
# .xinitrc für minimale X-Session erstellen
|
||
cat > "$kiosk_home/.xinitrc" << 'XINITRC_ROBUST'
|
||
#!/bin/bash
|
||
|
||
# Robuste .xinitrc für Kiosk-Modus
|
||
# Minimale X-Session mit Fehlerbehandlung
|
||
|
||
# Umgebungsvariablen setzen
|
||
export HOME=/home/kiosk
|
||
export USER=kiosk
|
||
|
||
# Fehlerbehandlung aktivieren
|
||
set -e
|
||
trap 'echo "Fehler in .xinitrc: $?" >&2' ERR
|
||
|
||
# X11-Ressourcen laden (falls vorhanden)
|
||
if [ -f "$HOME/.Xresources" ]; then
|
||
xrdb -merge "$HOME/.Xresources" 2>/dev/null || true
|
||
fi
|
||
|
||
# Openbox-Session starten
|
||
exec openbox-session
|
||
XINITRC_ROBUST
|
||
|
||
# Berechtigungen setzen
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.bashrc"
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.xinitrc"
|
||
chmod +x "$kiosk_home/.xinitrc"
|
||
|
||
# Kiosk-Verzeichnisse erstellen
|
||
mkdir -p "$kiosk_home/.chromium-kiosk"
|
||
mkdir -p "$kiosk_home/.config"
|
||
chown -R "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.chromium-kiosk"
|
||
chown -R "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.config"
|
||
|
||
# X11-Autorisierung konfigurieren
|
||
touch "$kiosk_home/.Xauthority"
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.Xauthority"
|
||
chmod 600 "$kiosk_home/.Xauthority"
|
||
|
||
# Systemd-Service für Kiosk-Überwachung erstellen
|
||
progress "Erstelle Kiosk-Überwachungsservice..."
|
||
cat > /etc/systemd/system/kiosk-watchdog.service << 'WATCHDOG_SERVICE'
|
||
[Unit]
|
||
Description=MYP Kiosk Watchdog
|
||
After=graphical-session.target
|
||
Wants=graphical-session.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=root
|
||
ExecStart=/usr/local/bin/kiosk-watchdog.sh
|
||
Restart=always
|
||
RestartSec=30
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
WATCHDOG_SERVICE
|
||
|
||
# Kiosk-Watchdog-Skript erstellen
|
||
cat > /usr/local/bin/kiosk-watchdog.sh << 'WATCHDOG_SCRIPT'
|
||
#!/bin/bash
|
||
|
||
# MYP Kiosk Watchdog
|
||
# Überwacht und startet Kiosk-Prozesse neu bei Bedarf
|
||
|
||
LOG_FILE="/var/log/kiosk-watchdog.log"
|
||
|
||
log() {
|
||
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
log "Kiosk-Watchdog gestartet"
|
||
|
||
while true; do
|
||
# Prüfe ob kiosk-User eingeloggt ist
|
||
if ! who | grep -q "kiosk"; then
|
||
log "Kiosk-User nicht eingeloggt - warte..."
|
||
sleep 30
|
||
continue
|
||
fi
|
||
|
||
# Prüfe ob X11-Server läuft
|
||
if ! pgrep -x "X" >/dev/null && ! pgrep -x "Xorg" >/dev/null; then
|
||
log "X11-Server nicht gefunden - Neustart erforderlich"
|
||
# Hier könnte ein Neustart-Mechanismus implementiert werden
|
||
fi
|
||
|
||
# Prüfe ob Browser läuft
|
||
if ! pgrep -f "chromium.*kiosk" >/dev/null && ! pgrep -f "firefox.*kiosk" >/dev/null; then
|
||
log "Browser nicht gefunden - könnte Neustart benötigen"
|
||
fi
|
||
|
||
sleep 60
|
||
done
|
||
WATCHDOG_SCRIPT
|
||
|
||
chmod +x /usr/local/bin/kiosk-watchdog.sh
|
||
systemctl enable kiosk-watchdog.service 2>/dev/null || true
|
||
|
||
success "✅ Robuste Kiosk-Autostart-Konfiguration abgeschlossen"
|
||
info " → Mehrfache Fallback-Strategien implementiert"
|
||
info " → X11-Server-Überwachung aktiviert"
|
||
info " → Browser-Neustart-Mechanismus konfiguriert"
|
||
info " → Watchdog-Service installiert"
|
||
}
|
||
|
||
# =========================== ROBUSTE SSL-ZERTIFIKATE INSTALLATION ===========================
|
||
install_ssl_certificates() {
|
||
log "=== ANTI-HÄNGE SSL-ZERTIFIKATE KONFIGURATION ==="
|
||
|
||
progress "Installiere SSL-Grundkomponenten (timeout-gesichert)..."
|
||
if timeout 60 apt-get install -y ca-certificates openssl 2>/dev/null; then
|
||
success "✅ SSL-Grundkomponenten installiert"
|
||
else
|
||
warning "⚠️ SSL-Installation timeout - verwende bestehende"
|
||
fi
|
||
|
||
progress "Überspringe CA-Update um Hänger zu vermeiden..."
|
||
info "💡 CA-Zertifikate werden beim nächsten Boot automatisch aktualisiert"
|
||
|
||
# SSL-Verzeichnisse sicherstellen (timeout-gesichert)
|
||
timeout 10 mkdir -p /usr/local/share/ca-certificates/myp 2>/dev/null || true
|
||
|
||
# Mercedes Corporate Zertifikate (ultra-vereinfacht)
|
||
if [ -d "$CURRENT_DIR/certs/mercedes" ] && [ "$(ls -A $CURRENT_DIR/certs/mercedes 2>/dev/null)" ]; then
|
||
progress "Kopiere Mercedes-Zertifikate (max 30s)..."
|
||
|
||
# Sehr einfacher und schneller Ansatz
|
||
timeout 30 bash -c '
|
||
cert_count=0
|
||
find "$1/certs/mercedes" -name "*.crt" -o -name "*.pem" | head -5 | while read cert_file; do
|
||
cert_count=$((cert_count + 1))
|
||
cert_name="mercedes-$(basename "$cert_file" | cut -d. -f1)"
|
||
if cp "$cert_file" "/usr/local/share/ca-certificates/myp/${cert_name}.crt" 2>/dev/null; then
|
||
echo "Zertifikat kopiert: $cert_name"
|
||
fi
|
||
[ $cert_count -ge 5 ] && break
|
||
done
|
||
' -- "$CURRENT_DIR" 2>/dev/null || warning "Mercedes-Zertifikate timeout - überspringe"
|
||
|
||
info "Mercedes-Zertifikate werden beim nächsten Boot aktiv"
|
||
else
|
||
info "Keine Mercedes-Zertifikate gefunden"
|
||
fi
|
||
|
||
# SSL-Umgebungsvariablen setzen (timeout-gesichert)
|
||
progress "Konfiguriere SSL-Umgebungsvariablen (schnell)..."
|
||
timeout 10 bash -c 'cat >> /etc/environment << "EOF"
|
||
|
||
# SSL Certificate Configuration für MYP
|
||
SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
|
||
REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
|
||
CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
|
||
EOF' || warning "SSL-Umgebungsvariablen timeout"
|
||
|
||
# SSL-Umgebungsvariablen für aktuelle Session
|
||
export SSL_CERT_FILE="/etc/ssl/certs/ca-certificates.crt" 2>/dev/null || true
|
||
export REQUESTS_CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt" 2>/dev/null || true
|
||
export CURL_CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt" 2>/dev/null || true
|
||
|
||
log "✅ SSL-Zertifikate anti-hänge konfiguriert"
|
||
info "📝 CA-Updates werden automatisch beim nächsten Boot durchgeführt"
|
||
}
|
||
|
||
# =========================== ROBUSTES ANWENDUNGS-DEPLOYMENT ===========================
|
||
deploy_application() {
|
||
log "=== ROBUSTES ANWENDUNGS-DEPLOYMENT ==="
|
||
|
||
progress "Erstelle sicheres Zielverzeichnis: $APP_DIR"
|
||
mkdir -p "$APP_DIR" || error "Konnte Zielverzeichnis nicht erstellen"
|
||
|
||
# Validiere Source-Verzeichnis
|
||
progress "Validiere Source-Dateien..."
|
||
if [ ! -f "$CURRENT_DIR/app.py" ]; then
|
||
error "Kritische Datei nicht gefunden: $CURRENT_DIR/app.py"
|
||
fi
|
||
|
||
if [ ! -f "$CURRENT_DIR/requirements.txt" ]; then
|
||
error "Kritische Datei nicht gefunden: $CURRENT_DIR/requirements.txt"
|
||
fi
|
||
|
||
progress "Kopiere Anwendungsdateien (robust)..."
|
||
|
||
# Kritische Dateien zuerst (mit Validierung)
|
||
local critical_files=(
|
||
"app.py"
|
||
"models.py"
|
||
"requirements.txt"
|
||
)
|
||
|
||
for file in "${critical_files[@]}"; do
|
||
if [ -f "$CURRENT_DIR/$file" ]; then
|
||
progress "Kopiere kritische Datei: $file"
|
||
if cp "$CURRENT_DIR/$file" "$APP_DIR/" 2>/dev/null; then
|
||
success "✅ $file erfolgreich kopiert"
|
||
else
|
||
error "❌ Fehler beim Kopieren der kritischen Datei: $file"
|
||
fi
|
||
else
|
||
error "❌ Kritische Datei fehlt: $file"
|
||
fi
|
||
done
|
||
|
||
# Verzeichnisse mit robuster Behandlung
|
||
local directories=(
|
||
"blueprints"
|
||
"config"
|
||
"database"
|
||
"static"
|
||
"templates"
|
||
"uploads"
|
||
"utils"
|
||
"logs"
|
||
"certs"
|
||
)
|
||
|
||
for dir in "${directories[@]}"; do
|
||
if [ -d "$CURRENT_DIR/$dir" ]; then
|
||
progress "Kopiere Verzeichnis: $dir"
|
||
if cp -r "$CURRENT_DIR/$dir" "$APP_DIR/" 2>/dev/null; then
|
||
success "✅ $dir erfolgreich kopiert"
|
||
else
|
||
warning "⚠️ Fehler beim Kopieren von $dir (möglicherweise nicht kritisch)"
|
||
fi
|
||
else
|
||
info "Verzeichnis nicht vorhanden: $dir"
|
||
fi
|
||
done
|
||
|
||
# Optionale Dateien
|
||
local optional_files=(
|
||
"package.json"
|
||
"package-lock.json"
|
||
"tailwind.config.js"
|
||
"postcss.config.js"
|
||
"README.md"
|
||
".gitignore"
|
||
)
|
||
|
||
for file in "${optional_files[@]}"; do
|
||
if [ -f "$CURRENT_DIR/$file" ]; then
|
||
progress "Kopiere optionale Datei: $file"
|
||
cp "$CURRENT_DIR/$file" "$APP_DIR/" 2>/dev/null || warning "⚠️ Kopieren von $file fehlgeschlagen"
|
||
fi
|
||
done
|
||
|
||
# Erstelle alle notwendigen Verzeichnisse mit korrekter Struktur
|
||
progress "Erstelle Verzeichnisstruktur..."
|
||
local required_dirs=(
|
||
"database/backups"
|
||
"logs/app"
|
||
"logs/auth"
|
||
"logs/errors"
|
||
"logs/system"
|
||
"uploads/temp"
|
||
"uploads/assets"
|
||
"uploads/avatars"
|
||
"uploads/backups"
|
||
"uploads/jobs"
|
||
"certs/localhost"
|
||
"instance"
|
||
"instance/ssl"
|
||
)
|
||
|
||
for dir in "${required_dirs[@]}"; do
|
||
mkdir -p "$APP_DIR/$dir" 2>/dev/null || warning "⚠️ Verzeichnis $dir konnte nicht erstellt werden"
|
||
done
|
||
|
||
# Sichere Berechtigungen setzen (robuster)
|
||
progress "Setze sichere Berechtigungen..."
|
||
|
||
# Basis-Berechtigungen
|
||
chown -R root:root "$APP_DIR" 2>/dev/null || warning "⚠️ Ownership konnte nicht gesetzt werden"
|
||
chmod 755 "$APP_DIR" 2>/dev/null || warning "⚠️ Verzeichnis-Permissions konnten nicht gesetzt werden"
|
||
|
||
# Ausführbare Dateien
|
||
if [ -f "$APP_DIR/app.py" ]; then
|
||
chmod +x "$APP_DIR/app.py" 2>/dev/null || warning "⚠️ app.py Ausführberechtigung konnte nicht gesetzt werden"
|
||
fi
|
||
|
||
# Sensitive Verzeichnisse
|
||
chmod 750 "$APP_DIR/database" 2>/dev/null || true
|
||
chmod 750 "$APP_DIR/logs" 2>/dev/null || true
|
||
chmod 750 "$APP_DIR/certs" 2>/dev/null || true
|
||
chmod 750 "$APP_DIR/instance" 2>/dev/null || true
|
||
|
||
# Upload-Verzeichnisse
|
||
chmod 755 "$APP_DIR/uploads" 2>/dev/null || true
|
||
chmod 755 "$APP_DIR/static" 2>/dev/null || true
|
||
|
||
# Python-Umgebung robust konfigurieren
|
||
progress "Konfiguriere robuste Python-Umgebung..."
|
||
|
||
# Ermittle Python site-packages Verzeichnis (robust)
|
||
local python_site_packages=""
|
||
for possible_path in \
|
||
"$(python3 -c "import site; print(site.getsitepackages()[0])" 2>/dev/null)" \
|
||
"/usr/local/lib/python3/dist-packages" \
|
||
"/usr/lib/python3/dist-packages" \
|
||
"/usr/local/lib/python$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null)/dist-packages"; do
|
||
|
||
if [ -d "$possible_path" ]; then
|
||
python_site_packages="$possible_path"
|
||
break
|
||
fi
|
||
done
|
||
|
||
if [ -n "$python_site_packages" ]; then
|
||
echo "$APP_DIR" > "$python_site_packages/myp-app.pth" 2>/dev/null || warning "⚠️ Python-Pfad konnte nicht konfiguriert werden"
|
||
log "✅ Python-Pfad konfiguriert: $python_site_packages/myp-app.pth"
|
||
else
|
||
warning "⚠️ Python site-packages Verzeichnis nicht gefunden"
|
||
fi
|
||
|
||
# Systemweite Umgebungsvariablen robust setzen
|
||
progress "Konfiguriere Umgebungsvariablen..."
|
||
cat >> /etc/environment << EOF
|
||
|
||
# MYP Application Environment
|
||
MYP_APP_DIR=$APP_DIR
|
||
PYTHONPATH=$APP_DIR:\${PYTHONPATH:-}
|
||
FLASK_APP=$APP_DIR/app.py
|
||
FLASK_ENV=production
|
||
EOF
|
||
|
||
# Bash-Profile Updates (optional - überspringen bei Problemen)
|
||
progress "Versuche Bash-Profile zu aktualisieren (optional)..."
|
||
|
||
# Führe Updates nur in einem Subshell mit Timeout aus
|
||
(
|
||
# Setze eine maximale Laufzeit von 10 Sekunden für alle Bash-Profile Updates
|
||
export BASH_PROFILE_TIMEOUT=10
|
||
|
||
# Starte einen Background-Timer
|
||
(sleep $BASH_PROFILE_TIMEOUT && kill -TERM $$ 2>/dev/null) &
|
||
local timer_pid=$!
|
||
|
||
# Nur /root/.bashrc aktualisieren (schnell und sicher)
|
||
if [ -f "/root/.bashrc" ] && [ -w "/root/.bashrc" ]; then
|
||
if ! grep -q "MYP Application Environment" "/root/.bashrc" 2>/dev/null; then
|
||
echo "" >> "/root/.bashrc"
|
||
echo "# MYP Application Environment" >> "/root/.bashrc"
|
||
echo 'if [ -d "/opt/myp" ]; then' >> "/root/.bashrc"
|
||
echo ' export MYP_APP_DIR="/opt/myp"' >> "/root/.bashrc"
|
||
echo ' export FLASK_APP="/opt/myp/app.py"' >> "/root/.bashrc"
|
||
echo ' export FLASK_ENV="production"' >> "/root/.bashrc"
|
||
echo ' export PYTHONPATH="/opt/myp:${PYTHONPATH:-}"' >> "/root/.bashrc"
|
||
echo 'fi' >> "/root/.bashrc"
|
||
log "✅ Root Bash-Profile aktualisiert"
|
||
fi
|
||
fi
|
||
|
||
# Timer beenden
|
||
kill $timer_pid 2>/dev/null || true
|
||
|
||
) 2>/dev/null || {
|
||
warning "⚠️ Bash-Profile Update übersprungen (Timeout oder Fehler)"
|
||
debug "Bash-Profile Updates sind optional - Installation wird fortgesetzt"
|
||
}
|
||
|
||
# Validiere Deployment
|
||
progress "Validiere Application Deployment..."
|
||
local validation_errors=0
|
||
|
||
# Prüfe kritische Dateien
|
||
for file in "app.py" "models.py" "requirements.txt"; do
|
||
if [ ! -f "$APP_DIR/$file" ]; then
|
||
warning "❌ Kritische Datei fehlt: $file"
|
||
((validation_errors++))
|
||
fi
|
||
done
|
||
|
||
# Prüfe wichtige Verzeichnisse
|
||
for dir in "static" "templates" "blueprints"; do
|
||
if [ ! -d "$APP_DIR/$dir" ]; then
|
||
warning "❌ Wichtiges Verzeichnis fehlt: $dir"
|
||
((validation_errors++))
|
||
fi
|
||
done
|
||
|
||
if [ $validation_errors -eq 0 ]; then
|
||
success "✅ Application Deployment vollständig validiert"
|
||
else
|
||
warning "⚠️ $validation_errors Probleme beim Deployment gefunden"
|
||
fi
|
||
|
||
log "✅ Robustes Anwendungs-Deployment abgeschlossen"
|
||
log " 📁 App-Verzeichnis: $APP_DIR"
|
||
log " 🐍 Python-Pfad konfiguriert"
|
||
log " 🔧 Bash-Profile konfiguriert"
|
||
log " 🛡️ Sichere Berechtigungen gesetzt"
|
||
}
|
||
|
||
# =========================== BERECHTIGEN-MANAGEMENT ===========================
|
||
fix_project_permissions() {
|
||
log "=== BERECHTIGEN-MANAGEMENT FÜR KIOSK-USER ==="
|
||
|
||
progress "Korrigiere Projekt-Berechtigungen für kiosk-User..."
|
||
|
||
# Prüfe ob kiosk User existiert
|
||
if ! id "$KIOSK_USER" &>/dev/null; then
|
||
warning "⚠️ Kiosk-User '$KIOSK_USER' existiert nicht - erstelle ihn zuerst"
|
||
create_kiosk_user
|
||
fi
|
||
|
||
local kiosk_home="/home/$KIOSK_USER"
|
||
|
||
# Erstelle Entwicklungs-/Arbeitsverzeichnis im kiosk home
|
||
local kiosk_project_dir="$kiosk_home/manage-your-printer"
|
||
|
||
progress "Erstelle kiosk-Arbeitsverzeichnis: $kiosk_project_dir"
|
||
if [ ! -d "$kiosk_project_dir" ]; then
|
||
mkdir -p "$kiosk_project_dir" 2>/dev/null || true
|
||
fi
|
||
|
||
# Kopiere/Synchronisiere Projekt-Dateien zum kiosk-Verzeichnis
|
||
progress "Synchronisiere Projekt-Dateien für kiosk-User..."
|
||
|
||
# Verwende rsync wenn verfügbar, sonst cp
|
||
if command -v rsync >/dev/null 2>&1; then
|
||
rsync -av --exclude='.git' --exclude='__pycache__' --exclude='*.pyc' \
|
||
--exclude='instance/ssl/*' --exclude='logs/*' \
|
||
"$CURRENT_DIR/" "$kiosk_project_dir/" 2>/dev/null || {
|
||
warning "⚠️ rsync fehlgeschlagen - verwende cp als Fallback"
|
||
cp -r "$CURRENT_DIR"/* "$kiosk_project_dir/" 2>/dev/null || true
|
||
}
|
||
else
|
||
cp -r "$CURRENT_DIR"/* "$kiosk_project_dir/" 2>/dev/null || true
|
||
fi
|
||
|
||
# Setze kiosk als Besitzer des Arbeitsverzeichnisses
|
||
progress "Setze kiosk-User als Besitzer des Arbeitsverzeichnisses..."
|
||
chown -R "$KIOSK_USER:$KIOSK_USER" "$kiosk_project_dir" 2>/dev/null || warning "⚠️ Ownership konnte nicht vollständig gesetzt werden"
|
||
|
||
# Spezielle Berechtigungen für verschiedene Bereiche
|
||
progress "Konfiguriere spezielle Berechtigungen..."
|
||
|
||
# node_modules: kiosk User soll vollen Zugriff haben
|
||
if [ -d "$kiosk_project_dir/node_modules" ]; then
|
||
chown -R "$KIOSK_USER:$KIOSK_USER" "$kiosk_project_dir/node_modules" 2>/dev/null || true
|
||
chmod -R 755 "$kiosk_project_dir/node_modules" 2>/dev/null || true
|
||
success "✅ node_modules Berechtigungen für kiosk-User gesetzt"
|
||
fi
|
||
|
||
# package.json und package-lock.json: kiosk User soll schreiben können
|
||
for file in package.json package-lock.json; do
|
||
if [ -f "$kiosk_project_dir/$file" ]; then
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_project_dir/$file" 2>/dev/null || true
|
||
chmod 664 "$kiosk_project_dir/$file" 2>/dev/null || true
|
||
fi
|
||
done
|
||
|
||
# logs Verzeichnis: kiosk User soll schreiben können
|
||
if [ -d "$kiosk_project_dir/logs" ]; then
|
||
chown -R "$KIOSK_USER:$KIOSK_USER" "$kiosk_project_dir/logs" 2>/dev/null || true
|
||
chmod -R 755 "$kiosk_project_dir/logs" 2>/dev/null || true
|
||
fi
|
||
|
||
# uploads Verzeichnis: kiosk User soll schreiben können
|
||
if [ -d "$kiosk_project_dir/uploads" ]; then
|
||
chown -R "$KIOSK_USER:$KIOSK_USER" "$kiosk_project_dir/uploads" 2>/dev/null || true
|
||
chmod -R 755 "$kiosk_project_dir/uploads" 2>/dev/null || true
|
||
fi
|
||
|
||
# Auch die Original node_modules in APP_DIR korrigieren
|
||
progress "Korrigiere node_modules Berechtigungen in $APP_DIR..."
|
||
if [ -d "$APP_DIR/node_modules" ]; then
|
||
# Erstelle kiosk-Gruppe und füge root hinzu für geteilten Zugriff
|
||
groupadd -f kiosk-shared 2>/dev/null || true
|
||
usermod -a -G kiosk-shared root 2>/dev/null || true
|
||
usermod -a -G kiosk-shared "$KIOSK_USER" 2>/dev/null || true
|
||
|
||
# Setze Gruppe auf kiosk-shared für geteilten Zugriff
|
||
chgrp -R kiosk-shared "$APP_DIR/node_modules" 2>/dev/null || true
|
||
chmod -R 775 "$APP_DIR/node_modules" 2>/dev/null || true
|
||
success "✅ node_modules geteilte Berechtigungen gesetzt"
|
||
fi
|
||
|
||
# Erstelle npm-Konfiguration für kiosk User
|
||
progress "Konfiguriere npm für kiosk-User..."
|
||
if [ ! -d "$kiosk_home/.npm" ]; then
|
||
mkdir -p "$kiosk_home/.npm" 2>/dev/null || true
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.npm" 2>/dev/null || true
|
||
fi
|
||
|
||
# Erstelle .npmrc für kiosk User
|
||
cat > "$kiosk_home/.npmrc" << 'NPMRCEOF'
|
||
# npm-Konfiguration für kiosk User
|
||
fund=false
|
||
audit-level=moderate
|
||
progress=false
|
||
loglevel=warn
|
||
cache=/home/kiosk/.npm
|
||
prefix=/home/kiosk/.npm-global
|
||
NPMRCEOF
|
||
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.npmrc" 2>/dev/null || true
|
||
|
||
# npm global Verzeichnis erstellen
|
||
mkdir -p "$kiosk_home/.npm-global" 2>/dev/null || true
|
||
chown -R "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.npm-global" 2>/dev/null || true
|
||
|
||
# X11-Autorisierung sicherstellen
|
||
progress "Sicherstelle X11-Autorisierung für kiosk-User..."
|
||
if [ ! -f "$kiosk_home/.Xauthority" ]; then
|
||
touch "$kiosk_home/.Xauthority"
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.Xauthority"
|
||
chmod 600 "$kiosk_home/.Xauthority"
|
||
success "✅ .Xauthority Datei erstellt"
|
||
fi
|
||
|
||
# DISPLAY-Variable in bashrc sicherstellen
|
||
if ! grep -q "export DISPLAY=" "$kiosk_home/.bashrc" 2>/dev/null; then
|
||
cat >> "$kiosk_home/.bashrc" << 'EOF'
|
||
|
||
# X11 Display Konfiguration
|
||
export DISPLAY=:0.0
|
||
export XAUTHORITY=/home/kiosk/.Xauthority
|
||
|
||
EOF
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.bashrc"
|
||
success "✅ X11-Variablen zu .bashrc hinzugefügt"
|
||
fi
|
||
|
||
success "✅ Projekt-Berechtigungen für kiosk-User konfiguriert"
|
||
info " 📁 Kiosk-Arbeitsverzeichnis: $kiosk_project_dir"
|
||
info " 👤 Besitzer: $KIOSK_USER"
|
||
info " 🔧 npm-Konfiguration erstellt"
|
||
}
|
||
|
||
create_permission_fix_script() {
|
||
log "=== ERSTELLE BERECHTIGEN-REPARATUR-SKRIPT ==="
|
||
|
||
local fix_script="$CURRENT_DIR/fix-permissions.sh"
|
||
|
||
progress "Erstelle automatisches Berechtigen-Reparatur-Skript..."
|
||
|
||
cat > "$fix_script" << 'FIXSCRIPTEOF'
|
||
#!/bin/bash
|
||
|
||
# ===================================================================
|
||
# MYP Berechtigen-Reparatur-Skript
|
||
# Behebt Berechtigungsprobleme nach npm install als root
|
||
# Kann von jedem User ausgeführt werden
|
||
# ===================================================================
|
||
|
||
set -euo pipefail
|
||
|
||
KIOSK_USER="kiosk"
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
||
# Farben für Ausgabe
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m'
|
||
|
||
log() {
|
||
echo -e "${GREEN}[$(date '+%H:%M:%S')] $1${NC}"
|
||
}
|
||
|
||
warning() {
|
||
echo -e "${YELLOW}[WARNUNG] $1${NC}"
|
||
}
|
||
|
||
error() {
|
||
echo -e "${RED}[FEHLER] $1${NC}"
|
||
exit 1
|
||
}
|
||
|
||
info() {
|
||
echo -e "${BLUE}[INFO] $1${NC}"
|
||
}
|
||
|
||
# Prüfe root-Berechtigung
|
||
if [ "$EUID" -ne 0 ]; then
|
||
error "Dieses Skript muss als Root ausgeführt werden: sudo $0"
|
||
fi
|
||
|
||
log "=== MYP BERECHTIGEN-REPARATUR ==="
|
||
log "Arbeitsverzeichnis: $SCRIPT_DIR"
|
||
|
||
# Prüfe ob kiosk User existiert
|
||
if ! id "$KIOSK_USER" &>/dev/null; then
|
||
error "Kiosk-User '$KIOSK_USER' existiert nicht!"
|
||
fi
|
||
|
||
# Lösche node_modules wenn vorhanden (für saubere Neuinstallation)
|
||
if [ -d "$SCRIPT_DIR/node_modules" ]; then
|
||
log "Entferne bestehende node_modules für saubere Neuinstallation..."
|
||
rm -rf "$SCRIPT_DIR/node_modules"
|
||
fi
|
||
|
||
# Erstelle kiosk-shared Gruppe für geteilten Zugriff
|
||
log "Erstelle geteilte Berechtigen-Gruppe..."
|
||
groupadd -f kiosk-shared 2>/dev/null || true
|
||
usermod -a -G kiosk-shared root 2>/dev/null || true
|
||
usermod -a -G kiosk-shared "$KIOSK_USER" 2>/dev/null || true
|
||
|
||
# Führe npm install als kiosk User aus
|
||
log "Führe npm install als kiosk-User aus..."
|
||
if [ -f "$SCRIPT_DIR/package.json" ]; then
|
||
# Wechsle zu kiosk User für npm install
|
||
sudo -u "$KIOSK_USER" bash -c "
|
||
cd '$SCRIPT_DIR'
|
||
export HOME=/home/$KIOSK_USER
|
||
if npm install --no-optional --no-audit --no-fund 2>/dev/null; then
|
||
echo 'npm install erfolgreich (Standard)'
|
||
elif npm install --legacy-peer-deps --no-optional 2>/dev/null; then
|
||
echo 'npm install erfolgreich (Legacy-Modus)'
|
||
elif npm install --force 2>/dev/null; then
|
||
echo 'npm install erfolgreich (Force-Modus)'
|
||
else
|
||
echo 'npm install fehlgeschlagen'
|
||
exit 1
|
||
fi
|
||
"
|
||
|
||
if [ $? -eq 0 ]; then
|
||
log "✅ npm install als kiosk-User erfolgreich"
|
||
else
|
||
warning "⚠️ npm install als kiosk-User fehlgeschlagen - versuche als root mit Berechtigen-Korrektur"
|
||
|
||
# Fallback: npm install als root, dann Berechtigungen korrigieren
|
||
if npm install --no-optional --no-audit --no-fund 2>/dev/null; then
|
||
log "npm install als root erfolgreich - korrigiere Berechtigungen..."
|
||
|
||
# Korrigiere node_modules Berechtigungen
|
||
if [ -d "$SCRIPT_DIR/node_modules" ]; then
|
||
chown -R "$KIOSK_USER:kiosk-shared" "$SCRIPT_DIR/node_modules" 2>/dev/null || true
|
||
chmod -R 775 "$SCRIPT_DIR/node_modules" 2>/dev/null || true
|
||
log "✅ node_modules Berechtigungen korrigiert"
|
||
fi
|
||
else
|
||
error "npm install auch als root fehlgeschlagen"
|
||
fi
|
||
fi
|
||
else
|
||
warning "Keine package.json gefunden"
|
||
fi
|
||
|
||
# Korrigiere allgemeine Projekt-Berechtigungen
|
||
log "Korrigiere allgemeine Projekt-Berechtigungen..."
|
||
|
||
# package.json und package-lock.json
|
||
for file in package.json package-lock.json; do
|
||
if [ -f "$SCRIPT_DIR/$file" ]; then
|
||
chown "$KIOSK_USER:kiosk-shared" "$SCRIPT_DIR/$file" 2>/dev/null || true
|
||
chmod 664 "$SCRIPT_DIR/$file" 2>/dev/null || true
|
||
fi
|
||
done
|
||
|
||
# logs Verzeichnis
|
||
if [ -d "$SCRIPT_DIR/logs" ]; then
|
||
chown -R "$KIOSK_USER:kiosk-shared" "$SCRIPT_DIR/logs" 2>/dev/null || true
|
||
chmod -R 775 "$SCRIPT_DIR/logs" 2>/dev/null || true
|
||
fi
|
||
|
||
# uploads Verzeichnis
|
||
if [ -d "$SCRIPT_DIR/uploads" ]; then
|
||
chown -R "$KIOSK_USER:kiosk-shared" "$SCRIPT_DIR/uploads" 2>/dev/null || true
|
||
chmod -R 775 "$SCRIPT_DIR/uploads" 2>/dev/null || true
|
||
fi
|
||
|
||
# static Verzeichnis (falls der User dort Änderungen macht)
|
||
if [ -d "$SCRIPT_DIR/static" ]; then
|
||
chgrp -R kiosk-shared "$SCRIPT_DIR/static" 2>/dev/null || true
|
||
chmod -R 775 "$SCRIPT_DIR/static" 2>/dev/null || true
|
||
fi
|
||
|
||
# X11-Autorisierung für kiosk-User sicherstellen
|
||
log "Sicherstelle X11-Autorisierung..."
|
||
kiosk_home="/home/$KIOSK_USER"
|
||
|
||
if [ ! -f "$kiosk_home/.Xauthority" ]; then
|
||
touch "$kiosk_home/.Xauthority"
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.Xauthority"
|
||
chmod 600 "$kiosk_home/.Xauthority"
|
||
log "✅ .Xauthority Datei erstellt"
|
||
fi
|
||
|
||
# DISPLAY-Variable in bashrc sicherstellen
|
||
if [ -f "$kiosk_home/.bashrc" ] && ! grep -q "export DISPLAY=" "$kiosk_home/.bashrc" 2>/dev/null; then
|
||
cat >> "$kiosk_home/.bashrc" << 'BASHRCEOF'
|
||
|
||
# X11 Display Konfiguration
|
||
export DISPLAY=:0.0
|
||
export XAUTHORITY=/home/kiosk/.Xauthority
|
||
|
||
BASHRCEOF
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.bashrc"
|
||
log "✅ X11-Variablen zu .bashrc hinzugefügt"
|
||
fi
|
||
|
||
log "✅ Berechtigen-Reparatur abgeschlossen"
|
||
info ""
|
||
info "📋 Zusammenfassung:"
|
||
info " - node_modules gehört jetzt dem kiosk-User"
|
||
info " - Geteilte kiosk-shared Gruppe erstellt"
|
||
info " - Entwicklungs-Dateien für kiosk-User beschreibbar"
|
||
info ""
|
||
info "🔧 Verwendung:"
|
||
info " - Als kiosk-User: cd $SCRIPT_DIR && npm install"
|
||
info " - Als root bei Problemen: sudo $0"
|
||
info ""
|
||
|
||
FIXSCRIPTEOF
|
||
|
||
# Mache Skript ausführbar
|
||
chmod +x "$fix_script" 2>/dev/null || warning "⚠️ Konnte fix-permissions.sh nicht ausführbar machen"
|
||
|
||
success "✅ Berechtigen-Reparatur-Skript erstellt: $fix_script"
|
||
info " 💡 Verwendung nach Setup: sudo ./fix-permissions.sh"
|
||
|
||
# Erstelle zusätzliches X11-Fix-Skript
|
||
local x11_fix_script="$CURRENT_DIR/fix-x11.sh"
|
||
|
||
progress "Erstelle X11-Reparatur-Skript..."
|
||
|
||
cat > "$x11_fix_script" << 'X11FIXSCRIPTEOF'
|
||
#!/bin/bash
|
||
|
||
# ===================================================================
|
||
# MYP X11-Reparatur-Skript
|
||
# Behebt X11/.Xauthority-Probleme für kiosk-User
|
||
# Kann als root oder kiosk-User ausgeführt werden
|
||
# ===================================================================
|
||
|
||
set -euo pipefail
|
||
|
||
KIOSK_USER="kiosk"
|
||
|
||
# Farben für Ausgabe
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m'
|
||
|
||
log() {
|
||
echo -e "${GREEN}[$(date '+%H:%M:%S')] $1${NC}"
|
||
}
|
||
|
||
warning() {
|
||
echo -e "${YELLOW}[WARNUNG] $1${NC}"
|
||
}
|
||
|
||
error() {
|
||
echo -e "${RED}[FEHLER] $1${NC}"
|
||
exit 1
|
||
}
|
||
|
||
info() {
|
||
echo -e "${BLUE}[INFO] $1${NC}"
|
||
}
|
||
|
||
log "=== MYP X11-REPARATUR ==="
|
||
|
||
# Prüfe ob kiosk User existiert
|
||
if ! id "$KIOSK_USER" &>/dev/null; then
|
||
error "Kiosk-User '$KIOSK_USER' existiert nicht!"
|
||
fi
|
||
|
||
kiosk_home="/home/$KIOSK_USER"
|
||
|
||
# Stoppe laufende X11-Prozesse
|
||
log "Stoppe laufende X11-Prozesse..."
|
||
pkill -f "startx" 2>/dev/null || true
|
||
pkill -f "X " 2>/dev/null || true
|
||
pkill -f "Xorg" 2>/dev/null || true
|
||
pkill -f "chromium" 2>/dev/null || true
|
||
sleep 2
|
||
|
||
# Bereinige alte X11-Session-Dateien
|
||
log "Bereinige alte X11-Session-Dateien..."
|
||
rm -f /tmp/.X0-lock 2>/dev/null || true
|
||
rm -f /tmp/.X11-unix/X0 2>/dev/null || true
|
||
|
||
# X11-Autorisierung neu erstellen
|
||
log "Erstelle X11-Autorisierung neu..."
|
||
|
||
# Entferne alte .Xauthority
|
||
if [ -f "$kiosk_home/.Xauthority" ]; then
|
||
rm -f "$kiosk_home/.Xauthority"
|
||
fi
|
||
|
||
# Erstelle neue .Xauthority
|
||
touch "$kiosk_home/.Xauthority"
|
||
|
||
# Setze korrekte Berechtigungen (funktioniert sowohl als root als auch als kiosk)
|
||
if [ "$EUID" -eq 0 ]; then
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.Xauthority"
|
||
fi
|
||
chmod 600 "$kiosk_home/.Xauthority"
|
||
|
||
log "✅ .Xauthority neu erstellt"
|
||
|
||
# Prüfe und korrigiere .bashrc
|
||
log "Prüfe X11-Umgebungsvariablen..."
|
||
|
||
if [ -f "$kiosk_home/.bashrc" ]; then
|
||
if ! grep -q "export DISPLAY=" "$kiosk_home/.bashrc" 2>/dev/null; then
|
||
log "Füge X11-Variablen zu .bashrc hinzu..."
|
||
cat >> "$kiosk_home/.bashrc" << 'BASHEOF2'
|
||
|
||
# X11 Display Konfiguration
|
||
export DISPLAY=:0.0
|
||
export XAUTHORITY=/home/kiosk/.Xauthority
|
||
|
||
BASHEOF2
|
||
|
||
if [ "$EUID" -eq 0 ]; then
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.bashrc"
|
||
fi
|
||
log "✅ X11-Variablen hinzugefügt"
|
||
else
|
||
log "✅ X11-Variablen bereits konfiguriert"
|
||
fi
|
||
else
|
||
warning "⚠️ .bashrc nicht gefunden"
|
||
fi
|
||
|
||
# Erstelle X11-Test-Skript
|
||
log "Erstelle X11-Test-Skript..."
|
||
cat > "$kiosk_home/test-x11.sh" << 'TESTEOF'
|
||
#!/bin/bash
|
||
|
||
# X11-Test für kiosk-User
|
||
|
||
export DISPLAY=:0.0
|
||
export XAUTHORITY=/home/kiosk/.Xauthority
|
||
|
||
echo "=== X11-Test ==="
|
||
echo "DISPLAY: $DISPLAY"
|
||
echo "XAUTHORITY: $XAUTHORITY"
|
||
echo ""
|
||
|
||
if [ -f "$XAUTHORITY" ]; then
|
||
echo "✅ .Xauthority existiert"
|
||
ls -la "$XAUTHORITY"
|
||
else
|
||
echo "❌ .Xauthority fehlt"
|
||
exit 1
|
||
fi
|
||
|
||
echo ""
|
||
echo "Teste X11-Verbindung..."
|
||
|
||
if command -v xset >/dev/null 2>&1; then
|
||
if xset q >/dev/null 2>&1; then
|
||
echo "✅ X11-Server erreichbar"
|
||
xset q | head -3
|
||
else
|
||
echo "❌ X11-Server nicht erreichbar"
|
||
echo "Versuche X11-Server zu starten..."
|
||
startx /home/kiosk/.xinitrc -- :0 vt1 &
|
||
sleep 5
|
||
|
||
if xset q >/dev/null 2>&1; then
|
||
echo "✅ X11-Server nach Start erreichbar"
|
||
else
|
||
echo "❌ X11-Server konnte nicht gestartet werden"
|
||
exit 1
|
||
fi
|
||
fi
|
||
else
|
||
echo "⚠️ xset nicht verfügbar - kann X11 nicht testen"
|
||
fi
|
||
|
||
echo ""
|
||
echo "✅ X11-Test abgeschlossen"
|
||
TESTEOF
|
||
|
||
chmod +x "$kiosk_home/test-x11.sh"
|
||
if [ "$EUID" -eq 0 ]; then
|
||
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/test-x11.sh"
|
||
fi
|
||
|
||
log "✅ X11-Reparatur abgeschlossen"
|
||
info ""
|
||
info "📋 Was wurde behoben:"
|
||
info " - Alte .Xauthority entfernt und neu erstellt"
|
||
info " - X11-Umgebungsvariablen konfiguriert"
|
||
info " - X11-Test-Skript erstellt"
|
||
info ""
|
||
info "🔧 Nächste Schritte:"
|
||
info " - Als kiosk-User einloggen: su - kiosk"
|
||
info " - X11 testen: ./test-x11.sh"
|
||
info " - Kiosk-Modus starten: ./start-x11.sh"
|
||
info ""
|
||
info "💡 Bei weiteren Problemen:"
|
||
info " - Neustart: sudo reboot"
|
||
info " - Manual X11 start: startx"
|
||
info ""
|
||
|
||
X11FIXSCRIPTEOF
|
||
|
||
chmod +x "$x11_fix_script" 2>/dev/null || warning "⚠️ Konnte fix-x11.sh nicht ausführbar machen"
|
||
|
||
success "✅ X11-Reparatur-Skript erstellt: $x11_fix_script"
|
||
info " 💡 Verwendung bei X11-Problemen: sudo ./fix-x11.sh"
|
||
}
|
||
|
||
install_npm_dependencies() {
|
||
log "=== NPM-ABHÄNGIGKEITEN INSTALLATION ==="
|
||
|
||
if [ -f "$APP_DIR/package.json" ]; then
|
||
progress "Installiere npm-Abhängigkeiten..."
|
||
|
||
cd "$APP_DIR"
|
||
|
||
# npm install mit verschiedenen Fallback-Strategien
|
||
if npm install --no-optional --no-audit --no-fund 2>/dev/null; then
|
||
log "✅ npm install erfolgreich (Standard)"
|
||
elif npm install --legacy-peer-deps --no-optional 2>/dev/null; then
|
||
log "✅ npm install erfolgreich (Legacy-Modus)"
|
||
elif npm install --force 2>/dev/null; then
|
||
log "✅ npm install erfolgreich (Force-Modus)"
|
||
else
|
||
warning "⚠️ npm install fehlgeschlagen - überspringe"
|
||
fi
|
||
|
||
# WICHTIG: Korrigiere Berechtigungen nach npm install
|
||
progress "Korrigiere npm-Berechtigungen für kiosk-User..."
|
||
if [ -d "$APP_DIR/node_modules" ]; then
|
||
# Erstelle geteilte Gruppe wenn noch nicht vorhanden
|
||
groupadd -f kiosk-shared 2>/dev/null || true
|
||
usermod -a -G kiosk-shared root 2>/dev/null || true
|
||
if id "$KIOSK_USER" &>/dev/null; then
|
||
usermod -a -G kiosk-shared "$KIOSK_USER" 2>/dev/null || true
|
||
chown -R "$KIOSK_USER:kiosk-shared" "$APP_DIR/node_modules" 2>/dev/null || true
|
||
success "✅ node_modules Berechtigungen für kiosk-User korrigiert"
|
||
else
|
||
warning "⚠️ Kiosk-User nicht gefunden - Berechtigungen werden später korrigiert"
|
||
fi
|
||
chmod -R 775 "$APP_DIR/node_modules" 2>/dev/null || true
|
||
fi
|
||
|
||
cd "$CURRENT_DIR"
|
||
else
|
||
info "Keine package.json gefunden - überspringe npm-Installation"
|
||
fi
|
||
|
||
log "✅ NPM-Abhängigkeiten verarbeitet"
|
||
}
|
||
|
||
# =========================== SSL-ZERTIFIKAT GENERIERUNG (ENTFERNT) ===========================
|
||
# SSL-Zertifikate nicht mehr benötigt - verwende HTTP statt HTTPS
|
||
|
||
# =========================== ROBUSTE SYSTEMD-SERVICES INSTALLATION ===========================
|
||
install_systemd_services() {
|
||
log "=== ROBUSTE SYSTEMD-SERVICES INSTALLATION ==="
|
||
|
||
# Prüfe ob systemd verfügbar ist
|
||
if ! command -v systemctl >/dev/null 2>&1; then
|
||
warning "⚠️ systemctl nicht gefunden - überspringe Service-Installation"
|
||
info " → System läuft möglicherweise ohne systemd (WSL, Docker, etc.)"
|
||
return
|
||
fi
|
||
|
||
# Validiere systemd-Verzeichnis
|
||
if [ ! -d "$SYSTEMD_DIR" ]; then
|
||
warning "⚠️ systemd-Verzeichnis nicht gefunden: $SYSTEMD_DIR"
|
||
info " → Überspringe Service-Installation"
|
||
return
|
||
fi
|
||
|
||
progress "Validiere und kopiere Service-Dateien..."
|
||
|
||
# Definiere Service-Dateien mit Priorität
|
||
local essential_services=(
|
||
"$HTTP_SERVICE_NAME.service"
|
||
)
|
||
|
||
local optional_services=(
|
||
"$KIOSK_SERVICE_NAME.service"
|
||
"$WATCHDOG_SERVICE_NAME.service"
|
||
"$WATCHDOG_PYTHON_SERVICE_NAME.service"
|
||
"$FIREWALL_SERVICE_NAME.service"
|
||
)
|
||
|
||
local installed_services=0
|
||
local essential_errors=0
|
||
|
||
# Essenzielle Services zuerst
|
||
for service_file in "${essential_services[@]}"; do
|
||
if [ -f "$SYSTEMD_DIR/$service_file" ]; then
|
||
progress "Kopiere essenziellen Service: $service_file"
|
||
if cp "$SYSTEMD_DIR/$service_file" "$SYSTEM_SYSTEMD_DIR/" 2>/dev/null; then
|
||
success "✅ $service_file erfolgreich installiert"
|
||
((installed_services++))
|
||
else
|
||
error "❌ Fehler beim Kopieren des essenziellen Service: $service_file"
|
||
((essential_errors++))
|
||
fi
|
||
else
|
||
error "❌ Essenzieller Service nicht gefunden: $service_file"
|
||
((essential_errors++))
|
||
fi
|
||
done
|
||
|
||
# Optionale Services
|
||
for service_file in "${optional_services[@]}"; do
|
||
if [ -f "$SYSTEMD_DIR/$service_file" ]; then
|
||
progress "Kopiere optionalen Service: $service_file"
|
||
if cp "$SYSTEMD_DIR/$service_file" "$SYSTEM_SYSTEMD_DIR/" 2>/dev/null; then
|
||
success "✅ $service_file erfolgreich installiert"
|
||
((installed_services++))
|
||
else
|
||
warning "⚠️ Fehler beim Kopieren des optionalen Service: $service_file"
|
||
fi
|
||
else
|
||
info "Optionaler Service nicht gefunden: $service_file"
|
||
fi
|
||
done
|
||
|
||
# Prüfe auf kritische Fehler
|
||
if [ $essential_errors -gt 0 ]; then
|
||
error "❌ $essential_errors essenzielle Services konnten nicht installiert werden!"
|
||
fi
|
||
|
||
# Validiere kopierte Service-Dateien
|
||
progress "Validiere Service-Dateien..."
|
||
for service_file in "${essential_services[@]}" "${optional_services[@]}"; do
|
||
if [ -f "$SYSTEM_SYSTEMD_DIR/$service_file" ]; then
|
||
# Syntaxprüfung für systemd-Services
|
||
if systemd-analyze verify "$SYSTEM_SYSTEMD_DIR/$service_file" 2>/dev/null; then
|
||
success "✅ $service_file Syntax-Validierung erfolgreich"
|
||
else
|
||
warning "⚠️ $service_file hat möglicherweise Syntax-Probleme"
|
||
fi
|
||
fi
|
||
done
|
||
|
||
# Systemd-Konfiguration neu laden
|
||
progress "Lade systemd-Konfiguration neu..."
|
||
retry_command "systemctl daemon-reload" "systemd daemon-reload"
|
||
|
||
log "✅ Systemd-Services installiert: $installed_services Services"
|
||
}
|
||
|
||
enable_and_start_services() {
|
||
log "=== ROBUSTE SERVICES AKTIVIERUNG UND START ==="
|
||
|
||
# Prüfe ob systemd verfügbar ist
|
||
if ! command -v systemctl >/dev/null 2>&1; then
|
||
warning "⚠️ systemctl nicht gefunden - überspringe Service-Aktivierung"
|
||
return
|
||
fi
|
||
|
||
# Service-Status tracking
|
||
local successful_services=0
|
||
local failed_services=0
|
||
|
||
# HTTP-Backend-Service (kritisch)
|
||
progress "Aktiviere und starte HTTP-Backend-Service (kritisch)..."
|
||
|
||
if systemctl enable "$HTTP_SERVICE_NAME" 2>/dev/null; then
|
||
success "✅ HTTP-Backend-Service erfolgreich aktiviert"
|
||
|
||
if systemctl start "$HTTP_SERVICE_NAME" 2>/dev/null; then
|
||
success "✅ HTTP-Backend-Service erfolgreich gestartet"
|
||
|
||
# Warte und prüfe Status gründlich
|
||
local startup_timeout=15
|
||
local check_interval=2
|
||
local elapsed=0
|
||
|
||
while [ $elapsed -lt $startup_timeout ]; do
|
||
if systemctl is-active --quiet "$HTTP_SERVICE_NAME"; then
|
||
success "✅ HTTP-Backend-Service läuft stabil nach ${elapsed}s"
|
||
((successful_services++))
|
||
break
|
||
fi
|
||
sleep $check_interval
|
||
elapsed=$((elapsed + check_interval))
|
||
progress "Warte auf HTTP-Backend-Service Startup... (${elapsed}/${startup_timeout}s)"
|
||
done
|
||
|
||
if [ $elapsed -ge $startup_timeout ]; then
|
||
error "❌ HTTP-Backend-Service Timeout nach ${startup_timeout}s - Service nicht verfügbar"
|
||
|
||
# Debugging-Informationen
|
||
info "HTTP-Backend-Service Status-Debug:"
|
||
systemctl status "$HTTP_SERVICE_NAME" --no-pager -l || true
|
||
journalctl -u "$HTTP_SERVICE_NAME" --no-pager -n 10 || true
|
||
((failed_services++))
|
||
fi
|
||
else
|
||
error "❌ HTTP-Backend-Service konnte nicht gestartet werden"
|
||
((failed_services++))
|
||
fi
|
||
else
|
||
error "❌ HTTP-Backend-Service konnte nicht aktiviert werden"
|
||
((failed_services++))
|
||
fi
|
||
|
||
# Kiosk-Service (für Produktionsinstallation)
|
||
if [ -f "$SYSTEM_SYSTEMD_DIR/$KIOSK_SERVICE_NAME.service" ]; then
|
||
progress "Aktiviere Kiosk-Service (startet beim nächsten Boot)..."
|
||
if systemctl enable "$KIOSK_SERVICE_NAME" 2>/dev/null; then
|
||
success "✅ Kiosk-Service erfolgreich aktiviert"
|
||
((successful_services++))
|
||
else
|
||
warning "⚠️ Kiosk-Service konnte nicht aktiviert werden"
|
||
((failed_services++))
|
||
fi
|
||
fi
|
||
|
||
# Watchdog-Service (optional)
|
||
if [ -f "$SYSTEM_SYSTEMD_DIR/$WATCHDOG_SERVICE_NAME.service" ]; then
|
||
progress "Aktiviere und starte Watchdog-Service..."
|
||
if systemctl enable "$WATCHDOG_SERVICE_NAME" 2>/dev/null; then
|
||
if systemctl start "$WATCHDOG_SERVICE_NAME" 2>/dev/null; then
|
||
success "✅ Watchdog-Service erfolgreich aktiviert und gestartet"
|
||
((successful_services++))
|
||
else
|
||
warning "⚠️ Watchdog-Service aktiviert, aber Start fehlgeschlagen"
|
||
fi
|
||
else
|
||
warning "⚠️ Watchdog-Service konnte nicht aktiviert werden"
|
||
fi
|
||
fi
|
||
|
||
# Python Watchdog-Service (optional)
|
||
if [ -f "$SYSTEM_SYSTEMD_DIR/$WATCHDOG_PYTHON_SERVICE_NAME.service" ]; then
|
||
progress "Aktiviere Python Watchdog-Service..."
|
||
if systemctl enable "$WATCHDOG_PYTHON_SERVICE_NAME" 2>/dev/null; then
|
||
success "✅ Python Watchdog-Service erfolgreich aktiviert"
|
||
((successful_services++))
|
||
else
|
||
warning "⚠️ Python Watchdog-Service konnte nicht aktiviert werden"
|
||
fi
|
||
fi
|
||
|
||
# Firewall-Service (optional)
|
||
if [ -f "$SYSTEM_SYSTEMD_DIR/$FIREWALL_SERVICE_NAME.service" ]; then
|
||
progress "Aktiviere Firewall-Service..."
|
||
if systemctl enable "$FIREWALL_SERVICE_NAME" 2>/dev/null; then
|
||
success "✅ Firewall-Service erfolgreich aktiviert"
|
||
((successful_services++))
|
||
else
|
||
warning "⚠️ Firewall-Service konnte nicht aktiviert werden"
|
||
fi
|
||
fi
|
||
|
||
# Zusammenfassung
|
||
log "📊 Service-Aktivierung Zusammenfassung:"
|
||
log " ✅ Erfolgreich: $successful_services Services"
|
||
log " ❌ Fehlgeschlagen: $failed_services Services"
|
||
|
||
if [ $failed_services -eq 0 ]; then
|
||
success "✅ Alle verfügbaren Services erfolgreich konfiguriert"
|
||
elif [ $successful_services -gt 0 ]; then
|
||
warning "⚠️ $failed_services Services fehlgeschlagen, aber $successful_services Services funktionieren"
|
||
info "→ System ist grundsätzlich funktionsfähig"
|
||
else
|
||
error "❌ Alle Services fehlgeschlagen - System möglicherweise nicht funktionsfähig"
|
||
fi
|
||
}
|
||
|
||
# =========================== ROBUSTE SYSTEM-TESTS ===========================
|
||
test_application() {
|
||
log "=== UMFASSENDE SYSTEM-TESTS ==="
|
||
|
||
echo ""
|
||
echo -e "${BLUE}🔍 Führe System-Tests durch...${NC}"
|
||
echo ""
|
||
|
||
local test_errors=0
|
||
local test_warnings=0
|
||
|
||
# Test 1: Service-Status prüfen
|
||
progress "Teste Service-Status..."
|
||
if systemctl is-active --quiet "$HTTP_SERVICE_NAME"; then
|
||
success "✅ HTTP-Backend-Service ist aktiv"
|
||
else
|
||
warning "⚠️ HTTP-Backend-Service ist nicht aktiv"
|
||
((test_warnings++))
|
||
|
||
# Debug-Informationen
|
||
info "Service-Status Debug:"
|
||
systemctl status "$HTTP_SERVICE_NAME" --no-pager -l || true
|
||
fi
|
||
|
||
# Test 2: Port-Verfügbarkeit
|
||
progress "Teste Port-Verfügbarkeit..."
|
||
if ss -tlnp | grep -q ":5000 "; then
|
||
success "✅ Port 5000 ist geöffnet"
|
||
else
|
||
warning "⚠️ Port 5000 ist nicht geöffnet"
|
||
((test_warnings++))
|
||
fi
|
||
|
||
# Test 3: HTTP-Backend-Verbindung (robust mit mehreren Methoden)
|
||
progress "Teste HTTP-Backend-Verbindung (robust)..."
|
||
|
||
local max_attempts=20
|
||
local attempt=1
|
||
local connection_successful=false
|
||
|
||
while [ $attempt -le $max_attempts ]; do
|
||
# Methode 1: curl mit verschiedenen Optionen
|
||
if curl -s --connect-timeout 3 --max-time 8 "$HTTP_URL" >/dev/null 2>&1; then
|
||
connection_successful=true
|
||
break
|
||
fi
|
||
|
||
# Methode 2: wget als Fallback
|
||
if command -v wget >/dev/null 2>&1; then
|
||
if wget -q --timeout=3 --tries=1 "$HTTP_URL" -O /dev/null 2>/dev/null; then
|
||
connection_successful=true
|
||
break
|
||
fi
|
||
fi
|
||
|
||
# Methode 3: nc als direkter Port-Test
|
||
if command -v nc >/dev/null 2>&1; then
|
||
if echo "GET / HTTP/1.0" | nc -w 3 localhost 5000 2>/dev/null | grep -q "HTTP"; then
|
||
connection_successful=true
|
||
break
|
||
fi
|
||
fi
|
||
|
||
progress "Warte auf HTTP-Backend... ($attempt/$max_attempts)"
|
||
sleep 3
|
||
((attempt++))
|
||
done
|
||
|
||
if [ "$connection_successful" = true ]; then
|
||
success "✅ HTTP-Backend erreichbar unter $HTTP_URL"
|
||
|
||
# Erweiterte Verbindungstests
|
||
progress "Führe erweiterte HTTP-Tests durch..."
|
||
|
||
# Test Antwortzeit
|
||
local response_time=$(curl -s -w "%{time_total}" -o /dev/null "$HTTP_URL" 2>/dev/null || echo "timeout")
|
||
if [ "$response_time" != "timeout" ]; then
|
||
info "🕐 HTTP Antwortzeit: ${response_time}s"
|
||
|
||
# Bewerte Antwortzeit (ohne bc für bessere Kompatibilität)
|
||
local response_ms=$(echo "$response_time * 1000" | awk '{print int($1)}' 2>/dev/null || echo "9999")
|
||
if [ "$response_ms" -lt 2000 ]; then
|
||
success "✅ Gute Antwortzeit"
|
||
elif [ "$response_ms" -lt 5000 ]; then
|
||
info "ℹ️ Akzeptable Antwortzeit"
|
||
else
|
||
warning "⚠️ Langsame Antwortzeit"
|
||
((test_warnings++))
|
||
fi
|
||
fi
|
||
|
||
# Test HTTP-Status
|
||
local http_status=$(curl -s -o /dev/null -w "%{http_code}" "$HTTP_URL" 2>/dev/null || echo "000")
|
||
if [ "$http_status" = "200" ]; then
|
||
success "✅ HTTP Status 200 OK"
|
||
else
|
||
info "ℹ️ HTTP Status: $http_status (möglicherweise Redirect oder Login-Seite)"
|
||
fi
|
||
|
||
else
|
||
error "❌ HTTP-Backend nicht erreichbar nach $max_attempts Versuchen"
|
||
((test_errors++))
|
||
|
||
# Debugging-Informationen
|
||
info "HTTP-Debug Informationen:"
|
||
netstat -tlnp | grep ":5000" || info "Port 5000 nicht gefunden"
|
||
ss -tlnp | grep ":5000" || info "Port 5000 nicht in ss gefunden"
|
||
fi
|
||
|
||
# Test 4: HTTP-Header und Content-Type Prüfung
|
||
progress "Teste HTTP-Header und Content-Type..."
|
||
|
||
if [ "$connection_successful" = true ]; then
|
||
# Test Content-Type Header
|
||
local content_type=$(curl -s -I "$HTTP_URL" 2>/dev/null | grep -i "content-type:" | head -1 | cut -d: -f2 | tr -d ' \r\n' || echo "unknown")
|
||
if [[ "$content_type" == *"text/html"* ]]; then
|
||
success "✅ Korrekte HTML-Antwort erkannt"
|
||
else
|
||
info "ℹ️ Content-Type: $content_type"
|
||
fi
|
||
|
||
# Test Server Header
|
||
local server_header=$(curl -s -I "$HTTP_URL" 2>/dev/null | grep -i "server:" | head -1 | cut -d: -f2 | tr -d ' \r\n' || echo "unknown")
|
||
if [ "$server_header" != "unknown" ]; then
|
||
info "🖥️ Server: $server_header"
|
||
fi
|
||
else
|
||
info "ℹ️ HTTP-Header Test übersprungen (Backend nicht erreichbar)"
|
||
fi
|
||
|
||
# Test 5: Python-Anwendung Import-Test
|
||
progress "Teste Python-Anwendung Import..."
|
||
|
||
cd "$APP_DIR" 2>/dev/null || true
|
||
|
||
# Setze Test-Umgebung
|
||
export FLASK_ENV=testing
|
||
export MYP_TESTING=1
|
||
export PYTHONPATH="$APP_DIR:${PYTHONPATH:-}"
|
||
|
||
if timeout 15 python3 -c "
|
||
import sys
|
||
import os
|
||
sys.path.insert(0, '$APP_DIR')
|
||
os.chdir('$APP_DIR')
|
||
|
||
try:
|
||
import app
|
||
print('✅ Flask-App Import erfolgreich')
|
||
|
||
# Test ob Flask-App-Objekt verfügbar
|
||
if hasattr(app, 'app'):
|
||
print('✅ Flask-App-Objekt verfügbar')
|
||
else:
|
||
print('⚠️ Flask-App-Objekt nicht gefunden')
|
||
|
||
except Exception as e:
|
||
print(f'⚠️ App-Import-Problem: {e}')
|
||
exit(1)
|
||
" 2>&1; then
|
||
success "✅ Python-Anwendung kann erfolgreich importiert werden"
|
||
else
|
||
warning "⚠️ Python-Anwendung Import-Probleme (möglicherweise nicht kritisch)"
|
||
((test_warnings++))
|
||
fi
|
||
|
||
cd "$CURRENT_DIR" 2>/dev/null || true
|
||
|
||
# Test 6: Verzeichnisstruktur-Validierung
|
||
progress "Validiere Verzeichnisstruktur..."
|
||
|
||
local structure_ok=true
|
||
local required_files=("$APP_DIR/app.py" "$APP_DIR/models.py" "$APP_DIR/requirements.txt")
|
||
local required_dirs=("$APP_DIR/static" "$APP_DIR/templates" "$APP_DIR/blueprints")
|
||
|
||
for file in "${required_files[@]}"; do
|
||
if [ ! -f "$file" ]; then
|
||
warning "❌ Wichtige Datei fehlt: $file"
|
||
structure_ok=false
|
||
((test_warnings++))
|
||
fi
|
||
done
|
||
|
||
for dir in "${required_dirs[@]}"; do
|
||
if [ ! -d "$dir" ]; then
|
||
warning "❌ Wichtiges Verzeichnis fehlt: $dir"
|
||
structure_ok=false
|
||
((test_warnings++))
|
||
fi
|
||
done
|
||
|
||
if [ "$structure_ok" = true ]; then
|
||
success "✅ Verzeichnisstruktur vollständig"
|
||
fi
|
||
|
||
# Zusammenfassung der Tests
|
||
echo ""
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo -e "${CYAN} SYSTEM-TEST ERGEBNISSE${NC}"
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo ""
|
||
echo -e "${BLUE}📊 Test-Zusammenfassung:${NC}"
|
||
echo -e " ❌ Fehler: $test_errors"
|
||
echo -e " ⚠️ Warnungen: $test_warnings"
|
||
echo ""
|
||
|
||
if [ $test_errors -eq 0 ] && [ $test_warnings -eq 0 ]; then
|
||
echo -e "${GREEN}✅ Alle System-Tests erfolgreich!${NC}"
|
||
echo -e "${GREEN} → System vollständig funktionsfähig${NC}"
|
||
echo ""
|
||
return 0
|
||
elif [ $test_errors -eq 0 ]; then
|
||
echo -e "${YELLOW}⚠️ System-Tests mit $test_warnings Warnungen abgeschlossen${NC}"
|
||
echo -e "${YELLOW} → System grundsätzlich funktionsfähig${NC}"
|
||
echo ""
|
||
return 0
|
||
else
|
||
echo -e "${RED}❌ System-Tests mit $test_errors Fehlern fehlgeschlagen${NC}"
|
||
echo -e "${RED} → System möglicherweise nicht funktionsfähig${NC}"
|
||
echo ""
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# =========================== AUFRÄUMEN ===========================
|
||
cleanup_old_files() {
|
||
log "=== AUFRÄUMEN ALTE DATEIEN ==="
|
||
|
||
progress "Entferne alte Shell-Skripte..."
|
||
|
||
# Entferne alte Skripte (falls vorhanden)
|
||
local old_scripts=("combined.sh" "installer.sh")
|
||
|
||
for script in "${old_scripts[@]}"; do
|
||
if [ -f "$CURRENT_DIR/$script" ]; then
|
||
progress "Entferne: $script"
|
||
rm -f "$CURRENT_DIR/$script" || warning "Fehler beim Entfernen von $script"
|
||
fi
|
||
done
|
||
|
||
log "✅ Aufräumen abgeschlossen"
|
||
}
|
||
|
||
# =========================== CREDENTIALS DEPLOYMENT ===========================
|
||
deploy_credentials() {
|
||
log "=== DEPLOYE CREDENTIALS KONFIGURATION ==="
|
||
|
||
# Erstelle .env-Datei für die Anwendung
|
||
progress "Erstelle .env-Datei mit Credentials..."
|
||
|
||
local env_file="$APP_DIR/.env"
|
||
|
||
cat > "$env_file" << EOF
|
||
# MYP Druckerverwaltung - Automatisch generierte Credentials
|
||
# Generiert am: $(date '+%Y-%m-%d %H:%M:%S')
|
||
# Setup-Version: $APP_VERSION
|
||
|
||
# Backend-Konfiguration
|
||
SECRET_KEY=$MYP_SECRET_KEY
|
||
KIOSK_DEACTIVATION_PASSWORD=$MYP_MAIN_PASSWORD
|
||
|
||
# Admin-Zugangsdaten
|
||
ADMIN_EMAIL=$MYP_ADMIN_EMAIL
|
||
ADMIN_PASSWORD=$MYP_MAIN_PASSWORD
|
||
|
||
# TP-Link Tapo Konfiguration
|
||
TAPO_USERNAME=$MYP_TAPO_EMAIL
|
||
TAPO_PASSWORD=$MYP_TAPO_PASSWORD
|
||
|
||
# GitHub OAuth
|
||
GITHUB_CLIENT_ID=$MYP_GITHUB_CLIENT_ID
|
||
GITHUB_CLIENT_SECRET=$MYP_GITHUB_CLIENT_SECRET
|
||
|
||
# System-Zugangsdaten (nur für Dokumentation)
|
||
SSH_USER=user
|
||
SSH_PASSWORD=$MYP_SSH_PASSWORD
|
||
RDP_USER=root
|
||
RDP_PASSWORD=$MYP_MAIN_PASSWORD
|
||
|
||
# Router-Zugangsdaten (nur für Dokumentation)
|
||
ROUTER_USER=$MYP_ROUTER_USER
|
||
ROUTER_PASSWORD=$MYP_ROUTER_PASSWORD
|
||
|
||
# SSL-Konfiguration
|
||
SSL_CERT_PATH=instance/ssl/myp.crt
|
||
SSL_KEY_PATH=instance/ssl/myp.key
|
||
|
||
# Produktions-Konfiguration
|
||
FLASK_ENV=production
|
||
DEBUG=False
|
||
TESTING=False
|
||
EOF
|
||
|
||
# Sichere Berechtigungen setzen
|
||
chmod 600 "$env_file" || warning "Konnte Berechtigungen für .env-Datei nicht setzen"
|
||
chown root:root "$env_file" 2>/dev/null || warning "Konnte Besitzer für .env-Datei nicht setzen"
|
||
|
||
# Backup der CREDENTIALS.md erstellen falls vorhanden
|
||
if [ -f "$CURRENT_DIR/../docs/CREDENTIALS.md" ]; then
|
||
progress "Erstelle Backup der CREDENTIALS.md..."
|
||
cp "$CURRENT_DIR/../docs/CREDENTIALS.md" "$APP_DIR/CREDENTIALS_backup.md" 2>/dev/null || true
|
||
fi
|
||
|
||
# Erstelle lokale Credentials-Dokumentation
|
||
progress "Erstelle lokale Credentials-Dokumentation..."
|
||
|
||
cat > "$APP_DIR/CREDENTIALS_LOCAL.md" << EOF
|
||
# MYP Druckerverwaltung - Lokale Credentials
|
||
|
||
**Automatisch generiert am:** $(date '+%Y-%m-%d %H:%M:%S')
|
||
**Setup-Version:** $APP_VERSION
|
||
**Hostname:** $(hostname)
|
||
|
||
## 🔐 System-Zugangsdaten
|
||
|
||
### SSH-Zugang
|
||
- **Benutzer:** user
|
||
- **Passwort:** $MYP_SSH_PASSWORD
|
||
- **Port:** 22
|
||
- **Verbindung:** \`ssh user@$(hostname)\`
|
||
|
||
### RDP-Zugang
|
||
- **Benutzer:** root
|
||
- **Passwort:** $MYP_MAIN_PASSWORD
|
||
- **Port:** 3389
|
||
- **Verbindung:** RDP-Client zu \`$(hostname):3389\`
|
||
|
||
## 🌐 Anwendungs-Credentials
|
||
|
||
### Backend-Konfiguration
|
||
- **SECRET_KEY:** \`${MYP_SECRET_KEY:0:8}...\` (${#MYP_SECRET_KEY} Zeichen)
|
||
- **Kiosk-Deaktivierung:** $MYP_MAIN_PASSWORD
|
||
|
||
### Admin-Zugang
|
||
- **E-Mail:** $MYP_ADMIN_EMAIL
|
||
- **Passwort:** $MYP_MAIN_PASSWORD
|
||
|
||
### TP-Link Tapo Steckdosen
|
||
- **E-Mail:** $MYP_TAPO_EMAIL
|
||
- **Passwort:** $MYP_TAPO_PASSWORD
|
||
|
||
### GitHub OAuth
|
||
- **Client ID:** ${MYP_GITHUB_CLIENT_ID:0:8}...
|
||
- **Client Secret:** ${MYP_GITHUB_CLIENT_SECRET:0:8}...
|
||
|
||
## 🔧 Netzwerk-Konfiguration
|
||
|
||
### Router-Zugang
|
||
- **Benutzer:** $MYP_ROUTER_USER
|
||
- **Passwort:** $MYP_ROUTER_PASSWORD
|
||
|
||
## 📁 Dateien
|
||
|
||
- **Anwendung:** $APP_DIR
|
||
- **SSL-Zertifikat:** $APP_DIR/instance/ssl/myp.crt
|
||
- **SSL-Schlüssel:** $APP_DIR/instance/ssl/myp.key
|
||
- **Umgebungsvariablen:** $APP_DIR/.env
|
||
|
||
## ⚠️ Sicherheitshinweise
|
||
|
||
1. Diese Datei enthält sensible Informationen
|
||
2. Zugriff nur für autorisierte Personen
|
||
3. Regelmäßige Passwort-Updates empfohlen
|
||
4. Backup der Credentials an sicherem Ort
|
||
|
||
---
|
||
**Erstellt durch:** MYP Setup-Skript v$APP_VERSION
|
||
EOF
|
||
|
||
# Sichere Berechtigungen für Dokumentation
|
||
chmod 600 "$APP_DIR/CREDENTIALS_LOCAL.md" || warning "Konnte Berechtigungen für Credentials-Dokumentation nicht setzen"
|
||
chown root:root "$APP_DIR/CREDENTIALS_LOCAL.md" 2>/dev/null || warning "Konnte Besitzer für Credentials-Dokumentation nicht setzen"
|
||
|
||
success "✅ Credentials erfolgreich deployed:"
|
||
log " 📄 .env-Datei: $env_file"
|
||
log " 📋 Lokale Dokumentation: $APP_DIR/CREDENTIALS_LOCAL.md"
|
||
log " 🔒 Sichere Berechtigungen gesetzt (600, root:root)"
|
||
}
|
||
|
||
# =========================== AUTOMATISCHE SYSTEM-ERKENNUNG ===========================
|
||
# Menü-System entfernt - vollautomatische Installation basierend auf System-Erkennung
|
||
|
||
# =========================== AUTOMATISCHE INSTALLATIONS-MODI ===========================
|
||
# Alte manuelle Installationsfunktionen entfernt - ersetzt durch automatische Varianten
|
||
|
||
# =========================== RDP & SSH ZUGANG ===========================
|
||
install_remote_access() {
|
||
log "=== INSTALLIERE REMOTE-ZUGANG (RDP & SSH) ==="
|
||
|
||
# SSH-Server installieren und konfigurieren
|
||
progress "Installiere und konfiguriere SSH-Server..."
|
||
apt-get install -y openssh-server || error "SSH-Server Installation fehlgeschlagen"
|
||
|
||
# SSH-Service aktivieren
|
||
systemctl enable ssh
|
||
systemctl start ssh
|
||
|
||
# SSH-Benutzer 'user' erstellen (falls nicht vorhanden)
|
||
if ! id "user" &>/dev/null; then
|
||
progress "Erstelle SSH-Benutzer: user"
|
||
useradd -m -s /bin/bash user || error "Kann SSH-Benutzer nicht erstellen"
|
||
echo "user:$MYP_SSH_PASSWORD" | chpasswd || error "Kann Passwort für SSH-Benutzer nicht setzen"
|
||
usermod -aG sudo user 2>/dev/null || true
|
||
|
||
# pip-Konfiguration für SSH-Benutzer
|
||
mkdir -p "/home/user/.pip" 2>/dev/null || true
|
||
cat > "/home/user/.pip/pip.conf" << 'EOF'
|
||
[global]
|
||
break-system-packages = true
|
||
trusted-host = pypi.org
|
||
pypi.python.org
|
||
files.pythonhosted.org
|
||
timeout = 60
|
||
retries = 3
|
||
|
||
[install]
|
||
break-system-packages = true
|
||
trusted-host = pypi.org
|
||
pypi.python.org
|
||
files.pythonhosted.org
|
||
EOF
|
||
chown "user:user" "/home/user/.pip/pip.conf" 2>/dev/null || true
|
||
|
||
log "✅ SSH-Benutzer 'user' erstellt mit Passwort '$MYP_SSH_PASSWORD'"
|
||
else
|
||
info "SSH-Benutzer 'user' existiert bereits"
|
||
echo "user:$MYP_SSH_PASSWORD" | chpasswd || warning "Konnte Passwort für SSH-Benutzer nicht aktualisieren"
|
||
fi
|
||
|
||
# RDP-Server (xrdp) installieren - vereinfachter Ansatz
|
||
progress "Installiere RDP-Server (xrdp) - vereinfachte Installation..."
|
||
|
||
# Alle bestehenden xrdp-Installationen entfernen
|
||
progress "Entferne vorherige xrdp-Installationen..."
|
||
systemctl stop xrdp xrdp-sesman 2>/dev/null || true
|
||
systemctl disable xrdp xrdp-sesman 2>/dev/null || true
|
||
apt-get remove --purge -y xrdp 2>/dev/null || true
|
||
rm -rf /etc/xrdp /var/log/xrdp* 2>/dev/null || true
|
||
|
||
# XFCE Desktop installieren (minimal)
|
||
progress "Installiere minimale XFCE-Umgebung..."
|
||
if ! apt-get install -y xfce4-session xfce4-panel xfce4-terminal xfce4-settings xfdesktop4 dbus-x11; then
|
||
warning "Minimale XFCE-Installation fehlgeschlagen - verwende Fallback..."
|
||
apt-get install -y xfce4 dbus-x11 || error "XFCE Installation fehlgeschlagen"
|
||
fi
|
||
|
||
# xrdp neu installieren
|
||
progress "Installiere xrdp neu..."
|
||
apt-get update
|
||
apt-get install -y xrdp || error "xrdp Installation fehlgeschlagen"
|
||
|
||
# Benutzer zur xrdp-Gruppe hinzufügen
|
||
usermod -aG xrdp root 2>/dev/null || true
|
||
if id "user" &>/dev/null; then
|
||
usermod -aG xrdp user 2>/dev/null || true
|
||
fi
|
||
|
||
# Erstelle minimale xrdp-Konfiguration
|
||
progress "Erstelle minimale xrdp-Konfiguration..."
|
||
|
||
# Backup der Original-Konfiguration
|
||
cp /etc/xrdp/xrdp.ini /etc/xrdp/xrdp.ini.original 2>/dev/null || true
|
||
|
||
# Sehr einfache xrdp.ini
|
||
cat > /etc/xrdp/xrdp.ini << 'EOF'
|
||
[Globals]
|
||
ini_version=1
|
||
fork=true
|
||
port=3389
|
||
tcp_nodelay=true
|
||
tcp_keepalive=true
|
||
security_layer=rdp
|
||
autorun=
|
||
allow_channels=true
|
||
allow_multimon=false
|
||
bitmap_cache=true
|
||
bitmap_compression=true
|
||
bulk_compression=false
|
||
max_bpp=24
|
||
new_cursors=true
|
||
use_fastpath=both
|
||
require_credentials=true
|
||
ask_for_reconnect_reason=false
|
||
enable_token_login=false
|
||
|
||
[Xorg]
|
||
name=Xorg
|
||
lib=libxup.so
|
||
username=ask
|
||
password=ask
|
||
ip=127.0.0.1
|
||
port=-1
|
||
code=20
|
||
EOF
|
||
|
||
# Einfache sesman.ini
|
||
cp /etc/xrdp/sesman.ini /etc/xrdp/sesman.ini.original 2>/dev/null || true
|
||
|
||
cat > /etc/xrdp/sesman.ini << 'EOF'
|
||
[Globals]
|
||
ListenAddress=127.0.0.1
|
||
ListenPort=3350
|
||
EnableUserWindowManager=true
|
||
UserWindowManager=startxfce4
|
||
DefaultWindowManager=startxfce4
|
||
|
||
[Security]
|
||
AllowRootLogin=true
|
||
MaxLoginRetry=4
|
||
AlwaysGroupCheck=false
|
||
|
||
[Sessions]
|
||
X11DisplayOffset=10
|
||
MaxSessions=10
|
||
KillDisconnected=false
|
||
IdleTimeLimit=0
|
||
DisconnectedTimeLimit=0
|
||
|
||
[Logging]
|
||
LogFile=xrdp-sesman.log
|
||
LogLevel=INFO
|
||
EnableSyslog=true
|
||
SyslogLevel=INFO
|
||
|
||
[Xorg]
|
||
param1=-bs
|
||
param2=-nolisten
|
||
param3=tcp
|
||
param4=-dpi
|
||
param5=96
|
||
EOF
|
||
|
||
# Erstelle .xsession für XFCE
|
||
progress "Konfiguriere XFCE-Sessions..."
|
||
|
||
# Root .xsession
|
||
cat > /root/.xsession << 'EOF'
|
||
#!/bin/bash
|
||
export XDG_SESSION_DESKTOP=xfce
|
||
export XDG_DATA_DIRS=/usr/share/xfce4:/usr/local/share:/usr/share
|
||
export XDG_CONFIG_DIRS=/etc/xdg/xdg-xfce:/etc/xdg
|
||
exec startxfce4
|
||
EOF
|
||
chmod +x /root/.xsession
|
||
|
||
# User .xsession (falls user existiert)
|
||
if id "user" &>/dev/null; then
|
||
cat > /home/user/.xsession << 'EOF'
|
||
#!/bin/bash
|
||
export XDG_SESSION_DESKTOP=xfce
|
||
export XDG_DATA_DIRS=/usr/share/xfce4:/usr/local/share:/usr/share
|
||
export XDG_CONFIG_DIRS=/etc/xdg/xdg-xfce:/etc/xdg
|
||
exec startxfce4
|
||
EOF
|
||
chown user:user /home/user/.xsession
|
||
chmod +x /home/user/.xsession
|
||
fi
|
||
|
||
# Root-Passwort setzen
|
||
progress "Setze Root-Passwort für RDP..."
|
||
echo "root:$MYP_MAIN_PASSWORD" | chpasswd || error "Kann Root-Passwort nicht setzen"
|
||
|
||
# Log-Verzeichnisse erstellen mit korrekten Berechtigungen
|
||
progress "Erstelle Log-Verzeichnisse..."
|
||
mkdir -p /var/log
|
||
touch /var/log/xrdp.log /var/log/xrdp-sesman.log 2>/dev/null || true
|
||
chown xrdp:xrdp /var/log/xrdp*.log 2>/dev/null || true
|
||
chmod 644 /var/log/xrdp*.log 2>/dev/null || true
|
||
|
||
# Erstelle xrdp-Konfigurationsverzeichnisse
|
||
mkdir -p /etc/xrdp/cert /var/run/xrdp
|
||
chown xrdp:xrdp /etc/xrdp/cert /var/run/xrdp 2>/dev/null || true
|
||
|
||
# Services aktivieren und starten
|
||
progress "Starte xrdp-Services..."
|
||
|
||
# systemd daemon reload
|
||
systemctl daemon-reload
|
||
|
||
# Services aktivieren
|
||
systemctl enable xrdp-sesman
|
||
systemctl enable xrdp
|
||
|
||
# Services starten (sesman zuerst)
|
||
systemctl start xrdp-sesman
|
||
sleep 3
|
||
|
||
# Prüfe sesman-Status
|
||
if systemctl is-active --quiet xrdp-sesman; then
|
||
success "✅ xrdp-sesman erfolgreich gestartet"
|
||
|
||
# Jetzt xrdp starten
|
||
systemctl start xrdp
|
||
sleep 3
|
||
|
||
if systemctl is-active --quiet xrdp; then
|
||
success "✅ xrdp erfolgreich gestartet"
|
||
else
|
||
warning "⚠️ xrdp konnte nicht gestartet werden"
|
||
journalctl -u xrdp --no-pager -l | tail -10
|
||
fi
|
||
else
|
||
warning "⚠️ xrdp-sesman konnte nicht gestartet werden"
|
||
journalctl -u xrdp-sesman --no-pager -l | tail -10
|
||
fi
|
||
|
||
cd "$CURRENT_DIR"
|
||
|
||
# Finaler Status-Check
|
||
if systemctl is-active --quiet xrdp && systemctl is-active --quiet xrdp-sesman; then
|
||
log "✅ Remote-Zugang vollständig konfiguriert:"
|
||
log " 📡 SSH: user:$MYP_SSH_PASSWORD (Port 22)"
|
||
log " 🖥️ RDP: root:$MYP_MAIN_PASSWORD (Port 3389)"
|
||
log " 🖥️ RDP: user:$MYP_SSH_PASSWORD (Port 3389)"
|
||
elif systemctl is-active --quiet ssh; then
|
||
log "✅ SSH-Zugang konfiguriert:"
|
||
log " 📡 SSH: user:$MYP_SSH_PASSWORD (Port 22)"
|
||
warning "⚠️ RDP-Installation unvollständig"
|
||
info "Manuelle Überprüfung erforderlich:"
|
||
info " systemctl status xrdp"
|
||
info " systemctl status xrdp-sesman"
|
||
info " journalctl -u xrdp -f"
|
||
else
|
||
error "❌ Weder SSH noch RDP konnten konfiguriert werden"
|
||
fi
|
||
}
|
||
|
||
# =========================== FIREWALL KONFIGURATION ===========================
|
||
configure_firewall() {
|
||
log "=== KONFIGURIERE FIREWALL (firewalld) ==="
|
||
|
||
# firewalld installieren
|
||
progress "Installiere firewalld..."
|
||
apt-get install -y firewalld || error "firewalld Installation fehlgeschlagen"
|
||
|
||
# firewalld aktivieren und starten
|
||
systemctl enable firewalld
|
||
systemctl start firewalld
|
||
|
||
# Warte kurz bis firewalld vollständig gestartet ist
|
||
sleep 5
|
||
|
||
progress "Konfiguriere firewalld-Zonen und -Regeln..."
|
||
|
||
# Firewall-Status prüfen
|
||
if ! firewall-cmd --state >/dev/null 2>&1; then
|
||
error "firewalld ist nicht aktiv oder reagiert nicht"
|
||
fi
|
||
|
||
# Bestehende Zone entfernen falls vorhanden
|
||
progress "Entferne bestehende myp-backend Zone falls vorhanden..."
|
||
if firewall-cmd --permanent --get-zones | grep -q "myp-backend"; then
|
||
log "Entferne bestehende myp-backend Zone..."
|
||
firewall-cmd --permanent --delete-zone=myp-backend 2>/dev/null || true
|
||
firewall-cmd --reload
|
||
sleep 2
|
||
fi
|
||
|
||
# Zone neu erstellen
|
||
progress "Erstelle neue myp-backend Zone..."
|
||
if ! firewall-cmd --permanent --new-zone=myp-backend; then
|
||
error "Fehler beim Erstellen der myp-backend Zone"
|
||
fi
|
||
|
||
# Konfiguration neu laden
|
||
firewall-cmd --reload
|
||
sleep 2
|
||
|
||
# Erweiterte Netzwerk-Quellen definieren (nur IPv4)
|
||
progress "Füge Netzwerk-Quellen hinzu..."
|
||
firewall-cmd --permanent --zone=myp-backend --add-source=192.168.0.0/16 || error "Fehler beim Hinzufügen des 192.168.0.0/16 Netzwerks"
|
||
firewall-cmd --permanent --zone=myp-backend --add-source=127.0.0.1/32 || error "Fehler beim Hinzufügen von localhost"
|
||
|
||
# Lokaler Hostname "raspberrypi" hinzufügen
|
||
local local_hostname="raspberrypi"
|
||
progress "Füge lokalen Hostname hinzu: $local_hostname"
|
||
local local_ip=$(getent hosts "$local_hostname" | awk '{print $1}' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -1 2>/dev/null || true)
|
||
if [ -n "$local_ip" ]; then
|
||
firewall-cmd --permanent --zone=myp-backend --add-source="$local_ip/32" 2>/dev/null || warning "Konnte lokalen Hostname nicht hinzufügen"
|
||
log "✅ Lokaler Hostname $local_hostname hinzugefügt: $local_ip"
|
||
else
|
||
info "Lokaler Hostname $local_hostname nicht auflösbar - wird beim nächsten Boot verfügbar sein"
|
||
fi
|
||
|
||
# Frontend-Server m040tbaraspi001 hinzufügen (falls auflösbar)
|
||
progress "Füge Frontend-Server hinzu: m040tbaraspi001"
|
||
local frontend_ip=$(getent hosts "m040tbaraspi001" | awk '{print $1}' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -1 2>/dev/null || true)
|
||
if [ -n "$frontend_ip" ]; then
|
||
firewall-cmd --permanent --zone=myp-backend --add-source="$frontend_ip/32" 2>/dev/null || warning "Konnte Frontend-Server IP nicht hinzufügen"
|
||
log "✅ Frontend-Server m040tbaraspi001 hinzugefügt: $frontend_ip"
|
||
else
|
||
# Versuche auch mit FQDN
|
||
local frontend_fqdn_ip=$(getent hosts "m040tbaraspi001.de040.corpintra.net" | awk '{print $1}' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -1 2>/dev/null || true)
|
||
if [ -n "$frontend_fqdn_ip" ]; then
|
||
firewall-cmd --permanent --zone=myp-backend --add-source="$frontend_fqdn_ip/32" 2>/dev/null || warning "Konnte Frontend-Server FQDN nicht hinzufügen"
|
||
log "✅ Frontend-Server m040tbaraspi001.de040.corpintra.net hinzugefügt: $frontend_fqdn_ip"
|
||
else
|
||
info "Frontend-Server m040tbaraspi001 nicht auflösbar - überspringe"
|
||
fi
|
||
fi
|
||
|
||
# Ports und Services hinzufügen
|
||
progress "Konfiguriere Ports und Services..."
|
||
|
||
# HTTPS für API & Kiosk zulassen
|
||
firewall-cmd --permanent --zone=myp-backend --add-port=443/tcp || error "Fehler beim Hinzufügen von Port 443"
|
||
|
||
# SSH für Wartung
|
||
firewall-cmd --permanent --zone=myp-backend --add-service=ssh || error "Fehler beim Hinzufügen des SSH-Service"
|
||
|
||
# RDP für Remote-Desktop
|
||
firewall-cmd --permanent --zone=myp-backend --add-port=3389/tcp || error "Fehler beim Hinzufügen von Port 3389"
|
||
|
||
# IPv6 in firewalld deaktivieren
|
||
progress "Deaktiviere IPv6 in firewalld..."
|
||
firewall-cmd --permanent --set-target=DROP --zone=public --family=ipv6 2>/dev/null || warning "IPv6 konnte nicht in public Zone deaktiviert werden"
|
||
firewall-cmd --permanent --set-target=DROP --zone=myp-backend --family=ipv6 2>/dev/null || warning "IPv6 konnte nicht in myp-backend Zone deaktiviert werden"
|
||
|
||
# Default-Zone setzen
|
||
progress "Setze Default-Zone..."
|
||
firewall-cmd --set-default-zone=myp-backend || error "Fehler beim Setzen der Default-Zone"
|
||
|
||
# Änderungen übernehmen
|
||
progress "Lade Firewall-Konfiguration neu..."
|
||
firewall-cmd --reload || error "Fehler beim Neuladen der Firewall-Konfiguration"
|
||
|
||
# Kurz warten und Status prüfen
|
||
sleep 3
|
||
|
||
# Firewall-Status anzeigen
|
||
progress "Firewall-Konfiguration:"
|
||
if firewall-cmd --list-all --zone=myp-backend 2>/dev/null; then
|
||
log "✅ Firewall-Konfiguration erfolgreich angezeigt"
|
||
else
|
||
warning "⚠️ Firewall-Status konnte nicht angezeigt werden"
|
||
fi
|
||
|
||
# Finale Validierung
|
||
progress "Validiere Firewall-Konfiguration..."
|
||
local validation_errors=0
|
||
|
||
# Prüfe ob Zone existiert
|
||
if ! firewall-cmd --get-zones | grep -q "myp-backend"; then
|
||
error "Zone myp-backend wurde nicht korrekt erstellt"
|
||
((validation_errors++))
|
||
fi
|
||
|
||
# Prüfe Default-Zone
|
||
if [ "$(firewall-cmd --get-default-zone)" != "myp-backend" ]; then
|
||
warning "Default-Zone ist nicht myp-backend"
|
||
((validation_errors++))
|
||
fi
|
||
|
||
# Prüfe Ports
|
||
if ! firewall-cmd --zone=myp-backend --query-port=443/tcp 2>/dev/null; then
|
||
warning "Port 443 nicht korrekt konfiguriert"
|
||
((validation_errors++))
|
||
fi
|
||
|
||
if ! firewall-cmd --zone=myp-backend --query-port=3389/tcp 2>/dev/null; then
|
||
warning "Port 3389 nicht korrekt konfiguriert"
|
||
((validation_errors++))
|
||
fi
|
||
|
||
if ! firewall-cmd --zone=myp-backend --query-service=ssh 2>/dev/null; then
|
||
warning "SSH-Service nicht korrekt konfiguriert"
|
||
((validation_errors++))
|
||
fi
|
||
|
||
if [ $validation_errors -eq 0 ]; then
|
||
log "✅ Firewall konfiguriert und validiert:"
|
||
log " 🔒 Zone: myp-backend (als Default gesetzt)"
|
||
log " 🌐 Netzwerk: 192.168.0.0/16 (nur IPv4)"
|
||
log " 🏠 Localhost: 127.0.0.1"
|
||
log " 🖥️ Lokaler Host: raspberrypi"
|
||
log " 📡 Frontend-Server: m040tbaraspi001"
|
||
log " 🔌 Ports: 443/tcp (HTTPS), 22/tcp (SSH), 3389/tcp (RDP)"
|
||
log " 🚫 IPv6 vollständig blockiert"
|
||
else
|
||
warning "⚠️ Firewall-Konfiguration mit $validation_errors Fehlern abgeschlossen"
|
||
info "System funktioniert möglicherweise trotzdem - manuelle Überprüfung empfohlen"
|
||
fi
|
||
}
|
||
|
||
# =========================== REMOTE-ZUGANG TESTEN ===========================
|
||
test_remote_access() {
|
||
log "=== TESTE REMOTE-ZUGANG ==="
|
||
|
||
# SSH-Service testen
|
||
progress "Teste SSH-Service..."
|
||
if systemctl is-active --quiet ssh; then
|
||
success "✅ SSH-Service läuft"
|
||
|
||
# SSH-Port testen
|
||
if ss -tlnp | grep -q ":22 "; then
|
||
success "✅ SSH-Port 22 ist offen"
|
||
else
|
||
warning "⚠️ SSH-Port 22 nicht erreichbar"
|
||
fi
|
||
else
|
||
warning "⚠️ SSH-Service läuft nicht"
|
||
fi
|
||
|
||
# RDP-Services testen
|
||
progress "Teste RDP-Services..."
|
||
|
||
local xrdp_sesman_status="❌"
|
||
local xrdp_status="❌"
|
||
|
||
if systemctl is-active --quiet xrdp-sesman; then
|
||
xrdp_sesman_status="✅"
|
||
success "✅ xrdp-sesman läuft"
|
||
else
|
||
warning "⚠️ xrdp-sesman läuft nicht"
|
||
fi
|
||
|
||
if systemctl is-active --quiet xrdp; then
|
||
xrdp_status="✅"
|
||
success "✅ xrdp läuft"
|
||
|
||
# RDP-Port testen
|
||
if ss -tlnp | grep -q ":3389 "; then
|
||
success "✅ RDP-Port 3389 ist offen"
|
||
else
|
||
warning "⚠️ RDP-Port 3389 nicht erreichbar"
|
||
fi
|
||
else
|
||
warning "⚠️ xrdp läuft nicht"
|
||
fi
|
||
|
||
# Firewall-Status testen
|
||
progress "Teste Firewall-Status..."
|
||
if systemctl is-active --quiet firewalld; then
|
||
success "✅ Firewall läuft"
|
||
|
||
# Prüfe ob Ports offen sind
|
||
if firewall-cmd --zone=myp-backend --query-port=22/tcp 2>/dev/null; then
|
||
success "✅ SSH-Port in Firewall freigegeben"
|
||
else
|
||
warning "⚠️ SSH-Port nicht in Firewall freigegeben"
|
||
fi
|
||
|
||
if firewall-cmd --zone=myp-backend --query-port=3389/tcp 2>/dev/null; then
|
||
success "✅ RDP-Port in Firewall freigegeben"
|
||
else
|
||
warning "⚠️ RDP-Port nicht in Firewall freigegeben"
|
||
fi
|
||
else
|
||
warning "⚠️ Firewall läuft nicht"
|
||
fi
|
||
|
||
# Netzwerk-Interface testen
|
||
progress "Teste Netzwerk-Konfiguration..."
|
||
local ip_address=$(ip route get 1.1.1.1 2>/dev/null | awk '{print $7}' | head -1 || echo "Unbekannt")
|
||
if [ "$ip_address" != "Unbekannt" ]; then
|
||
success "✅ Netzwerk-Interface aktiv: $ip_address"
|
||
info "Zugang-URLs:"
|
||
info " SSH: ssh user@$ip_address"
|
||
if [ "$xrdp_status" = "✅" ]; then
|
||
info " RDP: $ip_address:3389 (root:$MYP_MAIN_PASSWORD oder user:$MYP_SSH_PASSWORD)"
|
||
fi
|
||
else
|
||
warning "⚠️ Keine Netzwerk-IP ermittelt"
|
||
fi
|
||
|
||
# Status-Zusammenfassung
|
||
log "📊 Service-Status:"
|
||
log " SSH: $(systemctl is-active --quiet ssh && echo "✅ Aktiv" || echo "❌ Inaktiv")"
|
||
log " xrdp-sesman: $xrdp_sesman_status $(systemctl is-active --quiet xrdp-sesman && echo "Aktiv" || echo "Inaktiv")"
|
||
log " xrdp: $xrdp_status $(systemctl is-active --quiet xrdp && echo "Aktiv" || echo "Inaktiv")"
|
||
|
||
log "✅ Remote-Zugang-Test abgeschlossen"
|
||
}
|
||
|
||
# =========================== HOSTNAME KONFIGURATION ===========================
|
||
configure_hostname() {
|
||
log "=== KONFIGURIERE HOSTNAME ==="
|
||
|
||
local target_hostname="m040tbaraspi001"
|
||
local current_hostname=$(hostname)
|
||
|
||
if [ "$current_hostname" != "$target_hostname" ]; then
|
||
progress "Setze Hostname von '$current_hostname' auf '$target_hostname'..."
|
||
|
||
# Hostname sofort setzen
|
||
hostnamectl set-hostname "$target_hostname" || error "Fehler beim Setzen des Hostnames"
|
||
|
||
# /etc/hostname aktualisieren
|
||
echo "$target_hostname" > /etc/hostname
|
||
|
||
# /etc/hosts aktualisieren
|
||
cp /etc/hosts /etc/hosts.backup
|
||
sed -i "s/127.0.1.1.*/127.0.1.1\t$target_hostname/" /etc/hosts
|
||
|
||
# Falls kein 127.0.1.1 Eintrag existiert, hinzufügen
|
||
if ! grep -q "127.0.1.1" /etc/hosts; then
|
||
echo "127.0.1.1 $target_hostname" >> /etc/hosts
|
||
fi
|
||
|
||
# Intranet-Eintrag hinzufügen für Corporate Network Access
|
||
if ! grep -q "m040tbaraspi001.de040.corpintra.net" /etc/hosts; then
|
||
echo "127.0.1.1 $target_hostname.de040.corpintra.net" >> /etc/hosts
|
||
fi
|
||
|
||
log "✅ Hostname erfolgreich auf '$target_hostname' gesetzt"
|
||
log "✅ Intranet-Zugang konfiguriert: https://m040tbaraspi001.de040.corpintra.net"
|
||
else
|
||
log "✅ Hostname bereits korrekt: '$target_hostname'"
|
||
fi
|
||
|
||
# Hostname-Auflösung testen
|
||
if getent hosts "$target_hostname" >/dev/null 2>&1; then
|
||
local resolved_ip=$(getent hosts "$target_hostname" | awk '{print $1}' | head -1)
|
||
log "✅ Hostname-Auflösung funktioniert: $target_hostname -> $resolved_ip"
|
||
else
|
||
warning "⚠️ Hostname-Auflösung für '$target_hostname' fehlgeschlagen"
|
||
fi
|
||
}
|
||
|
||
# =========================== WEBAPP PERFORMANCE-OPTIMIERUNG ===========================
|
||
optimize_webapp_performance() {
|
||
log "=== WEBAPP PERFORMANCE-OPTIMIERUNG FÜR RASPBERRY PI ==="
|
||
|
||
# Python/Flask spezifische Optimierungen
|
||
progress "Konfiguriere Python-Performance-Optimierungen..."
|
||
|
||
# Python Bytecode Optimierung aktivieren
|
||
cat > /etc/environment << 'EOF'
|
||
# Python Performance Optimierungen
|
||
PYTHONOPTIMIZE=2
|
||
PYTHONDONTWRITEBYTECODE=1
|
||
PYTHONUNBUFFERED=1
|
||
PYTHONHASHSEED=random
|
||
|
||
# Flask/SQLite Optimierungen
|
||
FLASK_ENV=production
|
||
FLASK_DEBUG=0
|
||
SQLITE_TMPDIR=/tmp
|
||
|
||
# Memory Optimierungen
|
||
MALLOC_ARENA_MAX=2
|
||
MALLOC_MMAP_THRESHOLD=131072
|
||
MALLOC_TRIM_THRESHOLD=131072
|
||
|
||
EOF
|
||
|
||
# Systemd Service-Optimierungen
|
||
progress "Optimiere Systemd-Services für bessere Performance..."
|
||
|
||
# Stoppe unnötige Services
|
||
local unnecessary_services=(
|
||
"bluetooth.service"
|
||
"hciuart.service"
|
||
"avahi-daemon.service"
|
||
"cups.service"
|
||
"cups-browsed.service"
|
||
"ModemManager.service"
|
||
"wpa_supplicant.service"
|
||
)
|
||
|
||
for service in "${unnecessary_services[@]}"; do
|
||
if systemctl is-enabled "$service" 2>/dev/null; then
|
||
systemctl disable "$service" 2>/dev/null || true
|
||
systemctl stop "$service" 2>/dev/null || true
|
||
log "✅ Service deaktiviert: $service"
|
||
fi
|
||
done
|
||
|
||
# Tmpfs für temporäre Dateien
|
||
progress "Konfiguriere tmpfs für bessere I/O Performance..."
|
||
|
||
cat >> /etc/fstab << 'EOF'
|
||
|
||
# MYP Performance Optimierungen - tmpfs für temporäre Dateien
|
||
tmpfs /tmp tmpfs defaults,noatime,nosuid,size=256m 0 0
|
||
tmpfs /var/tmp tmpfs defaults,noatime,nosuid,size=128m 0 0
|
||
tmpfs /var/log tmpfs defaults,noatime,nosuid,size=64m 0 0
|
||
|
||
EOF
|
||
|
||
# Logrotate für tmpfs-Logs konfigurieren
|
||
cat > /etc/logrotate.d/myp-tmpfs << 'EOF'
|
||
/var/log/*.log {
|
||
daily
|
||
missingok
|
||
rotate 2
|
||
compress
|
||
notifempty
|
||
create 0644 root root
|
||
copytruncate
|
||
}
|
||
EOF
|
||
|
||
# Systemd Journal Einstellungen optimieren
|
||
progress "Optimiere systemd Journal für bessere Performance..."
|
||
|
||
mkdir -p /etc/systemd/journald.conf.d
|
||
cat > /etc/systemd/journald.conf.d/myp-performance.conf << 'EOF'
|
||
[Journal]
|
||
# Journal Optimierungen für Raspberry Pi
|
||
Storage=volatile
|
||
RuntimeMaxUse=32M
|
||
RuntimeKeepFree=16M
|
||
RuntimeMaxFileSize=8M
|
||
RuntimeMaxFiles=4
|
||
MaxRetentionSec=1day
|
||
MaxFileSec=1hour
|
||
ForwardToSyslog=no
|
||
ForwardToKMsg=no
|
||
ForwardToConsole=no
|
||
ForwardToWall=no
|
||
EOF
|
||
|
||
# Crontab für regelmäßige Cache-Bereinigung
|
||
progress "Installiere automatische Cache-Bereinigung..."
|
||
|
||
cat > /etc/cron.d/myp-cache-cleanup << 'EOF'
|
||
# MYP Cache und Memory Cleanup
|
||
# Alle 6 Stunden Cache bereinigen
|
||
0 */6 * * * root /bin/echo 3 > /proc/sys/vm/drop_caches
|
||
# Täglich um 3 Uhr temporäre Dateien bereinigen
|
||
0 3 * * * root /usr/bin/find /tmp -type f -atime +1 -delete 2>/dev/null
|
||
# Wöchentlich Python Cache bereinigen
|
||
0 2 * * 0 root /usr/bin/find /opt/myp -name "*.pyc" -delete 2>/dev/null
|
||
0 2 * * 0 root /usr/bin/find /opt/myp -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null
|
||
EOF
|
||
|
||
# Limits für bessere Ressourcen-Verwaltung
|
||
progress "Konfiguriere System-Limits..."
|
||
|
||
cat >> /etc/security/limits.conf << 'EOF'
|
||
|
||
# MYP Performance Limits
|
||
* soft nofile 65536
|
||
* hard nofile 65536
|
||
* soft nproc 32768
|
||
* hard nproc 32768
|
||
root soft nofile 65536
|
||
root hard nofile 65536
|
||
|
||
EOF
|
||
|
||
# Apache/Nginx entfernen falls vorhanden (Konflikt mit Flask)
|
||
progress "Entferne konfliktbehaftete Webserver..."
|
||
|
||
local webservers=("apache2" "nginx" "lighttpd")
|
||
for webserver in "${webservers[@]}"; do
|
||
if systemctl is-enabled "$webserver" 2>/dev/null; then
|
||
systemctl stop "$webserver" 2>/dev/null || true
|
||
systemctl disable "$webserver" 2>/dev/null || true
|
||
apt-get remove --purge -y "$webserver" 2>/dev/null || true
|
||
log "✅ Webserver entfernt: $webserver"
|
||
fi
|
||
done
|
||
|
||
log "✅ Webapp Performance-Optimierung abgeschlossen:"
|
||
log " 🚀 Python Bytecode-Optimierung aktiviert"
|
||
log " 💾 tmpfs für temporäre Dateien konfiguriert"
|
||
log " 📝 Journal-Logging optimiert"
|
||
log " 🧹 Automatische Cache-Bereinigung installiert"
|
||
log " ⚡ Unnötige Services deaktiviert"
|
||
log " 📊 System-Limits für bessere Performance gesetzt"
|
||
}
|
||
|
||
# =========================== CSS/JS OPTIMIERUNG ===========================
|
||
optimize_static_assets() {
|
||
log "=== STATISCHE DATEIEN OPTIMIERUNG ==="
|
||
|
||
# Stelle sicher, dass APP_DIR existiert
|
||
if [ -z "$APP_DIR" ] || [ ! -d "$APP_DIR" ]; then
|
||
warning "⚠️ APP_DIR nicht definiert oder nicht vorhanden - überspringe Asset-Optimierung"
|
||
return
|
||
fi
|
||
|
||
if [ ! -d "$APP_DIR/static" ]; then
|
||
warning "⚠️ Static-Ordner nicht gefunden: $APP_DIR/static - überspringe Asset-Optimierung"
|
||
return
|
||
fi
|
||
|
||
progress "Analysiere und optimiere CSS/JS Dateien..."
|
||
|
||
# Speichere aktuelles Verzeichnis
|
||
local original_dir=$(pwd)
|
||
|
||
# Wechsle zu static Verzeichnis
|
||
cd "$APP_DIR/static" 2>/dev/null || {
|
||
warning "⚠️ Konnte nicht zu $APP_DIR/static wechseln"
|
||
return
|
||
}
|
||
|
||
# Erstelle optimierte CSS-Datei durch Kombination kritischer Styles
|
||
progress "Erstelle optimierte CSS-Kombination..."
|
||
|
||
cat > css/critical.min.css << 'EOF'
|
||
/* Kritische Styles für ersten Seitenaufbau - Inline-optimiert */
|
||
*{box-sizing:border-box}body{margin:0;font-family:system-ui,-apple-system,sans-serif;line-height:1.5}
|
||
.container{max-width:1200px;margin:0 auto;padding:0 1rem}
|
||
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}
|
||
.btn{display:inline-flex;align-items:center;padding:0.5rem 1rem;border:none;border-radius:0.375rem;font-weight:500;text-decoration:none;cursor:pointer;transition:all 0.15s}
|
||
.btn-primary{background:#3b82f6;color:white}.btn-primary:hover{background:#2563eb}
|
||
.card{background:white;border-radius:0.5rem;padding:1.5rem;box-shadow:0 1px 3px rgba(0,0,0,0.1)}
|
||
.flex{display:flex}.items-center{align-items:center}.justify-between{justify-content:space-between}
|
||
.hidden{display:none}.block{display:block}.inline-block{display:inline-block}
|
||
.text-sm{font-size:0.875rem}.text-lg{font-size:1.125rem}
|
||
.font-medium{font-weight:500}.font-bold{font-weight:700}
|
||
.text-gray-600{color:#4b5563}.text-gray-900{color:#111827}
|
||
.mb-4{margin-bottom:1rem}.mt-6{margin-top:1.5rem}.p-4{padding:1rem}
|
||
.w-full{width:100%}.h-full{height:100%}
|
||
@media(max-width:768px){.container{padding:0 0.5rem}.card{padding:1rem}}
|
||
EOF
|
||
|
||
# Erstelle minimale JavaScript-Loader
|
||
progress "Erstelle optimierten JavaScript-Loader..."
|
||
|
||
cat > js/loader.min.js << 'EOF'
|
||
/*Minimaler Async Loader für bessere Performance*/
|
||
(function(){var d=document,w=window;function loadCSS(href){var l=d.createElement('link');l.rel='stylesheet';l.href=href;l.media='print';l.onload=function(){this.media='all'};d.head.appendChild(l)}function loadJS(src,cb){var s=d.createElement('script');s.async=true;s.src=src;if(cb)s.onload=cb;d.head.appendChild(s)}w.loadAssets=function(){if(w.assetsLoaded)return;w.assetsLoaded=true;loadCSS('/static/css/tailwind.min.css');loadJS('/static/js/app.min.js')};if(d.readyState==='loading'){d.addEventListener('DOMContentLoaded',w.loadAssets)}else{w.loadAssets()}})();
|
||
EOF
|
||
|
||
# Service Worker für besseres Caching
|
||
progress "Erstelle optimierten Service Worker..."
|
||
|
||
cat > sw-optimized.js << 'EOF'
|
||
const CACHE_NAME = 'myp-webapp-v1';
|
||
const ASSETS_TO_CACHE = [
|
||
'/',
|
||
'/static/css/critical.min.css',
|
||
'/static/js/loader.min.js',
|
||
'/static/favicon.svg'
|
||
];
|
||
|
||
self.addEventListener('install', event => {
|
||
event.waitUntil(
|
||
caches.open(CACHE_NAME)
|
||
.then(cache => cache.addAll(ASSETS_TO_CACHE))
|
||
);
|
||
});
|
||
|
||
self.addEventListener('fetch', event => {
|
||
if (event.request.destination === 'image' ||
|
||
event.request.url.includes('/static/')) {
|
||
event.respondWith(
|
||
caches.match(event.request)
|
||
.then(response => response || fetch(event.request))
|
||
);
|
||
}
|
||
});
|
||
EOF
|
||
|
||
# Gzip-Kompression für statische Dateien
|
||
progress "Komprimiere statische Dateien..."
|
||
|
||
find . -name "*.css" -o -name "*.js" -o -name "*.html" | while read file; do
|
||
if [ -f "$file" ] && [ ! -f "$file.gz" ]; then
|
||
gzip -c "$file" > "$file.gz" 2>/dev/null || true
|
||
fi
|
||
done
|
||
|
||
# Zurück zum Original-Verzeichnis
|
||
cd "$original_dir" 2>/dev/null || cd "$CURRENT_DIR" 2>/dev/null || true
|
||
|
||
log "✅ Statische Dateien optimiert:"
|
||
log " 📦 Kritische CSS-Styles kombiniert"
|
||
log " ⚡ Asynchroner Asset-Loader erstellt"
|
||
log " 🗜️ Gzip-Kompression angewendet"
|
||
log " 🔄 Service Worker für Caching installiert"
|
||
}
|
||
|
||
# =========================== INTERAKTIVES AUSWAHLMENÜ ===========================
|
||
show_main_menu() {
|
||
clear
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo -e "${CYAN} $APP_NAME - Setup-Skript v$APP_VERSION${NC}"
|
||
echo -e "${CYAN} Hostname: m040tbaraspi001${NC}"
|
||
echo -e "${CYAN} Intranet: https://m040tbaraspi001.de040.corpintra.net${NC}"
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo ""
|
||
echo -e "${YELLOW}🚀 INSTALLATIONS-OPTIONEN:${NC}"
|
||
echo ""
|
||
echo -e "${GREEN}[1]${NC} ${BLUE}Abhängigkeiten installieren${NC}"
|
||
echo -e " → Python 3.11, Node.js, SSL-Zertifikate"
|
||
echo -e " → Flask-Anwendung deployen und konfigurieren"
|
||
echo -e " → System für manuelle Tests vorbereiten"
|
||
echo ""
|
||
echo -e "${GREEN}[2]${NC} ${BLUE}Produktionsbetrieb einrichten${NC}"
|
||
echo -e " → Vollständige Kiosk-Installation mit Autostart"
|
||
echo -e " → Remote-Zugang (RDP/SSH) konfigurieren"
|
||
echo -e " → Automatischer Browser-Start beim Boot"
|
||
echo -e " → Performance-Optimierungen für Raspberry Pi"
|
||
echo ""
|
||
echo -e "${GREEN}[3]${NC} ${YELLOW}System-Status anzeigen${NC}"
|
||
echo -e " → Aktuelle Konfiguration prüfen"
|
||
echo -e " → Services und Logs anzeigen"
|
||
echo ""
|
||
echo -e "${GREEN}[4]${NC} ${YELLOW}Credentials anpassen${NC}"
|
||
echo -e " → Passwörter und Zugangsdaten ändern"
|
||
echo ""
|
||
echo -e "${GREEN}[5]${NC} ${PURPLE}Desktop-Verknüpfung erstellen${NC}"
|
||
echo -e " → Mercedes-Icon auf Desktop für Kiosk-Start"
|
||
echo -e " → Manuelle Kiosk-Aktivierung per Klick"
|
||
echo ""
|
||
echo -e "${GREEN}[0]${NC} ${RED}Beenden${NC}"
|
||
echo ""
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo -n "Ihre Auswahl [0-5]: "
|
||
}
|
||
|
||
handle_menu_selection() {
|
||
local choice=$1
|
||
|
||
case $choice in
|
||
1)
|
||
log "🔧 Benutzer wählte: Abhängigkeiten installieren"
|
||
install_dependencies_interactive
|
||
;;
|
||
2)
|
||
log "🚀 Benutzer wählte: Produktionsbetrieb einrichten"
|
||
install_production_interactive
|
||
;;
|
||
3)
|
||
log "📊 Benutzer wählte: System-Status anzeigen"
|
||
show_system_status
|
||
;;
|
||
4)
|
||
log "🔑 Benutzer wählte: Credentials anpassen"
|
||
interactive_credentials_setup
|
||
save_credentials_override
|
||
;;
|
||
5)
|
||
log "🖥️ Benutzer wählte: Desktop-Verknüpfung erstellen"
|
||
create_desktop_shortcut_interactive
|
||
;;
|
||
0)
|
||
log "👋 Benutzer beendet das Setup"
|
||
echo -e "\n${GREEN}Auf Wiedersehen! 👋${NC}"
|
||
exit 0
|
||
;;
|
||
*)
|
||
warning "❌ Ungültige Auswahl: $choice"
|
||
echo -e "\n${RED}Bitte wählen Sie eine Zahl zwischen 0 und 5.${NC}"
|
||
sleep 2
|
||
;;
|
||
esac
|
||
}
|
||
|
||
install_dependencies_interactive() {
|
||
clear
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo -e "${CYAN} ABHÄNGIGKEITEN INSTALLIEREN${NC}"
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo ""
|
||
echo -e "${YELLOW}📦 Was wird installiert:${NC}"
|
||
echo -e " • Python 3.11 und Flask-Abhängigkeiten"
|
||
echo -e " • Node.js und npm"
|
||
echo -e " • SSL-Zertifikate für HTTPS"
|
||
echo -e " • MYP-Anwendung nach /opt/myp"
|
||
echo -e " • Systemd-Services für automatischen Start"
|
||
echo ""
|
||
echo -n "Möchten Sie fortfahren? (j/N): "
|
||
read -r confirm
|
||
|
||
if [[ "$confirm" =~ ^[jJyY]$ ]]; then
|
||
log "✅ Benutzer bestätigte Abhängigkeiten-Installation"
|
||
install_dependencies_only_auto
|
||
echo ""
|
||
echo -e "${GREEN}✅ Abhängigkeiten erfolgreich installiert!${NC}"
|
||
echo -e "${BLUE}🌐 Anwendung verfügbar unter: $HTTP_URL${NC}"
|
||
echo ""
|
||
echo -n "Drücken Sie Enter um zum Hauptmenü zurückzukehren..."
|
||
read
|
||
else
|
||
log "❌ Benutzer brach Abhängigkeiten-Installation ab"
|
||
echo -e "${YELLOW}Installation abgebrochen.${NC}"
|
||
sleep 1
|
||
fi
|
||
}
|
||
|
||
install_production_interactive() {
|
||
clear
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo -e "${CYAN} PRODUKTIONSBETRIEB EINRICHTEN${NC}"
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo ""
|
||
echo -e "${YELLOW}🚀 Was wird konfiguriert:${NC}"
|
||
echo -e " • Vollständige Kiosk-Installation"
|
||
echo -e " • Automatischer Browser-Start beim Boot"
|
||
echo -e " • Remote-Zugang (RDP/SSH)"
|
||
echo -e " • Firewall und Sicherheitskonfiguration"
|
||
echo -e " • Performance-Optimierungen"
|
||
echo -e " • Hostname: m040tbaraspi001"
|
||
echo -e " • Intranet-Zugang: https://m040tbaraspi001.de040.corpintra.net"
|
||
echo ""
|
||
echo -e "${RED}⚠️ WARNUNG: System wird nach Installation automatisch neu gestartet!${NC}"
|
||
echo ""
|
||
echo -n "Möchten Sie den Produktionsbetrieb einrichten? (j/N): "
|
||
read -r confirm
|
||
|
||
if [[ "$confirm" =~ ^[jJyY]$ ]]; then
|
||
log "✅ Benutzer bestätigte Produktions-Installation"
|
||
install_full_production_system_auto
|
||
else
|
||
log "❌ Benutzer brach Produktions-Installation ab"
|
||
echo -e "${YELLOW}Installation abgebrochen.${NC}"
|
||
sleep 1
|
||
fi
|
||
}
|
||
|
||
show_system_status() {
|
||
clear
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo -e "${CYAN} SYSTEM-STATUS${NC}"
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo ""
|
||
|
||
# Grundlegende System-Informationen
|
||
echo -e "${YELLOW}🖥️ System-Informationen:${NC}"
|
||
echo -e " Hostname: $(hostname)"
|
||
echo -e " Betriebssystem: $(lsb_release -d 2>/dev/null | cut -f2 || echo 'Unbekannt')"
|
||
echo -e " Kernel: $(uname -r)"
|
||
echo -e " Architektur: $(uname -m)"
|
||
echo -e " RAM: $(free -h | awk '/^Mem:/ {print $2}')"
|
||
echo ""
|
||
|
||
# Anwendungs-Status
|
||
echo -e "${YELLOW}📦 Anwendungs-Status:${NC}"
|
||
if [ -d "$APP_DIR" ]; then
|
||
echo -e " ✅ Anwendung installiert: $APP_DIR"
|
||
if [ -f "$APP_DIR/app.py" ]; then
|
||
echo -e " ✅ Flask-App gefunden"
|
||
else
|
||
echo -e " ❌ Flask-App nicht gefunden"
|
||
fi
|
||
else
|
||
echo -e " ❌ Anwendung nicht installiert"
|
||
fi
|
||
echo ""
|
||
|
||
# Service-Status
|
||
echo -e "${YELLOW}⚙️ Service-Status:${NC}"
|
||
local services=("$HTTP_SERVICE_NAME" "$KIOSK_SERVICE_NAME" "ssh" "xrdp")
|
||
for service in "${services[@]}"; do
|
||
if systemctl is-active --quiet "$service" 2>/dev/null; then
|
||
echo -e " ✅ $service: Aktiv"
|
||
elif systemctl list-unit-files | grep -q "$service" 2>/dev/null; then
|
||
echo -e " ❌ $service: Inaktiv"
|
||
else
|
||
echo -e " ⚪ $service: Nicht installiert"
|
||
fi
|
||
done
|
||
echo ""
|
||
|
||
# Netzwerk-Status
|
||
echo -e "${YELLOW}🌐 Netzwerk-Status:${NC}"
|
||
local ip=$(ip route get 1 2>/dev/null | awk '{print $7}' | head -1)
|
||
if [ -n "$ip" ]; then
|
||
echo -e " IP-Adresse: $ip"
|
||
echo -e " Webapp-URL: http://$ip:5000"
|
||
echo -e " Intranet-URL: https://m040tbaraspi001.de040.corpintra.net"
|
||
else
|
||
echo -e " ❌ Keine Netzwerkverbindung"
|
||
fi
|
||
echo ""
|
||
|
||
# Log-Dateien
|
||
echo -e "${YELLOW}📄 Log-Dateien:${NC}"
|
||
if [ -f "$INSTALL_LOG" ]; then
|
||
echo -e " 📄 Installation: $INSTALL_LOG"
|
||
fi
|
||
if [ -f "$ERROR_LOG" ] && [ -s "$ERROR_LOG" ]; then
|
||
echo -e " 🚨 Fehler: $ERROR_LOG"
|
||
fi
|
||
echo ""
|
||
|
||
echo -n "Drücken Sie Enter um zum Hauptmenü zurückzukehren..."
|
||
read
|
||
}
|
||
|
||
create_desktop_shortcut_interactive() {
|
||
clear
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo -e "${CYAN} DESKTOP-VERKNÜPFUNG ERSTELLEN${NC}"
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo ""
|
||
echo -e "${YELLOW}🖥️ Was wird erstellt:${NC}"
|
||
echo -e " • Desktop-Icon mit Mercedes-Logo"
|
||
echo -e " • Kiosk-Start per Doppelklick"
|
||
echo -e " • Automatische Browser-Erkennung"
|
||
echo -e " • Intelligente URL-Ermittlung"
|
||
echo ""
|
||
echo -e "${PURPLE}📍 Verfügbare Desktop-Umgebungen:${NC}"
|
||
|
||
# Erkenne verfügbare Desktop-Umgebungen
|
||
local desktops_found=()
|
||
if [ -d "/home/$USER/Desktop" ]; then
|
||
desktops_found+=("Aktueller Benutzer: /home/$USER/Desktop")
|
||
fi
|
||
if [ -d "/home/kiosk/Desktop" ]; then
|
||
desktops_found+=("Kiosk-Benutzer: /home/kiosk/Desktop")
|
||
fi
|
||
if [ -d "/etc/skel/Desktop" ]; then
|
||
desktops_found+=("System-Standard: /etc/skel/Desktop")
|
||
fi
|
||
|
||
if [ ${#desktops_found[@]} -eq 0 ]; then
|
||
echo -e " ${RED}❌ Keine Desktop-Verzeichnisse gefunden${NC}"
|
||
echo -e " ${YELLOW}💡 Desktop-Environment möglicherweise nicht installiert${NC}"
|
||
echo ""
|
||
echo -n "Trotzdem fortfahren und Desktop-Verzeichnisse erstellen? (j/N): "
|
||
read -r create_desktop
|
||
if [[ ! "$create_desktop" =~ ^[jJyY]$ ]]; then
|
||
echo -e "${YELLOW}Abgebrochen.${NC}"
|
||
sleep 1
|
||
return
|
||
fi
|
||
else
|
||
for desktop in "${desktops_found[@]}"; do
|
||
echo -e " ✅ $desktop"
|
||
done
|
||
fi
|
||
|
||
echo ""
|
||
echo -n "Desktop-Verknüpfung erstellen? (j/N): "
|
||
read -r confirm
|
||
|
||
if [[ "$confirm" =~ ^[jJyY]$ ]]; then
|
||
log "✅ Benutzer bestätigte Desktop-Verknüpfung-Erstellung"
|
||
create_desktop_shortcut
|
||
echo ""
|
||
echo -e "${GREEN}✅ Desktop-Verknüpfung erfolgreich erstellt!${NC}"
|
||
echo -e "${BLUE}🖱️ Doppelklick auf das Mercedes-Icon zum Starten${NC}"
|
||
echo ""
|
||
echo -n "Drücken Sie Enter um zum Hauptmenü zurückzukehren..."
|
||
read
|
||
else
|
||
log "❌ Benutzer brach Desktop-Verknüpfung-Erstellung ab"
|
||
echo -e "${YELLOW}Erstellung abgebrochen.${NC}"
|
||
sleep 1
|
||
fi
|
||
}
|
||
|
||
create_desktop_shortcut() {
|
||
log "=== ERSTELLE DESKTOP-VERKNÜPFUNG ==="
|
||
|
||
# Erstelle Kiosk-Start-Skript
|
||
create_kiosk_launcher_script
|
||
|
||
# Erstelle Desktop-Einträge für alle verfügbaren Benutzer
|
||
create_desktop_entries
|
||
|
||
# Setze korrekte Berechtigungen
|
||
fix_desktop_permissions
|
||
|
||
log "✅ Desktop-Verknüpfung erfolgreich erstellt"
|
||
}
|
||
|
||
create_kiosk_launcher_script() {
|
||
log "=== ERSTELLE KIOSK-LAUNCHER-SKRIPT ==="
|
||
|
||
mkdir -p "$APP_DIR/scripts"
|
||
|
||
cat > "$APP_DIR/scripts/launch_kiosk.sh" << 'EOF'
|
||
#!/bin/bash
|
||
# MYP Kiosk-Modus Launcher
|
||
# Startet die MYP-Anwendung im Kiosk-Modus
|
||
|
||
# Logging-Setup
|
||
LOG_FILE="/var/log/myp-desktop-launcher.log"
|
||
exec 1> >(tee -a "$LOG_FILE")
|
||
exec 2>&1
|
||
|
||
echo "=== MYP Kiosk Desktop-Start $(date) ==="
|
||
|
||
# Prüfe ob bereits ein Kiosk-Prozess läuft
|
||
if pgrep -f "chromium.*kiosk.*localhost:5000" >/dev/null 2>&1; then
|
||
echo "⚠️ Kiosk-Modus bereits aktiv - bringe Fenster in den Vordergrund"
|
||
# Versuche existierendes Fenster zu aktivieren
|
||
if command -v wmctrl >/dev/null 2>&1; then
|
||
wmctrl -a "MYP Druckerverwaltung" 2>/dev/null || true
|
||
fi
|
||
exit 0
|
||
fi
|
||
|
||
# Ermittle optimale URL
|
||
if [ -x /opt/myp/scripts/get_kiosk_url.sh ]; then
|
||
TARGET_URL=$(/opt/myp/scripts/get_kiosk_url.sh)
|
||
else
|
||
TARGET_URL="http://localhost:5000"
|
||
fi
|
||
|
||
echo "🔗 Verwende URL: $TARGET_URL"
|
||
|
||
# Prüfe Backend-Verfügbarkeit
|
||
echo "🔍 Prüfe Backend-Verfügbarkeit..."
|
||
for i in {1..30}; do
|
||
if curl -s --connect-timeout 3 --max-time 5 "$TARGET_URL" >/dev/null 2>&1; then
|
||
echo "✅ Backend erreichbar"
|
||
break
|
||
fi
|
||
echo "⏳ Warte auf Backend... ($i/30)"
|
||
sleep 2
|
||
done
|
||
|
||
# Browser-Auswahl
|
||
BROWSER=""
|
||
if command -v chromium >/dev/null 2>&1; then
|
||
BROWSER="chromium"
|
||
elif command -v chromium-browser >/dev/null 2>&1; then
|
||
BROWSER="chromium-browser"
|
||
elif command -v google-chrome >/dev/null 2>&1; then
|
||
BROWSER="google-chrome"
|
||
elif command -v firefox-esr >/dev/null 2>&1; then
|
||
BROWSER="firefox-esr"
|
||
elif command -v firefox >/dev/null 2>&1; then
|
||
BROWSER="firefox"
|
||
else
|
||
echo "❌ Kein unterstützter Browser gefunden!"
|
||
zenity --error --text="Kein unterstützter Browser gefunden!\n\nBitte installieren Sie Chromium oder Firefox." --title="MYP Kiosk-Fehler" 2>/dev/null || \
|
||
notify-send "MYP Kiosk-Fehler" "Kein unterstützter Browser gefunden!" 2>/dev/null || \
|
||
echo "FEHLER: Kein Browser verfügbar"
|
||
exit 1
|
||
fi
|
||
|
||
echo "🌐 Verwende Browser: $BROWSER"
|
||
|
||
# Bildschirmauflösung ermitteln
|
||
if [ -n "$DISPLAY" ]; then
|
||
RESOLUTION=$(xrandr 2>/dev/null | grep -E '\*|\+' | head -1 | awk '{print $1}' || echo "1920x1080")
|
||
WIDTH=$(echo $RESOLUTION | cut -d'x' -f1)
|
||
HEIGHT=$(echo $RESOLUTION | cut -d'x' -f2)
|
||
echo "📺 Bildschirmauflösung: ${WIDTH}x${HEIGHT}"
|
||
else
|
||
WIDTH=1920
|
||
HEIGHT=1080
|
||
echo "📺 Verwende Standard-Auflösung: ${WIDTH}x${HEIGHT}"
|
||
fi
|
||
|
||
# Browser-spezifische Argumente
|
||
if [[ "$BROWSER" == "chromium"* ]] || [[ "$BROWSER" == "google-chrome"* ]]; then
|
||
BROWSER_ARGS=(
|
||
--kiosk
|
||
--no-sandbox
|
||
--disable-dev-shm-usage
|
||
--disable-gpu-sandbox
|
||
--disable-software-rasterizer
|
||
--disable-background-timer-throttling
|
||
--disable-backgrounding-occluded-windows
|
||
--disable-renderer-backgrounding
|
||
--disable-features=TranslateUI
|
||
--force-device-scale-factor=1.0
|
||
--window-size=$WIDTH,$HEIGHT
|
||
--window-position=0,0
|
||
--user-data-dir=/tmp/myp-kiosk-desktop
|
||
--disable-infobars
|
||
--disable-session-crashed-bubble
|
||
--disable-restore-session-state
|
||
--disable-extensions
|
||
--disable-plugins
|
||
--disable-popup-blocking
|
||
--disable-sync
|
||
--disable-translate
|
||
--noerrdialogs
|
||
--no-first-run
|
||
--no-default-browser-check
|
||
--autoplay-policy=no-user-gesture-required
|
||
--disable-background-mode
|
||
--disable-pinch
|
||
--hide-scrollbars
|
||
--ignore-certificate-errors
|
||
--ignore-ssl-errors
|
||
--disable-web-security
|
||
--allow-running-insecure-content
|
||
--app="$TARGET_URL"
|
||
)
|
||
else
|
||
# Firefox-Argumente
|
||
BROWSER_ARGS=(
|
||
--kiosk
|
||
--width=$WIDTH
|
||
--height=$HEIGHT
|
||
--no-remote
|
||
--new-instance
|
||
"$TARGET_URL"
|
||
)
|
||
fi
|
||
|
||
echo "🚀 Starte $BROWSER im Kiosk-Modus..."
|
||
|
||
# Browser starten
|
||
"$BROWSER" "${BROWSER_ARGS[@]}" &
|
||
BROWSER_PID=$!
|
||
|
||
echo "✅ Browser gestartet (PID: $BROWSER_PID)"
|
||
echo "🎯 Kiosk-Modus aktiv für URL: $TARGET_URL"
|
||
|
||
# Optional: Warte auf Browser-Beendigung
|
||
wait $BROWSER_PID
|
||
echo "🔚 Kiosk-Modus beendet"
|
||
EOF
|
||
|
||
chmod +x "$APP_DIR/scripts/launch_kiosk.sh"
|
||
|
||
log "✅ Kiosk-Launcher-Skript erstellt: $APP_DIR/scripts/launch_kiosk.sh"
|
||
}
|
||
|
||
create_desktop_entries() {
|
||
log "=== ERSTELLE DESKTOP-EINTRÄGE ==="
|
||
|
||
# Mercedes-Icon kopieren an zentrale Stelle
|
||
local icon_dir="/usr/share/pixmaps"
|
||
local icon_source="$CURRENT_DIR/static/mercedes.svg"
|
||
# Fallback-Pfade für das Mercedes-Icon
|
||
if [ ! -f "$icon_source" ]; then
|
||
icon_source="$APP_DIR/static/mercedes.svg"
|
||
fi
|
||
if [ ! -f "$icon_source" ]; then
|
||
icon_source="$(find "$CURRENT_DIR" -name "mercedes.svg" 2>/dev/null | head -1)"
|
||
fi
|
||
local icon_target="$icon_dir/myp-mercedes.svg"
|
||
|
||
if [ -f "$icon_source" ]; then
|
||
cp "$icon_source" "$icon_target" 2>/dev/null || {
|
||
# Fallback: Icon in App-Verzeichnis
|
||
mkdir -p "$APP_DIR/static"
|
||
cp "$icon_source" "$APP_DIR/static/mercedes.svg"
|
||
icon_target="$APP_DIR/static/mercedes.svg"
|
||
}
|
||
log "✅ Mercedes-Icon kopiert: $icon_target"
|
||
else
|
||
warning "⚠️ Mercedes-Icon nicht gefunden: $icon_source"
|
||
icon_target="applications-graphics" # Fallback-Icon
|
||
fi
|
||
|
||
# Desktop-Entry-Inhalt
|
||
local desktop_content="[Desktop Entry]
|
||
Version=1.0
|
||
Type=Application
|
||
Name=MYP Druckerverwaltung (Kiosk)
|
||
Comment=Starte MYP Druckerverwaltung im Kiosk-Modus
|
||
Exec=$APP_DIR/scripts/launch_kiosk.sh
|
||
Icon=$icon_target
|
||
Terminal=false
|
||
Categories=Office;Graphics;3DGraphics;Engineering;
|
||
StartupNotify=true
|
||
StartupWMClass=chromium-browser
|
||
Keywords=3D;Printing;Drucker;Kiosk;MYP;Mercedes;
|
||
MimeType=model/stl;model/obj;text/x.gcode;
|
||
Actions=OpenBrowser;OpenSettings;
|
||
|
||
[Desktop Action OpenBrowser]
|
||
Name=Im Browser öffnen
|
||
Exec=xdg-open http://localhost:5000
|
||
|
||
[Desktop Action OpenSettings]
|
||
Name=Einstellungen
|
||
Exec=$APP_DIR/scripts/launch_kiosk.sh --settings"
|
||
|
||
# Desktop-Einträge für verschiedene Benutzer erstellen
|
||
local desktop_dirs=(
|
||
"/home/$USER/Desktop"
|
||
"/home/kiosk/Desktop"
|
||
"/etc/skel/Desktop"
|
||
"/usr/share/applications" # System-weit verfügbar
|
||
)
|
||
|
||
for desktop_dir in "${desktop_dirs[@]}"; do
|
||
if [ "$desktop_dir" = "/usr/share/applications" ] || [ -d "$(dirname "$desktop_dir")" ]; then
|
||
mkdir -p "$desktop_dir" 2>/dev/null || continue
|
||
|
||
local desktop_file="$desktop_dir/myp-kiosk.desktop"
|
||
echo "$desktop_content" > "$desktop_file" 2>/dev/null && {
|
||
chmod +x "$desktop_file" 2>/dev/null || true
|
||
log "✅ Desktop-Eintrag erstellt: $desktop_file"
|
||
}
|
||
fi
|
||
done
|
||
|
||
# Spezielle Behandlung für aktuellen Benutzer-Desktop
|
||
if [ -n "$SUDO_USER" ] && [ "$SUDO_USER" != "root" ]; then
|
||
local user_desktop="/home/$SUDO_USER/Desktop"
|
||
mkdir -p "$user_desktop" 2>/dev/null || true
|
||
if [ -d "$user_desktop" ]; then
|
||
local user_desktop_file="$user_desktop/myp-kiosk.desktop"
|
||
echo "$desktop_content" > "$user_desktop_file" 2>/dev/null && {
|
||
chmod +x "$user_desktop_file" 2>/dev/null || true
|
||
chown "$SUDO_USER:$SUDO_USER" "$user_desktop_file" 2>/dev/null || true
|
||
log "✅ Benutzer-Desktop-Eintrag erstellt: $user_desktop_file"
|
||
}
|
||
fi
|
||
fi
|
||
}
|
||
|
||
fix_desktop_permissions() {
|
||
log "=== KORRIGIERE DESKTOP-BERECHTIGUNGEN ==="
|
||
|
||
# Desktop-Dateien für verschiedene Benutzer korrigieren
|
||
local users=("$USER" "kiosk")
|
||
if [ -n "$SUDO_USER" ] && [ "$SUDO_USER" != "root" ]; then
|
||
users+=("$SUDO_USER")
|
||
fi
|
||
|
||
for user in "${users[@]}"; do
|
||
if id "$user" >/dev/null 2>&1; then
|
||
local user_desktop="/home/$user/Desktop"
|
||
if [ -d "$user_desktop" ]; then
|
||
chown -R "$user:$user" "$user_desktop" 2>/dev/null || true
|
||
find "$user_desktop" -name "*.desktop" -exec chmod +x {} \; 2>/dev/null || true
|
||
log "✅ Berechtigungen korrigiert für: $user"
|
||
fi
|
||
fi
|
||
done
|
||
|
||
# System-weite Desktop-Datei
|
||
if [ -f "/usr/share/applications/myp-kiosk.desktop" ]; then
|
||
chmod 644 "/usr/share/applications/myp-kiosk.desktop" 2>/dev/null || true
|
||
log "✅ System-weite Desktop-Datei konfiguriert"
|
||
fi
|
||
|
||
# Update Desktop-Datenbank
|
||
if command -v update-desktop-database >/dev/null 2>&1; then
|
||
update-desktop-database /usr/share/applications 2>/dev/null || true
|
||
log "✅ Desktop-Datenbank aktualisiert"
|
||
fi
|
||
}
|
||
|
||
install_desktop_tools() {
|
||
log "=== INSTALLIERE DESKTOP-TOOLS ==="
|
||
|
||
# Tools für bessere Desktop-Integration installieren
|
||
local desktop_packages=(
|
||
"wmctrl" # Fenster-Management
|
||
"xdotool" # X11-Automatisierung
|
||
"zenity" # GUI-Dialoge
|
||
"notify-osd" # Desktop-Benachrichtigungen
|
||
"libnotify-bin" # notify-send Kommando
|
||
"unclutter" # Mauszeiger verstecken
|
||
)
|
||
|
||
progress "Installiere Desktop-Integration-Tools..."
|
||
|
||
for package in "${desktop_packages[@]}"; do
|
||
if ! dpkg -l | grep -q "^ii.*$package" 2>/dev/null; then
|
||
if apt-get install -y "$package" 2>/dev/null; then
|
||
log "✅ $package installiert"
|
||
else
|
||
warning "⚠️ $package konnte nicht installiert werden"
|
||
fi
|
||
else
|
||
log "✅ $package bereits installiert"
|
||
fi
|
||
done
|
||
|
||
log "✅ Desktop-Tools-Installation abgeschlossen"
|
||
}
|
||
|
||
# =========================== HAUPTPROGRAMM (INTERAKTIV) ===========================
|
||
main() {
|
||
# Stelle sicher, dass wir im richtigen Verzeichnis sind
|
||
cd "$CURRENT_DIR" 2>/dev/null || true
|
||
|
||
# Logging initialisieren
|
||
init_logging
|
||
|
||
log "=== MYP INTERAKTIVES SETUP GESTARTET ==="
|
||
log "Version: $APP_VERSION"
|
||
log "Arbeitsverzeichnis: $CURRENT_DIR"
|
||
|
||
# Grundlegende Validierung
|
||
check_root
|
||
|
||
# Credentials laden
|
||
load_dynamic_credentials
|
||
validate_credentials_comprehensive
|
||
|
||
# Automatische Modus-Erkennung nur für Parameter
|
||
detect_installation_mode "$@"
|
||
|
||
# Falls Kommandozeilen-Parameter gesetzt sind, direkt ausführen
|
||
if [ "$FORCE_PRODUCTION" = true ]; then
|
||
log "🚀 Starte PRODUKTIONS-INSTALLATION (Parameter)..."
|
||
install_full_production_system_auto
|
||
show_final_summary
|
||
log "✅ MYP SETUP ABGESCHLOSSEN"
|
||
return
|
||
elif [ "$FORCE_DEVELOPMENT" = true ]; then
|
||
log "🔧 Starte ENTWICKLUNGS-INSTALLATION (Parameter)..."
|
||
install_dependencies_only_auto
|
||
show_final_summary
|
||
log "✅ MYP SETUP ABGESCHLOSSEN"
|
||
return
|
||
fi
|
||
|
||
# Interaktives Menü
|
||
while true; do
|
||
show_main_menu
|
||
read -r choice
|
||
echo ""
|
||
handle_menu_selection "$choice"
|
||
echo ""
|
||
done
|
||
}
|
||
|
||
show_installation_banner() {
|
||
clear
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo -e "${CYAN} $APP_NAME - Automatisches Setup v$APP_VERSION${NC}"
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo ""
|
||
echo -e "${YELLOW}🤖 VOLLAUTOMATISCHE INSTALLATION${NC}"
|
||
echo ""
|
||
case "$AUTO_INSTALL_MODE" in
|
||
"production")
|
||
echo -e "${GREEN}📋 MODUS: PRODUKTIONS-INSTALLATION${NC}"
|
||
echo -e " ✅ Vollständige Kiosk-Installation"
|
||
echo -e " ✅ Remote-Zugang (RDP/SSH)"
|
||
echo -e " ✅ Automatischer Kiosk-Start beim Boot"
|
||
echo -e " ✅ Firewall und Sicherheit"
|
||
;;
|
||
"development")
|
||
echo -e "${BLUE}📋 MODUS: ENTWICKLUNGS-INSTALLATION${NC}"
|
||
echo -e " ✅ Python, Node.js, SSL-Zertifikate"
|
||
echo -e " ✅ Anwendung deployed und getestet"
|
||
echo -e " ✅ System bereit für manuelle Tests"
|
||
echo -e " ✅ Entwicklungsfreundliche Konfiguration"
|
||
;;
|
||
esac
|
||
echo ""
|
||
echo -e "${PURPLE}⏱️ Installation startet in 5 Sekunden...${NC}"
|
||
echo -e "${PURPLE} (Drücken Sie Ctrl+C zum Abbrechen)${NC}"
|
||
echo ""
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
|
||
# 5 Sekunden Countdown
|
||
for i in 5 4 3 2 1; do
|
||
echo -ne "\r${PURPLE}⏱️ Installation startet in $i Sekunden...${NC}"
|
||
sleep 1
|
||
done
|
||
echo -ne "\r${GREEN}🚀 Installation gestartet! ${NC}\n"
|
||
echo ""
|
||
}
|
||
|
||
install_dependencies_only_auto() {
|
||
log "=== AUTOMATISCHE ENTWICKLUNGS-INSTALLATION ==="
|
||
|
||
# Grundlegende System-Validierung
|
||
check_system_resources
|
||
check_debian_system
|
||
check_internet_connection
|
||
|
||
# System-Konfiguration
|
||
configure_hostname
|
||
update_system
|
||
configure_network_security
|
||
|
||
# Core-Abhängigkeiten installieren
|
||
install_python_dependencies
|
||
install_nodejs_npm
|
||
install_ssl_certificates
|
||
install_python_packages
|
||
|
||
# Anwendung deployen
|
||
deploy_application
|
||
install_npm_dependencies
|
||
|
||
# Desktop-Tools für bessere Benutzererfahrung installieren
|
||
install_desktop_tools
|
||
|
||
# Credentials deployen
|
||
deploy_credentials
|
||
|
||
# Berechtigungen für kiosk-User korrigieren
|
||
fix_project_permissions
|
||
create_permission_fix_script
|
||
|
||
# Services für manuelles Testen vorbereiten
|
||
install_systemd_services
|
||
enable_and_start_services
|
||
|
||
# Intelligente Kiosk-URL-Ermittlung erstellen
|
||
create_smart_kiosk_url_script
|
||
|
||
# Desktop-Verknüpfung für einfachen Zugang erstellen
|
||
if [ -n "$DISPLAY" ] || [ -d "/home/*/Desktop" ] 2>/dev/null; then
|
||
if create_desktop_shortcut 2>/dev/null; then
|
||
info "✅ Desktop-Verknüpfung mit Mercedes-Icon erstellt"
|
||
else
|
||
warning "⚠️ Desktop-Verknüpfung konnte nicht erstellt werden"
|
||
fi
|
||
else
|
||
info "ℹ️ Keine Desktop-Umgebung erkannt - Desktop-Verknüpfung übersprungen"
|
||
fi
|
||
|
||
# Performance-Optimierungen auch für manuelles Testen
|
||
optimize_webapp_performance
|
||
optimize_static_assets
|
||
|
||
# Umfassende System-Tests
|
||
progress "Starte umfassende System-Tests..."
|
||
if test_application; then
|
||
success "✅ Alle System-Tests erfolgreich!"
|
||
else
|
||
warning "⚠️ System-Tests mit Problemen - System möglicherweise eingeschränkt funktionsfähig"
|
||
fi
|
||
|
||
# Cleanup
|
||
cleanup_old_files
|
||
|
||
success "✅ Entwicklungs-Installation abgeschlossen!"
|
||
}
|
||
|
||
install_full_production_system_auto() {
|
||
log "=== AUTOMATISCHE PRODUKTIONS-INSTALLATION ==="
|
||
|
||
# Umfassende System-Validierung
|
||
check_system_resources
|
||
check_debian_system
|
||
check_internet_connection
|
||
|
||
# Dynamische Credentials laden
|
||
load_dynamic_credentials
|
||
|
||
# System-Grundkonfiguration
|
||
configure_hostname
|
||
|
||
# PHASE 1: VOLLSTÄNDIGE UMGEBUNGSBEREINIGUNG UND -VORBEREITUNG
|
||
log "🧹 PHASE 1: UMGEBUNGSBEREINIGUNG UND -VORBEREITUNG"
|
||
|
||
# Alle Desktop-Environments vollständig entfernen
|
||
complete_environment_cleanup
|
||
|
||
# System-Updates und Basis-Pakete
|
||
update_system
|
||
configure_network_security
|
||
|
||
# Python-Umgebung vollständig neu aufsetzen
|
||
setup_clean_python_environment
|
||
|
||
# PHASE 2: DESKTOP-ENVIRONMENT UND X11 INSTALLATION
|
||
log "🖥️ PHASE 2: DESKTOP-ENVIRONMENT UND X11 INSTALLATION"
|
||
|
||
# Minimales aber funktionales Desktop-Environment installieren
|
||
install_minimal_desktop_environment
|
||
configure_x11_for_raspberry_pi
|
||
|
||
# PHASE 3: ANWENDUNGS-INSTALLATION
|
||
log "📦 PHASE 3: ANWENDUNGS-INSTALLATION"
|
||
|
||
# Intelligente Abhängigkeiten-Installation
|
||
if [ ! -d "$APP_DIR" ] || [ ! -f "$APP_DIR/app.py" ]; then
|
||
warning "Anwendung noch nicht deployed - führe vollständige Installation durch..."
|
||
|
||
install_nodejs_npm
|
||
install_ssl_certificates
|
||
install_python_packages_with_break_system
|
||
deploy_application
|
||
install_npm_dependencies
|
||
|
||
# Desktop-Tools für bessere Benutzererfahrung installieren
|
||
install_desktop_tools
|
||
|
||
# Credentials deployen
|
||
deploy_credentials
|
||
|
||
# Berechtigungen für kiosk-User korrigieren
|
||
fix_project_permissions
|
||
create_permission_fix_script
|
||
else
|
||
info "Anwendung bereits deployed - aktualisiere Python-Pakete"
|
||
install_python_packages_with_break_system
|
||
deploy_credentials
|
||
fi
|
||
|
||
# PHASE 4: KIOSK-SYSTEM KONFIGURATION
|
||
log "🖥️ PHASE 4: KIOSK-SYSTEM KONFIGURATION"
|
||
|
||
# Remote-Zugang konfigurieren (robust)
|
||
install_remote_access
|
||
configure_firewall
|
||
|
||
# Kiosk-System konfigurieren
|
||
create_kiosk_user
|
||
configure_autologin_robust
|
||
configure_kiosk_autostart_robust
|
||
|
||
# PHASE 5: SERVICES UND OPTIMIERUNG
|
||
log "⚡ PHASE 5: SERVICES UND OPTIMIERUNG"
|
||
|
||
# Services installieren und aktivieren (robust)
|
||
install_systemd_services
|
||
enable_and_start_services
|
||
|
||
# Intelligente Kiosk-URL-Ermittlung erstellen
|
||
create_smart_kiosk_url_script
|
||
|
||
# Desktop-Verknüpfung für einfachen Zugang erstellen
|
||
if create_desktop_shortcut 2>/dev/null; then
|
||
info "✅ Desktop-Verknüpfung mit Mercedes-Icon erstellt"
|
||
else
|
||
warning "⚠️ Desktop-Verknüpfung konnte nicht erstellt werden"
|
||
fi
|
||
|
||
# Performance-Optimierungen für Raspberry Pi Webapp
|
||
optimize_webapp_performance
|
||
|
||
# Static Assets nur optimieren wenn App deployed wurde
|
||
if [ -d "$APP_DIR" ] && [ -d "$APP_DIR/static" ]; then
|
||
optimize_static_assets
|
||
else
|
||
info "⏭️ Static Asset Optimierung übersprungen - App noch nicht deployed"
|
||
fi
|
||
|
||
# PHASE 6: SYSTEM-TESTS UND VALIDIERUNG
|
||
log "🧪 PHASE 6: SYSTEM-TESTS UND VALIDIERUNG"
|
||
|
||
# Umfassende System-Tests
|
||
progress "Führe umfassende Produktions-System-Tests durch..."
|
||
local system_tests_passed=true
|
||
|
||
if test_application; then
|
||
success "✅ Anwendungs-Tests erfolgreich"
|
||
else
|
||
warning "⚠️ Anwendungs-Tests mit Problemen"
|
||
system_tests_passed=false
|
||
fi
|
||
|
||
# Cleanup
|
||
cleanup_old_files
|
||
|
||
success "✅ Produktions-Installation abgeschlossen!"
|
||
warning "🔄 AUTOMATISCHER NEUSTART in 10 Sekunden für vollständige Kiosk-Aktivierung!"
|
||
|
||
# FINALE PHASE: AUTOMATISCHER NEUSTART
|
||
log "🔄 FINALE PHASE: AUTOMATISCHER NEUSTART"
|
||
|
||
# Zusammenfassung der Installation
|
||
log ""
|
||
log "📋 INSTALLATIONS-ZUSAMMENFASSUNG:"
|
||
log " ✅ Vollständige Umgebungsbereinigung durchgeführt"
|
||
log " ✅ Python 3.11 mit --break-system-packages installiert"
|
||
log " ✅ Minimales Desktop-Environment konfiguriert"
|
||
log " ✅ Robuste Autologin-Konfiguration implementiert"
|
||
log " ✅ Kiosk-Autostart mit Watchdog aktiviert"
|
||
log " ✅ Alle Desktop-Environments deaktiviert"
|
||
log " ✅ Boot-Target auf multi-user gesetzt"
|
||
log ""
|
||
log "🎯 NACH DEM NEUSTART:"
|
||
log " → System startet automatisch ohne Desktop"
|
||
log " → Kiosk-User loggt sich automatisch ein (tty1)"
|
||
log " → X11-Server startet automatisch"
|
||
log " → Browser öffnet MYP-Anwendung im Kiosk-Modus"
|
||
log " → Vollautomatischer Betrieb ohne Benutzerinteraktion"
|
||
log ""
|
||
|
||
# Countdown für automatischen Reboot
|
||
progress "Starte automatischen Neustart in 10 Sekunden..."
|
||
for i in {10..1}; do
|
||
echo -ne "\r🔄 Neustart in $i Sekunden... (Ctrl+C zum Abbrechen)"
|
||
sleep 1
|
||
done
|
||
echo ""
|
||
|
||
log "🚀 STARTE NEUSTART FÜR KIOSK-AKTIVIERUNG..."
|
||
sync
|
||
|
||
# Automatischer Neustart
|
||
reboot
|
||
}
|
||
|
||
show_final_summary() {
|
||
echo ""
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo -e "${CYAN} INSTALLATION ERFOLGREICH ABGESCHLOSSEN!${NC}"
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
echo ""
|
||
|
||
case "$AUTO_INSTALL_MODE" in
|
||
"production")
|
||
echo -e "${GREEN}🎯 PRODUKTIONS-SYSTEM BEREIT${NC}"
|
||
echo ""
|
||
echo -e "${BLUE}📋 Was wurde installiert:${NC}"
|
||
echo -e " ✅ Vollständige Kiosk-Installation"
|
||
echo -e " ✅ Remote-Zugang (RDP: root:$MYP_MAIN_PASSWORD)"
|
||
echo -e " ✅ SSH-Zugang (user: $MYP_SSH_PASSWORD)"
|
||
echo -e " ✅ Automatischer Kiosk-Start beim Boot"
|
||
echo -e " ✅ Firewall und Sicherheitskonfiguration"
|
||
echo -e " ✅ Performance-Optimierungen"
|
||
echo -e " ✅ Desktop-Verknüpfung mit Mercedes-Icon"
|
||
echo ""
|
||
echo -e "${YELLOW}🚀 System-Status:${NC}"
|
||
echo -e " 🌐 Webapp: $HTTP_URL"
|
||
echo -e " 🖥️ Kiosk startet automatisch beim Boot"
|
||
echo -e " 🔒 Remote-Zugang konfiguriert"
|
||
echo ""
|
||
echo -e "${PURPLE}💡 Nächste Schritte:${NC}"
|
||
echo -e " 1. System neu starten für vollständige Kiosk-Aktivierung"
|
||
echo -e " 2. Remote-Zugang testen (RDP/SSH)"
|
||
echo -e " 3. Webapp über Browser testen"
|
||
;;
|
||
"development")
|
||
echo -e "${BLUE}🔧 ENTWICKLUNGS-SYSTEM BEREIT${NC}"
|
||
echo ""
|
||
echo -e "${BLUE}📋 Was wurde installiert:${NC}"
|
||
echo -e " ✅ Python 3 und alle Abhängigkeiten"
|
||
echo -e " ✅ Node.js und npm"
|
||
echo -e " ✅ SSL-Zertifikate"
|
||
echo -e " ✅ Anwendung deployed nach: $APP_DIR"
|
||
echo -e " ✅ Systemd-Services installiert"
|
||
echo -e " ✅ Performance-Optimierungen"
|
||
echo -e " ✅ Desktop-Verknüpfung mit Mercedes-Icon"
|
||
echo ""
|
||
echo -e "${YELLOW}🚀 System-Status:${NC}"
|
||
echo -e " 🌐 Webapp: $HTTP_URL"
|
||
echo -e " ⚙️ Services: sudo systemctl status $HTTP_SERVICE_NAME"
|
||
echo ""
|
||
echo -e "${PURPLE}💡 Nächste Schritte:${NC}"
|
||
echo -e " 1. Webapp testen: $HTTP_URL"
|
||
echo -e " 2. Kiosk-Modus testen: Doppelklick auf Mercedes-Icon"
|
||
echo -e " 3. Manuelle Tests durchführen"
|
||
echo -e " 4. Entwicklung starten: cd $APP_DIR"
|
||
echo -e " 5. Für Produktions-Kiosk: sudo $0 --production"
|
||
;;
|
||
esac
|
||
|
||
echo ""
|
||
echo -e "${BLUE}📁 Log-Dateien:${NC}"
|
||
echo -e " 📄 Vollständiges Log: $INSTALL_LOG"
|
||
[ $ERROR_COUNT -gt 0 ] && echo -e " 🚨 Fehler-Log: $ERROR_LOG"
|
||
[ $WARNING_COUNT -gt 0 ] && echo -e " ⚠️ Warnungs-Log: $WARNING_LOG"
|
||
echo -e " 🔍 Debug-Log: $DEBUG_LOG"
|
||
echo -e " 📊 Zusammenfassung: logs/install-summary.txt"
|
||
|
||
# Fehler-Zusammenfassung anzeigen
|
||
show_error_summary
|
||
|
||
echo ""
|
||
echo -e "${GREEN}✅ MYP Druckerverwaltung erfolgreich installiert!${NC}"
|
||
echo -e "${CYAN}=================================================================${NC}"
|
||
}
|
||
|
||
# =========================== INTELLIGENTE KIOSK-URL KONFIGURATION ===========================
|
||
get_kiosk_url() {
|
||
log "=== ERMITTLE OPTIMALE KIOSK-URL ==="
|
||
|
||
local kiosk_url="http://localhost:5000"
|
||
local intranet_url="https://m040tbaraspi001.de040.corpintra.net"
|
||
|
||
# Prüfe ob localhost erreichbar ist
|
||
if curl -s --connect-timeout 3 --max-time 5 "http://localhost:5000" >/dev/null 2>&1; then
|
||
log "✅ Localhost erreichbar - verwende lokale URL"
|
||
echo "$kiosk_url"
|
||
return
|
||
fi
|
||
|
||
# Prüfe ob Intranet erreichbar ist
|
||
if curl -s --connect-timeout 5 --max-time 10 "$intranet_url" >/dev/null 2>&1; then
|
||
log "✅ Intranet erreichbar - verwende Intranet-URL"
|
||
echo "$intranet_url"
|
||
return
|
||
fi
|
||
|
||
# Fallback: Versuche lokale IP-Adresse
|
||
local local_ip=$(ip route get 1 2>/dev/null | awk '{print $7}' | head -1)
|
||
if [ -n "$local_ip" ] && [ "$local_ip" != "127.0.0.1" ]; then
|
||
local ip_url="http://$local_ip:5000"
|
||
if curl -s --connect-timeout 3 --max-time 5 "$ip_url" >/dev/null 2>&1; then
|
||
log "✅ Lokale IP erreichbar - verwende IP-URL: $ip_url"
|
||
echo "$ip_url"
|
||
return
|
||
fi
|
||
fi
|
||
|
||
# Finaler Fallback: localhost
|
||
log "⚠️ Fallback auf localhost - Backend möglicherweise noch nicht gestartet"
|
||
echo "$kiosk_url"
|
||
}
|
||
|
||
create_smart_kiosk_url_script() {
|
||
log "=== ERSTELLE INTELLIGENTE KIOSK-URL ERMITTLUNG ==="
|
||
|
||
cat > "$APP_DIR/scripts/get_kiosk_url.sh" << 'EOF'
|
||
#!/bin/bash
|
||
# Intelligente Kiosk-URL-Ermittlung für MYP
|
||
# Priorisiert lokale Verbindung, fällt auf Intranet zurück
|
||
|
||
LOCALHOST_URL="http://localhost:5000"
|
||
INTRANET_URL="https://m040tbaraspi001.de040.corpintra.net"
|
||
|
||
# Funktion: URL testen
|
||
test_url() {
|
||
local url="$1"
|
||
local timeout="${2:-5}"
|
||
|
||
curl -s --connect-timeout "$timeout" --max-time "$timeout" "$url" >/dev/null 2>&1
|
||
return $?
|
||
}
|
||
|
||
# Priorisierte URL-Tests
|
||
echo "[$(date)] Ermittle optimale Kiosk-URL..." >> /var/log/kiosk-url.log
|
||
|
||
# 1. Priorität: Localhost (schnellste Option für Kiosk)
|
||
if test_url "$LOCALHOST_URL" 3; then
|
||
echo "[$(date)] Localhost verfügbar: $LOCALHOST_URL" >> /var/log/kiosk-url.log
|
||
echo "$LOCALHOST_URL"
|
||
exit 0
|
||
fi
|
||
|
||
# 2. Priorität: Intranet-URL (für Remote-Zugang)
|
||
if test_url "$INTRANET_URL" 8; then
|
||
echo "[$(date)] Intranet verfügbar: $INTRANET_URL" >> /var/log/kiosk-url.log
|
||
echo "$INTRANET_URL"
|
||
exit 0
|
||
fi
|
||
|
||
# 3. Priorität: Lokale IP-Adresse
|
||
LOCAL_IP=$(ip route get 1 2>/dev/null | awk '{print $7}' | head -1)
|
||
if [ -n "$LOCAL_IP" ] && [ "$LOCAL_IP" != "127.0.0.1" ]; then
|
||
IP_URL="http://$LOCAL_IP:5000"
|
||
if test_url "$IP_URL" 5; then
|
||
echo "[$(date)] Lokale IP verfügbar: $IP_URL" >> /var/log/kiosk-url.log
|
||
echo "$IP_URL"
|
||
exit 0
|
||
fi
|
||
fi
|
||
|
||
# 4. Fallback: Hostname-URL
|
||
HOSTNAME_URL="http://$(hostname):5000"
|
||
if test_url "$HOSTNAME_URL" 5; then
|
||
echo "[$(date)] Hostname verfügbar: $HOSTNAME_URL" >> /var/log/kiosk-url.log
|
||
echo "$HOSTNAME_URL"
|
||
exit 0
|
||
fi
|
||
|
||
# Finaler Fallback: Localhost (auch wenn nicht erreichbar)
|
||
echo "[$(date)] Fallback auf Localhost: $LOCALHOST_URL" >> /var/log/kiosk-url.log
|
||
echo "$LOCALHOST_URL"
|
||
EOF
|
||
|
||
chmod +x "$APP_DIR/scripts/get_kiosk_url.sh"
|
||
|
||
log "✅ Intelligente Kiosk-URL-Ermittlung erstellt: $APP_DIR/scripts/get_kiosk_url.sh"
|
||
}
|
||
|
||
# =========================== KIOSK-KONFIGURATION MIT INTELLIGENTER URL ===========================
|
||
|
||
# Skript starten mit automatischer Modus-Erkennung
|
||
main "$@" |