#!/bin/bash # =================================================================== # MYP Druckerverwaltung - Raspberry Pi Kiosk Installation # Vollautomatische Installation für echten Kiosk-Modus ohne Escape # Designed für Raspberry Pi OS, Ubuntu Server, Debian minimal # =================================================================== set -e # Bei Fehlern sofort beenden # =========================== KONFIGURATION =========================== KIOSK_USER="kiosk" APP_USER="myp" APP_DIR="/opt/myp-druckerverwaltung" BACKUP_DIR="/opt/myp-backups" CURRENT_DIR="" INSTALL_LOG="/var/log/myp-kiosk-install.log" # NEUE KONFIGURATION - Erweiterte Anforderungen ROOT_PASSWORD="744563017196A" HOSTNAME="raspberrypi" # Desktop Environment Pakete die entfernt werden sollen REMOVE_PACKAGES=( "gnome*" "kde*" "xfce*" "lxde*" "mate*" "cinnamon*" "lightdm" "gdm*" "xdm" "nodm" "firefox*" "thunderbird*" "libreoffice*" "wolfram-engine" "scratch*" "minecraft-pi" "sonic-pi" "idle*" "vlc" "smplayer" "totem" "rhythmbox" "gedit" "mousepad" "leafpad" "pluma" "file-roller" "xarchiver" "ark" "gimp" "inkscape" "blender" "chromium-browser" # Alte Version entfernen ) # Farben für Ausgabe RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' 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" } detect_system() { log "Erkenne System-Umgebung..." # Aktuelle Position ermitteln CURRENT_DIR="$(pwd)" log "Aktuelles Verzeichnis: $CURRENT_DIR" # Prüfe ob wir uns im richtigen Verzeichnis befinden if [ ! -f "$CURRENT_DIR/app.py" ]; then error "app.py nicht gefunden in $CURRENT_DIR - Bitte im MYP-Projektverzeichnis ausführen!" fi # System-Info sammeln info "System: $(uname -a)" info "Distribution: $(lsb_release -d 2>/dev/null || cat /etc/os-release | head -1 || echo 'Unbekannt')" info "Speicher: $(free -h | head -2 | tail -1)" info "Festplatte: $(df -h / | tail -1)" # Internetverbindung testen if ! ping -c 1 google.com &> /dev/null; then error "Keine Internetverbindung verfügbar!" fi # Minimal 2GB freier Speicher erforderlich available_kb=$(df / | awk 'NR==2 {print $4}') if [ "$available_kb" -lt 2000000 ]; then error "Nicht genügend Speicherplatz! Mindestens 2GB erforderlich." fi log "✅ System-Checks erfolgreich" } # ========================== SYSTEM-GRUNDKONFIGURATION ========================== setup_system_basics() { log "=== PHASE 0: SYSTEM-GRUNDKONFIGURATION ===" # Hostname setzen progress "Setze Hostname auf '$HOSTNAME'..." echo "$HOSTNAME" > /etc/hostname sed -i "s/127.0.1.1.*/127.0.1.1\t$HOSTNAME/" /etc/hosts hostnamectl set-hostname "$HOSTNAME" 2>/dev/null || true # Root-Passwort setzen progress "Setze Root-Passwort..." echo "root:$ROOT_PASSWORD" | chpasswd # Root-SSH-Zugang aktivieren (für Wartung) if [ -f "/etc/ssh/sshd_config" ]; then sed -i 's/#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config sed -i 's/#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config fi # Zeitzone setzen progress "Setze Zeitzone auf Europe/Berlin..." timedatectl set-timezone Europe/Berlin 2>/dev/null || true # Locales konfigurieren progress "Konfiguriere deutsche Locales..." if [ -f "/etc/locale.gen" ]; then sed -i 's/# de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/' /etc/locale.gen locale-gen || true update-locale LANG=de_DE.UTF-8 || true fi # Deutsche Tastaturlayout konfigurieren - VERBESSERTE VERSION progress "Konfiguriere deutsches Tastaturlayout..." # Sicherstellen dass keyboard-configuration installiert ist if ! dpkg -l | grep -q keyboard-configuration; then apt-get install -y keyboard-configuration console-setup console-data kbd fi # Debconf-Konfiguration für keyboard-configuration echo "keyboard-configuration keyboard-configuration/layout select German" | debconf-set-selections echo "keyboard-configuration keyboard-configuration/layoutcode string de" | debconf-set-selections echo "keyboard-configuration keyboard-configuration/model select Generic 105-key (Intl) PC" | debconf-set-selections echo "keyboard-configuration keyboard-configuration/modelcode string pc105" | debconf-set-selections echo "keyboard-configuration keyboard-configuration/variant select German" | debconf-set-selections echo "keyboard-configuration keyboard-configuration/variantcode string" | debconf-set-selections # Rekonfiguriere keyboard-configuration dpkg-reconfigure -f noninteractive keyboard-configuration # /etc/default/keyboard für Console und X11 cat > "/etc/default/keyboard" << EOF # Keyboard configuration file for Debian # Deutsches Tastaturlayout XKBMODEL="pc105" XKBLAYOUT="de" XKBVARIANT="" XKBOPTIONS="" BACKSPACE="guess" EOF # Console-Setup konfigurieren cat > "/etc/default/console-setup" << EOF # CONFIGURATION FILE FOR SETUPCON ACTIVE_CONSOLES="/dev/tty[1-6]" CHARMAP="UTF-8" CODESET="guess" FONTFACE="Fixed" FONTSIZE="8x16" VIDEOMODE= EOF # Console-Tastaturlayout sofort aktivieren if command -v loadkeys &> /dev/null; then loadkeys de 2>/dev/null || true info "Console-Tastaturlayout auf Deutsch gesetzt" fi # Setupcon ausführen für Console-Setup if command -v setupcon &> /dev/null; then setupcon --force --save 2>/dev/null || true info "Console-Setup konfiguriert" fi # X11-Tastaturlayout für Kiosk-Session vorbereiten mkdir -p /etc/X11/xorg.conf.d cat > "/etc/X11/xorg.conf.d/00-keyboard.conf" << EOF # Deutsches Tastaturlayout für X11 Section "InputClass" Identifier "system-keyboard" MatchIsKeyboard "on" Option "XkbLayout" "de" Option "XkbModel" "pc105" Option "XkbVariant" "" Option "XkbOptions" "" EndSection EOF # Systemd localectl für moderne Debian-Systeme (mit Fehlerbehandlung) if command -v localectl &> /dev/null; then # Prüfe ob localectl funktioniert if localectl status &> /dev/null; then localectl set-keymap de 2>/dev/null || warning "localectl set-keymap fehlgeschlagen" localectl set-x11-keymap de 2>/dev/null || warning "localectl set-x11-keymap fehlgeschlagen" info "Tastaturlayout via localectl auf Deutsch gesetzt" else warning "localectl nicht funktional - verwende alternative Methoden" # Alternative: Direkte Keymap-Datei setzen echo "KEYMAP=de" > /etc/vconsole.conf 2>/dev/null || true fi else warning "localectl nicht verfügbar - verwende legacy-Methoden" # Legacy-Methode für ältere Systeme echo "KEYMAP=de" > /etc/vconsole.conf 2>/dev/null || true fi # Keyboard-Services neu laden systemctl reload-or-restart keyboard-setup 2>/dev/null || true systemctl reload-or-restart console-setup 2>/dev/null || true # Keymap-Dateien manuell prüfen und erstellen falls nötig if [ ! -f "/usr/share/keymaps/i386/qwertz/de.kmap.gz" ] && [ ! -f "/usr/share/kbd/keymaps/i386/qwertz/de.map.gz" ]; then warning "Deutsche Keymap-Dateien fehlen - installiere kbd-Paket" apt-get install -y kbd console-data || true fi info "Deutsches Tastaturlayout global konfiguriert (Console + X11)" log "✅ System-Grundkonfiguration abgeschlossen" } # ========================== SYSTEM-UPDATE ========================== update_system() { log "=== PHASE 0.5: SYSTEM-UPDATE ===" progress "Aktualisiere Paketlisten..." apt-get update -y || error "APT Update fehlgeschlagen" progress "Upgrade bestehender Pakete..." apt-get upgrade -y || warning "APT Upgrade teilweise fehlgeschlagen" progress "Installiere essenzielle System-Tools..." apt-get install -y \ ca-certificates \ gnupg \ lsb-release \ software-properties-common \ apt-transport-https \ curl \ wget \ git \ unzip \ nano \ htop \ rsync \ sudo \ cron \ logrotate \ tree \ zip \ keyboard-configuration \ console-setup \ console-data \ kbd \ locales \ || error "Essenzielle Pakete Installation fehlgeschlagen" # Dist-upgrade für Kernel-Updates progress "Führe Distribution-Upgrade durch..." apt-get dist-upgrade -y || warning "Dist-upgrade teilweise fehlgeschlagen" log "✅ System-Update abgeschlossen" } # ========================== ZERTIFIKATE INSTALLIEREN ========================== install_certificates() { log "=== PHASE 0.8: ZERTIFIKATE-INSTALLATION ===" progress "Aktualisiere CA-Zertifikate..." apt-get install -y ca-certificates update-ca-certificates # Mozilla CA Bundle progress "Installiere erweiterte Zertifikate..." if ! wget -O /usr/local/share/ca-certificates/cacert.pem https://curl.se/ca/cacert.pem; then warning "Mozilla CA Bundle Download fehlgeschlagen" else update-ca-certificates fi # SSL-Zertifikate für Python requests if command -v python3 &> /dev/null; then python3 -m pip install --upgrade certifi --break-system-packages 2>/dev/null || true fi log "✅ Zertifikate installiert und aktualisiert" } # ========================== VERZEICHNISSTRUKTUR ERSTELLEN ========================== create_directory_structure() { log "=== PHASE 1.5: VERZEICHNISSTRUKTUR ERSTELLEN ===" progress "Erstelle MYP-Verzeichnisstruktur..." # Hauptverzeichnisse mkdir -p "$APP_DIR" mkdir -p "$BACKUP_DIR" # Upload-Ordner-Struktur progress "Erstelle Upload-Verzeichnisse..." UPLOAD_BASE="$APP_DIR/uploads" CURRENT_YEAR=$(date +%Y) CURRENT_MONTH=$(date +%m) # Upload-Kategorien mit Jahres-/Monats-Struktur for category in assets avatars backups guests jobs logs temp; do mkdir -p "$UPLOAD_BASE/$category/$CURRENT_YEAR/$CURRENT_MONTH" info "Erstellt: $UPLOAD_BASE/$category/$CURRENT_YEAR/$CURRENT_MONTH" done # Database-Verzeichnis mkdir -p "$APP_DIR/database/backups" # Log-Verzeichnisse progress "Erstelle Log-Verzeichnisse..." for log_cat in app auth errors jobs printers scheduler; do mkdir -p "$APP_DIR/logs/$log_cat" mkdir -p "/var/log/myp-$log_cat" done # Config-Verzeichnis mkdir -p "$APP_DIR/config" # Static Assets mkdir -p "$APP_DIR/static/css" mkdir -p "$APP_DIR/static/js" mkdir -p "$APP_DIR/static/icons" # Certificates mkdir -p "$APP_DIR/certs" log "✅ Verzeichnisstruktur erstellt" } # ========================== SYSTEM-BEREINIGUNG ========================== cleanup_system() { log "=== PHASE 1: SYSTEM-BEREINIGUNG ===" # APT-Cache aktualisieren progress "Aktualisiere Paketlisten..." apt-get update -y || warning "APT Update teilweise fehlgeschlagen" # Entferne unnötige Desktop-Umgebungen progress "Entferne Desktop-Umgebungen und unnötige Software..." for package in "${REMOVE_PACKAGES[@]}"; do if dpkg -l | grep -q "^ii.*$package"; then info "Entferne: $package" apt-get purge -y "$package" 2>/dev/null || true fi done # Aggressive Bereinigung apt-get autoremove -y --purge apt-get autoclean # Stoppe unnötige Services progress "Stoppe Desktop-Services..." for service in gdm lightdm xdm nodm plymouth; do systemctl stop "$service" 2>/dev/null || true systemctl disable "$service" 2>/dev/null || true done log "✅ System-Bereinigung abgeschlossen" } # ========================== PAKETE INSTALLIEREN ========================== install_packages() { log "=== PHASE 2: SYSTEM-PAKETE INSTALLATION ===" progress "Installiere Basis-Pakete..." apt-get install -y \ curl wget git unzip \ python3 python3-pip python3-venv python3-dev \ build-essential libssl-dev libffi-dev \ sqlite3 nginx supervisor \ xorg xinit openbox \ xserver-xorg-video-all \ x11-xserver-utils xdotool unclutter \ pulseaudio alsa-utils \ fonts-liberation fonts-dejavu \ ca-certificates apt-transport-https \ systemd-timesyncd \ ufw fail2ban \ htop nano \ || error "Basis-Pakete Installation fehlgeschlagen" # Node.js installieren - VERBESSERTE VERSION progress "Installiere Node.js mit mehreren Fallback-Methoden..." # Prüfe ob Node.js bereits verfügbar ist if command -v node &> /dev/null && command -v npm &> /dev/null; then info "Node.js bereits verfügbar: $(node --version)" info "NPM bereits verfügbar: $(npm --version)" else # Methode 1: NodeSource Repository (LTS) progress "Versuche NodeSource LTS Repository..." if curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && apt-get install -y nodejs; then log "✅ Node.js via NodeSource LTS installiert" else warning "NodeSource LTS fehlgeschlagen, versuche NodeSource 18.x..." # Methode 2: NodeSource 18.x (stabil) if curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && apt-get install -y nodejs; then log "✅ Node.js via NodeSource 18.x installiert" else warning "NodeSource fehlgeschlagen, versuche Standard-Repository..." # Methode 3: Standard Repository apt-get update && apt-get install -y nodejs npm || true # Methode 4: Snap als Fallback if ! command -v node &> /dev/null; then warning "Standard-Repository fehlgeschlagen, versuche Snap..." if command -v snap &> /dev/null || apt-get install -y snapd; then snap install node --classic || true fi fi # Methode 5: Manual Download als letzter Ausweg if ! command -v node &> /dev/null; then warning "Alle Repository-Methoden fehlgeschlagen, lade Node.js manuell herunter..." NODE_VERSION="18.17.0" ARCH=$(uname -m) case $ARCH in x86_64) NODE_ARCH="x64" ;; armv7l) NODE_ARCH="armv7l" ;; aarch64) NODE_ARCH="arm64" ;; *) NODE_ARCH="x64" ;; esac cd /tmp wget "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.xz" -O node.tar.xz || true if [ -f "node.tar.xz" ]; then tar -xf node.tar.xz cp -r "node-v${NODE_VERSION}-linux-${NODE_ARCH}"/* /usr/local/ log "✅ Node.js manuell installiert" fi fi fi fi # Finale Validierung if command -v node &> /dev/null && command -v npm &> /dev/null; then log "✅ Node.js erfolgreich installiert: $(node --version)" log "✅ NPM erfolgreich installiert: $(npm --version)" # NPM Global-Verzeichnis konfigurieren für bessere Berechtigungen mkdir -p /usr/local/lib/npm-global npm config set prefix '/usr/local/lib/npm-global' echo 'export PATH=/usr/local/lib/npm-global/bin:$PATH' >> /etc/profile export PATH=/usr/local/lib/npm-global/bin:$PATH else warning "⚠️ Node.js/NPM-Installation fehlgeschlagen - Node.js-Features werden übersprungen" # Erstelle Dummy-npm-Kommando um Skript-Fehler zu vermeiden cat > /usr/local/bin/npm << 'EOF' #!/bin/bash echo "NPM nicht verfügbar - Node.js-Installation fehlgeschlagen" echo "Node.js-Abhängigkeiten werden übersprungen" exit 0 EOF chmod +x /usr/local/bin/npm fi fi log "✅ System-Pakete installiert" } # ========================== CHROMIUM INSTALLATION ========================== install_chromium() { log "=== PHASE 3: CHROMIUM INSTALLATION ===" progress "Installiere Chromium Browser..." # Versuche verschiedene Installationsmethoden if apt-get install -y chromium 2>/dev/null; then CHROMIUM_BIN="/usr/bin/chromium" log "✅ Chromium via APT installiert" elif apt-get install -y chromium-browser 2>/dev/null; then CHROMIUM_BIN="/usr/bin/chromium-browser" log "✅ Chromium-Browser via APT installiert" else # Snap-Installation versuchen warning "APT-Installation fehlgeschlagen, versuche Snap..." if command -v snap &> /dev/null || (apt-get install -y snapd && systemctl enable --now snapd); then snap install chromium CHROMIUM_BIN="/snap/bin/chromium" log "✅ Chromium via Snap installiert" else # Flatpak als letzter Ausweg warning "Snap fehlgeschlagen, versuche Flatpak..." if apt-get install -y flatpak && flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo; then flatpak install -y flathub org.chromium.Chromium CHROMIUM_BIN="flatpak run org.chromium.Chromium" log "✅ Chromium via Flatpak installiert" else error "❌ Chromium konnte nicht installiert werden! Bitte manuell installieren." fi fi fi # Chromium-Binary validieren if [[ "$CHROMIUM_BIN" == "flatpak"* ]]; then # Flatpak-Spezialbehandlung log "Chromium via Flatpak verfügbar" elif [ ! -x "$CHROMIUM_BIN" ]; then error "Chromium-Binary nicht ausführbar: $CHROMIUM_BIN" fi log "✅ Chromium-Installation abgeschlossen: $CHROMIUM_BIN" } # ========================== BENUTZER ERSTELLEN ========================== create_users() { log "=== PHASE 4: BENUTZER-ERSTELLUNG ===" # App-Benutzer erstellen progress "Erstelle App-Benutzer: $APP_USER" if ! id "$APP_USER" &>/dev/null; then if ! useradd -m -s /bin/bash "$APP_USER" 2>/dev/null; then adduser --disabled-password --gecos "" "$APP_USER" || error "Kann App-Benutzer nicht erstellen" fi usermod -aG sudo "$APP_USER" 2>/dev/null || true fi # Kiosk-Benutzer erstellen progress "Erstelle Kiosk-Benutzer: $KIOSK_USER" if ! id "$KIOSK_USER" &>/dev/null; then if ! useradd -m -s /bin/bash "$KIOSK_USER" 2>/dev/null; then adduser --disabled-password --gecos "" "$KIOSK_USER" || error "Kann Kiosk-Benutzer nicht erstellen" fi # Kiosk-Benutzer zu Audio/Video-Gruppen hinzufügen usermod -aG audio,video,input "$KIOSK_USER" 2>/dev/null || true fi log "✅ Benutzer erstellt: $APP_USER, $KIOSK_USER" } # ========================== ANWENDUNG INSTALLIEREN ========================== install_application() { log "=== PHASE 5: ANWENDUNGS-INSTALLATION ===" # Anwendung kopieren progress "Kopiere Anwendung von $CURRENT_DIR nach $APP_DIR" rsync -av --exclude='.git' --exclude='__pycache__' --exclude='node_modules' "$CURRENT_DIR"/ "$APP_DIR/" chown -R "$APP_USER:$APP_USER" "$APP_DIR" # Wechsel ins Anwendungsverzeichnis cd "$APP_DIR" # DIREKTER PYTHON-PACKAGE INSTALL OHNE VENV - NEU! progress "Installiere Python-Dependencies DIREKT (ohne Virtual Environment)..." # Pip aktualisieren python3 -m pip install --upgrade pip --break-system-packages # Requirements installieren if [ -f "requirements.txt" ]; then info "Installiere aus requirements.txt..." python3 -m pip install -r requirements.txt --break-system-packages else # Basis-Pakete installieren info "Installiere Basis-Python-Pakete..." python3 -m pip install --break-system-packages \ flask \ flask-login \ flask-wtf \ flask-limiter \ sqlalchemy \ werkzeug \ requests \ gunicorn \ bcrypt \ cryptography \ PyP100 \ python-dotenv \ Pillow \ schedule fi # ENGINE-IMPORT-FEHLER BEHEBEN progress "Behebe Engine-Import-Problem..." # Prüfe und korrigiere models.py if [ -f "models.py" ]; then # Backup erstellen cp models.py models.py.backup # Sicherstellen dass engine richtig importiert wird if ! grep -q "from sqlalchemy import create_engine" models.py; then sed -i '1i from sqlalchemy import create_engine' models.py fi # engine Variable definieren falls fehlt if ! grep -q "^engine = " models.py; then echo "" >> models.py echo "# Engine für direkten Zugriff" >> models.py echo "try:" >> models.py echo " engine = create_optimized_engine()" >> models.py echo "except:" >> models.py echo " from sqlalchemy import create_engine" >> models.py echo " engine = create_engine('sqlite:///database.db')" >> models.py fi fi # app.py für engine-Kompatibilität erweitern if [ -f "app.py" ]; then # Backup erstellen cp app.py app.py.backup # Engine-Import sicherstellen if ! grep -q "from models import.*engine" app.py; then # Versuche engine zu importieren if grep -q "from models import" app.py; then sed -i '/from models import/s/$/,engine/' app.py 2>/dev/null || true else # Falls keine from models import Zeile existiert if grep -q "import models" app.py; then sed -i '/import models/a from models import engine' app.py fi fi fi # db-Variable für Kompatibilität if ! grep -q "^db = engine" app.py; then echo "" >> app.py echo "# DB-Engine für Kompatibilität" >> app.py echo "try:" >> app.py echo " from models import engine" >> app.py echo " db = engine" >> app.py echo "except ImportError:" >> app.py echo " from sqlalchemy import create_engine" >> app.py echo " db = create_engine('sqlite:///database.db')" >> app.py fi fi # Node.js Dependencies - VERBESSERTE VERSION if [ -f "package.json" ]; then progress "Installiere Node.js Dependencies..." # Prüfe ob npm verfügbar ist if command -v npm &> /dev/null && npm --version &> /dev/null; then info "NPM verfügbar: $(npm --version)" # Versuche npm install mit verschiedenen Methoden if sudo -u "$APP_USER" npm install; then log "✅ Node.js Dependencies installiert" # Versuche CSS-Build falls Tailwind vorhanden if [ -f "tailwind.config.js" ]; then info "Tailwind-Konfiguration gefunden, versuche CSS-Build..." if sudo -u "$APP_USER" npm run build:css; then log "✅ CSS erfolgreich gebaut" else warning "⚠️ CSS-Build fehlgeschlagen - wird übersprungen" # Fallback: Erstelle leere CSS-Datei mkdir -p "$APP_DIR/static/css" || true touch "$APP_DIR/static/css/tailwind.css" || true chown "$APP_USER:$APP_USER" "$APP_DIR/static/css/tailwind.css" 2>/dev/null || true fi fi else warning "⚠️ npm install fehlgeschlagen, versuche Alternativen..." # Alternative 1: npm install ohne Cache if sudo -u "$APP_USER" npm install --no-cache; then log "✅ Node.js Dependencies installiert (ohne Cache)" elif sudo -u "$APP_USER" npm install --force; then log "✅ Node.js Dependencies installiert (forciert)" else warning "⚠️ Alle npm-Installationsmethoden fehlgeschlagen" warning "Node.js-Abhängigkeiten werden übersprungen" # Erstelle leere CSS-Datei als Fallback mkdir -p "$APP_DIR/static/css" || true cat > "$APP_DIR/static/css/tailwind.css" << 'EOF' /* Fallback CSS - NPM-Installation fehlgeschlagen */ body { font-family: system-ui, sans-serif; margin: 0; padding: 0; } EOF chown "$APP_USER:$APP_USER" "$APP_DIR/static/css/tailwind.css" 2>/dev/null || true fi fi else warning "⚠️ NPM nicht verfügbar - Node.js-Dependencies werden übersprungen" info "Die Anwendung funktioniert auch ohne Node.js-Dependencies" # Erstelle Fallback CSS-Datei mkdir -p "$APP_DIR/static/css" || true cat > "$APP_DIR/static/css/tailwind.css" << 'EOF' /* Fallback CSS - NPM nicht verfügbar */ /* Basis-Styling für MYP-Anwendung */ body { font-family: system-ui, -apple-system, sans-serif; margin: 0; padding: 0; background: #f8f9fa; } .container { max-width: 1200px; margin: 0 auto; padding: 20px; } .btn { display: inline-block; padding: 8px 16px; background: #007bff; color: white; text-decoration: none; border-radius: 4px; border: none; cursor: pointer; } .btn:hover { background: #0056b3; } .alert { padding: 12px; margin: 10px 0; border-radius: 4px; background: #d4edda; border: 1px solid #c3e6cb; color: #155724; } .alert-danger { background: #f8d7da; border-color: #f5c6cb; color: #721c24; } .table { width: 100%; border-collapse: collapse; margin: 20px 0; } .table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid #dee2e6; } .table th { background: #e9ecef; font-weight: 600; } .form-control { width: 100%; padding: 8px 12px; border: 1px solid #ced4da; border-radius: 4px; font-size: 14px; max-width: 400px; } .card { background: white; border: 1px solid #dee2e6; border-radius: 8px; padding: 20px; margin: 20px 0; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .text-center { text-align: center; } .mt-4 { margin-top: 24px; } .mb-4 { margin-bottom: 24px; } .navbar { background: #343a40; color: white; padding: 15px 0; margin-bottom: 20px; } .navbar a { color: white; text-decoration: none; margin: 0 15px; } .navbar a:hover { color: #adb5bd; } EOF chown "$APP_USER:$APP_USER" "$APP_DIR/static/css/tailwind.css" 2>/dev/null || true log "✅ Fallback CSS-Datei erstellt" fi else info "Keine package.json gefunden - Node.js-Dependencies werden übersprungen" fi # Datenbank initialisieren (DB-Import-Fehler behoben) progress "Initialisiere Datenbank..." python3 -c " import sys sys.path.insert(0, '$APP_DIR') try: from models import init_database, create_initial_admin init_database() create_initial_admin() print('✅ Datenbank erfolgreich initialisiert') except Exception as e: print(f'⚠️ Datenbank-Initialisierung fehlgeschlagen: {str(e)}') # Fallback: Erstelle leere Datenbank import sqlite3 conn = sqlite3.connect('$APP_DIR/database.db') conn.close() print('✅ Fallback-Datenbank erstellt') " || warning "Datenbank-Initialisierung fehlgeschlagen" # Konfiguration erstellen progress "Erstelle Anwendungskonfiguration..." cat > "$APP_DIR/.env" << EOF FLASK_ENV=production SECRET_KEY=$(openssl rand -hex 32) DATABASE_URL=sqlite:///database.db HOST=0.0.0.0 PORT=5000 DEBUG=False KIOSK_MODE=true KIOSK_URL=http://localhost EOF chown "$APP_USER:$APP_USER" "$APP_DIR/.env" log "✅ Anwendung installiert" } # ========================== DATEIBERECHTIGUNGEN SETZEN ========================== set_file_permissions() { log "=== PHASE 5.5: DATEIBERECHTIGUNGEN SETZEN ===" progress "Setze korrekte Dateiberechtigungen..." # Basis-Anwendungsverzeichnis chown -R "$APP_USER:$APP_USER" "$APP_DIR" chown -R "$APP_USER:$APP_USER" "$BACKUP_DIR" # Verzeichnis-Berechtigungen find "$APP_DIR" -type d -exec chmod 755 {} \; find "$BACKUP_DIR" -type d -exec chmod 755 {} \; # Datei-Berechtigungen find "$APP_DIR" -type f -exec chmod 644 {} \; # Ausführbare Dateien if [ -f "$APP_DIR/app.py" ]; then chmod 755 "$APP_DIR/app.py" fi # Upload-Ordner spezielle Berechtigungen if [ -d "$APP_DIR/uploads" ]; then chmod 755 "$APP_DIR/uploads" find "$APP_DIR/uploads" -type d -exec chmod 755 {} \; find "$APP_DIR/uploads" -type f -exec chmod 644 {} \; chown -R "$APP_USER:www-data" "$APP_DIR/uploads" fi # Log-Verzeichnisse if [ -d "$APP_DIR/logs" ]; then chmod 755 "$APP_DIR/logs" find "$APP_DIR/logs" -type d -exec chmod 755 {} \; find "$APP_DIR/logs" -type f -exec chmod 644 {} \; chown -R "$APP_USER:$APP_USER" "$APP_DIR/logs" fi # Database-Verzeichnis if [ -d "$APP_DIR/database" ]; then chmod 755 "$APP_DIR/database" find "$APP_DIR/database" -type f -exec chmod 644 {} \; chown -R "$APP_USER:$APP_USER" "$APP_DIR/database" fi # Config-Dateien if [ -f "$APP_DIR/.env" ]; then chmod 600 "$APP_DIR/.env" chown "$APP_USER:$APP_USER" "$APP_DIR/.env" fi # Static-Verzeichnis if [ -d "$APP_DIR/static" ]; then chmod 755 "$APP_DIR/static" find "$APP_DIR/static" -type d -exec chmod 755 {} \; find "$APP_DIR/static" -type f -exec chmod 644 {} \; chown -R "$APP_USER:www-data" "$APP_DIR/static" fi # Templates-Verzeichnis if [ -d "$APP_DIR/templates" ]; then chmod 755 "$APP_DIR/templates" find "$APP_DIR/templates" -type f -exec chmod 644 {} \; chown -R "$APP_USER:$APP_USER" "$APP_DIR/templates" fi # System-Log-Verzeichnisse for log_cat in app auth errors jobs printers scheduler; do if [ -d "/var/log/myp-$log_cat" ]; then chown -R syslog:adm "/var/log/myp-$log_cat" chmod 755 "/var/log/myp-$log_cat" fi done log "✅ Dateiberechtigungen gesetzt" } # ========================== KIOSK-KONFIGURATION ========================== configure_kiosk() { log "=== PHASE 6: ERWEITERTE KIOSK-KONFIGURATION ===" # Sicherer Kiosk-Benutzer-Setup KIOSK_HOME="/home/$KIOSK_USER" progress "Konfiguriere Openbox für Kiosk..." sudo -u "$KIOSK_USER" mkdir -p "$KIOSK_HOME/.config/openbox" # Openbox-Konfiguration für maximale Sicherheit cat > "$KIOSK_HOME/.config/openbox/rc.xml" << 'EOF' 10 20 yes no yes no 200 no Smart
yes
Primary 1
Clearlooks NLIMC yes yes sans 8 bold normal 1 1 Kiosk 875 yes Nonpixel Center 10 10 TopLeft 0 0 no Above Vertical no 300 300 Middle 3 200 400 false no no 0 0 100% 100% yes yes yes yes
EOF # ERWEITERTE KIOSK-KONFIGURATION - Basierend auf Best Practices progress "Erstelle erweiterte Kiosk-Skripte..." # Haupt-Kiosk-Skript mit Raspberry Pi Optimierungen cat > "$KIOSK_HOME/start-kiosk.sh" << EOF #!/bin/bash # =================================================================== # MYP Kiosk-Starter - Optimiert für Raspberry Pi # Basierend auf: https://mpascucci.github.io/tutorial/rpi/ # Und: https://blog.kngstn.eu/article/2023-09-22-raspberrypi-als-web-kiosk/ # =================================================================== export DISPLAY=:0 # Logging für Debugging exec > >(tee -a /var/log/kiosk-session.log) 2>&1 echo "\$(date): Kiosk-Session gestartet für Benutzer $KIOSK_USER" # ===== RASPBERRY PI SPEZIFISCHE OPTIMIERUNGEN ===== # GPU Memory Split optimieren (falls verfügbar) if [ -f "/boot/config.txt" ]; then # Prüfe GPU Memory Split GPU_MEM=\$(vcgencmd get_mem gpu 2>/dev/null | cut -d= -f2 | cut -d'M' -f1) if [ "\$GPU_MEM" -lt 128 ]; then echo "Warnung: GPU Memory Split zu niedrig (\${GPU_MEM}M). Empfohlen: 128M+" fi fi # WLAN Power Save deaktivieren (Raspberry Pi spezifisch) if iwconfig wlan0 2>/dev/null | grep -q "Power Management:on"; then echo "Deaktiviere WLAN Power Save..." sudo iwconfig wlan0 power off 2>/dev/null || true fi # ===== BILDSCHIRM-KONFIGURATION ===== # Bildschirmschoner komplett deaktivieren xset s off xset s noblank xset s noexpose xset -dpms # Bildschirm-Blanking in /boot/cmdline.txt verhindern if ! grep -q "consoleblank=0" /boot/cmdline.txt 2>/dev/null; then echo "Hinweis: consoleblank=0 sollte in /boot/cmdline.txt gesetzt werden" fi # ===== MAUS UND EINGABE ===== # Mauszeiger verstecken mit unclutter if command -v unclutter &> /dev/null; then unclutter -idle 0.5 -root & echo "Mauszeiger wird nach 0.5s versteckt" else echo "Warnung: unclutter nicht installiert" fi # Virtuelle Tastatur deaktivieren killall onboard 2>/dev/null || true killall matchbox-keyboard 2>/dev/null || true # ===== CHROMIUM VORBEREITUNG ===== # Chromium Crash-Flags bereinigen (wichtig für Raspberry Pi) CHROMIUM_CONFIG_DIR="$KIOSK_HOME/.config/chromium/Default" if [ -f "\$CHROMIUM_CONFIG_DIR/Preferences" ]; then sed -i 's/"exited_cleanly":false/"exited_cleanly":true/' "\$CHROMIUM_CONFIG_DIR/Preferences" 2>/dev/null || true sed -i 's/"exit_type":"Crashed"/"exit_type":"Normal"/' "\$CHROMIUM_CONFIG_DIR/Preferences" 2>/dev/null || true echo "Chromium Crash-Flags bereinigt" fi # ===== WARTE AUF ANWENDUNG ===== echo "Warte auf MYP-Anwendung..." WAIT_COUNT=0 while ! curl -s http://localhost:5000 > /dev/null; do echo "Warte auf MYP-Anwendung... (\$WAIT_COUNT/60)" sleep 2 WAIT_COUNT=\$((WAIT_COUNT + 1)) if [ \$WAIT_COUNT -gt 60 ]; then echo "FEHLER: MYP-Anwendung nach 120s nicht erreichbar!" # Fallback: Zeige Fehlerseite echo "

