1387 lines
51 KiB
Bash
1387 lines
51 KiB
Bash
#!/bin/bash
|
|
|
|
# ===================================================================
|
|
# MYP Druckerverwaltung - VOLLSTÄNDIGER KIOSK-INSTALLER für Raspbian
|
|
# Entwickelt auf Windows, ausführbar auf Raspberry Pi / Debian
|
|
# OHNE virtualenv - verwendet System-Python mit --break-system-packages
|
|
# ECHTER KIOSK-MODUS: Entfernt Desktop, 1 Backend-Instanz HTTPS, Autologin
|
|
# ===================================================================
|
|
|
|
set -euo pipefail
|
|
|
|
# =========================== KONFIGURATION ===========================
|
|
APP_NAME="MYP Druckerverwaltung"
|
|
APP_DIR="/opt/myp"
|
|
SERVICE_NAME="myp-https"
|
|
KIOSK_USER="kiosk"
|
|
CURRENT_DIR="$(pwd)"
|
|
INSTALL_LOG="/var/log/myp-install.log"
|
|
|
|
# Farben für Ausgabe
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
PURPLE='\033[0;35m'
|
|
NC='\033[0m'
|
|
|
|
# ========================== LOGGING-SYSTEM ==========================
|
|
log() {
|
|
echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}" | tee -a "$INSTALL_LOG"
|
|
}
|
|
|
|
error() {
|
|
echo -e "${RED}[FEHLER] $1${NC}" | tee -a "$INSTALL_LOG"
|
|
exit 1
|
|
}
|
|
|
|
warning() {
|
|
echo -e "${YELLOW}[WARNUNG] $1${NC}" | tee -a "$INSTALL_LOG"
|
|
}
|
|
|
|
info() {
|
|
echo -e "${BLUE}[INFO] $1${NC}" | tee -a "$INSTALL_LOG"
|
|
}
|
|
|
|
progress() {
|
|
echo -e "${PURPLE}[FORTSCHRITT] $1${NC}" | tee -a "$INSTALL_LOG"
|
|
}
|
|
|
|
# ========================== SYSTEM-CHECKS ==========================
|
|
check_root() {
|
|
if [ "$EUID" -ne 0 ]; then
|
|
error "Dieses Skript muss als Root ausgeführt werden: sudo $0"
|
|
fi
|
|
export PATH="/usr/sbin:/sbin:/usr/bin:/bin:/usr/local/bin:$PATH"
|
|
}
|
|
|
|
check_debian_system() {
|
|
if [ ! -f /etc/debian_version ]; then
|
|
error "Dieses Skript ist nur für Debian/Raspbian-Systeme geeignet!"
|
|
fi
|
|
log "✅ Debian/Raspbian-System erkannt"
|
|
}
|
|
|
|
# ========================== DESKTOP ENVIRONMENTS ENTFERNEN ==========================
|
|
remove_desktop_environments() {
|
|
log "=== ENTFERNE ALLE DESKTOP ENVIRONMENTS ==="
|
|
|
|
progress "Stoppe alle Desktop-Services..."
|
|
systemctl stop lightdm 2>/dev/null || true
|
|
systemctl stop gdm3 2>/dev/null || true
|
|
systemctl stop sddm 2>/dev/null || true
|
|
systemctl stop xdm 2>/dev/null || true
|
|
|
|
systemctl disable lightdm 2>/dev/null || true
|
|
systemctl disable gdm3 2>/dev/null || true
|
|
systemctl disable sddm 2>/dev/null || true
|
|
systemctl disable xdm 2>/dev/null || true
|
|
|
|
progress "Entferne Desktop-Pakete vollständig..."
|
|
|
|
# Raspberry Pi OS Desktop entfernen
|
|
apt-get remove --purge -y \
|
|
raspberrypi-ui-mods \
|
|
pi-package \
|
|
desktop-base \
|
|
lxde* \
|
|
xfce4* \
|
|
gnome* \
|
|
kde* \
|
|
mate* \
|
|
cinnamon* \
|
|
openbox \
|
|
pcmanfm \
|
|
file-manager* \
|
|
task-lxde-desktop \
|
|
task-xfce-desktop \
|
|
task-gnome-desktop \
|
|
task-kde-desktop \
|
|
2>/dev/null || true
|
|
|
|
# Display Manager entfernen
|
|
apt-get remove --purge -y \
|
|
lightdm* \
|
|
gdm3* \
|
|
sddm* \
|
|
xdm* \
|
|
nodm* \
|
|
2>/dev/null || true
|
|
|
|
# Unnötige Pakete entfernen
|
|
apt-get remove --purge -y \
|
|
libreoffice* \
|
|
thunderbird* \
|
|
firefox* \
|
|
vlc* \
|
|
gimp* \
|
|
scratch* \
|
|
minecraft-pi \
|
|
sonic-pi \
|
|
2>/dev/null || true
|
|
|
|
# Autoremove und Autoclean
|
|
apt-get autoremove --purge -y
|
|
apt-get autoclean
|
|
|
|
log "✅ Desktop Environments vollständig entfernt"
|
|
}
|
|
|
|
# ========================== KIOSK BENUTZER ERSTELLEN ==========================
|
|
create_kiosk_user() {
|
|
log "=== ERSTELLE KIOSK-BENUTZER ==="
|
|
|
|
# Kiosk-Benutzer erstellen falls nicht vorhanden
|
|
if ! id "$KIOSK_USER" &>/dev/null; then
|
|
progress "Erstelle Kiosk-Benutzer: $KIOSK_USER"
|
|
useradd -m -s /bin/bash "$KIOSK_USER" || error "Kann Kiosk-Benutzer nicht erstellen"
|
|
|
|
# Gruppen hinzufügen
|
|
usermod -aG audio,video,input,dialout,plugdev,users "$KIOSK_USER" 2>/dev/null || true
|
|
else
|
|
info "Kiosk-Benutzer $KIOSK_USER existiert bereits"
|
|
fi
|
|
|
|
# Passwort entfernen für automatischen Login
|
|
passwd -d "$KIOSK_USER" || warning "Konnte Passwort nicht entfernen"
|
|
|
|
log "✅ Kiosk-Benutzer erstellt: $KIOSK_USER"
|
|
}
|
|
|
|
# ========================== MINIMALE X11 INSTALLATION ==========================
|
|
install_minimal_x11() {
|
|
log "=== INSTALLIERE MINIMALE X11-UMGEBUNG ==="
|
|
|
|
progress "Installiere minimale X11-Pakete..."
|
|
apt-get install -y \
|
|
xserver-xorg-core \
|
|
xserver-xorg-input-all \
|
|
xserver-xorg-video-fbdev \
|
|
xserver-xorg-video-vesa \
|
|
xinit \
|
|
x11-xserver-utils \
|
|
xdotool \
|
|
unclutter \
|
|
openbox \
|
|
|| error "X11 Installation fehlgeschlagen"
|
|
|
|
# Chromium Browser mit Fallback-Mechanismus installieren
|
|
progress "Installiere Chromium Browser..."
|
|
if apt-get install -y chromium 2>/dev/null; then
|
|
log "✅ Chromium erfolgreich installiert"
|
|
elif apt-get install -y chromium-browser 2>/dev/null; then
|
|
log "✅ Chromium-Browser erfolgreich installiert"
|
|
elif apt-get install -y firefox-esr 2>/dev/null; then
|
|
warning "⚠️ Chromium nicht verfügbar - Firefox ESR als Fallback installiert"
|
|
# Firefox-Konfiguration für Kiosk-Modus anpassen
|
|
progress "Konfiguriere Firefox für Kiosk-Modus..."
|
|
FIREFOX_BROWSER="firefox-esr"
|
|
else
|
|
error "❌ Kein Browser verfügbar (chromium, chromium-browser, firefox-esr)"
|
|
fi
|
|
|
|
log "✅ Minimale X11-Umgebung installiert"
|
|
}
|
|
|
|
# ========================== MERCEDES ZERTIFIKATE ==========================
|
|
install_mercedes_certificates() {
|
|
log "=== INSTALLIERE MERCEDES SSL-ZERTIFIKATE ==="
|
|
|
|
progress "Aktualisiere CA-Zertifikate..."
|
|
|
|
# CA-Zertifikate Paket installieren/aktualisieren
|
|
apt-get install -y ca-certificates curl openssl || error "CA-Zertifikate Installation fehlgeschlagen"
|
|
|
|
# Standard CA-Bundle aktualisieren
|
|
update-ca-certificates || warning "CA-Zertifikate Update teilweise fehlgeschlagen"
|
|
|
|
# Mercedes Corporate Zertifikate installieren (falls vorhanden)
|
|
if [ -d "$CURRENT_DIR/certs/mercedes" ] && [ "$(ls -A $CURRENT_DIR/certs/mercedes 2>/dev/null)" ]; then
|
|
progress "Installiere Mercedes Corporate Zertifikate..."
|
|
|
|
# Erstelle temporäres Verzeichnis für Zertifikat-Verarbeitung
|
|
TEMP_CERT_DIR="/tmp/mercedes_certs"
|
|
mkdir -p "$TEMP_CERT_DIR"
|
|
|
|
# Alle Zertifikatsdateien verarbeiten (.crt, .pem, .cer)
|
|
find "$CURRENT_DIR/certs/mercedes" -type f \( -name "*.crt" -o -name "*.pem" -o -name "*.cer" \) | while read cert_file; do
|
|
cert_basename=$(basename "$cert_file")
|
|
cert_name="${cert_basename%.*}"
|
|
|
|
progress "Verarbeite Mercedes-Zertifikat: $cert_basename"
|
|
|
|
# .cer Dateien in .crt konvertieren (falls nötig)
|
|
if [[ "$cert_file" == *.cer ]]; then
|
|
progress "Konvertiere .cer zu .crt: $cert_basename"
|
|
|
|
# Überprüfe ob es sich um DER- oder PEM-Format handelt
|
|
if openssl x509 -in "$cert_file" -text -noout >/dev/null 2>&1; then
|
|
# PEM-Format - direkt kopieren mit .crt Endung
|
|
cp "$cert_file" "$TEMP_CERT_DIR/${cert_name}.crt"
|
|
elif openssl x509 -in "$cert_file" -inform DER -text -noout >/dev/null 2>&1; then
|
|
# DER-Format - zu PEM konvertieren
|
|
openssl x509 -in "$cert_file" -inform DER -out "$TEMP_CERT_DIR/${cert_name}.crt" -outform PEM
|
|
else
|
|
warning "Unbekanntes Zertifikatformat: $cert_file"
|
|
continue
|
|
fi
|
|
else
|
|
# .crt oder .pem - direkt kopieren
|
|
cp "$cert_file" "$TEMP_CERT_DIR/"
|
|
fi
|
|
|
|
# Zertifikat validieren
|
|
if openssl x509 -in "$TEMP_CERT_DIR/${cert_name}.crt" -text -noout >/dev/null 2>&1; then
|
|
log "✅ Zertifikat validiert: ${cert_name}.crt"
|
|
|
|
# In CA-Zertifikate-Verzeichnis kopieren
|
|
cp "$TEMP_CERT_DIR/${cert_name}.crt" "/usr/local/share/ca-certificates/"
|
|
else
|
|
warning "⚠️ Ungültiges Zertifikat übersprungen: $cert_file"
|
|
fi
|
|
done
|
|
|
|
# Spezielle Mercedes-Zertifikate verarbeiten
|
|
if [ -f "$CURRENT_DIR/certs/mercedes/Corp-Pri-Root-CA.cer" ]; then
|
|
progress "Installiere Mercedes Corporate Primary Root CA..."
|
|
|
|
# Versuche DER-zu-PEM Konvertierung
|
|
if openssl x509 -in "$CURRENT_DIR/certs/mercedes/Corp-Pri-Root-CA.cer" -inform DER -out "/usr/local/share/ca-certificates/Mercedes-Corp-Pri-Root-CA.crt" -outform PEM 2>/dev/null; then
|
|
log "✅ Corp-Pri-Root-CA.cer erfolgreich als DER konvertiert"
|
|
# Versuche direkte PEM-Kopie
|
|
elif openssl x509 -in "$CURRENT_DIR/certs/mercedes/Corp-Pri-Root-CA.cer" -text -noout >/dev/null 2>&1; then
|
|
cp "$CURRENT_DIR/certs/mercedes/Corp-Pri-Root-CA.cer" "/usr/local/share/ca-certificates/Mercedes-Corp-Pri-Root-CA.crt"
|
|
log "✅ Corp-Pri-Root-CA.cer direkt als PEM kopiert"
|
|
else
|
|
warning "⚠️ Corp-Pri-Root-CA.cer Format nicht erkannt - übersprungen"
|
|
fi
|
|
fi
|
|
|
|
if [ -f "$CURRENT_DIR/certs/mercedes/Corp-Root-CA-G2.cer" ]; then
|
|
progress "Installiere Mercedes Corporate Root CA G2..."
|
|
|
|
# Versuche DER-zu-PEM Konvertierung
|
|
if openssl x509 -in "$CURRENT_DIR/certs/mercedes/Corp-Root-CA-G2.cer" -inform DER -out "/usr/local/share/ca-certificates/Mercedes-Corp-Root-CA-G2.crt" -outform PEM 2>/dev/null; then
|
|
log "✅ Corp-Root-CA-G2.cer erfolgreich als DER konvertiert"
|
|
# Versuche direkte PEM-Kopie
|
|
elif openssl x509 -in "$CURRENT_DIR/certs/mercedes/Corp-Root-CA-G2.cer" -text -noout >/dev/null 2>&1; then
|
|
cp "$CURRENT_DIR/certs/mercedes/Corp-Root-CA-G2.cer" "/usr/local/share/ca-certificates/Mercedes-Corp-Root-CA-G2.crt"
|
|
log "✅ Corp-Root-CA-G2.cer direkt als PEM kopiert"
|
|
else
|
|
warning "⚠️ Corp-Root-CA-G2.cer Format nicht erkannt - übersprungen"
|
|
fi
|
|
fi
|
|
|
|
# Temporäres Verzeichnis aufräumen
|
|
rm -rf "$TEMP_CERT_DIR"
|
|
|
|
# CA-Zertifikate aktualisieren
|
|
update-ca-certificates || warning "Mercedes Zertifikate Update fehlgeschlagen"
|
|
|
|
# Installierte Mercedes-Zertifikate auflisten
|
|
MERCEDES_CERTS=$(ls /usr/local/share/ca-certificates/*Mercedes* 2>/dev/null | wc -l)
|
|
if [ "$MERCEDES_CERTS" -gt 0 ]; then
|
|
log "✅ $MERCEDES_CERTS Mercedes-Zertifikate erfolgreich installiert"
|
|
ls /usr/local/share/ca-certificates/*Mercedes* 2>/dev/null | while read cert; do
|
|
log " 📜 $(basename "$cert")"
|
|
done
|
|
else
|
|
warning "⚠️ Keine Mercedes-Zertifikate installiert"
|
|
fi
|
|
|
|
else
|
|
info "Keine Mercedes-Zertifikate gefunden - verwende Standard CA-Bundle"
|
|
fi
|
|
|
|
# Python SSL-Konfiguration optimieren
|
|
progress "Konfiguriere Python SSL-Einstellungen..."
|
|
|
|
# pip Konfiguration für SSL mit erweiterten Optionen
|
|
mkdir -p /root/.pip
|
|
cat > /root/.pip/pip.conf << EOF
|
|
[global]
|
|
trusted-host = pypi.org
|
|
pypi.python.org
|
|
files.pythonhosted.org
|
|
cert = /etc/ssl/certs/ca-certificates.crt
|
|
timeout = 60
|
|
retries = 3
|
|
no-cache-dir = true
|
|
|
|
[install]
|
|
trusted-host = pypi.org
|
|
pypi.python.org
|
|
files.pythonhosted.org
|
|
no-warn-script-location = true
|
|
EOF
|
|
|
|
# Python HTTPS-Konfiguration mit Mercedes-Support
|
|
export SSL_CERT_FILE="/etc/ssl/certs/ca-certificates.crt"
|
|
export REQUESTS_CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt"
|
|
export CURL_CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt"
|
|
export PYTHONHTTPSVERIFY=1
|
|
|
|
# Node.js SSL-Konfiguration hinzufügen
|
|
export NODE_TLS_REJECT_UNAUTHORIZED=1
|
|
export NODE_EXTRA_CA_CERTS="/etc/ssl/certs/ca-certificates.crt"
|
|
|
|
# npm SSL-Konfiguration mit verbesserter Fehlerbehandlung
|
|
progress "Konfiguriere npm SSL-Einstellungen..."
|
|
npm config set ca "" 2>/dev/null || true
|
|
npm config set cafile "/etc/ssl/certs/ca-certificates.crt" 2>/dev/null || true
|
|
npm config set strict-ssl true 2>/dev/null || true
|
|
npm config set registry "https://registry.npmjs.org/" 2>/dev/null || true
|
|
|
|
# Pip auf neueste Version aktualisieren
|
|
progress "Aktualisiere pip auf neueste Version..."
|
|
python3 -m pip install --upgrade pip --break-system-packages --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org || warning "pip Update fehlgeschlagen"
|
|
|
|
# SSL-Tests durchführen
|
|
progress "Teste SSL-Verbindungen..."
|
|
|
|
# Test PyPI
|
|
if python3 -c "import ssl, urllib.request; urllib.request.urlopen('https://pypi.org')" 2>/dev/null; then
|
|
log "✅ SSL-Verbindung zu PyPI erfolgreich"
|
|
else
|
|
warning "⚠️ SSL-Verbindung zu PyPI problematisch"
|
|
fi
|
|
|
|
# Test npm Registry
|
|
if npm ping --registry https://registry.npmjs.org >/dev/null 2>&1; then
|
|
log "✅ SSL-Verbindung zu npm Registry erfolgreich"
|
|
else
|
|
warning "⚠️ SSL-Verbindung zu npm Registry problematisch"
|
|
fi
|
|
|
|
# Zeige installierte CA-Zertifikate-Anzahl
|
|
CA_COUNT=$(ls /etc/ssl/certs/*.pem 2>/dev/null | wc -l)
|
|
log "✅ Insgesamt $CA_COUNT CA-Zertifikate im System verfügbar"
|
|
|
|
log "✅ Mercedes SSL-Zertifikate und System-Konfiguration abgeschlossen"
|
|
}
|
|
|
|
# ========================== ABHÄNGIGKEITEN INSTALLIEREN ==========================
|
|
install_system_dependencies() {
|
|
log "=== INSTALLIERE SYSTEM-ABHÄNGIGKEITEN ==="
|
|
|
|
progress "Aktualisiere Paketlisten..."
|
|
apt-get update -y || error "APT Update fehlgeschlagen"
|
|
|
|
progress "Installiere Python 3 und grundlegende Pakete..."
|
|
apt-get install -y \
|
|
python3 \
|
|
python3-pip \
|
|
python3-dev \
|
|
python3-setuptools \
|
|
build-essential \
|
|
libssl-dev \
|
|
libffi-dev \
|
|
git \
|
|
curl \
|
|
wget \
|
|
nano \
|
|
htop \
|
|
rsync \
|
|
unzip \
|
|
sudo \
|
|
systemd \
|
|
ca-certificates \
|
|
gnupg \
|
|
lsb-release \
|
|
sqlite3 \
|
|
|| error "System-Pakete Installation fehlgeschlagen"
|
|
|
|
# ========================== NODE.JS UND NPM INSTALLATION ==========================
|
|
progress "Installiere Node.js und npm..."
|
|
|
|
# Alte Node.js-Installationen entfernen
|
|
progress "Entferne alte Node.js-Installationen..."
|
|
apt-get remove --purge -y nodejs npm 2>/dev/null || true
|
|
apt-get autoremove -y 2>/dev/null || true
|
|
|
|
# NodeSource Repository für Node.js LTS 20.x hinzufügen
|
|
progress "Füge NodeSource Repository für Node.js 20.x LTS hinzu..."
|
|
curl -fsSL https://deb.nodesource.com/setup_20.x | bash - || {
|
|
warning "NodeSource Repository konnte nicht hinzugefügt werden"
|
|
|
|
# Fallback: Manueller Download und Installation
|
|
progress "Fallback: Installiere Node.js aus Debian-Repository..."
|
|
apt-get update -y
|
|
apt-get install -y nodejs npm || {
|
|
error "Node.js Installation komplett fehlgeschlagen"
|
|
}
|
|
}
|
|
|
|
# Node.js aus NodeSource Repository installieren (falls Repository erfolgreich hinzugefügt)
|
|
if [ -f /etc/apt/sources.list.d/nodesource.list ]; then
|
|
progress "Installiere Node.js 20.x LTS aus NodeSource Repository..."
|
|
apt-get update -y
|
|
apt-get install -y nodejs || {
|
|
warning "NodeSource Installation fehlgeschlagen - verwende Fallback"
|
|
apt-get install -y nodejs npm || error "Node.js Fallback Installation fehlgeschlagen"
|
|
}
|
|
fi
|
|
|
|
# Überprüfe Node.js Installation
|
|
if command -v node >/dev/null 2>&1; then
|
|
NODE_VERSION=$(node --version)
|
|
log "✅ Node.js erfolgreich installiert: $NODE_VERSION"
|
|
else
|
|
error "❌ Node.js Installation fehlgeschlagen"
|
|
fi
|
|
|
|
# npm sollte automatisch mit Node.js mitgeliefert werden
|
|
if command -v npm >/dev/null 2>&1; then
|
|
NPM_VERSION=$(npm --version)
|
|
log "✅ npm automatisch installiert: $NPM_VERSION"
|
|
|
|
# VORSICHTIG: npm NUR aktualisieren wenn Node.js >= 18
|
|
NODE_MAJOR_VERSION=$(node --version | cut -d'.' -f1 | sed 's/v//')
|
|
if [ "$NODE_MAJOR_VERSION" -ge 18 ]; then
|
|
progress "Node.js $NODE_MAJOR_VERSION erkannt - npm-Update möglich..."
|
|
npm install -g npm@latest --force 2>/dev/null || {
|
|
warning "npm-Update fehlgeschlagen - verwende bestehende Version $NPM_VERSION"
|
|
}
|
|
NPM_VERSION_NEW=$(npm --version)
|
|
log "✅ npm Version: $NPM_VERSION_NEW"
|
|
else
|
|
warning "⚠️ Node.js < 18 - npm-Update übersprungen für Kompatibilität"
|
|
fi
|
|
else
|
|
error "❌ npm nicht verfügbar"
|
|
fi
|
|
|
|
# npm-Konfiguration für bessere Performance
|
|
progress "Konfiguriere npm-Einstellungen..."
|
|
npm config set fund false 2>/dev/null || true
|
|
npm config set audit-level moderate 2>/dev/null || true
|
|
npm config set package-lock true 2>/dev/null || true
|
|
|
|
# WICHTIG: Mercedes Zertifikate vor Python-Paketen installieren
|
|
install_mercedes_certificates
|
|
|
|
progress "Installiere Python-Abhängigkeiten mit Mercedes SSL-Konfiguration..."
|
|
|
|
# SSL-freundliche pip-Installation mit Fallback-Optionen
|
|
PIP_OPTS="--break-system-packages --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --timeout 60 --retries 3"
|
|
|
|
# Core Flask Framework
|
|
pip3 install $PIP_OPTS Flask==3.1.1 || pip3 install $PIP_OPTS Flask || error "Flask Installation fehlgeschlagen"
|
|
pip3 install $PIP_OPTS Flask-Login==0.6.3 || pip3 install $PIP_OPTS Flask-Login || error "Flask-Login Installation fehlgeschlagen"
|
|
pip3 install $PIP_OPTS Flask-WTF==1.2.1 || pip3 install $PIP_OPTS Flask-WTF || error "Flask-WTF Installation fehlgeschlagen"
|
|
|
|
# Datenbank
|
|
pip3 install $PIP_OPTS SQLAlchemy==2.0.36 || pip3 install $PIP_OPTS SQLAlchemy || error "SQLAlchemy Installation fehlgeschlagen"
|
|
|
|
# Sicherheit
|
|
pip3 install $PIP_OPTS bcrypt==4.2.1 || pip3 install $PIP_OPTS bcrypt || error "bcrypt Installation fehlgeschlagen"
|
|
pip3 install $PIP_OPTS cryptography==44.0.0 || pip3 install $PIP_OPTS cryptography || error "cryptography Installation fehlgeschlagen"
|
|
pip3 install $PIP_OPTS Werkzeug==3.1.3 || pip3 install $PIP_OPTS Werkzeug || error "Werkzeug Installation fehlgeschlagen"
|
|
|
|
# Smart Plug Steuerung
|
|
pip3 install $PIP_OPTS PyP100 || warning "PyP100 Installation fehlgeschlagen (optional)"
|
|
|
|
# HTTP Requests
|
|
pip3 install $PIP_OPTS requests==2.32.3 || pip3 install $PIP_OPTS requests || error "requests Installation fehlgeschlagen"
|
|
|
|
# System Monitoring
|
|
pip3 install $PIP_OPTS psutil==6.1.1 || pip3 install $PIP_OPTS psutil || error "psutil Installation fehlgeschlagen"
|
|
|
|
# Redis (optional)
|
|
pip3 install $PIP_OPTS redis==5.2.1 || warning "redis Installation fehlgeschlagen (optional)"
|
|
|
|
# Weitere Core-Abhängigkeiten
|
|
pip3 install $PIP_OPTS MarkupSafe==3.0.2 || pip3 install $PIP_OPTS MarkupSafe || error "MarkupSafe Installation fehlgeschlagen"
|
|
|
|
# Produktions-Server
|
|
pip3 install $PIP_OPTS gunicorn==23.0.0 || pip3 install $PIP_OPTS gunicorn || error "gunicorn Installation fehlgeschlagen"
|
|
|
|
# ========================== NPM-ABHÄNGIGKEITEN INSTALLIEREN ==========================
|
|
progress "Prüfe auf package.json für npm-Abhängigkeiten..."
|
|
|
|
if [ -f "$CURRENT_DIR/package.json" ]; then
|
|
progress "package.json gefunden - installiere npm-Abhängigkeiten..."
|
|
|
|
cd "$CURRENT_DIR"
|
|
|
|
# npm install OHNE --production um auch devDependencies (TailwindCSS) zu installieren
|
|
progress "Installiere alle npm-Abhängigkeiten (inklusive devDependencies für TailwindCSS)..."
|
|
|
|
# Erste Versuche: Standard-Installation
|
|
if npm install --no-optional --no-audit --no-fund 2>/dev/null; then
|
|
log "✅ npm install erfolgreich (Standard)"
|
|
# Zweiter Versuch: Mit legacy-peer-deps
|
|
elif npm install --no-optional --no-audit --no-fund --legacy-peer-deps 2>/dev/null; then
|
|
log "✅ npm install erfolgreich (mit --legacy-peer-deps)"
|
|
# Dritter Versuch: Mit force Flag
|
|
elif npm install --no-optional --no-audit --no-fund --force 2>/dev/null; then
|
|
log "✅ npm install erfolgreich (mit --force)"
|
|
# Vierter Versuch: Mit allen Flags
|
|
elif npm install --no-optional --no-audit --no-fund --legacy-peer-deps --force 2>/dev/null; then
|
|
log "✅ npm install erfolgreich (mit allen Flags)"
|
|
else
|
|
warning "⚠️ npm install fehlgeschlagen - versuche manuelle Paket-Installation..."
|
|
|
|
# Manuelle Installation der wichtigsten Pakete
|
|
npm install tailwindcss --no-audit --no-fund --force 2>/dev/null || warning "TailwindCSS Installation fehlgeschlagen"
|
|
npm install @tailwindcss/forms --no-audit --no-fund --force 2>/dev/null || warning "@tailwindcss/forms Installation fehlgeschlagen"
|
|
npm install chart.js --no-audit --no-fund --force 2>/dev/null || warning "Chart.js Installation fehlgeschlagen"
|
|
npm install @fortawesome/fontawesome-free --no-audit --no-fund --force 2>/dev/null || warning "FontAwesome Installation fehlgeschlagen"
|
|
fi
|
|
|
|
log "✅ npm-Abhängigkeiten-Installation abgeschlossen:"
|
|
log " 📦 Dependencies: FontAwesome, FullCalendar, Chart.js, Vite"
|
|
log " 🛠️ DevDependencies: TailwindCSS, PostCSS, Autoprefixer"
|
|
|
|
# Überprüfe TailwindCSS Installation speziell
|
|
if npx tailwindcss --help >/dev/null 2>&1; then
|
|
log "✅ TailwindCSS erfolgreich installiert und verfügbar"
|
|
else
|
|
warning "❌ TailwindCSS nicht verfügbar - versuche globale Installation..."
|
|
npm install -g tailwindcss --force 2>/dev/null || error "TailwindCSS Installation komplett fehlgeschlagen"
|
|
fi
|
|
|
|
# Überprüfe auf Build-Scripts und führe sie aus
|
|
if npm run | grep -q "build:css"; then
|
|
progress "CSS-Build-Script gefunden - führe npm run build:css aus..."
|
|
if npm run build:css 2>/dev/null; then
|
|
log "✅ TailwindCSS Build erfolgreich abgeschlossen"
|
|
else
|
|
warning "⚠️ npm run build:css fehlgeschlagen - versuche direkten npx-Aufruf..."
|
|
if npx tailwindcss -i ./static/css/input.css -o ./static/css/tailwind.min.css --minify 2>/dev/null; then
|
|
log "✅ TailwindCSS mit npx erfolgreich kompiliert"
|
|
else
|
|
error "❌ TailwindCSS Build komplett fehlgeschlagen"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if npm run | grep -q "build" && ! npm run | grep -q "build:css"; then
|
|
progress "Haupt-Build-Script gefunden - führe npm run build aus..."
|
|
npm run build 2>/dev/null || warning "npm run build fehlgeschlagen"
|
|
log "✅ Frontend-Build abgeschlossen"
|
|
fi
|
|
|
|
# Überprüfe generierte CSS-Dateien
|
|
if [ -f "$CURRENT_DIR/static/css/tailwind.min.css" ]; then
|
|
TAILWIND_SIZE=$(du -h "$CURRENT_DIR/static/css/tailwind.min.css" | cut -f1)
|
|
log "✅ TailwindCSS erfolgreich kompiliert: tailwind.min.css ($TAILWIND_SIZE)"
|
|
else
|
|
warning "⚠️ tailwind.min.css nicht gefunden - CSS-Build möglicherweise fehlgeschlagen"
|
|
fi
|
|
|
|
else
|
|
info "Keine package.json gefunden - überspringe npm-Abhängigkeiten"
|
|
fi
|
|
|
|
log "✅ Alle Abhängigkeiten (Python + Node.js + npm) erfolgreich installiert"
|
|
}
|
|
|
|
# ========================== SSL-ZERTIFIKATE FÜR LOCALHOST ERSTELLEN ==========================
|
|
create_localhost_ssl_certificates() {
|
|
log "=== ERSTELLE SSL-ZERTIFIKATE FÜR LOCALHOST ==="
|
|
|
|
SSL_DIR="$APP_DIR/certs/localhost"
|
|
mkdir -p "$SSL_DIR"
|
|
|
|
progress "Erstelle SSL-Zertifikate für localhost..."
|
|
|
|
# Private Key erstellen
|
|
openssl genrsa -out "$SSL_DIR/localhost.key" 2048 || error "Private Key Erstellung fehlgeschlagen"
|
|
|
|
# Certificate Signing Request (CSR) erstellen
|
|
openssl req -new -key "$SSL_DIR/localhost.key" -out "$SSL_DIR/localhost.csr" -subj "/C=DE/ST=Baden-Wuerttemberg/L=Stuttgart/O=Mercedes-Benz/OU=MYP/CN=localhost" || error "CSR Erstellung fehlgeschlagen"
|
|
|
|
# Self-signed Zertifikat erstellen (gültig für 365 Tage)
|
|
openssl x509 -req -days 365 -in "$SSL_DIR/localhost.csr" -signkey "$SSL_DIR/localhost.key" -out "$SSL_DIR/localhost.crt" -extensions v3_req -extfile <(
|
|
cat <<EOF
|
|
[req]
|
|
distinguished_name = req_distinguished_name
|
|
req_extensions = v3_req
|
|
prompt = no
|
|
|
|
[req_distinguished_name]
|
|
C = DE
|
|
ST = Baden-Wuerttemberg
|
|
L = Stuttgart
|
|
O = Mercedes-Benz
|
|
OU = MYP
|
|
CN = localhost
|
|
|
|
[v3_req]
|
|
keyUsage = keyEncipherment, dataEncipherment
|
|
extendedKeyUsage = serverAuth
|
|
subjectAltName = @alt_names
|
|
|
|
[alt_names]
|
|
DNS.1 = localhost
|
|
DNS.2 = *.localhost
|
|
IP.1 = 127.0.0.1
|
|
IP.2 = 0.0.0.0
|
|
EOF
|
|
) || error "SSL-Zertifikat Erstellung fehlgeschlagen"
|
|
|
|
# CSR-Datei aufräumen
|
|
rm -f "$SSL_DIR/localhost.csr"
|
|
|
|
# Berechtigungen setzen
|
|
chmod 600 "$SSL_DIR/localhost.key"
|
|
chmod 644 "$SSL_DIR/localhost.crt"
|
|
chown -R root:root "$SSL_DIR"
|
|
|
|
# Zertifikat zu System CA-Store hinzufügen
|
|
progress "Füge localhost-Zertifikat zu System CA-Store hinzu..."
|
|
cp "$SSL_DIR/localhost.crt" "/usr/local/share/ca-certificates/localhost.crt"
|
|
update-ca-certificates || warning "CA-Zertifikate Update fehlgeschlagen"
|
|
|
|
# Zertifikat-Info anzeigen
|
|
log "✅ SSL-Zertifikate für localhost erstellt:"
|
|
log " 📜 Private Key: $SSL_DIR/localhost.key"
|
|
log " 📜 Zertifikat: $SSL_DIR/localhost.crt"
|
|
log " 📜 System CA-Store: /usr/local/share/ca-certificates/localhost.crt"
|
|
|
|
# Zertifikat validieren
|
|
if openssl x509 -in "$SSL_DIR/localhost.crt" -text -noout | grep -q "localhost"; then
|
|
log "✅ SSL-Zertifikat validiert - localhost Subject gefunden"
|
|
else
|
|
warning "⚠️ SSL-Zertifikat Validierung fehlgeschlagen"
|
|
fi
|
|
|
|
log "✅ SSL-Zertifikate für localhost erfolgreich installiert"
|
|
}
|
|
|
|
# ========================== EINZELNER HTTPS BACKEND SERVICE ==========================
|
|
create_backend_service() {
|
|
log "=== ERSTELLE HTTPS BACKEND SERVICE ==="
|
|
|
|
# HTTPS-Startskript (Port 443)
|
|
progress "Erstelle HTTPS-Startskript..."
|
|
cat > "$APP_DIR/start_https.py" << 'EOF'
|
|
#!/usr/bin/env python3
|
|
import sys
|
|
import os
|
|
|
|
# Füge App-Verzeichnis zum Python-Pfad hinzu
|
|
sys.path.insert(0, '/opt/myp')
|
|
|
|
# Setze Umgebungsvariablen
|
|
os.environ['FLASK_PORT'] = '443'
|
|
os.environ['FLASK_HOST'] = '0.0.0.0'
|
|
os.environ['FLASK_ENV'] = 'production'
|
|
|
|
try:
|
|
from app import app, get_ssl_context
|
|
|
|
ssl_context = get_ssl_context()
|
|
if ssl_context:
|
|
print("Starte HTTPS-Server auf Port 443...")
|
|
app.run(host='0.0.0.0', port=443, debug=False, ssl_context=ssl_context, threaded=True)
|
|
else:
|
|
print('SSL-Kontext nicht verfügbar - verwende localhost Zertifikate')
|
|
# Fallback auf localhost-Zertifikate
|
|
ssl_context = ('/opt/myp/certs/localhost/localhost.crt', '/opt/myp/certs/localhost/localhost.key')
|
|
app.run(host='0.0.0.0', port=443, debug=False, ssl_context=ssl_context, threaded=True)
|
|
except Exception as e:
|
|
print(f"Fehler beim Starten des HTTPS-Servers: {e}")
|
|
sys.exit(1)
|
|
EOF
|
|
|
|
# Skript ausführbar machen
|
|
chmod +x "$APP_DIR/start_https.py"
|
|
|
|
# HTTPS-Service (Port 443)
|
|
progress "Erstelle myp-https.service (Port 443)..."
|
|
cat > "/etc/systemd/system/${SERVICE_NAME}.service" << EOF
|
|
[Unit]
|
|
Description=MYP HTTPS Backend (Port 443)
|
|
After=network.target network-online.target
|
|
Wants=network-online.target
|
|
Requires=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=root
|
|
Group=root
|
|
WorkingDirectory=$APP_DIR
|
|
ExecStart=/usr/bin/python3 $APP_DIR/start_https.py
|
|
Restart=always
|
|
RestartSec=5
|
|
StartLimitBurst=5
|
|
StartLimitInterval=60
|
|
|
|
# Umgebungsvariablen
|
|
Environment=PYTHONUNBUFFERED=1
|
|
Environment=FLASK_ENV=production
|
|
Environment=FLASK_HOST=0.0.0.0
|
|
Environment=FLASK_PORT=443
|
|
Environment=PYTHONPATH=$APP_DIR
|
|
Environment=LC_ALL=C.UTF-8
|
|
Environment=LANG=C.UTF-8
|
|
Environment=SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
|
|
Environment=REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
|
|
|
|
# Logging
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
SyslogIdentifier=myp-https
|
|
|
|
# Security-Einstellungen
|
|
NoNewPrivileges=true
|
|
PrivateTmp=false
|
|
ProtectSystem=strict
|
|
ReadWritePaths=$APP_DIR
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
log "✅ HTTPS Backend-Service erstellt"
|
|
}
|
|
|
|
# ========================== KIOSK BROWSER KONFIGURATION ==========================
|
|
configure_kiosk_browser() {
|
|
log "=== KONFIGURIERE KIOSK-BROWSER FÜR HTTPS ==="
|
|
|
|
KIOSK_HOME="/home/$KIOSK_USER"
|
|
|
|
# Openbox-Konfiguration für randlosen Vollbildmodus
|
|
progress "Konfiguriere Openbox für randlosen Vollbildmodus..."
|
|
mkdir -p "$KIOSK_HOME/.config/openbox"
|
|
|
|
cat > "$KIOSK_HOME/.config/openbox/rc.xml" << 'EOF'
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<openbox_config xmlns="http://openbox.org/3.4/rc" xmlns:xi="http://www.w3.org/2001/XInclude">
|
|
<resistance>
|
|
<strength>10</strength>
|
|
<screen_edge_strength>20</screen_edge_strength>
|
|
</resistance>
|
|
<focus>
|
|
<focusNew>yes</focusNew>
|
|
<followMouse>no</followMouse>
|
|
</focus>
|
|
<placement>
|
|
<policy>Smart</policy>
|
|
<center>yes</center>
|
|
</placement>
|
|
<theme>
|
|
<name>Clearlooks</name>
|
|
<titleLayout>NLIMC</titleLayout>
|
|
<keepBorder>no</keepBorder>
|
|
<animateIconify>yes</animateIconify>
|
|
</theme>
|
|
<desktops>
|
|
<number>1</number>
|
|
<firstdesk>1</firstdesk>
|
|
<names>
|
|
<name>Desktop 1</name>
|
|
</names>
|
|
<popupTime>875</popupTime>
|
|
</desktops>
|
|
<resize>
|
|
<drawContents>yes</drawContents>
|
|
<popupShow>Nonpixel</popupShow>
|
|
<popupPosition>Center</popupPosition>
|
|
</resize>
|
|
<margins>
|
|
<top>0</top>
|
|
<bottom>0</bottom>
|
|
<left>0</left>
|
|
<right>0</right>
|
|
</margins>
|
|
<dock>
|
|
<position>TopLeft</position>
|
|
<floatingX>0</floatingX>
|
|
<floatingY>0</floatingY>
|
|
<noStrut>no</noStrut>
|
|
<stacking>Above</stacking>
|
|
<direction>Vertical</direction>
|
|
<autoHide>no</autoHide>
|
|
<hideDelay>300</hideDelay>
|
|
<showDelay>300</showDelay>
|
|
<moveButton>Middle</moveButton>
|
|
</dock>
|
|
<keyboard>
|
|
<!-- Deaktiviere alle Tastenkombinationen für Kiosk-Sicherheit -->
|
|
</keyboard>
|
|
<mouse>
|
|
<dragThreshold>8</dragThreshold>
|
|
<doubleClickTime>200</doubleClickTime>
|
|
<screenEdgeWarpTime>400</screenEdgeWarpTime>
|
|
</mouse>
|
|
<applications>
|
|
<!-- Chromium/Browser Konfiguration -->
|
|
<application name="chromium*">
|
|
<decor>no</decor>
|
|
<shade>no</shade>
|
|
<position force="yes">
|
|
<x>0</x>
|
|
<y>0</y>
|
|
</position>
|
|
<size>
|
|
<width>100%</width>
|
|
<height>100%</height>
|
|
</size>
|
|
<fullscreen>yes</fullscreen>
|
|
<maximized>yes</maximized>
|
|
<skip_pager>yes</skip_pager>
|
|
<skip_taskbar>yes</skip_taskbar>
|
|
<layer>above</layer>
|
|
</application>
|
|
<application name="firefox*">
|
|
<decor>no</decor>
|
|
<shade>no</shade>
|
|
<position force="yes">
|
|
<x>0</x>
|
|
<y>0</y>
|
|
</position>
|
|
<size>
|
|
<width>100%</width>
|
|
<height>100%</height>
|
|
</size>
|
|
<fullscreen>yes</fullscreen>
|
|
<maximized>yes</maximized>
|
|
<skip_pager>yes</skip_pager>
|
|
<skip_taskbar>yes</skip_taskbar>
|
|
<layer>above</layer>
|
|
</application>
|
|
</applications>
|
|
</openbox_config>
|
|
EOF
|
|
|
|
# .bashrc für automatischen X-Start erweitern
|
|
progress "Konfiguriere automatischen X-Start..."
|
|
cat >> "$KIOSK_HOME/.bashrc" << 'EOF'
|
|
|
|
# Automatischer X-Start für Kiosk-Modus
|
|
if [ -z "$DISPLAY" ] && [ "$(tty)" = "/dev/tty1" ]; then
|
|
exec startx
|
|
fi
|
|
EOF
|
|
|
|
# .xinitrc für HTTPS Kiosk-Session erstellen
|
|
progress "Erstelle optimierte HTTPS Kiosk X-Session..."
|
|
cat > "$KIOSK_HOME/.xinitrc" << 'EOF'
|
|
#!/bin/bash
|
|
|
|
# Bildschirmauflösung automatisch erkennen
|
|
RESOLUTION=$(xrandr | grep '*' | head -1 | awk '{print $1}')
|
|
if [ -z "$RESOLUTION" ]; then
|
|
RESOLUTION="1920x1080" # Fallback-Auflösung
|
|
fi
|
|
WIDTH=$(echo $RESOLUTION | cut -d'x' -f1)
|
|
HEIGHT=$(echo $RESOLUTION | cut -d'x' -f2)
|
|
|
|
echo "Erkannte Bildschirmauflösung: ${WIDTH}x${HEIGHT}"
|
|
|
|
# Bildschirmschoner und Energieverwaltung komplett deaktivieren
|
|
xset s off
|
|
xset s noblank
|
|
xset s noexpose
|
|
xset -dpms
|
|
xset s 0 0
|
|
|
|
# Mauszeiger verstecken (aggressiver)
|
|
unclutter -idle 0.1 -root -noevents &
|
|
|
|
# Openbox im Hintergrund starten
|
|
openbox &
|
|
|
|
# Warte auf HTTPS Backend-Service
|
|
echo "Warte auf MYP HTTPS Backend-Service..."
|
|
WAIT_COUNT=0
|
|
while ! curl -k -s https://localhost:443 > /dev/null; do
|
|
echo "Warte auf HTTPS Backend (Port 443)... ($WAIT_COUNT/60)"
|
|
sleep 2
|
|
WAIT_COUNT=$((WAIT_COUNT + 1))
|
|
if [ $WAIT_COUNT -gt 60 ]; then
|
|
echo "FEHLER: HTTPS Backend nach 120s nicht erreichbar!"
|
|
break
|
|
fi
|
|
done
|
|
|
|
echo "HTTPS Backend erreichbar - starte Kiosk-Browser..."
|
|
|
|
# Browser-Erkennung und -Start mit HTTPS-optimierten Vollbild-Flags
|
|
if command -v chromium >/dev/null 2>&1; then
|
|
echo "Starte Chromium Browser mit HTTPS und Auflösung ${WIDTH}x${HEIGHT}..."
|
|
exec chromium \
|
|
--kiosk \
|
|
--no-sandbox \
|
|
--disable-infobars \
|
|
--disable-session-crashed-bubble \
|
|
--disable-restore-session-state \
|
|
--disable-features=TranslateUI \
|
|
--disable-extensions \
|
|
--disable-plugins \
|
|
--disable-popup-blocking \
|
|
--disable-prompt-on-repost \
|
|
--disable-sync \
|
|
--disable-translate \
|
|
--noerrdialogs \
|
|
--no-first-run \
|
|
--no-default-browser-check \
|
|
--autoplay-policy=no-user-gesture-required \
|
|
--start-fullscreen \
|
|
--start-maximized \
|
|
--window-size=${WIDTH},${HEIGHT} \
|
|
--window-position=0,0 \
|
|
--user-data-dir=/home/kiosk/.chromium-kiosk \
|
|
--disable-background-mode \
|
|
--force-device-scale-factor=1.0 \
|
|
--disable-pinch \
|
|
--overscroll-history-navigation=0 \
|
|
--disable-dev-shm-usage \
|
|
--memory-pressure-off \
|
|
--max_old_space_size=512 \
|
|
--disable-background-timer-throttling \
|
|
--disable-backgrounding-occluded-windows \
|
|
--disable-renderer-backgrounding \
|
|
--disable-features=VizDisplayCompositor \
|
|
--enable-features=OverlayScrollbar \
|
|
--hide-scrollbars \
|
|
--ignore-certificate-errors \
|
|
--ignore-ssl-errors \
|
|
--ignore-certificate-errors-spki-list \
|
|
--disable-web-security \
|
|
--allow-running-insecure-content \
|
|
--unsafely-treat-insecure-origin-as-secure=https://localhost:443 \
|
|
https://localhost:443
|
|
elif command -v chromium-browser >/dev/null 2>&1; then
|
|
echo "Starte Chromium-Browser mit HTTPS und Auflösung ${WIDTH}x${HEIGHT}..."
|
|
exec chromium-browser \
|
|
--kiosk \
|
|
--no-sandbox \
|
|
--disable-infobars \
|
|
--disable-session-crashed-bubble \
|
|
--disable-restore-session-state \
|
|
--disable-features=TranslateUI \
|
|
--disable-extensions \
|
|
--disable-plugins \
|
|
--disable-popup-blocking \
|
|
--disable-prompt-on-repost \
|
|
--disable-sync \
|
|
--disable-translate \
|
|
--noerrdialogs \
|
|
--no-first-run \
|
|
--no-default-browser-check \
|
|
--autoplay-policy=no-user-gesture-required \
|
|
--start-fullscreen \
|
|
--start-maximized \
|
|
--window-size=${WIDTH},${HEIGHT} \
|
|
--window-position=0,0 \
|
|
--user-data-dir=/home/kiosk/.chromium-kiosk \
|
|
--disable-background-mode \
|
|
--force-device-scale-factor=1.0 \
|
|
--disable-pinch \
|
|
--overscroll-history-navigation=0 \
|
|
--disable-dev-shm-usage \
|
|
--memory-pressure-off \
|
|
--max_old_space_size=512 \
|
|
--disable-background-timer-throttling \
|
|
--disable-backgrounding-occluded-windows \
|
|
--disable-renderer-backgrounding \
|
|
--disable-features=VizDisplayCompositor \
|
|
--enable-features=OverlayScrollbar \
|
|
--hide-scrollbars \
|
|
--ignore-certificate-errors \
|
|
--ignore-ssl-errors \
|
|
--ignore-certificate-errors-spki-list \
|
|
--disable-web-security \
|
|
--allow-running-insecure-content \
|
|
--unsafely-treat-insecure-origin-as-secure=https://localhost:443 \
|
|
https://localhost:443
|
|
elif command -v firefox-esr >/dev/null 2>&1; then
|
|
echo "Starte Firefox ESR mit HTTPS und Auflösung ${WIDTH}x${HEIGHT}..."
|
|
# Firefox-Profil für HTTPS Kiosk erstellen
|
|
mkdir -p /home/kiosk/.mozilla/firefox/kiosk.default
|
|
cat > /home/kiosk/.mozilla/firefox/kiosk.default/user.js << FIREFOXEOF
|
|
user_pref("browser.shell.checkDefaultBrowser", false);
|
|
user_pref("browser.startup.homepage", "https://localhost:443");
|
|
user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true);
|
|
user_pref("browser.tabs.warnOnClose", false);
|
|
user_pref("browser.sessionstore.resume_from_crash", false);
|
|
user_pref("security.tls.insecure_fallback_hosts", "localhost");
|
|
user_pref("security.mixed_content.block_active_content", false);
|
|
user_pref("security.mixed_content.block_display_content", false);
|
|
user_pref("browser.cache.disk.enable", false);
|
|
user_pref("browser.cache.memory.enable", true);
|
|
user_pref("browser.cache.offline.enable", false);
|
|
user_pref("network.http.use-cache", false);
|
|
user_pref("browser.fullscreen.autohide", true);
|
|
user_pref("dom.disable_open_during_load", false);
|
|
user_pref("privacy.popups.disable_from_plugins", 0);
|
|
user_pref("dom.popup_maximum", 0);
|
|
user_pref("security.cert_pinning.enforcement_level", 0);
|
|
user_pref("security.tls.unrestricted_rc4_fallback", true);
|
|
FIREFOXEOF
|
|
|
|
# Firefox CSS für randlosen Vollbildmodus
|
|
mkdir -p /home/kiosk/.mozilla/firefox/kiosk.default/chrome
|
|
cat > /home/kiosk/.mozilla/firefox/kiosk.default/chrome/userChrome.css << FIREFOXCSS
|
|
/* Firefox Kiosk Mode - Hide all UI elements */
|
|
#navigator-toolbox { display: none !important; }
|
|
#sidebar-box { display: none !important; }
|
|
#urlbar-container { display: none !important; }
|
|
#TabsToolbar { display: none !important; }
|
|
#nav-bar { display: none !important; }
|
|
#PersonalToolbar { display: none !important; }
|
|
.toolbar-items { display: none !important; }
|
|
#main-window[sizemode="fullscreen"] .tabbrowser-tab {
|
|
visibility: collapse !important;
|
|
}
|
|
FIREFOXCSS
|
|
|
|
exec firefox-esr \
|
|
--kiosk \
|
|
--width=${WIDTH} \
|
|
--height=${HEIGHT} \
|
|
--profile /home/kiosk/.mozilla/firefox/kiosk.default \
|
|
https://localhost:443
|
|
else
|
|
echo "FEHLER: Kein Browser verfügbar!"
|
|
exit 1
|
|
fi
|
|
EOF
|
|
|
|
# Berechtigungen setzen
|
|
chmod +x "$KIOSK_HOME/.xinitrc"
|
|
chown -R "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME"
|
|
|
|
log "✅ Kiosk-Browser mit HTTPS-Vollbildmodus konfiguriert"
|
|
}
|
|
|
|
# ========================== APP.PY SSL-UNTERSTÜTZUNG PRÜFEN ==========================
|
|
verify_app_ssl_support() {
|
|
log "=== PRÜFE APP.PY SSL-UNTERSTÜTZUNG ==="
|
|
|
|
if [ ! -f "$APP_DIR/app.py" ]; then
|
|
error "app.py nicht gefunden in $APP_DIR"
|
|
fi
|
|
|
|
# Prüfe ob get_ssl_context Funktion existiert
|
|
if grep -q "def get_ssl_context" "$APP_DIR/app.py"; then
|
|
log "✅ get_ssl_context Funktion bereits vorhanden in app.py"
|
|
else
|
|
progress "Füge SSL-Unterstützung zu app.py hinzu..."
|
|
|
|
# Backup der originalen app.py
|
|
cp "$APP_DIR/app.py" "$APP_DIR/app.py.backup.$(date +%s)"
|
|
|
|
# SSL-Funktion am Ende der Datei hinzufügen (vor dem if __name__ == '__main__' Block)
|
|
cat >> "$APP_DIR/app.py" << 'EOF'
|
|
|
|
def get_ssl_context():
|
|
"""
|
|
SSL-Kontext für HTTPS-Server erstellen
|
|
Verwendet localhost-Zertifikate falls verfügbar
|
|
"""
|
|
import os
|
|
|
|
ssl_cert_path = '/opt/myp/certs/localhost/localhost.crt'
|
|
ssl_key_path = '/opt/myp/certs/localhost/localhost.key'
|
|
|
|
if os.path.exists(ssl_cert_path) and os.path.exists(ssl_key_path):
|
|
try:
|
|
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
|
|
context.load_cert_chain(ssl_cert_path, ssl_key_path)
|
|
context.check_hostname = False
|
|
context.verify_mode = ssl.CERT_NONE
|
|
print(f"✅ SSL-Kontext erstellt mit: {ssl_cert_path}")
|
|
return context
|
|
except Exception as e:
|
|
print(f"❌ Fehler beim Erstellen des SSL-Kontexts: {e}")
|
|
return None
|
|
else:
|
|
print(f"❌ SSL-Zertifikate nicht gefunden:")
|
|
print(f" Cert: {ssl_cert_path}")
|
|
print(f" Key: {ssl_key_path}")
|
|
return None
|
|
|
|
EOF
|
|
|
|
log "✅ SSL-Unterstützung zu app.py hinzugefügt"
|
|
fi
|
|
|
|
# Prüfe ob SSL-Imports vorhanden sind
|
|
if ! grep -q "import ssl" "$APP_DIR/app.py"; then
|
|
progress "Füge SSL-Import zu app.py hinzu..."
|
|
sed -i '1i import ssl' "$APP_DIR/app.py"
|
|
fi
|
|
|
|
log "✅ app.py SSL-Unterstützung verifiziert"
|
|
}
|
|
|
|
# ========================== PRODUKTIONS-KIOSK SETUP ==========================
|
|
setup_production_kiosk() {
|
|
log "=== RICHTE PRODUKTIONS-KIOSK-MODUS MIT HTTPS EIN ==="
|
|
|
|
# 1. System-Abhängigkeiten installieren
|
|
install_system_dependencies
|
|
|
|
# 2. Desktop-Environments entfernen
|
|
remove_desktop_environments
|
|
|
|
# 3. Minimale X11-Umgebung installieren
|
|
install_minimal_x11
|
|
|
|
# 4. Kiosk-Benutzer erstellen
|
|
create_kiosk_user
|
|
|
|
# 5. Anwendung kopieren
|
|
progress "Erstelle Zielverzeichnis /opt/myp..."
|
|
mkdir -p "$APP_DIR" || error "Konnte Zielverzeichnis nicht erstellen"
|
|
|
|
progress "Kopiere Projektdateien selektiv nach $APP_DIR..."
|
|
|
|
# Liste der zu kopierenden Dateien/Ordner (ohne unnötige Inhalte)
|
|
declare -a COPY_ITEMS=(
|
|
"app.py"
|
|
"models.py"
|
|
"requirements.txt"
|
|
"blueprints/"
|
|
"config/"
|
|
"database/"
|
|
"docs/"
|
|
"static/"
|
|
"templates/"
|
|
"uploads/"
|
|
"utils/"
|
|
"logs/"
|
|
"certs/"
|
|
)
|
|
|
|
# Sichere selektive Kopie
|
|
for item in "${COPY_ITEMS[@]}"; do
|
|
if [ -e "$CURRENT_DIR/$item" ]; then
|
|
progress "Kopiere: $item"
|
|
cp -r "$CURRENT_DIR/$item" "$APP_DIR/" || warning "Fehler beim Kopieren von $item"
|
|
else
|
|
info "Überspringe nicht vorhandenes Element: $item"
|
|
fi
|
|
done
|
|
|
|
# Spezielle Dateien einzeln kopieren (falls vorhanden)
|
|
for file in "package.json" "package-lock.json" "tailwind.config.js" "postcss.config.js"; do
|
|
if [ -f "$CURRENT_DIR/$file" ]; then
|
|
cp "$CURRENT_DIR/$file" "$APP_DIR/" || warning "Fehler beim Kopieren von $file"
|
|
fi
|
|
done
|
|
|
|
# Stelle sicher, dass app.py ausführbar ist
|
|
chmod +x "$APP_DIR/app.py" || error "Konnte app.py nicht ausführbar machen"
|
|
|
|
# Erstelle notwendige Verzeichnisse falls sie nicht existieren
|
|
mkdir -p "$APP_DIR/database/backups"
|
|
mkdir -p "$APP_DIR/logs/app"
|
|
mkdir -p "$APP_DIR/logs/auth"
|
|
mkdir -p "$APP_DIR/logs/errors"
|
|
mkdir -p "$APP_DIR/uploads/temp"
|
|
mkdir -p "$APP_DIR/certs/localhost"
|
|
|
|
# Berechtigungen setzen
|
|
chown -R root:root "$APP_DIR"
|
|
chmod -R 755 "$APP_DIR"
|
|
chmod 750 "$APP_DIR/database"
|
|
chmod 750 "$APP_DIR/logs"
|
|
chmod 755 "$APP_DIR/uploads"
|
|
chmod 750 "$APP_DIR/certs"
|
|
|
|
# 6. App.py SSL-Unterstützung prüfen und hinzufügen
|
|
verify_app_ssl_support
|
|
|
|
# 7. SSL-Zertifikate für localhost erstellen
|
|
create_localhost_ssl_certificates
|
|
|
|
# 8. Backend-Service erstellen
|
|
create_backend_service
|
|
|
|
# 9. Autologin konfigurieren
|
|
configure_autologin
|
|
|
|
# 10. Kiosk-Browser konfigurieren
|
|
configure_kiosk_browser
|
|
|
|
# 11. Service aktivieren und starten
|
|
progress "Lade Systemd-Konfiguration neu..."
|
|
systemctl daemon-reload || error "Systemd Reload fehlgeschlagen"
|
|
|
|
progress "Aktiviere HTTPS Backend-Service..."
|
|
systemctl enable "$SERVICE_NAME.service" || error "HTTPS-Service Enable fehlgeschlagen"
|
|
|
|
progress "Starte HTTPS Backend-Service..."
|
|
systemctl start "$SERVICE_NAME.service" || error "HTTPS-Service Start fehlgeschlagen"
|
|
|
|
# Service-Status prüfen
|
|
sleep 5
|
|
|
|
info "=== SERVICE-STATUS ==="
|
|
if systemctl is-active --quiet "$SERVICE_NAME.service"; then
|
|
log "✅ $SERVICE_NAME Service läuft erfolgreich"
|
|
else
|
|
warning "⚠️ $SERVICE_NAME Service läuft nicht - prüfen Sie die Logs: journalctl -u $SERVICE_NAME -f"
|
|
fi
|
|
|
|
# Backend-Tests
|
|
progress "Teste HTTPS Backend-Erreichbarkeit..."
|
|
sleep 3
|
|
|
|
if curl -k -s https://localhost:443 > /dev/null 2>&1; then
|
|
log "✅ Port 443 (HTTPS) erreichbar"
|
|
else
|
|
warning "⚠️ Port 443 (HTTPS) nicht erreichbar"
|
|
# Zusätzliche Debug-Information
|
|
progress "Versuche SSL-Zertifikat zu testen..."
|
|
if openssl s_client -connect localhost:443 -servername localhost < /dev/null 2>/dev/null | grep -q "CONNECTED"; then
|
|
log "✅ SSL-Verbindung funktioniert"
|
|
else
|
|
warning "⚠️ SSL-Verbindung fehlgeschlagen"
|
|
fi
|
|
fi
|
|
|
|
# SSL-Zertifikat Status
|
|
if [ -f "$APP_DIR/certs/localhost/localhost.crt" ]; then
|
|
log "✅ SSL-Zertifikat vorhanden: $APP_DIR/certs/localhost/localhost.crt"
|
|
CERT_EXPIRY=$(openssl x509 -in "$APP_DIR/certs/localhost/localhost.crt" -noout -enddate | cut -d= -f2)
|
|
log "📅 Zertifikat läuft ab: $CERT_EXPIRY"
|
|
else
|
|
warning "⚠️ SSL-Zertifikat nicht gefunden"
|
|
fi
|
|
|
|
log "✅ PRODUKTIONS-KIOSK-MODUS MIT HTTPS ERFOLGREICH EINGERICHTET"
|
|
log ""
|
|
log "🚀 WICHTIG: NEUSTART ERFORDERLICH!"
|
|
log " sudo reboot"
|
|
log ""
|
|
log "📊 NACH DEM NEUSTART:"
|
|
log " • Automatischer Login als Benutzer: $KIOSK_USER"
|
|
log " • Automatischer X-Start und Chromium-Kiosk"
|
|
log " • Backend läuft auf HTTPS:"
|
|
log " - https://localhost:443 (Kiosk-Anzeige mit SSL)"
|
|
log " - https://0.0.0.0:443 (Netzwerk-Zugriff)"
|
|
log ""
|
|
log "🔐 SSL-ZERTIFIKATE:"
|
|
log " • Self-Signed Zertifikat für localhost erstellt"
|
|
log " • Chromium akzeptiert Zertifikat automatisch"
|
|
log " • Zertifikat im System CA-Store installiert"
|
|
log ""
|
|
log "🔧 SERVICE-BEFEHLE:"
|
|
log " • Status: sudo systemctl status $SERVICE_NAME"
|
|
log " • Logs: sudo journalctl -u $SERVICE_NAME -f"
|
|
log " • Restart: sudo systemctl restart $SERVICE_NAME"
|
|
log " • SSL-Test: curl -k https://localhost:443"
|
|
log ""
|
|
warning "🔄 FÜHRE JETZT 'sudo reboot' AUS, UM DEN HTTPS-KIOSK-MODUS ZU AKTIVIEREN!"
|
|
}
|
|
|
|
# ========================== HAUPTMENÜ ==========================
|
|
show_menu() {
|
|
clear
|
|
echo -e "${BLUE}=================================================================${NC}"
|
|
echo -e "${GREEN} $APP_NAME - HTTPS KIOSK-INSTALLER${NC}"
|
|
echo -e "${BLUE}=================================================================${NC}"
|
|
echo ""
|
|
echo -e "${YELLOW}Aktuelles Verzeichnis:${NC} $CURRENT_DIR"
|
|
echo -e "${YELLOW}Systemzeit:${NC} $(date)"
|
|
echo -e "${YELLOW}Zielverzeichnis:${NC} $APP_DIR"
|
|
echo -e "${YELLOW}Kiosk-Benutzer:${NC} $KIOSK_USER"
|
|
echo -e "${YELLOW}HTTPS-Service:${NC} $SERVICE_NAME"
|
|
echo ""
|
|
echo -e "${PURPLE}Wählen Sie eine Option:${NC}"
|
|
echo ""
|
|
echo -e "${GREEN}1)${NC} System vorbereiten (Abhängigkeiten installieren)"
|
|
echo -e " → Installiert Python 3, pip und alle benötigten Pakete"
|
|
echo -e " → Verwendet: pip install --break-system-packages"
|
|
echo -e " → Mercedes SSL-Zertifikate werden konfiguriert"
|
|
echo -e " → Node.js und npm für Frontend-Build"
|
|
echo ""
|
|
echo -e "${GREEN}2)${NC} VOLLSTÄNDIGER HTTPS KIOSK-MODUS installieren"
|
|
echo -e " → ${RED}ENTFERNT ALLE DESKTOP-ENVIRONMENTS!${NC}"
|
|
echo -e " → Installiert minimale X11-Umgebung"
|
|
echo -e " → Erstellt Self-Signed SSL-Zertifikate für localhost"
|
|
echo -e " → Erstellt HTTPS Backend-Service (Port 443)"
|
|
echo -e " → Konfiguriert Autologin und HTTPS Kiosk-Browser"
|
|
echo -e " → Browser öffnet: ${BLUE}https://localhost:443${NC}"
|
|
echo -e " → ${YELLOW}NEUSTART ERFORDERLICH!${NC}"
|
|
echo ""
|
|
echo -e "${RED}0)${NC} Beenden"
|
|
echo ""
|
|
echo -e "${RED}⚠️ WARNUNG: Option 2 macht Raspberry Pi zu reinem HTTPS-Kiosk-System!${NC}"
|
|
echo -e "${GREEN}🔐 HTTPS: Automatische SSL-Zertifikat-Generierung für localhost${NC}"
|
|
echo -e "${BLUE}=================================================================${NC}"
|
|
echo -n "Ihre Wahl [0-2]: "
|
|
}
|
|
|
|
# ========================== MAIN LOGIC ==========================
|
|
main() {
|
|
# System-Checks
|
|
check_root
|
|
check_debian_system
|
|
|
|
# Erstelle Log-Datei
|
|
mkdir -p "$(dirname "$INSTALL_LOG")"
|
|
touch "$INSTALL_LOG"
|
|
|
|
log "=== MYP HTTPS KIOSK-INSTALLER GESTARTET ==="
|
|
log "Arbeitsverzeichnis: $CURRENT_DIR"
|
|
log "Zielverzeichnis: $APP_DIR"
|
|
log "HTTPS-Service: $SERVICE_NAME"
|
|
log "Kiosk-Benutzer: $KIOSK_USER"
|
|
log "SSL-Zertifikate: $APP_DIR/certs/localhost/"
|
|
log "System: $(uname -a)"
|
|
log "Debian-Version: $(cat /etc/debian_version 2>/dev/null || echo 'Unbekannt')"
|
|
|
|
while true; do
|
|
show_menu
|
|
read -r choice
|
|
|
|
case $choice in
|
|
1)
|
|
clear
|
|
log "=== OPTION 1: SYSTEM VORBEREITEN ==="
|
|
install_system_dependencies
|
|
echo ""
|
|
echo -e "${GREEN}✅ System-Vorbereitung abgeschlossen!${NC}"
|
|
echo -e "${YELLOW}Drücken Sie Enter, um fortzufahren...${NC}"
|
|
read -r
|
|
;;
|
|
2)
|
|
clear
|
|
echo -e "${RED}⚠️ WARNUNG: Sie sind dabei, alle Desktop-Environments zu entfernen!${NC}"
|
|
echo -e "${YELLOW}Der Raspberry Pi wird zu einem reinen HTTPS-Kiosk-System umgebaut.${NC}"
|
|
echo -e "${BLUE}Nach der Installation startet automatisch der HTTPS-Kiosk-Browser.${NC}"
|
|
echo -e "${GREEN}SSL-Zertifikate für localhost werden automatisch generiert.${NC}"
|
|
echo ""
|
|
echo -n "Sind Sie sicher? [ja/NEIN]: "
|
|
read -r confirm
|
|
|
|
if [ "$confirm" = "ja" ] || [ "$confirm" = "JA" ]; then
|
|
clear
|
|
log "=== OPTION 2: VOLLSTÄNDIGER HTTPS KIOSK-MODUS ==="
|
|
setup_production_kiosk
|
|
echo ""
|
|
echo -e "${GREEN}✅ HTTPS KIOSK-MODUS ERFOLGREICH EINGERICHTET!${NC}"
|
|
echo -e "${RED}🔄 NEUSTART JETZT ERFORDERLICH: sudo reboot${NC}"
|
|
echo -e "${BLUE}🔐 HTTPS-URL: https://localhost:443${NC}"
|
|
echo -e "${YELLOW}Drücken Sie Enter, um fortzufahren...${NC}"
|
|
read -r
|
|
else
|
|
echo -e "${BLUE}Installation abgebrochen.${NC}"
|
|
sleep 2
|
|
fi
|
|
;;
|
|
0)
|
|
log "=== HTTPS KIOSK-INSTALLER BEENDET ==="
|
|
echo -e "${GREEN}Auf Wiedersehen!${NC}"
|
|
echo -e "${BLUE}Log-Datei: $INSTALL_LOG${NC}"
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo -e "${RED}Ungültige Eingabe. Bitte wählen Sie 0-2.${NC}"
|
|
sleep 2
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# Script starten
|
|
main "$@" |