#!/bin/bash # =================================================================== # MYP Druckerverwaltung - Installer für Raspbian Kiosk-System # Entwickelt auf Windows, ausführbar auf Raspberry Pi / Debian # OHNE virtualenv - verwendet System-Python mit --break-system-packages # =================================================================== set -euo pipefail # =========================== KONFIGURATION =========================== APP_NAME="MYP Druckerverwaltung" APP_DIR="/opt/myp" SERVICE_NAME="myp-kiosk" CURRENT_DIR="$(pwd)" INSTALL_LOG="/var/log/myp-install.log" # Farben für Ausgabe RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' NC='\033[0m' # ========================== LOGGING-SYSTEM ========================== log() { echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}" | tee -a "$INSTALL_LOG" } error() { echo -e "${RED}[FEHLER] $1${NC}" | tee -a "$INSTALL_LOG" exit 1 } warning() { echo -e "${YELLOW}[WARNUNG] $1${NC}" | tee -a "$INSTALL_LOG" } info() { echo -e "${BLUE}[INFO] $1${NC}" | tee -a "$INSTALL_LOG" } progress() { echo -e "${PURPLE}[FORTSCHRITT] $1${NC}" | tee -a "$INSTALL_LOG" } # ========================== SYSTEM-CHECKS ========================== 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" } check_debian_system() { if [ ! -f /etc/debian_version ]; then error "Dieses Skript ist nur für Debian/Raspbian-Systeme geeignet!" fi log "✅ Debian/Raspbian-System erkannt" } # ========================== MERCEDES ZERTIFIKATE ========================== install_mercedes_certificates() { log "=== INSTALLIERE MERCEDES SSL-ZERTIFIKATE ===" progress "Aktualisiere CA-Zertifikate..." # CA-Zertifikate Paket installieren/aktualisieren apt-get install -y ca-certificates curl || error "CA-Zertifikate Installation fehlgeschlagen" # Standard CA-Bundle aktualisieren update-ca-certificates || warning "CA-Zertifikate Update teilweise fehlgeschlagen" # Mercedes Corporate Zertifikate installieren (falls vorhanden) if [ -d "$CURRENT_DIR/certs/mercedes" ] && [ "$(ls -A $CURRENT_DIR/certs/mercedes 2>/dev/null)" ]; then progress "Installiere Mercedes Corporate Zertifikate..." # Alle .crt und .pem Dateien kopieren find "$CURRENT_DIR/certs/mercedes" -type f \( -name "*.crt" -o -name "*.pem" -o -name "*.cer" \) -exec cp {} /usr/local/share/ca-certificates/ \; 2>/dev/null || true # Zertifikate aktualisieren update-ca-certificates || warning "Mercedes Zertifikate Update fehlgeschlagen" log "✅ Mercedes Zertifikate installiert" else info "Keine Mercedes Zertifikate gefunden - verwende Standard CA-Bundle" fi # Python SSL-Konfiguration optimieren progress "Konfiguriere Python SSL-Einstellungen..." # pip Konfiguration für SSL 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 = 60 retries = 3 [install] trusted-host = pypi.org pypi.python.org files.pythonhosted.org EOF # Python HTTPS-Konfiguration export SSL_CERT_FILE="/etc/ssl/certs/ca-certificates.crt" export REQUESTS_CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt" export CURL_CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt" # Pip auf neueste Version aktualisieren progress "Aktualisiere pip auf neueste Version..." python3 -m pip install --upgrade pip --break-system-packages --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org || warning "pip Update fehlgeschlagen" # SSL-Test durchführen progress "Teste SSL-Verbindung zu PyPI..." if python3 -c "import ssl, urllib.request; urllib.request.urlopen('https://pypi.org')" 2>/dev/null; then log "✅ SSL-Verbindung zu PyPI erfolgreich" else warning "⚠️ SSL-Verbindung zu PyPI problematisch - Installation wird dennoch versucht" fi log "✅ Mercedes SSL-Zertifikate und Python-Konfiguration abgeschlossen" } # ========================== ABHÄNGIGKEITEN INSTALLIEREN ========================== install_system_dependencies() { log "=== INSTALLIERE SYSTEM-ABHÄNGIGKEITEN ===" progress "Aktualisiere Paketlisten..." apt-get update -y || error "APT Update fehlgeschlagen" progress "Installiere Python 3 und grundlegende Pakete..." apt-get install -y \ python3 \ python3-pip \ python3-dev \ python3-setuptools \ build-essential \ libssl-dev \ libffi-dev \ git \ curl \ wget \ nano \ htop \ rsync \ unzip \ sudo \ systemd \ ca-certificates \ gnupg \ lsb-release \ sqlite3 \ || error "System-Pakete Installation fehlgeschlagen" # WICHTIG: Mercedes Zertifikate vor Python-Paketen installieren install_mercedes_certificates progress "Installiere Python-Abhängigkeiten mit Mercedes SSL-Konfiguration..." # SSL-freundliche pip-Installation mit Fallback-Optionen PIP_OPTS="--break-system-packages --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --timeout 60 --retries 3" # Core Flask Framework pip3 install $PIP_OPTS Flask==3.1.1 || pip3 install $PIP_OPTS Flask || error "Flask Installation fehlgeschlagen" pip3 install $PIP_OPTS Flask-Login==0.6.3 || pip3 install $PIP_OPTS Flask-Login || error "Flask-Login Installation fehlgeschlagen" pip3 install $PIP_OPTS Flask-WTF==1.2.1 || pip3 install $PIP_OPTS Flask-WTF || error "Flask-WTF Installation fehlgeschlagen" # Datenbank pip3 install $PIP_OPTS SQLAlchemy==2.0.36 || pip3 install $PIP_OPTS SQLAlchemy || error "SQLAlchemy Installation fehlgeschlagen" # Sicherheit pip3 install $PIP_OPTS bcrypt==4.2.1 || pip3 install $PIP_OPTS bcrypt || error "bcrypt Installation fehlgeschlagen" pip3 install $PIP_OPTS cryptography==44.0.0 || pip3 install $PIP_OPTS cryptography || error "cryptography Installation fehlgeschlagen" pip3 install $PIP_OPTS Werkzeug==3.1.3 || pip3 install $PIP_OPTS Werkzeug || error "Werkzeug Installation fehlgeschlagen" # Smart Plug Steuerung pip3 install $PIP_OPTS PyP100 || warning "PyP100 Installation fehlgeschlagen (optional)" # HTTP Requests pip3 install $PIP_OPTS requests==2.32.3 || pip3 install $PIP_OPTS requests || error "requests Installation fehlgeschlagen" # System Monitoring pip3 install $PIP_OPTS psutil==6.1.1 || pip3 install $PIP_OPTS psutil || error "psutil Installation fehlgeschlagen" # Redis (optional) pip3 install $PIP_OPTS redis==5.2.1 || warning "redis Installation fehlgeschlagen (optional)" # Weitere Core-Abhängigkeiten pip3 install $PIP_OPTS MarkupSafe==3.0.2 || pip3 install $PIP_OPTS MarkupSafe || error "MarkupSafe Installation fehlgeschlagen" # Produktions-Server pip3 install $PIP_OPTS gunicorn==23.0.0 || pip3 install $PIP_OPTS gunicorn || error "gunicorn Installation fehlgeschlagen" log "✅ Alle Abhängigkeiten erfolgreich installiert" } # ========================== PRODUKTIONS-KIOSK SETUP ========================== setup_production_kiosk() { log "=== RICHTE PRODUKTIONS-KIOSK-MODUS EIN ===" # Zuerst Abhängigkeiten installieren install_system_dependencies progress "Erstelle Zielverzeichnis /opt/myp..." mkdir -p "$APP_DIR" || error "Konnte Zielverzeichnis nicht erstellen" progress "Kopiere Projektdateien selektiv nach $APP_DIR..." # Liste der zu kopierenden Dateien/Ordner (ohne unnötige Inhalte) declare -a COPY_ITEMS=( "app.py" "models.py" "requirements.txt" "blueprints/" "config/" "database/" "docs/" "static/" "templates/" "uploads/" "utils/" "logs/" "certs/" ) # Sichere selektive Kopie for item in "${COPY_ITEMS[@]}"; do if [ -e "$CURRENT_DIR/$item" ]; then progress "Kopiere: $item" cp -r "$CURRENT_DIR/$item" "$APP_DIR/" || warning "Fehler beim Kopieren von $item" else info "Überspringe nicht vorhandenes Element: $item" fi done # Spezielle Dateien einzeln kopieren (falls vorhanden) for file in "package.json" "package-lock.json" "tailwind.config.js" "postcss.config.js"; do if [ -f "$CURRENT_DIR/$file" ]; then cp "$CURRENT_DIR/$file" "$APP_DIR/" || warning "Fehler beim Kopieren von $file" fi done # Stelle sicher, dass app.py ausführbar ist chmod +x "$APP_DIR/app.py" || error "Konnte app.py nicht ausführbar machen" # Erstelle notwendige Verzeichnisse falls sie nicht existieren mkdir -p "$APP_DIR/database/backups" mkdir -p "$APP_DIR/logs/app" mkdir -p "$APP_DIR/logs/auth" mkdir -p "$APP_DIR/logs/errors" mkdir -p "$APP_DIR/uploads/temp" # Berechtigungen setzen chown -R root:root "$APP_DIR" chmod -R 755 "$APP_DIR" chmod 750 "$APP_DIR/database" chmod 750 "$APP_DIR/logs" chmod 755 "$APP_DIR/uploads" progress "Erstelle Systemd-Service myp-kiosk.service..." cat > "/etc/systemd/system/${SERVICE_NAME}.service" << EOF [Unit] Description=MYP Druckerverwaltung Kiosk-Modus After=network.target network-online.target Wants=network-online.target Requires=network.target [Service] Type=simple User=root Group=root WorkingDirectory=$APP_DIR ExecStart=/usr/bin/python3 $APP_DIR/app.py --debug Restart=always RestartSec=5 StartLimitBurst=5 StartLimitInterval=60 # Umgebungsvariablen Environment=PYTHONUNBUFFERED=1 Environment=FLASK_ENV=production Environment=FLASK_HOST=0.0.0.0 Environment=FLASK_PORT=5000 Environment=PYTHONPATH=$APP_DIR Environment=LC_ALL=C.UTF-8 Environment=LANG=C.UTF-8 # Logging StandardOutput=journal StandardError=journal SyslogIdentifier=myp-kiosk # Security-Einstellungen NoNewPrivileges=true PrivateTmp=false ProtectSystem=strict ReadWritePaths=$APP_DIR [Install] WantedBy=multi-user.target EOF progress "Lade Systemd-Konfiguration neu..." systemctl daemon-reload || error "Systemd Reload fehlgeschlagen" progress "Aktiviere und starte $SERVICE_NAME Service..." systemctl enable "$SERVICE_NAME.service" || error "Service Enable fehlgeschlagen" systemctl start "$SERVICE_NAME.service" || error "Service Start fehlgeschlagen" # Service-Status prüfen sleep 5 if systemctl is-active --quiet "$SERVICE_NAME.service"; then log "✅ $SERVICE_NAME Service läuft erfolgreich" info "Service-Status: $(systemctl is-active $SERVICE_NAME.service)" info "Port 5000: Flask-App läuft im Debug-Modus" info "Projektverzeichnis: $APP_DIR" # Test der Anwendung progress "Teste Anwendungserreichbarkeit..." sleep 3 if curl -s http://localhost:5000 > /dev/null 2>&1; then log "✅ Anwendung ist unter http://localhost:5000 erreichbar" else warning "⚠️ Anwendung noch nicht erreichbar (möglicherweise noch beim Starten)" fi else error "$SERVICE_NAME Service konnte nicht gestartet werden - prüfen Sie die Logs: journalctl -u $SERVICE_NAME -f" fi log "✅ Produktions-Kiosk-Modus erfolgreich eingerichtet" log "🎯 Anwendung erreichbar unter: http://localhost:5000" log "📋 Service-Befehle:" log " • Status: sudo systemctl status $SERVICE_NAME" log " • Stoppen: sudo systemctl stop $SERVICE_NAME" log " • Starten: sudo systemctl start $SERVICE_NAME" log " • Neustarten: sudo systemctl restart $SERVICE_NAME" log " • Logs: sudo journalctl -u $SERVICE_NAME -f" log " • Service-Info: sudo journalctl -u $SERVICE_NAME --no-pager" } # ========================== HAUPTMENÜ ========================== show_menu() { clear echo -e "${BLUE}=================================================================${NC}" echo -e "${GREEN} $APP_NAME - Installer für Raspbian${NC}" echo -e "${BLUE}=================================================================${NC}" echo "" echo -e "${YELLOW}Aktuelles Verzeichnis:${NC} $CURRENT_DIR" echo -e "${YELLOW}Systemzeit:${NC} $(date)" echo -e "${YELLOW}Zielverzeichnis:${NC} $APP_DIR" echo "" echo -e "${PURPLE}Wählen Sie eine Option:${NC}" echo "" echo -e "${GREEN}1)${NC} System vorbereiten (Abhängigkeiten installieren)" echo -e " → Installiert Python 3, pip und alle benötigten Pakete" echo -e " → Verwendet: pip install --break-system-packages" echo -e " → Keine virtualenv, direktes System-Python" echo "" echo -e "${GREEN}2)${NC} Produktions-Kiosk-Modus installieren" echo -e " → Führt System-Vorbereitung durch" echo -e " → Verschiebt Dateien selektiv nach /opt/myp/" echo -e " → Erstellt systemd-Service: myp-kiosk.service" echo -e " → Startet Flask-App mit --debug auf Port 5000" echo -e " → Testet Anwendungserreichbarkeit" echo "" echo -e "${RED}0)${NC} Beenden" echo "" echo -e "${BLUE}=================================================================${NC}" echo -n "Ihre Wahl [0-2]: " } # ========================== MAIN LOGIC ========================== main() { # System-Checks check_root check_debian_system # Erstelle Log-Datei mkdir -p "$(dirname "$INSTALL_LOG")" touch "$INSTALL_LOG" log "=== MYP INSTALLER GESTARTET ===" log "Arbeitsverzeichnis: $CURRENT_DIR" log "Zielverzeichnis: $APP_DIR" log "Service-Name: $SERVICE_NAME" log "System: $(uname -a)" log "Debian-Version: $(cat /etc/debian_version 2>/dev/null || echo 'Unbekannt')" while true; do show_menu read -r choice case $choice in 1) clear log "=== OPTION 1: SYSTEM VORBEREITEN ===" install_system_dependencies echo "" echo -e "${GREEN}✅ System-Vorbereitung abgeschlossen!${NC}" echo -e "${YELLOW}Drücken Sie Enter, um fortzufahren...${NC}" read -r ;; 2) clear log "=== OPTION 2: PRODUKTIONS-KIOSK-MODUS ===" setup_production_kiosk echo "" echo -e "${GREEN}✅ Produktions-Kiosk-Modus erfolgreich eingerichtet!${NC}" echo -e "${BLUE}ℹ️ Die Anwendung startet automatisch bei jedem Systemstart.${NC}" echo -e "${YELLOW}Drücken Sie Enter, um fortzufahren...${NC}" read -r ;; 0) log "=== INSTALLER BEENDET ===" echo -e "${GREEN}Auf Wiedersehen!${NC}" echo -e "${BLUE}Log-Datei: $INSTALL_LOG${NC}" exit 0 ;; *) echo -e "${RED}Ungültige Eingabe. Bitte wählen Sie 0-2.${NC}" sleep 2 ;; esac done } # Script starten main "$@"