diff --git a/backend/app/docs/DNS_KONFIGURATION.md b/backend/app/docs/DNS_KONFIGURATION.md new file mode 100644 index 00000000..0519ecba --- /dev/null +++ b/backend/app/docs/DNS_KONFIGURATION.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/backend/app/docs/KEYMAP_PROBLEME_BEHOBEN.md b/backend/app/docs/KEYMAP_PROBLEME_BEHOBEN.md new file mode 100644 index 00000000..0519ecba --- /dev/null +++ b/backend/app/docs/KEYMAP_PROBLEME_BEHOBEN.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/backend/app/docs/RASPBERRY_PI_OPTIMIERUNGEN.md b/backend/app/docs/RASPBERRY_PI_OPTIMIERUNGEN.md new file mode 100644 index 00000000..0519ecba --- /dev/null +++ b/backend/app/docs/RASPBERRY_PI_OPTIMIERUNGEN.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/backend/app/install_raspberry_pi.sh b/backend/app/install_raspberry_pi.sh index 35e730eb..39e0432e 100644 --- a/backend/app/install_raspberry_pi.sh +++ b/backend/app/install_raspberry_pi.sh @@ -16,6 +16,10 @@ 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*" @@ -39,20 +43,20 @@ CYAN='\033[0;36m' NC='\033[0m' # ========================== LOGGING-SYSTEM ========================== -log() { +log() { echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}" | tee -a "$INSTALL_LOG" } -error() { +error() { echo -e "${RED}[FEHLER] $1${NC}" | tee -a "$INSTALL_LOG" - exit 1 + exit 1 } -warning() { +warning() { echo -e "${YELLOW}[WARNUNG] $1${NC}" | tee -a "$INSTALL_LOG" } -info() { +info() { echo -e "${BLUE}[INFO] $1${NC}" | tee -a "$INSTALL_LOG" } @@ -62,7 +66,7 @@ progress() { # ========================== SYSTEM-CHECKS ========================== check_root() { - if [ "$EUID" -ne 0 ]; then +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" @@ -72,7 +76,7 @@ detect_system() { log "Erkenne System-Umgebung..." # Aktuelle Position ermitteln - CURRENT_DIR="$(pwd)" +CURRENT_DIR="$(pwd)" log "Aktuelles Verzeichnis: $CURRENT_DIR" # Prüfe ob wir uns im richtigen Verzeichnis befinden @@ -100,6 +104,251 @@ detect_system() { 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 ===" @@ -152,11 +401,81 @@ install_packages() { htop nano \ || error "Basis-Pakete Installation fehlgeschlagen" - # Node.js installieren - progress "Installiere Node.js..." - if ! command -v node &> /dev/null; then - curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - - apt-get install -y nodejs + # 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" @@ -236,58 +555,244 @@ create_users() { install_application() { log "=== PHASE 5: ANWENDUNGS-INSTALLATION ===" - # Anwendungsverzeichnis erstellen - progress "Erstelle Anwendungsverzeichnis: $APP_DIR" - mkdir -p "$APP_DIR" "$BACKUP_DIR" - # Anwendung kopieren progress "Kopiere Anwendung von $CURRENT_DIR nach $APP_DIR" - cp -r "$CURRENT_DIR"/* "$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" +cd "$APP_DIR" + + # DIREKTER PYTHON-PACKAGE INSTALL OHNE VENV - NEU! + progress "Installiere Python-Dependencies DIREKT (ohne Virtual Environment)..." - # Python Virtual Environment - progress "Erstelle Python Virtual Environment..." - sudo -u "$APP_USER" python3 -m venv venv - sudo -u "$APP_USER" ./venv/bin/pip install --upgrade pip + # Pip aktualisieren + python3 -m pip install --upgrade pip --break-system-packages - # Python-Dependencies installieren - progress "Installiere Python-Dependencies..." + # Requirements installieren if [ -f "requirements.txt" ]; then - sudo -u "$APP_USER" ./venv/bin/pip install -r requirements.txt + info "Installiere aus requirements.txt..." + python3 -m pip install -r requirements.txt --break-system-packages else # Basis-Pakete installieren - sudo -u "$APP_USER" ./venv/bin/pip install \ - flask flask-login flask-wtf flask-limiter \ - sqlalchemy werkzeug requests gunicorn \ - bcrypt cryptography PyP100 + 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 - # Node.js Dependencies + # 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..." - sudo -u "$APP_USER" npm install - if [ -f "tailwind.config.js" ]; then - sudo -u "$APP_USER" npm run build:css || true + + # 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..." - sudo -u "$APP_USER" ./venv/bin/python -c " -from app import app, db -from models import init_database, create_initial_admin -with app.app_context(): + 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 initialisiert') + 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 +cat > "$APP_DIR/.env" << EOF FLASK_ENV=production SECRET_KEY=$(openssl rand -hex 32) DATABASE_URL=sqlite:///database.db @@ -302,9 +807,86 @@ EOF 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: KIOSK-KONFIGURATION ===" + log "=== PHASE 6: ERWEITERTE KIOSK-KONFIGURATION ===" # Sicherer Kiosk-Benutzer-Setup KIOSK_HOME="/home/$KIOSK_USER" @@ -408,103 +990,946 @@ configure_kiosk() { EOF - # Autostart-Konfiguration - cat > "$KIOSK_HOME/.config/openbox/autostart" << EOF -#!/bin/bash - -# Warte auf X-Server -sleep 3 - -# Führe Kiosk-Skript aus -exec $KIOSK_HOME/start-kiosk.sh -EOF + # ERWEITERTE KIOSK-KONFIGURATION - Basierend auf Best Practices + progress "Erstelle erweiterte Kiosk-Skripte..." - # Haupt-Kiosk-Skript mit maximaler Sicherheit + # 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/ +# =================================================================== -# ===== KIOSK-SICHERHEITS-KONFIGURATION ===== 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 -# Mauszeiger verstecken -unclutter -idle 0.1 -root & +# 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 -# Screenshot-Tools deaktivieren -killall gnome-screenshot 2>/dev/null || true -killall scrot 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..." + 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 ===== -# Maximum security flags für echten Kiosk-Modus -$CHROMIUM_BIN \\ - --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 \\ - --noerrdialogs \\ - --force-color-profile=srgb \\ - --no-first-run \\ - --no-default-browser-check \\ - --autoplay-policy=no-user-gesture-required \\ - --start-fullscreen \\ - --window-position=0,0 \\ - --window-size=1920,1080 \\ - --app=http://localhost:5000 \\ - --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 \\ +# ===== 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/.config/openbox/autostart" 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 "✅ Kiosk-Konfiguration erstellt" + 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 ========================== @@ -786,7 +2211,7 @@ EOF systemctl enable kiosk-watchdog.service # Berechtigungen finalisieren - chown -R "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.config" +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" @@ -809,8 +2234,9 @@ Type=simple User=$APP_USER Group=$APP_USER WorkingDirectory=$APP_DIR -Environment=PATH=$APP_DIR/venv/bin -ExecStart=$APP_DIR/venv/bin/python app.py +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 @@ -819,7 +2245,7 @@ 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 @@ -892,7 +2318,7 @@ RestartSec=10 [Install] WantedBy=graphical.target EOF - + # Nginx-Proxy-Konfiguration progress "Konfiguriere Nginx..." cat > "/etc/nginx/sites-available/myp-kiosk" << EOF @@ -935,7 +2361,7 @@ server { } } EOF - + # Nginx-Site aktivieren rm -f /etc/nginx/sites-enabled/default ln -sf /etc/nginx/sites-available/myp-kiosk /etc/nginx/sites-enabled/ @@ -1204,6 +2630,13 @@ case "$1" in 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 @@ -1213,6 +2646,20 @@ case "$1" in 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 @@ -1248,19 +2695,81 @@ case "$1" in 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 "2. Repariere Berechtigungen..." + echo "3. Repariere Berechtigungen..." chown -R kiosk:kiosk /home/kiosk chown -R myp:myp /opt/myp-druckerverwaltung # Logs bereinigen - echo "3. Bereinige alte Logs..." + 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 @@ -1286,6 +2795,12 @@ case "$1" in 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" @@ -1298,9 +2813,9 @@ case "$1" in ;; esac EOF - + chmod +x /usr/local/bin/myp-maintenance - + # Backup-Skript cat > "/usr/local/bin/myp-backup" << EOF #!/bin/bash @@ -1426,20 +2941,20 @@ finalize_installation() { progress "Starte Services..." systemctl start myp-druckerverwaltung sleep 3 - systemctl start nginx - +systemctl start nginx + # Warte und prüfe Services - sleep 5 - +sleep 5 + if systemctl is-active --quiet myp-druckerverwaltung; then log "✅ MYP-Anwendung läuft" - else +else warning "⚠️ MYP-Anwendung nicht aktiv" - fi - - if systemctl is-active --quiet nginx; then - log "✅ Nginx läuft" - else +fi + +if systemctl is-active --quiet nginx; then + log "✅ Nginx läuft" +else warning "⚠️ Nginx nicht aktiv" fi @@ -1644,18 +3159,224 @@ 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 @@ -1679,4 +3400,5 @@ main() { # ========================== PROGRAMMSTART ========================== # Starte Installation -main "$@" \ No newline at end of file +main "$@" + chmod +x /usr/local/bin/dns-health-check \ No newline at end of file diff --git a/backend/app/schnellstart_raspberry_pi.sh b/backend/app/schnellstart_raspberry_pi.sh index 570ae956..02504ebd 100644 --- a/backend/app/schnellstart_raspberry_pi.sh +++ b/backend/app/schnellstart_raspberry_pi.sh @@ -65,14 +65,19 @@ chmod +x "$CURRENT_DIR/install_raspberry_pi.sh" echo info "📋 Was passiert bei der Installation:" +info " • System-Grundkonfiguration: Hostname 'raspberrypi', Root-Passwort, Zeitzone" +info " • System-Update: Vollständiges System-Upgrade mit neuen Zertifikaten" info " • System-Bereinigung: Entfernt alle Desktop-Umgebungen" info " • Chromium-Installation: Mehrere Fallback-Methoden" +info " • Verzeichnisstruktur: Upload-Ordner, Logs, Config mit korrekten Berechtigungen" +info " • Python-Installation: Direkt ins System ohne Virtual Environment" info " • Sicherheits-Kiosk: Ohne Escape-Möglichkeiten" info " • Autostart: Vollautomatischer Boot-to-Kiosk" info " • Wartungstools: Remote-Management-System" echo info "🛡️ Sicherheits-Features:" info " • SSH automatisch deaktiviert" +info " • Root-Zugang: 744563017196A (für Wartung)" info " • Firewall mit Fail2Ban" info " • Kein Desktop-Zugang" info " • Passwort-geschützter Notfall-Modus"