#!/bin/bash # =================================================================== # MYP Druckerverwaltung - VOLLSTÄNDIGES SETUP-SKRIPT # Optimiert für Raspberry Pi OS (Debian-basiert) # Version: 5.0.0 - Komplett überarbeitet und getestet # =================================================================== set -euo pipefail # =========================== GLOBALE KONFIGURATION =========================== readonly APP_NAME="MYP Druckerverwaltung" readonly APP_VERSION="5.0.0" readonly APP_DIR="/opt/myp" readonly HTTPS_SERVICE_NAME="myp-https" readonly KIOSK_SERVICE_NAME="myp-kiosk" readonly KIOSK_USER="kiosk" readonly CURRENT_DIR="$(pwd)" readonly INSTALL_LOG="${CURRENT_DIR}/logs/myp-install.log" readonly ERROR_LOG="${CURRENT_DIR}/logs/myp-install-errors.log" readonly HTTPS_PORT="443" # 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' # =========================== LOGGING-FUNKTIONEN =========================== init_logging() { mkdir -p "${CURRENT_DIR}/logs" 2>/dev/null || true echo "MYP Installation Log - $(date '+%Y-%m-%d %H:%M:%S')" > "$INSTALL_LOG" echo "MYP Installation Errors - $(date '+%Y-%m-%d %H:%M:%S')" > "$ERROR_LOG" } log() { local message="[$(date '+%Y-%m-%d %H:%M:%S')] $1" echo -e "${GREEN}${message}${NC}" | tee -a "$INSTALL_LOG" } error() { local message="[ERROR] $1" echo -e "${RED}${message}${NC}" | tee -a "$INSTALL_LOG" | tee -a "$ERROR_LOG" exit 1 } warning() { local message="[WARNING] $1" echo -e "${YELLOW}${message}${NC}" | tee -a "$INSTALL_LOG" } info() { echo -e "${BLUE}[INFO] $1${NC}" | tee -a "$INSTALL_LOG" } progress() { echo -e "${PURPLE}[PROGRESS] $1${NC}" | tee -a "$INSTALL_LOG" } success() { echo -e "${CYAN}[SUCCESS] $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 log "✅ Root-Berechtigung bestätigt" } check_debian_system() { if [ ! -f /etc/debian_version ]; then error "Dieses Skript ist nur für Debian/Raspberry Pi OS gedacht!" fi log "✅ Debian-basiertes System erkannt" } check_required_files() { log "=== PRÜFE ERFORDERLICHE DATEIEN ===" local required_files=( "app.py" "models.py" "requirements.txt" ) for file in "${required_files[@]}"; do if [ ! -f "${CURRENT_DIR}/${file}" ]; then error "Erforderliche Datei nicht gefunden: ${file}" fi success "✅ ${file} gefunden" done } # =========================== SYSTEM-UPDATE =========================== update_system() { log "=== SYSTEM UPDATE ===" progress "Aktualisiere Paketlisten..." apt-get update || error "Fehler beim Update der Paketlisten" progress "Aktualisiere System-Pakete..." DEBIAN_FRONTEND=noninteractive apt-get upgrade -y || warning "Einige Pakete konnten nicht aktualisiert werden" success "✅ System aktualisiert" } # =========================== ABHÄNGIGKEITEN INSTALLATION =========================== install_base_dependencies() { log "=== INSTALLIERE BASIS-ABHÄNGIGKEITEN ===" local packages=( # Python und Entwicklung "python3" "python3-pip" "python3-venv" "python3-dev" "build-essential" # System-Tools "git" "curl" "wget" "nano" "htop" "net-tools" # Datenbank "sqlite3" # SSL/Sicherheit "openssl" "ca-certificates" # Kiosk-Modus "chromium-browser" "xserver-xorg" "xinit" "x11-xserver-utils" "unclutter" # Remote-Zugang "openssh-server" "xrdp" # Firewall "firewalld" ) progress "Installiere Pakete..." for package in "${packages[@]}"; do progress "Installiere ${package}..." DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends "$package" || warning "Fehler bei Installation von ${package}" done success "✅ Basis-Abhängigkeiten installiert" } # =========================== PYTHON-UMGEBUNG =========================== setup_python_environment() { log "=== PYTHON-UMGEBUNG EINRICHTEN ===" # App-Verzeichnis erstellen progress "Erstelle App-Verzeichnis..." mkdir -p "$APP_DIR" # Dateien kopieren progress "Kopiere Anwendungsdateien..." cp -r "${CURRENT_DIR}"/* "$APP_DIR/" 2>/dev/null || true # Python-Abhängigkeiten installieren progress "Installiere Python-Abhängigkeiten..." cd "$APP_DIR" if [ -f "requirements.txt" ]; then pip3 install --no-cache-dir -r requirements.txt || error "Fehler beim Installieren der Python-Abhängigkeiten" else # Minimale Abhängigkeiten direkt installieren pip3 install --no-cache-dir \ Flask==2.3.3 \ Flask-Login==0.6.2 \ Flask-WTF==1.1.1 \ SQLAlchemy==2.0.21 \ Werkzeug==2.3.7 \ python-dotenv==1.0.0 \ PyP100==0.1.2 \ || error "Fehler beim Installieren der Python-Pakete" fi cd "$CURRENT_DIR" success "✅ Python-Umgebung eingerichtet" } # =========================== NODE.JS INSTALLATION =========================== install_nodejs() { log "=== INSTALLIERE NODE.JS ===" if command -v node >/dev/null 2>&1; then log "Node.js bereits installiert: $(node --version)" return fi progress "Installiere Node.js..." curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - || error "Fehler beim Hinzufügen des Node.js Repository" apt-get install -y nodejs || error "Fehler bei der Node.js Installation" success "✅ Node.js installiert: $(node --version)" } # =========================== FRONTEND BUILD =========================== build_frontend() { log "=== BAUE FRONTEND ===" cd "$APP_DIR" # Prüfe ob package.json existiert if [ -f "package.json" ]; then progress "Installiere Frontend-Abhängigkeiten..." npm install || warning "Fehler bei npm install" progress "Baue Frontend-Assets..." npm run build || warning "Fehler beim Frontend-Build" else warning "package.json nicht gefunden - überspringe Frontend-Build" fi cd "$CURRENT_DIR" success "✅ Frontend-Build abgeschlossen" } # =========================== SSL-ZERTIFIKATE =========================== setup_ssl_certificates() { log "=== SSL-ZERTIFIKATE EINRICHTEN ===" local cert_dir="${APP_DIR}/instance/ssl" mkdir -p "$cert_dir" progress "Generiere selbstsigniertes SSL-Zertifikat..." openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout "${cert_dir}/key.pem" \ -out "${cert_dir}/cert.pem" \ -subj "/C=DE/ST=NRW/L=Local/O=MYP/CN=localhost" \ 2>/dev/null || error "Fehler beim Generieren des SSL-Zertifikats" chmod 600 "${cert_dir}/key.pem" chmod 644 "${cert_dir}/cert.pem" success "✅ SSL-Zertifikate erstellt" } # =========================== SYSTEMD SERVICES =========================== setup_systemd_services() { log "=== SYSTEMD SERVICES EINRICHTEN ===" # HTTPS Service progress "Erstelle HTTPS Service..." cat > "/etc/systemd/system/${HTTPS_SERVICE_NAME}.service" << EOF [Unit] Description=MYP HTTPS Server After=network.target [Service] Type=simple User=root WorkingDirectory=${APP_DIR} Environment="PYTHONUNBUFFERED=1" Environment="FLASK_ENV=production" ExecStart=/usr/bin/python3 ${APP_DIR}/app.py Restart=always RestartSec=10 [Install] WantedBy=multi-user.target EOF # Kiosk Service progress "Erstelle Kiosk Service..." cat > "/etc/systemd/system/${KIOSK_SERVICE_NAME}.service" << EOF [Unit] Description=MYP Kiosk Mode After=network.target ${HTTPS_SERVICE_NAME}.service [Service] Type=simple User=${KIOSK_USER} Environment="DISPLAY=:0" ExecStart=/usr/bin/xinit /usr/bin/chromium-browser --kiosk --no-sandbox --disable-dev-shm-usage --disable-gpu --disable-software-rasterizer --disable-features=TranslateUI --disable-infobars https://localhost:${HTTPS_PORT} -- :0 -nocursor -dpms Restart=always RestartSec=10 [Install] WantedBy=graphical.target EOF systemctl daemon-reload success "✅ Systemd Services erstellt" } # =========================== KIOSK-BENUTZER =========================== setup_kiosk_user() { log "=== KIOSK-BENUTZER EINRICHTEN ===" if ! id "$KIOSK_USER" &>/dev/null; then progress "Erstelle Kiosk-Benutzer..." useradd -m -s /bin/bash "$KIOSK_USER" usermod -aG video,audio "$KIOSK_USER" fi # Auto-Login konfigurieren mkdir -p /etc/systemd/system/getty@tty1.service.d/ cat > /etc/systemd/system/getty@tty1.service.d/autologin.conf << EOF [Service] ExecStart= ExecStart=-/sbin/agetty --autologin ${KIOSK_USER} --noclear %I \$TERM EOF success "✅ Kiosk-Benutzer konfiguriert" } # =========================== FIREWALL =========================== configure_firewall() { log "=== FIREWALL KONFIGURIEREN ===" systemctl start firewalld systemctl enable firewalld # HTTPS Port öffnen firewall-cmd --permanent --add-port=${HTTPS_PORT}/tcp # SSH erlauben firewall-cmd --permanent --add-service=ssh # RDP für Remote-Desktop firewall-cmd --permanent --add-port=3389/tcp firewall-cmd --reload success "✅ Firewall konfiguriert" } # =========================== DATENBANK INITIALISIERUNG =========================== initialize_database() { log "=== DATENBANK INITIALISIEREN ===" cd "$APP_DIR" progress "Initialisiere Datenbank..." python3 << EOF import sys sys.path.append('${APP_DIR}') from models import init_database, create_initial_admin try: init_database() create_initial_admin() print("✅ Datenbank erfolgreich initialisiert") except Exception as e: print(f"❌ Fehler bei Datenbank-Initialisierung: {e}") sys.exit(1) EOF cd "$CURRENT_DIR" } # =========================== SERVICES STARTEN =========================== start_services() { log "=== SERVICES STARTEN ===" # SSH aktivieren systemctl enable ssh systemctl start ssh # HTTPS Service systemctl enable "${HTTPS_SERVICE_NAME}" systemctl start "${HTTPS_SERVICE_NAME}" # Warte bis Service läuft sleep 5 # Kiosk Service (optional) # systemctl enable "${KIOSK_SERVICE_NAME}" # systemctl start "${KIOSK_SERVICE_NAME}" success "✅ Services gestartet" } # =========================== INSTALLATION TESTEN =========================== test_installation() { log "=== INSTALLATION TESTEN ===" # Teste HTTPS Service if systemctl is-active --quiet "${HTTPS_SERVICE_NAME}"; then success "✅ HTTPS Service läuft" else warning "⚠️ HTTPS Service läuft nicht" fi # Teste Webserver if curl -k -s -o /dev/null -w "%{http_code}" https://localhost:${HTTPS_PORT} | grep -q "200\|302"; then success "✅ Webserver antwortet" else warning "⚠️ Webserver antwortet nicht" fi # Zeige Zugriffs-URLs local ip_address=$(hostname -I | awk '{print $1}') log "" log "🌐 ZUGRIFFS-INFORMATIONEN:" log " Local: https://localhost:${HTTPS_PORT}" log " Netzwerk: https://${ip_address}:${HTTPS_PORT}" log " SSH: ssh pi@${ip_address}" log "" log "📝 STANDARD-ANMELDEDATEN:" log " Admin-Benutzer: admin" log " Admin-Passwort: admin123" log "" } # =========================== HAUPTMENÜ =========================== show_menu() { clear echo -e "${CYAN}╔══════════════════════════════════════════════════════════════╗${NC}" echo -e "${CYAN}║ MYP DRUCKERVERWALTUNG - SETUP v${APP_VERSION} ║${NC}" echo -e "${CYAN}╚══════════════════════════════════════════════════════════════╝${NC}" echo "" echo -e "${BLUE}Wählen Sie eine Option:${NC}" echo "" echo -e "${GREEN}1)${NC} Vollständige Installation (Produktion)" echo -e "${GREEN}2)${NC} Nur Abhängigkeiten installieren (Entwicklung)" echo -e "${GREEN}3)${NC} Beenden" echo "" echo -n "Ihre Auswahl [1-3]: " } # =========================== HAUPTPROGRAMM =========================== main() { init_logging while true; do show_menu read -r choice case $choice in 1) log "=== VOLLSTÄNDIGE INSTALLATION GESTARTET ===" check_root check_debian_system check_required_files update_system install_base_dependencies setup_python_environment install_nodejs build_frontend setup_ssl_certificates setup_systemd_services setup_kiosk_user configure_firewall initialize_database start_services test_installation log "✅ Installation erfolgreich abgeschlossen!" echo "" echo -n "Drücken Sie Enter um fortzufahren..." read -r ;; 2) log "=== NUR ABHÄNGIGKEITEN INSTALLATION ===" check_root check_debian_system update_system install_base_dependencies setup_python_environment install_nodejs log "✅ Abhängigkeiten installiert!" echo "" echo -n "Drücken Sie Enter um fortzufahren..." read -r ;; 3) echo -e "${CYAN}Setup beendet.${NC}" exit 0 ;; *) echo -e "${RED}Ungültige Auswahl!${NC}" sleep 2 ;; esac done } # Skript starten main "$@"