Files
Projektarbeit-MYP/backend/setup.sh

6488 lines
224 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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
success "✅ Dynamische Credentials geladen"
}
# 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"
}
create_clean_requirements() {
log "=== ERSTELLE BEREINIGTE REQUIREMENTS.TXT ==="
local original_req="$CURRENT_DIR/requirements.txt"
local clean_req="$CURRENT_DIR/requirements_clean.txt"
# Problematische Pakete, die übersprungen werden sollen
local problematic_packages=(
"Send2Trash"
"pywin32"
"wmi"
"RPi.GPIO"
"python-magic-bin"
)
progress "Erstelle bereinigte requirements.txt..."
# Erstelle neue requirements.txt ohne problematische Pakete
> "$clean_req" # Datei leeren
while IFS= read -r line || [ -n "$line" ]; do
local skip_line=false
local package_name=$(echo "$line" | sed 's/[<>=!].*//' | xargs)
# Überspringe leere Zeilen und Kommentare
if [[ -z "${line// }" ]] || [[ "$line" =~ ^[[:space:]]*# ]]; then
echo "$line" >> "$clean_req"
continue
fi
# Prüfe ob Paket problematisch ist
for problematic in "${problematic_packages[@]}"; do
if [[ "$package_name" == "$problematic" ]]; then
echo "# ÜBERSPRUNGEN (problematisch): $line" >> "$clean_req"
log "⚠️ Überspringe problematisches Paket: $package_name"
skip_line=true
break
fi
done
# Spezielle Behandlung für plattformspezifische Pakete
if [[ "$line" =~ "sys_platform" ]]; then
# Prüfe Plattform-Kompatibilität
if [[ "$line" =~ "win32" ]] && [[ "$(uname -s)" != "CYGWIN"* ]] && [[ "$(uname -s)" != "MINGW"* ]]; then
echo "# ÜBERSPRUNGEN (Windows): $line" >> "$clean_req"
log " Überspringe Windows-spezifisches Paket: $package_name"
skip_line=true
elif [[ "$line" =~ "linux" ]] && [[ "$(uname -s)" != "Linux" ]]; then
echo "# ÜBERSPRUNGEN (Linux): $line" >> "$clean_req"
log " Überspringe Linux-spezifisches Paket: $package_name"
skip_line=true
fi
fi
# Füge Zeile hinzu wenn nicht übersprungen
if [ "$skip_line" = false ]; then
echo "$line" >> "$clean_req"
fi
done < "$original_req"
log "✅ Bereinigte requirements.txt erstellt: $clean_req"
# Zeige Statistiken
local original_count=$(grep -v -E '^[[:space:]]*#|^[[:space:]]*$' "$original_req" | wc -l)
local clean_count=$(grep -v -E '^[[:space:]]*#|^[[:space:]]*$' "$clean_req" | wc -l)
log "📊 Pakete: $original_count$clean_count ($(($original_count - $clean_count)) übersprungen)"
}
install_essential_packages_fallback() {
log "=== INSTALLIERE ESSENTIELLE PAKETE (FALLBACK) ==="
# Minimale Liste essentieller Pakete für MYP
local essential_packages=(
"Flask>=2.0.0"
"Werkzeug>=2.0.0"
"Jinja2>=3.0.0"
"requests>=2.25.0"
"SQLAlchemy>=1.4.0"
"Flask-Login>=0.6.0"
"Flask-WTF>=1.0.0"
"WTForms>=3.0.0"
"cryptography>=3.4.0"
"bcrypt>=3.2.0"
"psutil>=5.8.0"
"python-dateutil>=2.8.0"
"click>=8.0.0"
"colorlog>=6.6.0"
"watchdog>=2.1.0"
"schedule>=1.1.0"
"Pillow>=8.3.0"
)
progress "Installiere essentielle Pakete einzeln..."
local install_count=0
local total_count=${#essential_packages[@]}
for package in "${essential_packages[@]}"; do
local package_name=$(echo "$package" | sed 's/[<>=!].*//')
progress "Installiere $package_name... ($((++install_count))/$total_count)"
# Mehrere Installationsstrategien
if python3 -m pip install "$package" --break-system-packages --no-cache-dir >/dev/null 2>&1; then
log "$package_name erfolgreich installiert"
elif python3 -m pip install "$package_name" --break-system-packages --no-cache-dir >/dev/null 2>&1; then
log "$package_name erfolgreich installiert (ohne Version)"
elif python3 -m pip install "$package" --user --no-cache-dir >/dev/null 2>&1; then
log "$package_name erfolgreich installiert (user)"
else
warning "⚠️ $package_name Installation fehlgeschlagen"
fi
done
log "✅ Essentieller Pakete Installation abgeschlossen"
}
install_python_packages() {
log "=== ROBUSTE PYTHON-PAKETE INSTALLATION ==="
progress "Installiere Python-Pakete..."
if [ ! -f "$CURRENT_DIR/requirements.txt" ]; then
error "requirements.txt nicht gefunden: $CURRENT_DIR/requirements.txt"
install_essential_packages_fallback
return
fi
# Kopiere requirements.txt
cp "$CURRENT_DIR/requirements.txt" "$APP_DIR/" 2>/dev/null || true
# Erstelle bereinigte requirements.txt
create_clean_requirements
# Installiere bereinigte Pakete
progress "Installiere bereinigte requirements.txt..."
local install_success=false
# Strategie 1: Bereinigte requirements.txt mit --break-system-packages
if python3 -m pip install -r "$CURRENT_DIR/requirements_clean.txt" --break-system-packages --no-cache-dir; then
install_success=true
success "✅ Bereinigte requirements.txt erfolgreich installiert"
else
warning "⚠️ Bereinigte requirements.txt Installation fehlgeschlagen"
# Strategie 2: Essentielle Pakete einzeln installieren
warning "Verwende Fallback: Essentielle Pakete einzeln installieren"
install_essential_packages_fallback
install_success=true
fi
# Aufräumen
rm -f "$CURRENT_DIR/requirements_clean.txt" 2>/dev/null || true
# Validiere essenzielle Module
progress "Validiere essenzielle Python-Module..."
local essential_modules=("flask" "requests" "werkzeug" "jinja2" "sqlalchemy")
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 - versuche nachinstallation..."
python3 -m pip install "$module" --break-system-packages --no-cache-dir >/dev/null 2>&1 || true
fi
done
# Finale Validierung
for module in "${essential_modules[@]}"; do
if python3 -c "import $module" 2>/dev/null; then
log "$module verfügbar"
else
warning "⚠️ $module fehlt"
validation_success=false
fi
done
if [ "$validation_success" = true ]; then
success "✅ Alle essentiellen Python-Module verfügbar"
else
warning "⚠️ Einige essenzielle Module fehlen - Fallback verwendet"
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|SQLAlchemy)" | 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
# Erstelle bereinigte requirements.txt für Installation
if [ ! -f "$CURRENT_DIR/requirements_clean.txt" ]; then
create_clean_requirements
fi
# Strategie 1: Mit --break-system-packages und bereinigter requirements.txt
if python3.11 -m pip install -r "$CURRENT_DIR/requirements_clean.txt" --break-system-packages --force-reinstall --no-cache-dir; then
install_success=true
success "✅ Bereinigte requirements.txt mit --break-system-packages erfolgreich installiert"
else
warning "⚠️ Strategie 1 fehlgeschlagen, versuche Alternative..."
# Strategie 2: Bereinigte Einzelinstallation
progress "Installiere bereinigte Pakete einzeln..."
# Erstelle bereinigte requirements.txt falls nicht vorhanden
if [ ! -f "$CURRENT_DIR/requirements_clean.txt" ]; then
create_clean_requirements
fi
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
local package_name=$(echo "$package" | sed 's/[<>=!].*//')
progress "Installiere: $package_name"
if python3.11 -m pip install "$package" --break-system-packages --no-cache-dir; then
debug "$package_name erfolgreich installiert"
else
warning "⚠️ $package_name Installation fehlgeschlagen"
fi
fi
done < "$CURRENT_DIR/requirements_clean.txt"
# Aufräumen
rm -f "$CURRENT_DIR/requirements_clean.txt" 2>/dev/null || true
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 "$@"