MYP-System wird geladen...

Bitte warten Sie einen Moment.

" > /tmp/loading.html break fi done # ===== CHROMIUM KIOSK-MODUS MIT RASPBERRY PI OPTIMIERUNGEN ===== # Raspberry Pi spezifische Chromium-Flags CHROMIUM_FLAGS=" --kiosk --no-sandbox --disable-web-security --disable-features=TranslateUI,BlinkGenPropertyTrees --disable-ipc-flooding-protection --disable-renderer-backgrounding --disable-backgrounding-occluded-windows --disable-background-timer-throttling --disable-background-networking --disable-breakpad --disable-component-extensions-with-background-pages --disable-dev-shm-usage --disable-extensions --disable-hang-monitor --disable-popup-blocking --disable-prompt-on-repost --disable-sync --disable-translate --disable-infobars --disable-session-crashed-bubble --disable-restore-session-state --disable-crash-reporter --noerrdialogs --no-first-run --no-default-browser-check --autoplay-policy=no-user-gesture-required --start-fullscreen --window-position=0,0 --window-size=1920,1080 --user-data-dir=$KIOSK_HOME/.chromium-kiosk --disable-features=VizDisplayCompositor --enable-features=OverlayScrollbar --disable-gpu-sandbox --disable-software-rasterizer --ignore-certificate-errors --ignore-ssl-errors --ignore-certificate-errors-spki-list --ignore-ssl-errors-list --disable-logging --silent-debugger-extension-api --disable-default-apps --disable-background-mode --app-auto-launched --no-startup-window --force-device-scale-factor=1.0 --disable-pinch --overscroll-history-navigation=0 " # Raspberry Pi Hardware-spezifische Optimierungen if grep -q "Raspberry Pi" /proc/cpuinfo 2>/dev/null; then echo "Raspberry Pi erkannt - aktiviere Hardware-Optimierungen" CHROMIUM_FLAGS="\$CHROMIUM_FLAGS --disable-gpu-compositing --enable-gpu-rasterization --disable-smooth-scrolling --disable-2d-canvas-image-chromium --disable-accelerated-2d-canvas --num-raster-threads=2 --enable-zero-copy " fi # URL bestimmen if curl -s http://localhost:5000 > /dev/null; then KIOSK_URL="http://localhost:5000" else KIOSK_URL="file:///tmp/loading.html" fi echo "Starte Chromium im Kiosk-Modus mit URL: \$KIOSK_URL" # Chromium mit Restart-Loop starten (wichtig für Stabilität) while true; do echo "\$(date): Starte Chromium..." \$CHROMIUM_BIN \$CHROMIUM_FLAGS "\$KIOSK_URL" EXIT_CODE=\$? echo "\$(date): Chromium beendet mit Exit-Code: \$EXIT_CODE" # Bei normalem Exit (0) oder Kiosk-Exit (15) nicht neustarten if [ \$EXIT_CODE -eq 0 ] || [ \$EXIT_CODE -eq 15 ]; then echo "Chromium normal beendet - Kiosk-Modus verlassen" break fi # Bei Crash: Kurz warten und neustarten echo "Chromium-Crash erkannt - Neustart in 3 Sekunden..." sleep 3 # Bereinige Chromium-Prozesse pkill -f chromium 2>/dev/null || true sleep 1 done echo "\$(date): Kiosk-Session beendet" EOF # LXDE Autostart-Konfiguration (Alternative Methode) progress "Konfiguriere LXDE Autostart..." sudo -u "$KIOSK_USER" mkdir -p "$KIOSK_HOME/.config/lxsession/LXDE-pi" cat > "$KIOSK_HOME/.config/lxsession/LXDE-pi/autostart" << EOF ################################################# # LXDE-pi autostart script für MYP Kiosk # # Basierend auf: https://mpascucci.github.io/tutorial/rpi/ ################################################# # Bildschirmschoner deaktivieren @xset s noblank @xset s off @xset -dpms # Mauszeiger verstecken @unclutter -idle 0.5 -root # Kiosk-Anwendung starten @bash $KIOSK_HOME/start-kiosk.sh EOF # Desktop-Autostart-Datei (systemd-kompatibel) progress "Erstelle Desktop-Autostart-Datei..." sudo -u "$KIOSK_USER" mkdir -p "$KIOSK_HOME/.config/autostart" cat > "$KIOSK_HOME/.config/autostart/myp-kiosk.desktop" << EOF [Desktop Entry] Type=Application Name=MYP Kiosk Application Comment=Startet die MYP Kiosk-Anwendung automatisch Exec=/bin/bash $KIOSK_HOME/start-kiosk.sh Hidden=false NoDisplay=false X-GNOME-Autostart-enabled=true StartupNotify=false Categories=System; EOF # Skripte ausführbar machen chmod +x "$KIOSK_HOME/start-kiosk.sh" chmod +x "$KIOSK_HOME/.config/lxsession/LXDE-pi/autostart" chown -R "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.config" chown "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/start-kiosk.sh" log "✅ Erweiterte Kiosk-Konfiguration erstellt" } # ========================== RASPBERRY PI OPTIMIERUNGEN ========================== optimize_raspberry_pi() { log "=== PHASE 6.2: RASPBERRY PI OPTIMIERUNGEN ===" # Prüfe ob es sich um einen Raspberry Pi handelt if ! grep -q "Raspberry Pi" /proc/cpuinfo 2>/dev/null; then info "Kein Raspberry Pi erkannt - überspringe Pi-spezifische Optimierungen" return 0 fi progress "Raspberry Pi erkannt - aktiviere Hardware-Optimierungen..." # ===== BOOT-KONFIGURATION OPTIMIEREN ===== progress "Optimiere Boot-Konfiguration..." # /boot/config.txt Optimierungen if [ -f "/boot/config.txt" ]; then # Backup erstellen cp /boot/config.txt /boot/config.txt.backup # GPU Memory Split für bessere Browser-Performance if ! grep -q "gpu_mem=" /boot/config.txt; then echo "" >> /boot/config.txt echo "# MYP Kiosk Optimierungen" >> /boot/config.txt echo "gpu_mem=128" >> /boot/config.txt info "GPU Memory Split auf 128MB gesetzt" fi # Disable Rainbow Splash if ! grep -q "disable_splash=1" /boot/config.txt; then echo "disable_splash=1" >> /boot/config.txt fi # HDMI Force Hotplug für bessere Display-Kompatibilität if ! grep -q "hdmi_force_hotplug=1" /boot/config.txt; then echo "hdmi_force_hotplug=1" >> /boot/config.txt fi # Disable Overscan für Kiosk-Displays if ! grep -q "disable_overscan=1" /boot/config.txt; then echo "disable_overscan=1" >> /boot/config.txt fi # Audio über HDMI aktivieren if ! grep -q "hdmi_drive=2" /boot/config.txt; then echo "hdmi_drive=2" >> /boot/config.txt fi info "Boot-Konfiguration optimiert" fi # /boot/cmdline.txt Optimierungen if [ -f "/boot/cmdline.txt" ]; then # Backup erstellen cp /boot/cmdline.txt /boot/cmdline.txt.backup # Console Blanking deaktivieren if ! grep -q "consoleblank=0" /boot/cmdline.txt; then sed -i 's/$/ consoleblank=0/' /boot/cmdline.txt info "Console Blanking deaktiviert" fi # Logo deaktivieren für schnelleren Boot if ! grep -q "logo.nologo" /boot/cmdline.txt; then sed -i 's/$/ logo.nologo/' /boot/cmdline.txt fi # Quiet Boot für saubere Kiosk-Erfahrung if ! grep -q "quiet" /boot/cmdline.txt; then sed -i 's/$/ quiet/' /boot/cmdline.txt fi fi # ===== WLAN POWER MANAGEMENT DEAKTIVIEREN ===== progress "Deaktiviere WLAN Power Management..." # Systemd-Service für WLAN Power Management cat > "/etc/systemd/system/disable-wifi-power-management.service" << 'EOF' [Unit] Description=Disable WiFi Power Management After=multi-user.target [Service] Type=oneshot RemainAfterExit=yes ExecStart=/bin/bash -c 'iwconfig wlan0 power off 2>/dev/null || true' [Install] WantedBy=multi-user.target EOF systemctl enable disable-wifi-power-management.service # NetworkManager Konfiguration (falls vorhanden) if [ -d "/etc/NetworkManager/conf.d" ]; then cat > "/etc/NetworkManager/conf.d/default-wifi-powersave-on.conf" << 'EOF' [connection] wifi.powersave = 2 EOF info "NetworkManager WLAN Power Save deaktiviert" fi # ===== ENERGIESPARMODUS KOMPLETT DEAKTIVIEREN ===== progress "Deaktiviere Energiesparmodus..." # LightDM Konfiguration erweitern if [ -f "/etc/lightdm/lightdm.conf" ]; then # Backup erstellen cp /etc/lightdm/lightdm.conf /etc/lightdm/lightdm.conf.backup # X-Server Kommando mit DPMS-Deaktivierung if ! grep -q "xserver-command=X -s 0 -dpms" /etc/lightdm/lightdm.conf; then sed -i '/^\[Seat:\*\]/a xserver-command=X -s 0 -dpms' /etc/lightdm/lightdm.conf info "X-Server Energiesparmodus deaktiviert" fi fi # ===== SYSTEMD POWER MANAGEMENT ===== progress "Konfiguriere systemd Power Management..." # Logind-Konfiguration für Kiosk mkdir -p /etc/systemd/logind.conf.d cat > "/etc/systemd/logind.conf.d/kiosk-power.conf" << 'EOF' [Login] # Verhindere Suspend/Hibernate im Kiosk-Modus HandlePowerKey=ignore HandleSuspendKey=ignore HandleHibernateKey=ignore HandleLidSwitch=ignore HandleLidSwitchExternalPower=ignore HandleLidSwitchDocked=ignore # Idle-Verhalten für Kiosk IdleAction=ignore IdleActionSec=infinity # Session-Management KillUserProcesses=no UserStopDelaySec=10 EOF # ===== RASPBERRY PI SPEZIFISCHE PAKETE ===== progress "Installiere Raspberry Pi spezifische Tools..." # Raspberry Pi Tools (falls verfügbar) apt-get install -y \ libraspberrypi-bin \ raspberrypi-kernel-headers \ wireless-tools \ bc \ 2>/dev/null || warning "Einige Pi-spezifische Pakete nicht verfügbar" # ===== TEMPERATUR-MONITORING ===== progress "Konfiguriere Temperatur-Monitoring..." # Temperatur-Check-Skript cat > "/usr/local/bin/pi-temp-check" << 'EOF' #!/bin/bash # Raspberry Pi Temperatur-Check für Kiosk-System TEMP=$(vcgencmd measure_temp 2>/dev/null | cut -d= -f2 | cut -d"'" -f1) if [ -n "$TEMP" ]; then echo "$(date): CPU Temperatur: ${TEMP}°C" >> /var/log/pi-temperature.log # Warnung bei hoher Temperatur if (( $(echo "$TEMP > 70" | bc -l) )); then echo "$(date): WARNUNG - Hohe CPU Temperatur: ${TEMP}°C" >> /var/log/pi-temperature.log logger "Raspberry Pi: Hohe CPU Temperatur: ${TEMP}°C" fi # Kritische Temperatur if (( $(echo "$TEMP > 80" | bc -l) )); then echo "$(date): KRITISCH - Sehr hohe CPU Temperatur: ${TEMP}°C" >> /var/log/pi-temperature.log logger "Raspberry Pi: KRITISCHE Temperatur: ${TEMP}°C" fi fi EOF chmod +x /usr/local/bin/pi-temp-check # Cron-Job für Temperatur-Monitoring cat > "/etc/cron.d/pi-temperature" << 'EOF' # Raspberry Pi Temperatur-Monitoring alle 5 Minuten */5 * * * * root /usr/local/bin/pi-temp-check EOF # ===== PERFORMANCE-OPTIMIERUNGEN ===== progress "Aktiviere Performance-Optimierungen..." # Swappiness reduzieren für bessere Performance echo "vm.swappiness=10" >> /etc/sysctl.conf # Dirty Ratio optimieren echo "vm.dirty_ratio=15" >> /etc/sysctl.conf echo "vm.dirty_background_ratio=5" >> /etc/sysctl.conf # ===== UNCLUTTER INSTALLATION ===== progress "Installiere unclutter für Mauszeiger-Verstecken..." apt-get install -y unclutter || warning "unclutter Installation fehlgeschlagen" # ===== CHROMIUM OPTIMIERUNGEN FÜR RASPBERRY PI ===== progress "Konfiguriere Chromium für Raspberry Pi..." # Chromium GPU-Konfiguration mkdir -p /etc/chromium-browser/policies/managed cat > "/etc/chromium-browser/policies/managed/kiosk-policy.json" << 'EOF' { "DefaultBrowserSettingEnabled": false, "BackgroundModeEnabled": false, "BookmarkBarEnabled": false, "BrowserSignin": 0, "DefaultNotificationsSetting": 2, "DefaultGeolocationSetting": 2, "DefaultMediaStreamSetting": 2, "PasswordManagerEnabled": false, "AutofillAddressEnabled": false, "AutofillCreditCardEnabled": false, "TranslateEnabled": false, "SpellCheckServiceEnabled": false, "SearchSuggestEnabled": false, "ImportBookmarks": false, "ImportHistory": false, "ImportSavedPasswords": false, "ImportSearchEngine": false, "MetricsReportingEnabled": false, "UserFeedbackAllowed": false } EOF info "Chromium-Richtlinien für Kiosk-Modus konfiguriert" log "✅ Raspberry Pi Optimierungen abgeschlossen" } # ========================== DNS UND NETZWERK OPTIMIERUNG ========================== configure_dns_and_network() { log "=== PHASE 6.3: DNS UND NETZWERK OPTIMIERUNG ===" progress "Konfiguriere intelligente DNS-Auflösung..." # ===== IPv6 DEAKTIVIEREN ===== progress "Deaktiviere IPv6 systemweit..." # Kernel-Parameter für IPv6-Deaktivierung cat >> /etc/sysctl.conf << 'EOF' # IPv6 deaktivieren für Kiosk-System net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 net.ipv6.conf.lo.disable_ipv6 = 1 EOF # IPv6 sofort deaktivieren sysctl -w net.ipv6.conf.all.disable_ipv6=1 sysctl -w net.ipv6.conf.default.disable_ipv6=1 sysctl -w net.ipv6.conf.lo.disable_ipv6=1 # IPv6 in GRUB deaktivieren (falls vorhanden) if [ -f "/etc/default/grub" ]; then if ! grep -q "ipv6.disable=1" /etc/default/grub; then sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="/GRUB_CMDLINE_LINUX_DEFAULT="ipv6.disable=1 /' /etc/default/grub update-grub 2>/dev/null || true fi fi # IPv6 in /boot/cmdline.txt deaktivieren (Raspberry Pi) if [ -f "/boot/cmdline.txt" ]; then if ! grep -q "ipv6.disable=1" /boot/cmdline.txt; then sed -i 's/$/ ipv6.disable=1/' /boot/cmdline.txt fi fi info "IPv6 systemweit deaktiviert" # ===== UNBOUND DNS RESOLVER INSTALLIEREN ===== progress "Installiere Unbound DNS Resolver..." apt-get install -y unbound unbound-host dnsutils || error "Unbound Installation fehlgeschlagen" # ===== DNS KONFIGURATION MIT PRIORITÄTEN ===== progress "Konfiguriere DNS mit intelligenten Prioritäten..." # Unbound Hauptkonfiguration cat > "/etc/unbound/unbound.conf" << 'EOF' # Unbound DNS Resolver Konfiguration für MYP Kiosk # Intelligente DNS-Auflösung mit Fallback-Mechanismen server: # Basis-Konfiguration verbosity: 1 interface: 127.0.0.1 port: 53 do-ip4: yes do-ip6: no do-udp: yes do-tcp: yes # Sicherheit chroot: "" username: "unbound" directory: "/etc/unbound" logfile: "/var/log/unbound.log" use-syslog: yes log-queries: no log-replies: no # Performance num-threads: 2 msg-cache-slabs: 4 rrset-cache-slabs: 4 infra-cache-slabs: 4 key-cache-slabs: 4 msg-cache-size: 64m rrset-cache-size: 128m cache-max-ttl: 86400 cache-min-ttl: 300 # Netzwerk-Einstellungen outgoing-range: 4096 num-queries-per-thread: 2048 so-rcvbuf: 4m so-sndbuf: 4m # Lokale Netzwerke erlauben access-control: 127.0.0.0/8 allow access-control: 192.168.0.0/16 allow access-control: 10.0.0.0/8 allow access-control: 172.16.0.0/12 allow # Root Hints root-hints: "/var/lib/unbound/root.hints" # DNSSEC auto-trust-anchor-file: "/var/lib/unbound/root.key" # Lokale Auflösung private-address: 192.168.0.0/16 private-address: 172.16.0.0/12 private-address: 10.0.0.0/8 private-address: 127.0.0.0/8 # Upstream DNS Server mit Prioritäten # 1. Prio: Router DNS (wird dynamisch gesetzt) # 2. Prio: Google DNS # 3. Prio: Cloudflare DNS # 4. Prio: Custom DNS Server forward-zone: name: "." # Fallback DNS Server (werden durch Skript überschrieben) forward-addr: 8.8.8.8 forward-addr: 8.8.4.4 forward-addr: 1.1.1.1 forward-addr: 1.0.0.1 forward-addr: 163.116.178.73 forward-addr: 163.116.178.74 EOF # ===== DYNAMISCHE DNS-KONFIGURATION ===== progress "Erstelle dynamisches DNS-Konfigurationsskript..." cat > "/usr/local/bin/configure-dns-priority" << 'EOF' #!/bin/bash # Dynamische DNS-Konfiguration mit Router-Priorität # Automatische Erkennung und Konfiguration der besten DNS-Server LOG_FILE="/var/log/dns-configuration.log" UNBOUND_CONF="/etc/unbound/unbound.conf" RESOLV_CONF="/etc/resolv.conf" log_dns() { echo "$(date): $1" >> "$LOG_FILE" } # Erkenne Router-DNS get_router_dns() { local router_dns="" # Methode 1: DHCP Lease-Datei if [ -f "/var/lib/dhcp/dhclient.leases" ]; then router_dns=$(grep "domain-name-servers" /var/lib/dhcp/dhclient.leases | tail -1 | cut -d' ' -f3- | tr -d ';' | tr ',' ' ') fi # Methode 2: systemd-resolved if [ -z "$router_dns" ] && command -v systemd-resolve &> /dev/null; then router_dns=$(systemd-resolve --status | grep "DNS Servers" | head -1 | cut -d: -f2 | xargs) fi # Methode 3: NetworkManager if [ -z "$router_dns" ] && command -v nmcli &> /dev/null; then router_dns=$(nmcli dev show | grep "IP4.DNS" | head -1 | cut -d: -f2 | xargs) fi # Methode 4: Route-basierte Erkennung if [ -z "$router_dns" ]; then local gateway=$(ip route | grep default | head -1 | awk '{print $3}') if [ -n "$gateway" ]; then # Versuche Gateway als DNS if nslookup google.com "$gateway" &> /dev/null; then router_dns="$gateway" fi fi fi echo "$router_dns" } # Teste DNS-Server test_dns_server() { local dns_server="$1" local timeout=3 if [ -z "$dns_server" ]; then return 1 fi # Teste mit nslookup if timeout "$timeout" nslookup google.com "$dns_server" &> /dev/null; then return 0 fi # Teste mit dig (falls verfügbar) if command -v dig &> /dev/null; then if timeout "$timeout" dig @"$dns_server" google.com &> /dev/null; then return 0 fi fi return 1 } # Konfiguriere Unbound mit priorisierten DNS-Servern configure_unbound() { local router_dns="$1" local config_section="" log_dns "Konfiguriere Unbound mit Router-DNS: $router_dns" # Erstelle Forward-Zone-Konfiguration config_section="forward-zone:\n name: \".\"\n" # 1. Priorität: Router DNS (falls verfügbar und funktional) if [ -n "$router_dns" ]; then for dns in $router_dns; do if test_dns_server "$dns"; then config_section="${config_section} forward-addr: $dns\n" log_dns "Router DNS hinzugefügt: $dns" else log_dns "Router DNS nicht erreichbar: $dns" fi done fi # 2. Priorität: Google DNS config_section="${config_section} forward-addr: 8.8.8.8\n" config_section="${config_section} forward-addr: 8.8.4.4\n" # 3. Priorität: Cloudflare DNS config_section="${config_section} forward-addr: 1.1.1.1\n" config_section="${config_section} forward-addr: 1.0.0.1\n" # 4. Priorität: Custom DNS Server config_section="${config_section} forward-addr: 163.116.178.73\n" config_section="${config_section} forward-addr: 163.116.178.74\n" # Ersetze Forward-Zone in Unbound-Konfiguration sed -i '/^forward-zone:/,$d' "$UNBOUND_CONF" echo -e "$config_section" >> "$UNBOUND_CONF" # Unbound neu laden systemctl reload unbound || systemctl restart unbound log_dns "Unbound-Konfiguration aktualisiert und neu geladen" } # Konfiguriere /etc/resolv.conf configure_resolv_conf() { log_dns "Konfiguriere /etc/resolv.conf für lokalen Unbound" # Backup erstellen cp "$RESOLV_CONF" "${RESOLV_CONF}.backup" 2>/dev/null || true # Neue resolv.conf erstellen cat > "$RESOLV_CONF" << 'RESOLV_EOF' # MYP Kiosk DNS-Konfiguration # Lokaler Unbound DNS Resolver mit intelligenten Fallbacks nameserver 127.0.0.1 # Fallback DNS Server (falls Unbound nicht verfügbar) nameserver 8.8.8.8 nameserver 8.8.4.4 # Suchdomänen search local # Optionen options timeout:2 options attempts:3 options rotate RESOLV_EOF # Schreibschutz setzen (verhindert Überschreibung durch DHCP) chattr +i "$RESOLV_CONF" 2>/dev/null || true log_dns "/etc/resolv.conf konfiguriert und geschützt" } # Hauptfunktion main() { log_dns "=== DNS-Konfiguration gestartet ===" # Router-DNS ermitteln router_dns=$(get_router_dns) log_dns "Erkannte Router-DNS: ${router_dns:-'Keine gefunden'}" # Unbound konfigurieren configure_unbound "$router_dns" # resolv.conf konfigurieren configure_resolv_conf # DNS-Test if nslookup google.com 127.0.0.1 &> /dev/null; then log_dns "✅ DNS-Konfiguration erfolgreich - Test bestanden" else log_dns "⚠️ DNS-Test fehlgeschlagen - Fallback aktiv" fi log_dns "=== DNS-Konfiguration abgeschlossen ===" } # Skript ausführen main "$@" EOF chmod +x /usr/local/bin/configure-dns-priority # ===== SYSTEMD-SERVICE FÜR DNS-KONFIGURATION ===== progress "Erstelle systemd-Service für DNS-Konfiguration..." cat > "/etc/systemd/system/dns-priority-config.service" << 'EOF' [Unit] Description=Configure DNS Priority with Router Detection After=network-online.target unbound.service Wants=network-online.target Before=myp-druckerverwaltung.service [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/local/bin/configure-dns-priority StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target EOF systemctl enable dns-priority-config.service # ===== DHCP-CLIENT KONFIGURATION ===== progress "Konfiguriere DHCP-Client für DNS-Schutz..." # dhclient-Konfiguration (verhindert DNS-Überschreibung) if [ -f "/etc/dhcp/dhclient.conf" ]; then # Backup erstellen cp /etc/dhcp/dhclient.conf /etc/dhcp/dhclient.conf.backup # DNS-Überschreibung verhindern if ! grep -q "supersede domain-name-servers" /etc/dhcp/dhclient.conf; then echo "" >> /etc/dhcp/dhclient.conf echo "# MYP Kiosk: Verhindere DNS-Überschreibung durch DHCP" >> /etc/dhcp/dhclient.conf echo "supersede domain-name-servers 127.0.0.1;" >> /etc/dhcp/dhclient.conf fi fi # NetworkManager-Konfiguration (falls vorhanden) if [ -d "/etc/NetworkManager/conf.d" ]; then cat > "/etc/NetworkManager/conf.d/dns-priority.conf" << 'EOF' [main] dns=none [connection] ipv6.method=ignore EOF info "NetworkManager DNS-Überschreibung deaktiviert" fi # ===== UNBOUND STARTEN UND KONFIGURIEREN ===== progress "Starte und konfiguriere Unbound..." # Root Hints herunterladen curl -o /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache 2>/dev/null || \ wget -O /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache 2>/dev/null || \ warning "Root Hints Download fehlgeschlagen" # Unbound-Benutzer Berechtigungen chown -R unbound:unbound /var/lib/unbound chown unbound:unbound /etc/unbound/unbound.conf # Unbound aktivieren und starten systemctl enable unbound systemctl start unbound # DNS-Konfiguration ausführen /usr/local/bin/configure-dns-priority # ===== CRON-JOB FÜR REGELMÄSSIGE DNS-UPDATES ===== progress "Konfiguriere automatische DNS-Updates..." cat > "/etc/cron.d/dns-priority-update" << 'EOF' # DNS-Priorität alle 30 Minuten aktualisieren */30 * * * * root /usr/local/bin/configure-dns-priority >/dev/null 2>&1 # Root Hints wöchentlich aktualisieren 0 3 * * 0 root curl -s -o /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache && systemctl reload unbound EOF # ===== DNS-MONITORING SKRIPT ===== progress "Erstelle DNS-Monitoring..." cat > "/usr/local/bin/dns-health-check" << 'EOF' #!/bin/bash # DNS-Gesundheitscheck für MYP Kiosk LOG_FILE="/var/log/dns-health.log" log_health() { echo "$(date): $1" >> "$LOG_FILE" } # Teste DNS-Auflösung test_dns_resolution() { local test_domains=("google.com" "github.com" "debian.org") local failed_count=0 for domain in "${test_domains[@]}"; do if ! nslookup "$domain" 127.0.0.1 &> /dev/null; then ((failed_count++)) log_health "DNS-Auflösung fehlgeschlagen für: $domain" fi done if [ $failed_count -eq 0 ]; then log_health "✅ DNS-Gesundheitscheck bestanden" return 0 elif [ $failed_count -lt ${#test_domains[@]} ]; then log_health "⚠️ DNS-Gesundheitscheck teilweise fehlgeschlagen ($failed_count/${#test_domains[@]})" return 1 else log_health "❌ DNS-Gesundheitscheck komplett fehlgeschlagen" return 2 fi } # Unbound-Status prüfen check_unbound_status() { if systemctl is-active --quiet unbound; then log_health "✅ Unbound läuft" return 0 else log_health "❌ Unbound läuft nicht - versuche Neustart" systemctl restart unbound sleep 3 if systemctl is-active --quiet unbound; then log_health "✅ Unbound erfolgreich neu gestartet" return 0 else log_health "❌ Unbound-Neustart fehlgeschlagen" return 1 fi fi } # Hauptfunktion main() { check_unbound_status test_dns_resolution local exit_code=$? # Bei kritischen Fehlern: DNS-Konfiguration neu laden if [ $exit_code -eq 2 ]; then log_health "Kritischer DNS-Fehler - lade Konfiguration neu" /usr/local/bin/configure-dns-priority fi return $exit_code } main "$@" EOF chmod +x /usr/local/bin/dns-health-check # DNS-Health-Check zu Cron hinzufügen cat >> "/etc/cron.d/dns-priority-update" << 'EOF' # DNS-Gesundheitscheck alle 10 Minuten */10 * * * * root /usr/local/bin/dns-health-check >/dev/null 2>&1 EOF log "✅ DNS und Netzwerk-Optimierung abgeschlossen" } # ========================== AUTO-LOGIN KONFIGURATION ========================== configure_autologin() { log "=== PHASE 6.5: AUTO-LOGIN KONFIGURATION ===" progress "Installiere und konfiguriere Display Manager..." # LightDM installieren für besseres Auto-Login-Management apt-get install -y lightdm lightdm-gtk-greeter || true # Stoppe andere Display Manager for dm in gdm gdm3 sddm xdm nodm; do systemctl stop "$dm" 2>/dev/null || true systemctl disable "$dm" 2>/dev/null || true done progress "Konfiguriere LightDM für Auto-Login..." # LightDM-Konfiguration für automatischen Login cat > "/etc/lightdm/lightdm.conf" << EOF [Seat:*] # Automatischer Login für Kiosk-Benutzer autologin-user=$KIOSK_USER autologin-user-timeout=0 autologin-session=openbox user-session=openbox session-wrapper=/etc/X11/Xsession greeter-session=lightdm-gtk-greeter allow-guest=false # Kein Benutzer-Wechsel möglich greeter-hide-users=true greeter-show-manual-login=false # Automatischer Start ohne Verzögerung autologin-in-background=false # Session-Setup session-setup-script=/usr/share/lightdm/setup-kiosk-session.sh EOF progress "Erstelle Session-Setup-Skript..." # Session-Setup-Skript für zusätzliche Sicherheit cat > "/usr/share/lightdm/setup-kiosk-session.sh" << EOF #!/bin/bash # Session-Setup für Kiosk-Modus # Stelle sicher, dass X11-Display verfügbar ist export DISPLAY=:0 # Deaktiviere Bildschirmschoner und Power Management xset s off xset s noblank xset s noexpose xset -dpms # Verstecke Mauszeiger unclutter -idle 0.5 -root & # Logge Session-Start echo "\$(date): Kiosk-Session für Benutzer $KIOSK_USER gestartet" >> /var/log/kiosk-session.log EOF chmod +x "/usr/share/lightdm/setup-kiosk-session.sh" progress "Konfiguriere Getty Auto-Login als Fallback..." # Getty Auto-Login als Fallback konfigurieren (falls LightDM fehlschlägt) 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 Type=simple EOF progress "Erstelle Desktop-Session für Openbox..." # Desktop-Session-Datei für Openbox mkdir -p "/usr/share/xsessions" cat > "/usr/share/xsessions/openbox.desktop" << EOF [Desktop Entry] Name=Openbox Comment=A lightweight window manager Exec=openbox-session Type=XSession DesktopNames=OPENBOX EOF # Kiosk-Benutzer Desktop-Umgebung konfigurieren progress "Konfiguriere Desktop-Umgebung für Kiosk-Benutzer..." KIOSK_HOME="/home/$KIOSK_USER" # .xsessionrc für X-Session-Setup cat > "$KIOSK_HOME/.xsessionrc" << EOF #!/bin/bash # X-Session-Setup für Kiosk-Modus # Export Display export DISPLAY=:0 # Starte Session-Log echo "\$(date): X-Session gestartet für Kiosk-Benutzer" >> /var/log/kiosk-session.log # Führe Kiosk-Setup aus exec openbox-session EOF # .xinitrc für xinit/startx cat > "$KIOSK_HOME/.xinitrc" << EOF #!/bin/bash # Xinit-Konfiguration für Kiosk-Modus # Export Display export DISPLAY=:0 # Session-Setup xset s off xset s noblank xset s noexpose xset -dpms # Verstecke Mauszeiger unclutter -idle 0.5 -root & # Starte Openbox exec openbox-session EOF # Berechtigungen setzen chmod +x "$KIOSK_HOME/.xsessionrc" chmod +x "$KIOSK_HOME/.xinitrc" chown "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.xsessionrc" chown "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.xinitrc" # LightDM aktivieren systemctl enable lightdm # Sicherstellen, dass graphical.target als Standard gesetzt ist systemctl set-default graphical.target log "✅ Auto-Login konfiguriert" } # ========================== MEHRFACHE AUTOSTART-ABSICHERUNG ========================== configure_multiple_autostart() { log "=== PHASE 6.8: MEHRFACHE AUTOSTART-ABSICHERUNG ===" KIOSK_HOME="/home/$KIOSK_USER" progress "Implementiere mehrfache Autostart-Mechanismen..." # 1. SYSTEMD USER-SESSION AUTOSTART progress "Konfiguriere systemd user session autostart..." sudo -u "$KIOSK_USER" mkdir -p "$KIOSK_HOME/.config/systemd/user" cat > "$KIOSK_HOME/.config/systemd/user/kiosk-autostart.service" << EOF [Unit] Description=Kiosk Autostart (User Session) After=graphical-session.target [Service] Type=simple ExecStart=$KIOSK_HOME/start-kiosk.sh Restart=always RestartSec=5 Environment=DISPLAY=:0 [Install] WantedBy=default.target EOF chown "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.config/systemd/user/kiosk-autostart.service" # Aktiviere User-Service sudo -u "$KIOSK_USER" systemctl --user enable kiosk-autostart.service || true # 2. BASHRC AUTOSTART progress "Konfiguriere .bashrc autostart..." cat >> "$KIOSK_HOME/.bashrc" << 'EOF' # ===== KIOSK AUTOSTART (BASHRC) ===== if [ -z "$SSH_CLIENT" ] && [ -z "$SSH_TTY" ] && [ -z "$KIOSK_STARTED" ]; then export KIOSK_STARTED=1 # Prüfe ob X-Session läuft if [ -n "$DISPLAY" ] || [ "$XDG_SESSION_TYPE" = "x11" ]; then echo "Kiosk-Autostart via .bashrc" exec $HOME/start-kiosk.sh fi fi EOF # 3. PROFILE AUTOSTART progress "Konfiguriere .profile autostart..." cat >> "$KIOSK_HOME/.profile" << 'EOF' # ===== KIOSK AUTOSTART (PROFILE) ===== if [ -z "$SSH_CLIENT" ] && [ -z "$SSH_TTY" ] && [ -z "$KIOSK_STARTED" ]; then export KIOSK_STARTED=1 # Starte X-Session falls nicht vorhanden if [ -z "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ] && [ "$(tty)" = "/dev/tty1" ]; then echo "Starte X-Session via .profile" exec startx fi fi EOF # 4. DESKTOP AUTOSTART progress "Konfiguriere XDG autostart..." sudo -u "$KIOSK_USER" mkdir -p "$KIOSK_HOME/.config/autostart" cat > "$KIOSK_HOME/.config/autostart/kiosk-app.desktop" << EOF [Desktop Entry] Type=Application Name=MYP Kiosk Application Comment=Startet die MYP Kiosk-Anwendung Exec=$KIOSK_HOME/start-kiosk.sh Hidden=false NoDisplay=false X-GNOME-Autostart-enabled=true StartupNotify=false EOF chown "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.config/autostart/kiosk-app.desktop" # 5. CRON AUTOSTART (ÜBERWACHUNG) progress "Konfiguriere Cron-Überwachung..." cat > "/etc/cron.d/kiosk-watchdog" << EOF # Kiosk-Überwachung: Startet Kiosk neu falls nicht läuft */2 * * * * $KIOSK_USER /bin/bash -c 'if ! pgrep -f "chromium.*kiosk" > /dev/null; then echo "\$(date): Kiosk-Watchdog startet Anwendung neu" >> /var/log/kiosk-watchdog.log; DISPLAY=:0 $HOME/start-kiosk.sh & fi' EOF # 6. RC.LOCAL FALLBACK progress "Konfiguriere rc.local Fallback..." cat > "/etc/rc.local" << EOF #!/bin/bash # rc.local - Kiosk-Fallback # Warte auf System-Initialisierung sleep 10 # Starte Kiosk-Services falls nicht läuft if ! systemctl is-active --quiet lightdm; then systemctl start lightdm fi if ! systemctl is-active --quiet myp-druckerverwaltung; then systemctl start myp-druckerverwaltung fi # Logge Start echo "\$(date): rc.local Kiosk-Fallback ausgeführt" >> /var/log/kiosk-fallback.log exit 0 EOF chmod +x "/etc/rc.local" # 7. SYSTEMD SERVICE ÜBERWACHUNG progress "Konfiguriere Service-Überwachung..." cat > "/etc/systemd/system/kiosk-watchdog.service" << EOF [Unit] Description=Kiosk Watchdog Service After=multi-user.target [Service] Type=simple User=root ExecStart=/bin/bash -c 'while true; do if ! systemctl is-active --quiet myp-kiosk; then systemctl start myp-kiosk; fi; sleep 30; done' Restart=always RestartSec=10 [Install] WantedBy=multi-user.target EOF systemctl enable kiosk-watchdog.service # Berechtigungen finalisieren chown -R "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.config" chown "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.bashrc" chown "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.profile" log "✅ Mehrfache Autostart-Absicherung implementiert" } # ========================== AUTOSTART KONFIGURATION ========================== configure_autostart() { log "=== PHASE 7: AUTOSTART-KONFIGURATION ===" # Systemd Service für Anwendung progress "Erstelle Systemd-Service für Anwendung..." cat > "/etc/systemd/system/myp-druckerverwaltung.service" << EOF [Unit] Description=MYP Druckerverwaltung Flask Application After=network.target [Service] Type=simple User=$APP_USER Group=$APP_USER WorkingDirectory=$APP_DIR Environment=PATH=/usr/local/bin:/usr/bin:/bin Environment=PYTHONPATH=$APP_DIR ExecStart=/usr/bin/python3 $APP_DIR/app.py Restart=always RestartSec=10 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target EOF # Systemd Service für LightDM Management (ersetzt den alten X-Server Service) progress "Erstelle Systemd-Service für Display Manager..." cat > "/etc/systemd/system/myp-display.service" << EOF [Unit] Description=MYP Display Manager Service After=myp-druckerverwaltung.service network.target Requires=myp-druckerverwaltung.service Wants=myp-druckerverwaltung.service [Service] Type=oneshot RemainAfterExit=yes ExecStartPre=/bin/bash -c 'while ! curl -s http://localhost:5000 > /dev/null; do sleep 2; done' ExecStart=/bin/systemctl start lightdm ExecStop=/bin/systemctl stop lightdm StandardOutput=journal StandardError=journal [Install] WantedBy=graphical.target EOF # Systemd Service für Kiosk-Überwachung progress "Erstelle erweiterten Kiosk-Überwachungs-Service..." cat > "/etc/systemd/system/myp-kiosk-monitor.service" << EOF [Unit] Description=MYP Kiosk Monitor und Recovery Service After=graphical.target lightdm.service Requires=myp-druckerverwaltung.service [Service] Type=simple User=root ExecStart=/bin/bash -c ' while true; do # Prüfe ob Anwendung läuft if ! curl -s http://localhost:5000 > /dev/null; then echo "\$(date): Anwendung nicht erreichbar - starte neu" >> /var/log/kiosk-monitor.log systemctl restart myp-druckerverwaltung sleep 10 fi # Prüfe ob LightDM läuft if ! systemctl is-active --quiet lightdm; then echo "\$(date): LightDM nicht aktiv - starte neu" >> /var/log/kiosk-monitor.log systemctl start lightdm sleep 5 fi # Prüfe ob Kiosk-Benutzer angemeldet ist if ! pgrep -u $KIOSK_USER > /dev/null; then echo "\$(date): Kiosk-Benutzer nicht angemeldet - starte LightDM neu" >> /var/log/kiosk-monitor.log systemctl restart lightdm sleep 10 fi # Prüfe ob Chromium im Kiosk-Modus läuft if ! pgrep -u $KIOSK_USER -f "chromium.*kiosk" > /dev/null; then echo "\$(date): Chromium-Kiosk nicht gefunden - starte Kiosk-Session neu" >> /var/log/kiosk-monitor.log # Versuche Kiosk-Neustart als Kiosk-Benutzer sudo -u $KIOSK_USER DISPLAY=:0 $HOME/start-kiosk.sh & fi sleep 30 done ' Restart=always RestartSec=10 [Install] WantedBy=graphical.target EOF # Nginx-Proxy-Konfiguration progress "Konfiguriere Nginx..." cat > "/etc/nginx/sites-available/myp-kiosk" << EOF server { listen 80 default_server; listen [::]:80 default_server; server_name _; # Security Headers add_header X-Frame-Options DENY always; add_header X-Content-Type-Options nosniff always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';" always; location / { proxy_pass http://127.0.0.1:5000; proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto \$scheme; # WebSocket-Support proxy_http_version 1.1; proxy_set_header Upgrade \$http_upgrade; proxy_set_header Connection "upgrade"; # Timeout-Konfiguration proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; } # Statische Dateien location /static/ { alias $APP_DIR/static/; expires 1y; add_header Cache-Control "public, immutable"; } } EOF # Nginx-Site aktivieren rm -f /etc/nginx/sites-enabled/default ln -sf /etc/nginx/sites-available/myp-kiosk /etc/nginx/sites-enabled/ # Erstelle systemd-logind Konfiguration für besseres Session-Management progress "Konfiguriere systemd-logind für Kiosk..." cat > "/etc/systemd/logind.conf.d/kiosk.conf" << EOF [Login] # Verhindere dass System bei Inaktivität heruntergefahren wird IdleAction=ignore IdleActionSec=infinity # Verhindere Suspend/Hibernate HandlePowerKey=ignore HandleSuspendKey=ignore HandleHibernateKey=ignore HandleLidSwitch=ignore # Session-Einstellungen für Kiosk KillUserProcesses=no UserStopDelaySec=10 # Automatic VT allocation ReserveVT=1 EOF # Erstelle PAM-Konfiguration für Auto-Login progress "Konfiguriere PAM für Auto-Login..." cat > "/etc/pam.d/lightdm-autologin" << EOF # PAM configuration for LightDM autologin auth required pam_env.so auth required pam_permit.so @include common-account session required pam_limits.so @include common-session @include common-password EOF # Services aktivieren progress "Aktiviere Services..." systemctl daemon-reload systemctl enable myp-druckerverwaltung systemctl enable nginx systemctl enable myp-display systemctl enable myp-kiosk-monitor # SSH standardmäßig deaktivieren für Sicherheit systemctl disable ssh || true # Sicherstellen dass graphical.target Standard ist systemctl set-default graphical.target # Erstelle systemd override für bessere Kiosk-Integration progress "Erstelle systemd-Overrides..." mkdir -p "/etc/systemd/system/lightdm.service.d" cat > "/etc/systemd/system/lightdm.service.d/kiosk-override.conf" << EOF [Unit] After=myp-druckerverwaltung.service [Service] # Automatischer Restart bei Fehlern Restart=always RestartSec=5 # Umgebungsvariablen für Kiosk Environment=DISPLAY=:0 Environment=KIOSK_MODE=1 EOF log "✅ Autostart konfiguriert mit LightDM-Integration" } # ========================== SICHERHEIT ========================== configure_security() { log "=== PHASE 8: SICHERHEITS-KONFIGURATION ===" progress "Konfiguriere Firewall..." ufw --force enable ufw default deny incoming ufw default allow outgoing ufw allow 22/tcp # SSH ufw allow 80/tcp # HTTP progress "Konfiguriere Fail2Ban..." cat > "/etc/fail2ban/jail.local" << EOF [DEFAULT] bantime = 600 findtime = 600 maxretry = 3 [sshd] enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 3 [nginx-http-auth] enabled = true filter = nginx-http-auth port = http,https logpath = /var/log/nginx/error.log maxretry = 5 EOF # Automatische Updates progress "Konfiguriere automatische Updates..." apt-get install -y unattended-upgrades echo 'Unattended-Upgrade::Automatic-Reboot "false";' > /etc/apt/apt.conf.d/50unattended-upgrades-local # Kiosk-Benutzer Einschränkungen progress "Beschränke Kiosk-Benutzer..." # Kein sudo für kiosk-Benutzer gpasswd -d "$KIOSK_USER" sudo 2>/dev/null || true # Shell auf /bin/false für bessere Sicherheit (aber X11 muss funktionieren) # usermod -s /bin/false "$KIOSK_USER" # Erstmal nicht, da X11 funktionieren muss log "✅ Sicherheit konfiguriert" } # ========================== WARTUNGSTOOLS ========================== create_maintenance_tools() { log "=== PHASE 9: WARTUNGSTOOLS ===" # Wartungsskript cat > "/usr/local/bin/myp-maintenance" << 'EOF' #!/bin/bash case "$1" in start) echo "Starte alle MYP-Services..." systemctl start myp-druckerverwaltung systemctl start nginx systemctl start myp-display systemctl start myp-kiosk-monitor echo "Services gestartet." ;; stop) echo "Stoppe alle MYP-Services..." systemctl stop myp-kiosk-monitor systemctl stop myp-display systemctl stop lightdm systemctl stop nginx systemctl stop myp-druckerverwaltung echo "Services gestoppt." ;; restart) echo "Starte alle MYP-Services neu..." systemctl restart myp-druckerverwaltung sleep 3 systemctl restart nginx systemctl restart myp-display systemctl restart myp-kiosk-monitor echo "Services neugestartet." ;; status) echo "=== MYP SYSTEM STATUS ===" echo echo "📱 Anwendung:" systemctl status myp-druckerverwaltung --no-pager -l echo echo "🌐 Nginx Proxy:" systemctl status nginx --no-pager -l echo echo "🖥️ Display Manager:" systemctl status lightdm --no-pager -l echo echo "🔍 Kiosk Monitor:" systemctl status myp-kiosk-monitor --no-pager -l echo echo "👤 Kiosk-Benutzer-Sessions:" who | grep kiosk || echo "Kein Kiosk-Benutzer angemeldet" echo echo "🌐 Anwendung erreichbar:" if curl -s http://localhost:5000 > /dev/null; then echo "✅ http://localhost:5000 erreichbar" else echo "❌ http://localhost:5000 NICHT erreichbar" fi ;; logs) echo "=== ANWENDUNGS-LOGS (Strg+C zum Beenden) ===" journalctl -u myp-druckerverwaltung -f ;; kiosk-logs) echo "=== KIOSK-LOGS (Strg+C zum Beenden) ===" echo "Monitor-Logs:" journalctl -u myp-kiosk-monitor -f & echo "LightDM-Logs:" journalctl -u lightdm -f & echo "Session-Logs:" tail -f /var/log/kiosk-session.log 2>/dev/null & wait ;; app-restart) echo "Starte nur Anwendung neu..." systemctl restart myp-druckerverwaltung echo "Anwendung neugestartet." ;; kiosk-restart) echo "Starte nur Kiosk-Display neu..." systemctl restart lightdm echo "Kiosk-Display neugestartet." ;; monitor-restart) echo "Starte Kiosk-Monitor neu..." systemctl restart myp-kiosk-monitor echo "Kiosk-Monitor neugestartet." ;; enable-ssh) echo "Aktiviere SSH für Wartung..." systemctl enable ssh systemctl start ssh echo "✅ SSH aktiviert für Remote-Wartung" echo "SSH-Status: $(systemctl is-active ssh)" echo "IP-Adresse: $(hostname -I | awk '{print $1}')" ;; disable-ssh) echo "Deaktiviere SSH für Sicherheit..." systemctl stop ssh systemctl disable ssh echo "✅ SSH deaktiviert" ;; exit-kiosk) echo "🔐 KIOSK-MODUS BEENDEN" echo "WARNUNG: Stoppt den Kiosk und aktiviert Wartungsmodus!" echo "Passwort erforderlich für Sicherheit." read -s -p "Kiosk-Passwort: " password echo if [ "$password" = "744563017196A" ]; then echo "✅ Passwort korrekt - beende Kiosk-Modus..." systemctl stop myp-kiosk-monitor systemctl stop lightdm systemctl enable ssh systemctl start ssh echo "🔧 Wartungsmodus aktiviert:" echo " • Kiosk gestoppt" echo " • SSH aktiviert" echo " • Console verfügbar" echo "Kiosk-Neustart mit: myp-maintenance start" else echo "❌ Falsches Passwort! Kiosk bleibt aktiv." exit 1 fi ;; enter-kiosk) echo "Aktiviere Kiosk-Modus..." systemctl disable ssh 2>/dev/null || true systemctl stop ssh 2>/dev/null || true systemctl start myp-druckerverwaltung systemctl start nginx systemctl start myp-display systemctl start myp-kiosk-monitor echo "✅ Kiosk-Modus aktiviert" ;; check-health) echo "=== SYSTEM-GESUNDHEITSCHECK ===" echo # Services-Check echo "📋 Service-Status:" for service in myp-druckerverwaltung nginx lightdm myp-kiosk-monitor; do if systemctl is-active --quiet $service; then echo " ✅ $service: aktiv" else echo " ❌ $service: INAKTIV" fi done # DNS-Service-Check if systemctl is-active --quiet unbound; then echo " ✅ unbound: aktiv" else echo " ❌ unbound: INAKTIV" fi echo # Netzwerk-Check echo "🌐 Netzwerk-Status:" if curl -s http://localhost:5000 > /dev/null; then echo " ✅ Anwendung erreichbar" else echo " ❌ Anwendung NICHT erreichbar" fi # DNS-Check if nslookup google.com 127.0.0.1 &> /dev/null; then echo " ✅ DNS-Auflösung funktional" else echo " ❌ DNS-Auflösung FEHLERHAFT" fi # IPv6-Check if [ "$(sysctl -n net.ipv6.conf.all.disable_ipv6)" = "1" ]; then echo " ✅ IPv6 deaktiviert (gewünscht)" else echo " ⚠️ IPv6 noch aktiv" fi echo # Kiosk-Check echo "🖥️ Kiosk-Status:" if pgrep -u kiosk > /dev/null; then echo " ✅ Kiosk-Benutzer angemeldet" else echo " ❌ Kiosk-Benutzer NICHT angemeldet" fi if pgrep -f "chromium.*kiosk" > /dev/null; then echo " ✅ Chromium-Kiosk läuft" else echo " ❌ Chromium-Kiosk läuft NICHT" fi echo # Ressourcen-Check echo "💾 System-Ressourcen:" echo " CPU: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)% belegt" echo " RAM: $(free | grep Mem | awk '{printf "%.1f%%", $3/$2 * 100.0}')" echo " Disk: $(df / | tail -1 | awk '{print $5}')" ;; auto-fix) echo "🔧 AUTOMATISCHE REPARATUR" echo "Versuche häufige Probleme zu beheben..." # Services neu starten echo "1. Starte Services neu..." systemctl restart myp-druckerverwaltung sleep 3 systemctl restart nginx systemctl restart lightdm systemctl restart myp-kiosk-monitor # DNS-Services reparieren echo "2. Repariere DNS-Services..." systemctl restart unbound systemctl restart dns-priority-config /usr/local/bin/configure-dns-priority # Berechtigungen reparieren echo "3. Repariere Berechtigungen..." chown -R kiosk:kiosk /home/kiosk chown -R myp:myp /opt/myp-druckerverwaltung # Logs bereinigen echo "4. Bereinige alte Logs..." journalctl --rotate journalctl --vacuum-time=7d echo "✅ Automatische Reparatur abgeschlossen" echo "Prüfe Status mit: myp-maintenance check-health" ;; dns-status) echo "=== DNS-KONFIGURATION STATUS ===" echo echo "🔍 Unbound Service:" systemctl status unbound --no-pager -l echo echo "📋 Aktuelle DNS-Server:" cat /etc/resolv.conf | grep nameserver echo echo "🌐 Router-DNS (erkannt):" /usr/local/bin/configure-dns-priority 2>/dev/null | grep "Erkannte Router-DNS" | tail -1 || echo "Keine Router-DNS erkannt" echo echo "📊 DNS-Statistiken:" if command -v unbound-control &> /dev/null; then unbound-control stats_noreset 2>/dev/null | head -10 || echo "Unbound-Control nicht verfügbar" fi echo echo "📝 Letzte DNS-Logs:" tail -10 /var/log/dns-configuration.log 2>/dev/null || echo "Keine DNS-Logs verfügbar" ;; dns-test) echo "=== DNS-AUFLÖSUNGSTEST ===" echo test_domains=("google.com" "github.com" "debian.org" "cloudflare.com") for domain in "${test_domains[@]}"; do echo -n "Testing $domain: " if nslookup "$domain" 127.0.0.1 &> /dev/null; then echo "✅ OK" else echo "❌ FEHLER" fi done echo echo "🔍 DNS-Gesundheitscheck:" /usr/local/bin/dns-health-check ;; dns-reconfigure) echo "=== DNS-KONFIGURATION NEU LADEN ===" echo "Lade DNS-Konfiguration mit Router-Erkennung neu..." /usr/local/bin/configure-dns-priority echo "✅ DNS-Konfiguration neu geladen" echo "Test mit: myp-maintenance dns-test" ;; ipv6-status) echo "=== IPv6-STATUS ===" echo echo "🔍 IPv6 Kernel-Parameter:" sysctl net.ipv6.conf.all.disable_ipv6 sysctl net.ipv6.conf.default.disable_ipv6 echo echo "🌐 IPv6-Adressen:" ip -6 addr show | grep inet6 || echo "Keine IPv6-Adressen (deaktiviert)" echo echo "📋 IPv6-Routen:" ip -6 route show 2>/dev/null || echo "Keine IPv6-Routen (deaktiviert)" ;; *) echo "MYP Druckerverwaltung - Wartungstool" echo echo "VERWENDUNG: $0 BEFEHL" echo echo "SERVICE-MANAGEMENT:" echo " start Alle Services starten" echo " stop Alle Services stoppen" echo " restart Alle Services neustarten" echo " status Detaillierter Status aller Services" echo echo "EINZELNE SERVICES:" echo " app-restart Nur Anwendung neustarten" echo " kiosk-restart Nur Kiosk-Display neustarten" echo " monitor-restart Nur Kiosk-Monitor neustarten" echo echo "LOGS & MONITORING:" echo " logs Live Anwendungs-Logs anzeigen" echo " kiosk-logs Live Kiosk-Logs anzeigen" echo " check-health System-Gesundheitscheck" echo echo "KIOSK-KONTROLLE:" echo " exit-kiosk Kiosk beenden (Passwort: 744563017196A)" echo " enter-kiosk Kiosk-Modus aktivieren" echo echo "DNS & NETZWERK:" echo " dns-status DNS-Konfiguration anzeigen" echo " dns-test DNS-Auflösung testen" echo " dns-reconfigure DNS-Konfiguration neu laden" echo " ipv6-status IPv6-Status prüfen" echo echo "WARTUNG:" echo " enable-ssh SSH für Remote-Wartung aktivieren" echo " disable-ssh SSH wieder deaktivieren" echo " auto-fix Automatische Problemreparatur" echo echo "BEISPIELE:" echo " $0 status # System-Status anzeigen" echo " $0 logs # Live-Logs verfolgen" echo " $0 exit-kiosk # Wartungsmodus aktivieren" ;; esac EOF chmod +x /usr/local/bin/myp-maintenance # Backup-Skript cat > "/usr/local/bin/myp-backup" << EOF #!/bin/bash BACKUP_DIR="$BACKUP_DIR" DATE=\$(date +%Y%m%d_%H%M%S) mkdir -p "\$BACKUP_DIR" echo "Erstelle MYP-System-Backup..." # Services kurz stoppen für konsistentes Backup systemctl stop myp-druckerverwaltung # Erstelle Backup tar -czf "\$BACKUP_DIR/myp_backup_\$DATE.tar.gz" \\ -C "$APP_DIR" \\ --exclude='node_modules' \\ --exclude='__pycache__' \\ --exclude='venv' \\ --exclude='*.log' \\ database.db .env uploads/ config/ 2>/dev/null || true # Backup der Kiosk-Konfiguration tar -czf "\$BACKUP_DIR/kiosk_config_\$DATE.tar.gz" \\ /home/kiosk/.config \\ /etc/lightdm/lightdm.conf \\ /usr/share/lightdm/setup-kiosk-session.sh \\ /etc/systemd/system/myp-*.service \\ /usr/local/bin/myp-* 2>/dev/null || true # Services wieder starten systemctl start myp-druckerverwaltung echo "✅ Backup erstellt:" echo " Anwendung: \$BACKUP_DIR/myp_backup_\$DATE.tar.gz" echo " Kiosk-Config: \$BACKUP_DIR/kiosk_config_\$DATE.tar.gz" # Alte Backups löschen (älter als 30 Tage) find "\$BACKUP_DIR" -name "myp_backup_*.tar.gz" -mtime +30 -delete 2>/dev/null || true find "\$BACKUP_DIR" -name "kiosk_config_*.tar.gz" -mtime +30 -delete 2>/dev/null || true echo "🧹 Alte Backups (>30 Tage) entfernt" EOF chmod +x /usr/local/bin/myp-backup # Notfall-Reset cat > "/usr/local/bin/myp-emergency-reset" << 'EOF' #!/bin/bash echo "🚨 NOTFALL-RESET für MYP Kiosk-System" echo "======================================" echo echo "WARNUNG: Dieser Befehl wird:" echo " • Alle Kiosk-Services stoppen" echo " • SSH für Remote-Wartung aktivieren" echo " • Console-Zugang ermöglichen" echo " • System in Wartungsmodus versetzen" echo echo "Nur bei kritischen Problemen verwenden!" echo read -p "Notfall-Reset durchführen? (RESET eingeben): " confirm if [ "$confirm" = "RESET" ]; then echo echo "🔧 Führe Notfall-Reset durch..." # Stoppe alle Kiosk-Services systemctl stop myp-kiosk-monitor 2>/dev/null || true systemctl stop lightdm 2>/dev/null || true # Aktiviere SSH systemctl enable ssh 2>/dev/null || true systemctl start ssh 2>/dev/null || true # Logge Reset echo "$(date): Notfall-Reset durchgeführt" >> /var/log/emergency-reset.log echo "✅ Notfall-Reset abgeschlossen!" echo echo "📋 AKTUELLE SITUATION:" echo " • Kiosk-Modus: GESTOPPT" echo " • SSH: AKTIVIERT für Remote-Wartung" echo " • Console: Verfügbar auf TTY1-6 (Strg+Alt+F1-F6)" echo " • IP-Adresse: $(hostname -I | awk '{print $1}')" echo echo "🔧 WARTUNGSOPTIONEN:" echo " • Status prüfen: myp-maintenance status" echo " • Gesundheitscheck: myp-maintenance check-health" echo " • Automatische Fix: myp-maintenance auto-fix" echo " • Kiosk reaktivieren: myp-maintenance enter-kiosk" echo else echo "❌ Abgebrochen. System bleibt unverändert." fi EOF chmod +x /usr/local/bin/myp-emergency-reset # Erweiterte Cron-Jobs cat > "/etc/cron.d/myp-system" << EOF # MYP System Maintenance Cron Jobs # Tägliches Backup um 2:00 Uhr 0 2 * * * root /usr/local/bin/myp-backup >> /var/log/myp-backup.log 2>&1 # Gesundheitscheck alle 10 Minuten */10 * * * * root /usr/local/bin/myp-maintenance check-health > /dev/null 2>&1 || echo "\$(date): Health check failed" >> /var/log/myp-health.log # Log-Rotation wöchentlich (Sonntags um 3:00) 0 3 * * 0 root journalctl --rotate && journalctl --vacuum-time=30d # System-Ressourcen-Log alle 5 Minuten */5 * * * * root echo "\$(date),\$(cat /proc/loadavg | cut -d' ' -f1-3),\$(free | grep Mem | awk '{printf \"%.1f\", \$3/\$2 * 100.0}')" >> /var/log/system-resources.log EOF log "✅ Erweiterte Wartungstools erstellt" } # ========================== FINALE KONFIGURATION ========================== finalize_installation() { log "=== PHASE 10: FINALISIERUNG ===" # Services starten progress "Starte Services..." systemctl start myp-druckerverwaltung sleep 3 systemctl start nginx # Warte und prüfe Services sleep 5 if systemctl is-active --quiet myp-druckerverwaltung; then log "✅ MYP-Anwendung läuft" else warning "⚠️ MYP-Anwendung nicht aktiv" fi if systemctl is-active --quiet nginx; then log "✅ Nginx läuft" else warning "⚠️ Nginx nicht aktiv" fi # Test ob Anwendung erreichbar ist progress "Teste Anwendung..." for i in {1..30}; do if curl -s http://localhost:5000 > /dev/null; then log "✅ Anwendung erreichbar unter http://localhost:5000" break else if [ $i -eq 30 ]; then warning "⚠️ Anwendung nach 30 Versuchen nicht erreichbar" else sleep 2 fi fi done # Chromium-Test progress "Teste Chromium-Installation..." if [[ "$CHROMIUM_BIN" == "flatpak"* ]]; then sudo -u "$KIOSK_USER" flatpak run org.chromium.Chromium --version > /dev/null 2>&1 && log "✅ Chromium (Flatpak) funktional" || warning "⚠️ Chromium (Flatpak) Test fehlgeschlagen" else sudo -u "$KIOSK_USER" "$CHROMIUM_BIN" --version > /dev/null 2>&1 && log "✅ Chromium funktional" || warning "⚠️ Chromium-Test fehlgeschlagen" fi # Teste Auto-Login-Konfiguration progress "Teste Auto-Login-Konfiguration..." if [ -f "/etc/lightdm/lightdm.conf" ] && grep -q "autologin-user=$KIOSK_USER" "/etc/lightdm/lightdm.conf"; then log "✅ Auto-Login für $KIOSK_USER konfiguriert" else warning "⚠️ Auto-Login-Konfiguration unvollständig" fi # Teste Systemd-Services progress "Teste Service-Konfiguration..." for service in myp-druckerverwaltung myp-display myp-kiosk-monitor; do if systemctl is-enabled --quiet "$service" 2>/dev/null; then log "✅ Service $service aktiviert" else warning "⚠️ Service $service nicht aktiviert" fi done # Teste Wartungstools progress "Teste Wartungstools..." if [ -x "/usr/local/bin/myp-maintenance" ]; then log "✅ myp-maintenance verfügbar" else warning "⚠️ myp-maintenance nicht verfügbar" fi if [ -x "/usr/local/bin/myp-backup" ]; then log "✅ myp-backup verfügbar" else warning "⚠️ myp-backup nicht verfügbar" fi if [ -x "/usr/local/bin/myp-emergency-reset" ]; then log "✅ myp-emergency-reset verfügbar" else warning "⚠️ myp-emergency-reset nicht verfügbar" fi # Erstelle erste Logs progress "Initialisiere Logging..." touch /var/log/kiosk-session.log touch /var/log/kiosk-monitor.log touch /var/log/kiosk-watchdog.log touch /var/log/emergency-reset.log touch /var/log/myp-backup.log touch /var/log/myp-health.log touch /var/log/system-resources.log # Berechtigungen setzen chown syslog:adm /var/log/kiosk-*.log chown syslog:adm /var/log/myp-*.log chown syslog:adm /var/log/emergency-reset.log chown syslog:adm /var/log/system-resources.log # Finale Berechtigungen chown -R "$APP_USER:$APP_USER" "$APP_DIR" chown -R "$KIOSK_USER:$KIOSK_USER" "/home/$KIOSK_USER" # System-Target finalisieren systemctl set-default graphical.target log "✅ Installation finalisiert" } # ========================== INSTALLATIONS-BERICHT ========================== show_installation_report() { local ip_address=$(hostname -I | awk '{print $1}') cat << EOF ╔══════════════════════════════════════════════════════════════╗ ║ 🎉 KIOSK-INSTALLATION ERFOLGREICH! 🎉 ║ ╚══════════════════════════════════════════════════════════════╝ 📋 INSTALLATIONS-ZUSAMMENFASSUNG: • System-Typ: Vollautomatischer Sicherheits-Kiosk • Anwendung: $APP_DIR • Kiosk-URL: http://$ip_address (nach Neustart) • Chromium: $CHROMIUM_BIN • Display Manager: LightDM mit Auto-Login • Kiosk-Benutzer: $KIOSK_USER (automatisch angemeldet) • App-Benutzer: $APP_USER 🛡️ SICHERHEITS-FEATURES: • Desktop-Flucht: Vollständig verhindert • Tastatur-Shortcuts: Alle deaktiviert • Browser-Escape: Unmöglich (Kiosk-Flags) • SSH: Standardmäßig deaktiviert • Firewall: Aktiv mit Fail2Ban-Schutz • Auto-Login: Sicher konfiguriert • Session-Isolation: Kiosk-Benutzer ohne sudo 🔧 AUTOSTART-ABSICHERUNG (7-fach): ✅ 1. LightDM Auto-Login ✅ 2. Systemd User-Service ✅ 3. Bashrc Autostart ✅ 4. Profile Autostart ✅ 5. XDG Desktop Autostart ✅ 6. Cron Watchdog ✅ 7. RC.Local Fallback 🚀 SYSTEMD-SERVICES: • myp-druckerverwaltung.service → Flask-Anwendung • myp-display.service → LightDM-Management • myp-kiosk-monitor.service → Kiosk-Überwachung + Recovery • nginx.service → Reverse-Proxy • lightdm.service → Display Manager mit Auto-Login 🔧 WARTUNGSTOOLS: 📱 myp-maintenance: • status - Detaillierter System-Status • restart - Alle Services neustarten • exit-kiosk - Wartungsmodus (Passwort: 744563017196A) • enable-ssh - SSH für Remote-Wartung • check-health - Automatischer Gesundheitscheck • auto-fix - Automatische Problemreparatur 💾 myp-backup: • Automatisch: Täglich 2:00 Uhr • Manuell: myp-backup • Aufbewahrung: 30 Tage 🚨 myp-emergency-reset: • Notfall-Tool bei kritischen Problemen • Stoppt Kiosk, aktiviert SSH 📊 MONITORING & LOGS: • System-Health: Alle 10 Minuten automatisch • Resource-Logs: Alle 5 Minuten • Service-Überwachung: Kontinuierlich mit Auto-Recovery • Log-Rotation: Wöchentlich (30 Tage Aufbewahrung) ⚠️ WICHTIGE HINWEISE: • System bootet automatisch in VOLLBILD-KIOSK ohne Escape • Kein Desktop verfügbar - nur MYP-Anwendung sichtbar • SSH deaktiviert für maximale Sicherheit • Bei Problemen: Console-Zugang via Strg+Alt+F1-F6 🔐 NOTFALL-ZUGANG: 1. Console: Strg+Alt+F1 bis F6 → Login als Root/sudo-User 2. Emergency: myp-emergency-reset → RESET eingeben 3. Remote: myp-maintenance enable-ssh → SSH verfügbar 🚀 NÄCHSTE SCHRITTE: 1. System neustarten: sudo reboot 2. ⏱️ System bootet in ~2 Minuten automatisch in Kiosk-Modus 3. 🖥️ Chromium startet automatisch im Vollbild 4. 📱 MYP-Anwendung verfügbar unter http://$ip_address 5. 🔒 Kein Escape möglich - echtes Kiosk-System 📞 WARTUNG & SUPPORT: • Live Status: myp-maintenance status • Logs verfolgen: myp-maintenance logs • Kiosk beenden: myp-maintenance exit-kiosk • Gesundheitscheck: myp-maintenance check-health • Backup erstellen: myp-backup 🎯 LEISTUNGS-FEATURES: ✅ Multi-Browser-Fallback (APT → Snap → Flatpak) ✅ Service-Recovery bei Fehlern ✅ Session-Monitoring mit Auto-Restart ✅ Resource-Monitoring und Logging ✅ Automatische Backups mit Rotation ✅ Health-Checks mit Auto-Fix ✅ Emergency-Recovery-System ══════════════════════════════════════════════════════════════ Installation abgeschlossen: $(date) Installationslog: $INSTALL_LOG SYSTEM BEREIT FÜR PRODUKTIONS-KIOSK-BETRIEB! 🚀 ══════════════════════════════════════════════════════════════ EOF } # ========================== KEYMAP-PROBLEM BEHEBEN ========================== fix_keymap_issues() { log "=== PHASE 0.3: KEYMAP-PROBLEME BEHEBEN ===" progress "Behebe bekannte Keymap-Probleme..." # Installiere alle keyboard-bezogenen Pakete progress "Installiere vollständige Keyboard-Unterstützung..." apt-get install -y \ keyboard-configuration \ console-setup \ console-data \ kbd \ console-common \ xkb-data \ locales \ 2>/dev/null || warning "Einige Keyboard-Pakete konnten nicht installiert werden" # Generiere Locales falls noch nicht vorhanden progress "Generiere deutsche Locales..." if [ -f "/etc/locale.gen" ]; then sed -i 's/# de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/' /etc/locale.gen sed -i 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen locale-gen 2>/dev/null || warning "Locale-Generierung teilweise fehlgeschlagen" update-locale LANG=de_DE.UTF-8 2>/dev/null || true fi # Prüfe und repariere Keymap-Verzeichnisse progress "Prüfe Keymap-Verzeichnisse..." # Erstelle Keymap-Verzeichnisse falls sie fehlen mkdir -p /usr/share/keymaps/i386/qwertz 2>/dev/null || true mkdir -p /usr/share/kbd/keymaps/i386/qwertz 2>/dev/null || true mkdir -p /lib/kbd/keymaps/i386/qwertz 2>/dev/null || true # Prüfe ob deutsche Keymap verfügbar ist KEYMAP_FOUND=false for keymap_path in \ "/usr/share/keymaps/i386/qwertz/de.kmap.gz" \ "/usr/share/kbd/keymaps/i386/qwertz/de.map.gz" \ "/lib/kbd/keymaps/i386/qwertz/de.map.gz" \ "/usr/share/keymaps/i386/qwertz/de-latin1.kmap.gz" \ "/usr/share/kbd/keymaps/i386/qwertz/de-latin1.map.gz"; do if [ -f "$keymap_path" ]; then KEYMAP_FOUND=true info "Deutsche Keymap gefunden: $keymap_path" break fi done if [ "$KEYMAP_FOUND" = false ]; then warning "Keine deutsche Keymap gefunden - versuche Reparatur..." # Versuche console-data zu rekonfigurieren if dpkg -l | grep -q console-data; then dpkg-reconfigure -f noninteractive console-data 2>/dev/null || true fi # Versuche kbd zu rekonfigurieren if dpkg -l | grep -q "^ii.*kbd"; then dpkg-reconfigure -f noninteractive kbd 2>/dev/null || true fi # Fallback: Erstelle minimale deutsche Keymap if [ ! -f "/usr/share/keymaps/i386/qwertz/de.kmap.gz" ]; then warning "Erstelle Fallback-Keymap..." mkdir -p /usr/share/keymaps/i386/qwertz # Erstelle einfache deutsche Keymap cat > /tmp/de.kmap << 'EOF' # German keyboard layout keymaps 0-15 keycode 1 = Escape keycode 2 = one exclam keycode 3 = two quotedbl keycode 4 = three section keycode 5 = four dollar keycode 6 = five percent keycode 7 = six ampersand keycode 8 = seven slash keycode 9 = eight parenleft keycode 10 = nine parenright keycode 11 = zero equal keycode 12 = ssharp question keycode 13 = dead_acute dead_grave keycode 14 = BackSpace keycode 15 = Tab keycode 16 = q Q keycode 17 = w W keycode 18 = e E keycode 19 = r R keycode 20 = t T keycode 21 = z Z keycode 22 = u U keycode 23 = i I keycode 24 = o O keycode 25 = p P keycode 26 = udiaeresis Udiaeresis keycode 27 = plus asterisk keycode 28 = Return keycode 29 = Control keycode 30 = a A keycode 31 = s S keycode 32 = d D keycode 33 = f F keycode 34 = g G keycode 35 = h H keycode 36 = j J keycode 37 = k K keycode 38 = l L keycode 39 = odiaeresis Odiaeresis keycode 40 = adiaeresis Adiaeresis keycode 41 = dead_circumflex degree keycode 42 = Shift keycode 43 = numbersign apostrophe keycode 44 = y Y keycode 45 = x X keycode 46 = c C keycode 47 = v V keycode 48 = b B keycode 49 = n N keycode 50 = m M keycode 51 = comma semicolon keycode 52 = period colon keycode 53 = minus underscore keycode 54 = Shift keycode 57 = space EOF gzip /tmp/de.kmap mv /tmp/de.kmap.gz /usr/share/keymaps/i386/qwertz/de.kmap.gz 2>/dev/null || true info "Fallback deutsche Keymap erstellt" fi fi # Teste Keymap-Funktionalität progress "Teste Keymap-Funktionalität..." if command -v loadkeys &> /dev/null; then if loadkeys de 2>/dev/null; then info "✅ Deutsche Keymap erfolgreich geladen" else warning "⚠️ Deutsche Keymap konnte nicht geladen werden" # Versuche alternative Keymaps for alt_keymap in de-latin1 de_DE german; do if loadkeys "$alt_keymap" 2>/dev/null; then info "✅ Alternative Keymap '$alt_keymap' geladen" break fi done fi fi # Repariere localectl falls verfügbar if command -v localectl &> /dev/null; then progress "Repariere localectl-Konfiguration..." # Erstelle systemd-localed Verzeichnis falls es fehlt mkdir -p /etc/systemd/system/systemd-localed.service.d 2>/dev/null || true # Versuche localectl zu reparieren if ! localectl status &> /dev/null; then warning "localectl nicht funktional - versuche Reparatur..." # Starte systemd-localed Service systemctl start systemd-localed 2>/dev/null || true systemctl enable systemd-localed 2>/dev/null || true # Warte kurz und versuche erneut sleep 2 if localectl status &> /dev/null; then info "✅ localectl repariert" localectl set-keymap de 2>/dev/null || true localectl set-x11-keymap de 2>/dev/null || true else warning "localectl bleibt nicht funktional - verwende alternative Methoden" fi else info "✅ localectl funktional" fi fi # Erstelle vconsole.conf für systemd-Systeme progress "Konfiguriere vconsole.conf..." cat > /etc/vconsole.conf << EOF KEYMAP=de FONT=eurlatgr EOF # Aktualisiere initramfs mit neuen Keymap-Einstellungen if command -v update-initramfs &> /dev/null; then progress "Aktualisiere initramfs..." update-initramfs -u 2>/dev/null || warning "initramfs-Update fehlgeschlagen" fi log "✅ Keymap-Probleme behoben" } # ========================== HAUPTPROGRAMM ========================== main() { log "🚀 MYP Kiosk-Installation gestartet: $(date)" check_root detect_system setup_system_basics fix_keymap_issues update_system install_certificates create_directory_structure cleanup_system install_packages install_chromium create_users install_application set_file_permissions configure_kiosk optimize_raspberry_pi configure_dns_and_network configure_autologin configure_multiple_autostart configure_autostart configure_security create_maintenance_tools finalize_installation show_installation_report # Abschließende Frage echo read -p "🔄 System jetzt neustarten für Kiosk-Modus? (j/N): " reboot_choice if [[ "$reboot_choice" =~ ^[jJ]$ ]]; then log "🚀 Neustart für Kiosk-Modus..." sleep 3 reboot else log "⚠️ Manueller Neustart erforderlich: sudo reboot" fi } # ========================== PROGRAMMSTART ========================== # Starte Installation main "$@" chmod +x /usr/local/bin/dns-health-check