2127 lines
72 KiB
Bash
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# ===================================================================
# MYP Druckerverwaltung - KONSOLIDIERTES SETUP-SKRIPT
# Kombiniert alle Installationsfunktionen in einer einzigen Datei
# Optimiert für Debian/Linux (Raspberry Pi OS) - KEIN Windows-Support
# HTTPS auf Port 443 mit automatischer SSL-Zertifikat-Generierung
# Kiosk-Modus mit Chromium-Autostart ohne Desktop-Environment
# RASPBERRY PI CSS/JS PERFORMANCE-OPTIMIERUNGEN INTEGRIERT
# Automatische Hardware-Erkennung und spezifische Browser-Optimierungen
# Version: 4.1.0 - Raspberry Pi CSS-Optimiert
# ===================================================================
set -euo pipefail
# =========================== GLOBALE KONFIGURATION ===========================
readonly APP_NAME="MYP Druckerverwaltung"
readonly APP_VERSION="4.1.0"
readonly APP_DIR="/opt/myp"
readonly HTTPS_SERVICE_NAME="myp-https"
readonly KIOSK_SERVICE_NAME="myp-kiosk"
readonly WATCHDOG_SERVICE_NAME="kiosk-watchdog"
readonly WATCHDOG_PYTHON_SERVICE_NAME="kiosk-watchdog-python"
readonly FIREWALL_SERVICE_NAME="myp-firewall"
readonly KIOSK_USER="kiosk"
readonly CURRENT_DIR="$(pwd)"
readonly INSTALL_LOG="/var/log/myp-install.log"
readonly HTTPS_PORT="443"
readonly HTTPS_URL="https://localhost:${HTTPS_PORT}"
readonly SYSTEMD_DIR="$CURRENT_DIR/systemd"
readonly SYSTEM_SYSTEMD_DIR="/etc/systemd/system"
# Farben für Ausgabe
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly PURPLE='\033[0;35m'
readonly CYAN='\033[0;36m'
readonly NC='\033[0m'
# =========================== LOGGING-FUNKTIONEN ===========================
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"
}
success() {
echo -e "${CYAN}[ERFOLG] $1${NC}" | tee -a "$INSTALL_LOG"
}
# =========================== SYSTEM-VALIDIERUNG ===========================
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"
log "✅ Root-Berechtigung bestätigt"
}
check_debian_system() {
if [ ! -f /etc/debian_version ]; then
error "Dieses Skript ist nur für Debian/Raspbian-Systeme geeignet!"
fi
local debian_version=$(cat /etc/debian_version 2>/dev/null || echo "Unbekannt")
log "✅ Debian/Raspbian-System erkannt (Version: $debian_version)"
# Prüfe auf Raspberry Pi
if [ -f /proc/device-tree/model ]; then
local pi_model=$(cat /proc/device-tree/model 2>/dev/null || echo "Unbekannt")
info "Raspberry Pi Modell: $pi_model"
# Exportiere Raspberry Pi Detection für spätere Verwendung
export IS_RASPBERRY_PI=true
export PI_MODEL="$pi_model"
# Raspberry Pi spezifische Optimierungen aktivieren
log "✅ Raspberry Pi Hardware erkannt - CSS-Optimierungen werden aktiviert"
else
export IS_RASPBERRY_PI=false
fi
}
check_internet_connection() {
progress "Prüfe Internetverbindung..."
local test_urls=("8.8.8.8" "1.1.1.1" "google.com")
local connection_ok=false
for url in "${test_urls[@]}"; do
if ping -c 1 -W 3 "$url" >/dev/null 2>&1; then
connection_ok=true
break
fi
done
if [ "$connection_ok" = true ]; then
log "✅ Internetverbindung verfügbar"
else
warning "⚠️ Keine Internetverbindung - Installation könnte fehlschlagen"
fi
}
# =========================== SYSTEM-VORBEREITUNG ===========================
update_system() {
log "=== SYSTEM-UPDATE ==="
progress "Aktualisiere Paketlisten..."
apt-get update -y || error "APT Update fehlgeschlagen"
progress "Führe System-Upgrade durch..."
apt-get upgrade -y || warning "System-Upgrade teilweise fehlgeschlagen"
progress "Installiere grundlegende System-Tools..."
apt-get install -y \
curl \
wget \
git \
nano \
htop \
rsync \
unzip \
sudo \
systemd \
ca-certificates \
gnupg \
lsb-release \
apt-transport-https \
software-properties-common \
bc \
|| error "Grundlegende Tools Installation fehlgeschlagen"
log "✅ System-Update abgeschlossen"
}
# =========================== NETZWERK-SICHERHEIT ===========================
configure_network_security() {
log "=== KONFIGURIERE ERWEITERTE NETZWERK-SICHERHEIT ==="
# IPv6 vollständig deaktivieren
progress "Deaktiviere IPv6..."
# IPv6 in GRUB deaktivieren
if [ -f /etc/default/grub ]; then
cp /etc/default/grub /etc/default/grub.backup
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="[^"]*/& ipv6.disable=1/' /etc/default/grub
sed -i 's/GRUB_CMDLINE_LINUX="[^"]*/& ipv6.disable=1/' /etc/default/grub
update-grub 2>/dev/null || true
fi
# IPv6 in sysctl deaktivieren
cat >> /etc/sysctl.conf << 'EOF'
# ===================================================================
# MYP Netzwerk-Sicherheitskonfiguration
# ===================================================================
# IPv6 vollständig deaktivieren
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
# IP-Spoofing-Schutz aktivieren
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Source-Routing deaktivieren (verhindert IP-Spoofing)
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# ICMP-Redirects ignorieren (verhindert Man-in-the-Middle)
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
# Secure ICMP-Redirects ignorieren
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
# SYN-Flood-Schutz aktivieren
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5
# TCP-RFC-Compliance (verhindert aggressive Paketwiederholungen)
net.ipv4.tcp_retries1 = 3
net.ipv4.tcp_retries2 = 15
net.ipv4.tcp_orphan_retries = 3
# TCP-Window-Skalierung optimieren (geringere Netzwerkauslastung)
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_rmem = 4096 65536 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 5000
# Broadcast-Pings ignorieren (verhindert Smurf-Angriffe)
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Bogus ICMP-Antworten ignorieren
net.ipv4.icmp_ignore_bogus_error_responses = 1
# Paketweiterleitung verhindern (Router-Funktionalität deaktivieren)
net.ipv4.ip_forward = 0
# Martian-Pakete loggen (verdächtige Pakete)
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
# TCP-Timestamps deaktivieren (verhindert Fingerprinting)
net.ipv4.tcp_timestamps = 0
# TCP-SACK deaktivieren (verhindert bestimmte Angriffe)
net.ipv4.tcp_sack = 0
# TCP-Keepalive optimieren
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
# Memory-Limits für Netzwerk-Buffers
net.core.rmem_default = 262144
net.core.wmem_default = 262144
# Schutz vor Time-Wait-Assassination
net.ipv4.tcp_rfc1337 = 1
# ===================================================================
# RASPBERRY PI PERFORMANCE-OPTIMIERUNGEN FÜR WEBAPP
# ===================================================================
# Memory Management für schwache Hardware optimieren
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
vm.vfs_cache_pressure = 50
vm.min_free_kbytes = 8192
vm.overcommit_memory = 1
# CPU Scheduler für bessere Responsivität
kernel.sched_min_granularity_ns = 10000000
kernel.sched_wakeup_granularity_ns = 15000000
kernel.sched_migration_cost_ns = 5000000
# Filesystem Performance
vm.dirty_expire_centisecs = 500
vm.dirty_writeback_centisecs = 100
# Memory Compaction für bessere Speichernutzung
vm.compact_memory = 1
# OOM Killer weniger aggressiv
vm.oom_kill_allocating_task = 0
vm.panic_on_oom = 0
# Kernel Preemption für bessere Interaktivität
kernel.sched_rt_runtime_us = 950000
kernel.sched_rt_period_us = 1000000
# I/O Scheduler Optimierungen für SD-Karte
# (wird später per udev-Regel angewendet)
EOF
# Sysctl-Einstellungen sofort anwenden
sysctl -p || warning "Einige sysctl-Einstellungen konnten nicht angewendet werden"
# IPv6 in Netzwerk-Interfaces deaktivieren
progress "Deaktiviere IPv6 in Netzwerk-Interfaces..."
# Für systemd-networkd
if systemctl is-enabled systemd-networkd 2>/dev/null; then
mkdir -p /etc/systemd/network
cat > /etc/systemd/network/99-disable-ipv6.network << 'EOF'
[Match]
Name=*
[Network]
IPv6AcceptRA=no
LinkLocalAddressing=no
EOF
systemctl restart systemd-networkd 2>/dev/null || true
fi
# Für NetworkManager
if systemctl is-enabled NetworkManager 2>/dev/null; then
cat > /etc/NetworkManager/conf.d/99-disable-ipv6.conf << 'EOF'
[main]
plugins=keyfile
[keyfile]
unmanaged-devices=none
[connection]
ipv6.method=ignore
EOF
systemctl restart NetworkManager 2>/dev/null || true
fi
# IPv6 in /etc/hosts auskommentieren
sed -i 's/^::1/#::1/' /etc/hosts 2>/dev/null || true
log "✅ Erweiterte Netzwerk-Sicherheit konfiguriert:"
log " 🚫 IPv6 vollständig deaktiviert"
log " 🛡️ IP-Spoofing-Schutz aktiviert"
log " 🔒 SYN-Flood-Schutz aktiviert"
log " 📝 Verdächtige Pakete werden geloggt"
log " 🚫 Paketweiterleitung deaktiviert"
log " ⚡ TCP-Performance optimiert"
log " 🔐 RFC-Compliance für TCP aktiviert"
}
# =========================== DESKTOP-ENVIRONMENT ENTFERNUNG ===========================
remove_desktop_environments() {
log "=== ENTFERNE DESKTOP ENVIRONMENTS FÜR KIOSK-MODUS ==="
progress "Stoppe alle Desktop-Services..."
local desktop_services=("lightdm" "gdm3" "sddm" "xdm" "nodm")
for service in "${desktop_services[@]}"; do
systemctl stop "$service" 2>/dev/null || true
systemctl disable "$service" 2>/dev/null || true
done
progress "Entferne Desktop-Pakete vollständig..."
# Raspberry Pi OS Desktop-Pakete
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 Anwendungen entfernen
apt-get remove --purge -y \
libreoffice* \
thunderbird* \
firefox* \
vlc* \
gimp* \
scratch* \
minecraft-pi \
sonic-pi \
2>/dev/null || true
# Aufräumen
apt-get autoremove --purge -y
apt-get autoclean
log "✅ Desktop Environments vollständig entfernt"
}
# =========================== MINIMALE X11-UMGEBUNG ===========================
install_minimal_x11() {
log "=== INSTALLIERE MINIMALE X11-UMGEBUNG FÜR KIOSK ==="
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"
# Browser-Installation mit Fallback-Mechanismus
progress "Installiere Browser für Kiosk-Modus..."
local browser_installed=false
# Versuche Chromium zu installieren
if apt-get install -y chromium 2>/dev/null; then
log "✅ Chromium erfolgreich installiert"
browser_installed=true
elif apt-get install -y chromium-browser 2>/dev/null; then
log "✅ Chromium-Browser erfolgreich installiert"
browser_installed=true
elif apt-get install -y firefox-esr 2>/dev/null; then
warning "⚠️ Chromium nicht verfügbar - Firefox ESR als Fallback installiert"
browser_installed=true
fi
if [ "$browser_installed" = false ]; then
error "❌ Kein Browser verfügbar (chromium, chromium-browser, firefox-esr)"
fi
log "✅ Minimale X11-Umgebung installiert"
}
# =========================== KIOSK-BENUTZER MANAGEMENT ===========================
create_kiosk_user() {
log "=== KIOSK-BENUTZER SETUP ==="
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 konfiguriert: $KIOSK_USER"
}
configure_autologin() {
log "=== KONFIGURIERE AUTOLOGIN FÜR KIOSK-BENUTZER ==="
# Getty-Service für automatischen Login konfigurieren
progress "Konfiguriere automatischen Login auf tty1..."
local getty_override_dir="/etc/systemd/system/getty@tty1.service.d"
mkdir -p "$getty_override_dir"
cat > "$getty_override_dir/override.conf" << EOF
[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin $KIOSK_USER --noclear %I \$TERM
EOF
# Systemd-Konfiguration neu laden
systemctl daemon-reload
systemctl enable getty@tty1.service
log "✅ Autologin für $KIOSK_USER konfiguriert"
}
configure_kiosk_autostart() {
log "=== KONFIGURIERE AUTOMATISCHEN KIOSK-START ==="
# Erstelle .bashrc für automatischen X-Server und Browser-Start
progress "Konfiguriere automatischen Kiosk-Start für $KIOSK_USER..."
local kiosk_home="/home/$KIOSK_USER"
# .bashrc für automatischen Start erstellen
cat > "$kiosk_home/.bashrc" << 'EOF'
# Automatischer Kiosk-Start beim Login
if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = "1" ]; then
echo "Starte Kiosk-Modus..."
# X-Server im Hintergrund starten
startx /home/kiosk/.xinitrc -- :0 vt1 &
# Warte bis X-Server bereit ist
sleep 5
# Setze DISPLAY-Variable
export DISPLAY=:0
# Warte auf HTTPS-Backend
echo "Warte auf HTTPS-Backend..."
for i in {1..60}; do
if curl -k -s https://localhost:443 >/dev/null 2>&1; then
echo "HTTPS-Backend erreichbar"
break
fi
echo "Warte... ($i/60)"
sleep 2
done
# Bildschirmschoner deaktivieren
xset s off
xset s noblank
xset -dpms
# Mauszeiger verstecken
unclutter -idle 0.1 -root -noevents &
# Browser im Kiosk-Modus starten
if command -v chromium >/dev/null 2>&1; then
BROWSER="chromium"
elif command -v chromium-browser >/dev/null 2>&1; then
BROWSER="chromium-browser"
else
BROWSER="firefox-esr"
fi
echo "Starte $BROWSER im Kiosk-Modus..."
if [[ "$BROWSER" == "chromium"* ]]; then
exec $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 \
--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 \
--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 \
--disable-gpu-sandbox \
--disable-software-rasterizer \
--enable-low-end-device-mode \
--disable-features=VizHitTestSurfaceLayer \
--disable-partial-raster \
--disable-threaded-animation \
--disable-checker-imaging \
--disable-new-content-rendering-timeout \
--run-all-compositor-stages-before-draw \
--disable-ipc-flooding-protection \
https://localhost:443
else
exec firefox-esr \
--kiosk \
https://localhost:443
fi
fi
EOF
# .xinitrc für X-Server-Konfiguration erstellen
cat > "$kiosk_home/.xinitrc" << 'EOF'
#!/bin/bash
# Minimale X-Session für Kiosk-Modus
exec openbox-session
EOF
# Berechtigungen setzen
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.bashrc"
chown "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.xinitrc"
chmod +x "$kiosk_home/.xinitrc"
# Erstelle Kiosk-Verzeichnisse
mkdir -p "$kiosk_home/.chromium-kiosk"
chown -R "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.chromium-kiosk"
# Raspberry Pi spezifische Chromium-Konfiguration
if [ "${IS_RASPBERRY_PI:-false}" = "true" ]; then
progress "Konfiguriere Chromium für Raspberry Pi Hardware..."
# Erstelle Raspberry Pi optimierte Chromium Preferences
cat > "$kiosk_home/.chromium-kiosk/Default/Preferences" << 'EOF'
{
"browser" : {
"check_default_browser" : false,
"show_home_button" : false
},
"profile" : {
"default_content_setting_values" : {
"notifications" : 2
},
"password_manager_enabled" : false
},
"translate" : {
"enabled" : false
},
"extensions" : {
"ui" : {
"developer_mode" : false
}
},
"browser_switcher" : {
"enabled" : false
},
"performance_tuning" : {
"high_efficiency_mode" : {
"enabled" : true
},
"battery_saver_mode" : {
"enabled" : false
}
},
"privacy" : {
"ad_measurement_enabled" : false,
"enable_do_not_track" : true
}
}
EOF
# Erstelle Raspberry Pi optimierte Local State
cat > "$kiosk_home/.chromium-kiosk/Local State" << 'EOF'
{
"background_mode" : {
"enabled" : false
},
"browser" : {
"enabled_labs_experiments" : [ ]
},
"user_experience_metrics" : {
"reporting_enabled" : false
}
}
EOF
chown -R "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.chromium-kiosk"
log "✅ Raspberry Pi optimierte Chromium-Konfiguration erstellt"
fi
log "✅ Automatischer Kiosk-Start konfiguriert"
info "Der Kiosk-Modus startet automatisch beim Login des $KIOSK_USER"
}
# =========================== PYTHON & NODE.JS INSTALLATION ===========================
install_python_dependencies() {
log "=== PYTHON-ABHÄNGIGKEITEN INSTALLATION ==="
progress "Installiere Python 3 und Entwicklungstools..."
apt-get install -y \
python3 \
python3-pip \
python3-dev \
python3-setuptools \
python3-venv \
build-essential \
libssl-dev \
libffi-dev \
sqlite3 \
|| error "Python Installation fehlgeschlagen"
# pip auf neueste Version aktualisieren
progress "Aktualisiere pip..."
python3 -m pip install --upgrade pip --break-system-packages || warning "pip Update fehlgeschlagen"
# SSL-Konfiguration für pip
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
log "✅ Python-Umgebung vorbereitet"
}
install_nodejs_npm() {
log "=== NODE.JS UND NPM INSTALLATION ==="
# 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 hinzufügen
progress "Installiere Node.js LTS..."
if curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - 2>/dev/null; then
apt-get update -y
apt-get install -y nodejs || error "Node.js Installation fehlgeschlagen"
else
warning "NodeSource Repository nicht verfügbar - verwende Debian-Repository"
apt-get install -y nodejs npm || error "Node.js Fallback Installation fehlgeschlagen"
fi
# Versionen prüfen
if command -v node >/dev/null 2>&1; then
local node_version=$(node --version)
log "✅ Node.js installiert: $node_version"
else
error "❌ Node.js Installation fehlgeschlagen"
fi
if command -v npm >/dev/null 2>&1; then
local npm_version=$(npm --version)
log "✅ npm installiert: $npm_version"
# npm-Konfiguration optimieren
npm config set fund false 2>/dev/null || true
npm config set audit-level moderate 2>/dev/null || true
else
error "❌ npm Installation fehlgeschlagen"
fi
log "✅ Node.js und npm erfolgreich installiert"
}
install_python_packages() {
log "=== PYTHON-PAKETE INSTALLATION ==="
local pip_opts="--break-system-packages --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --timeout 60 --retries 3"
progress "Installiere 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"
progress "Installiere Datenbank-Komponenten..."
pip3 install $pip_opts SQLAlchemy==2.0.36 || pip3 install $pip_opts SQLAlchemy || error "SQLAlchemy Installation fehlgeschlagen"
progress "Installiere Sicherheits-Komponenten..."
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"
progress "Installiere weitere Abhängigkeiten..."
pip3 install $pip_opts requests==2.32.3 || pip3 install $pip_opts requests || error "requests Installation fehlgeschlagen"
pip3 install $pip_opts psutil==6.1.1 || pip3 install $pip_opts psutil || error "psutil Installation fehlgeschlagen"
pip3 install $pip_opts MarkupSafe==3.0.2 || pip3 install $pip_opts MarkupSafe || error "MarkupSafe Installation fehlgeschlagen"
pip3 install $pip_opts gunicorn==23.0.0 || pip3 install $pip_opts gunicorn || error "gunicorn Installation fehlgeschlagen"
# Optionale Pakete
pip3 install $pip_opts PyP100 || warning "PyP100 Installation fehlgeschlagen (optional)"
pip3 install $pip_opts redis==5.2.1 || warning "redis Installation fehlgeschlagen (optional)"
log "✅ Python-Pakete erfolgreich installiert"
}
# =========================== SSL-ZERTIFIKATE ===========================
install_ssl_certificates() {
log "=== SSL-ZERTIFIKATE KONFIGURATION ==="
progress "Aktualisiere CA-Zertifikate..."
apt-get install -y ca-certificates openssl || error "CA-Zertifikate Installation fehlgeschlagen"
update-ca-certificates || warning "CA-Zertifikate Update fehlgeschlagen"
# Mercedes Corporate Zertifikate (falls vorhanden)
if [ -d "$CURRENT_DIR/certs/mercedes" ] && [ "$(ls -A $CURRENT_DIR/certs/mercedes 2>/dev/null)" ]; then
progress "Installiere Mercedes Corporate Zertifikate..."
find "$CURRENT_DIR/certs/mercedes" -type f \( -name "*.crt" -o -name "*.pem" -o -name "*.cer" \) | while read cert_file; do
local cert_basename=$(basename "$cert_file")
local cert_name="${cert_basename%.*}"
progress "Verarbeite Mercedes-Zertifikat: $cert_basename"
# Zertifikat validieren und installieren
if openssl x509 -in "$cert_file" -text -noout >/dev/null 2>&1; then
cp "$cert_file" "/usr/local/share/ca-certificates/${cert_name}.crt"
log "✅ Zertifikat installiert: ${cert_name}.crt"
elif openssl x509 -in "$cert_file" -inform DER -text -noout >/dev/null 2>&1; then
openssl x509 -in "$cert_file" -inform DER -out "/usr/local/share/ca-certificates/${cert_name}.crt" -outform PEM
log "✅ DER-Zertifikat konvertiert und installiert: ${cert_name}.crt"
else
warning "⚠️ Ungültiges Zertifikat übersprungen: $cert_file"
fi
done
update-ca-certificates || warning "Mercedes Zertifikate Update fehlgeschlagen"
fi
# SSL-Umgebungsvariablen setzen
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"
log "✅ SSL-Zertifikate konfiguriert"
}
# =========================== ANWENDUNGS-DEPLOYMENT ===========================
deploy_application() {
log "=== ANWENDUNGS-DEPLOYMENT ==="
progress "Erstelle Zielverzeichnis: $APP_DIR"
mkdir -p "$APP_DIR" || error "Konnte Zielverzeichnis nicht erstellen"
progress "Kopiere Anwendungsdateien..."
# Liste der zu kopierenden Dateien/Ordner
local copy_items=(
"app.py"
"models.py"
"requirements.txt"
"blueprints/"
"config/"
"database/"
"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
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
# Erstelle notwendige Verzeichnisse
mkdir -p "$APP_DIR"/{database/backups,logs/{app,auth,errors},uploads/temp,certs/localhost}
# Berechtigungen setzen
chown -R root:root "$APP_DIR"
chmod -R 755 "$APP_DIR"
chmod 750 "$APP_DIR"/{database,logs,certs}
chmod +x "$APP_DIR/app.py"
log "✅ Anwendung erfolgreich deployed"
}
install_npm_dependencies() {
log "=== NPM-ABHÄNGIGKEITEN INSTALLATION ==="
if [ -f "$APP_DIR/package.json" ]; then
progress "Installiere npm-Abhängigkeiten..."
cd "$APP_DIR"
# npm install mit verschiedenen Fallback-Strategien
if npm install --no-optional --no-audit --no-fund 2>/dev/null; then
log "✅ npm install erfolgreich (Standard)"
elif npm install --legacy-peer-deps --no-optional 2>/dev/null; then
log "✅ npm install erfolgreich (Legacy-Modus)"
elif npm install --force 2>/dev/null; then
log "✅ npm install erfolgreich (Force-Modus)"
else
warning "⚠️ npm install fehlgeschlagen - überspringe"
fi
cd "$CURRENT_DIR"
else
info "Keine package.json gefunden - überspringe npm-Installation"
fi
log "✅ NPM-Abhängigkeiten verarbeitet"
}
# =========================== SSL-ZERTIFIKAT GENERIERUNG ===========================
generate_ssl_certificate() {
log "=== SSL-ZERTIFIKAT GENERIERUNG ==="
progress "Generiere selbstsigniertes SSL-Zertifikat für localhost..."
local cert_dir="$APP_DIR/certs/localhost"
mkdir -p "$cert_dir"
# Generiere privaten Schlüssel
openssl genrsa -out "$cert_dir/localhost.key" 2048 || error "Fehler beim Generieren des privaten Schlüssels"
# Generiere Zertifikat
openssl req -new -x509 -key "$cert_dir/localhost.key" -out "$cert_dir/localhost.crt" -days 365 \
-subj "/C=DE/ST=Baden-Wuerttemberg/L=Stuttgart/O=Mercedes-Benz/OU=IT/CN=localhost" \
|| error "Fehler beim Generieren des SSL-Zertifikats"
# Berechtigungen setzen
chmod 600 "$cert_dir/localhost.key"
chmod 644 "$cert_dir/localhost.crt"
log "✅ SSL-Zertifikat erfolgreich generiert"
}
# =========================== SYSTEMD-SERVICES ===========================
install_systemd_services() {
log "=== SYSTEMD-SERVICES INSTALLATION ==="
# Prüfe ob systemd-Verzeichnis existiert
if [ ! -d "$SYSTEMD_DIR" ]; then
error "systemd-Verzeichnis nicht gefunden: $SYSTEMD_DIR"
fi
progress "Kopiere Service-Dateien nach $SYSTEM_SYSTEMD_DIR..."
# Kopiere alle Service-Dateien
local service_files=(
"$HTTPS_SERVICE_NAME.service"
"$KIOSK_SERVICE_NAME.service"
"$WATCHDOG_SERVICE_NAME.service"
"$WATCHDOG_PYTHON_SERVICE_NAME.service"
"$FIREWALL_SERVICE_NAME.service"
)
for service_file in "${service_files[@]}"; do
if [ -f "$SYSTEMD_DIR/$service_file" ]; then
progress "Kopiere Service: $service_file"
cp "$SYSTEMD_DIR/$service_file" "$SYSTEM_SYSTEMD_DIR/" || error "Fehler beim Kopieren von $service_file"
else
warning "Service-Datei nicht gefunden: $service_file"
fi
done
# Systemd-Konfiguration neu laden
progress "Lade systemd-Konfiguration neu..."
systemctl daemon-reload || error "systemctl daemon-reload fehlgeschlagen"
log "✅ Systemd-Services installiert"
}
enable_and_start_services() {
log "=== SERVICES AKTIVIEREN UND STARTEN ==="
# HTTPS-Service aktivieren und starten
progress "Aktiviere und starte HTTPS-Service..."
systemctl enable "$HTTPS_SERVICE_NAME" || error "Fehler beim Aktivieren des HTTPS-Service"
systemctl start "$HTTPS_SERVICE_NAME" || error "Fehler beim Starten des HTTPS-Service"
# Warte kurz und prüfe Status
sleep 5
if systemctl is-active --quiet "$HTTPS_SERVICE_NAME"; then
log "✅ HTTPS-Service läuft erfolgreich"
else
error "❌ HTTPS-Service konnte nicht gestartet werden"
fi
# Kiosk-Service aktivieren (aber nicht starten - wird beim nächsten Boot gestartet)
progress "Aktiviere Kiosk-Service..."
systemctl enable "$KIOSK_SERVICE_NAME" || warning "Fehler beim Aktivieren des Kiosk-Service"
# Watchdog-Service aktivieren und starten
progress "Aktiviere und starte Watchdog-Service..."
systemctl enable "$WATCHDOG_SERVICE_NAME" || warning "Fehler beim Aktivieren des Watchdog-Service"
systemctl start "$WATCHDOG_SERVICE_NAME" || warning "Fehler beim Starten des Watchdog-Service"
# Firewall-Service aktivieren (falls vorhanden)
if [ -f "$SYSTEM_SYSTEMD_DIR/$FIREWALL_SERVICE_NAME.service" ]; then
progress "Aktiviere Firewall-Service..."
systemctl enable "$FIREWALL_SERVICE_NAME" || warning "Fehler beim Aktivieren des Firewall-Service"
fi
log "✅ Services erfolgreich konfiguriert"
}
# =========================== SYSTEM-TEST ===========================
test_application() {
log "=== SYSTEM-TEST ==="
progress "Teste HTTPS-Verbindung..."
# Warte auf Service-Start
local max_attempts=30
local attempt=1
while [ $attempt -le $max_attempts ]; do
if curl -k -s --connect-timeout 5 "$HTTPS_URL" >/dev/null 2>&1; then
success "✅ HTTPS-Backend erreichbar unter $HTTPS_URL"
break
fi
progress "Warte auf HTTPS-Backend... ($attempt/$max_attempts)"
sleep 2
((attempt++))
done
if [ $attempt -gt $max_attempts ]; then
error "❌ HTTPS-Backend nicht erreichbar nach $max_attempts Versuchen"
fi
# Teste SSL-Zertifikat
progress "Teste SSL-Zertifikat..."
if openssl s_client -connect localhost:443 -servername localhost </dev/null 2>/dev/null | openssl x509 -noout -text >/dev/null 2>&1; then
success "✅ SSL-Zertifikat gültig"
else
warning "⚠️ SSL-Zertifikat-Test fehlgeschlagen"
fi
log "✅ System-Test abgeschlossen"
}
# =========================== AUFRÄUMEN ===========================
cleanup_old_files() {
log "=== AUFRÄUMEN ALTE DATEIEN ==="
progress "Entferne alte Shell-Skripte..."
# Entferne alte Skripte (falls vorhanden)
local old_scripts=("combined.sh" "installer.sh")
for script in "${old_scripts[@]}"; do
if [ -f "$CURRENT_DIR/$script" ]; then
progress "Entferne: $script"
rm -f "$CURRENT_DIR/$script" || warning "Fehler beim Entfernen von $script"
fi
done
log "✅ Aufräumen abgeschlossen"
}
# =========================== HAUPTMENÜ ===========================
show_menu() {
clear
echo -e "${CYAN}=================================================================${NC}"
echo -e "${CYAN} $APP_NAME - Setup-Skript v$APP_VERSION${NC}"
echo -e "${CYAN}=================================================================${NC}"
echo ""
echo -e "${YELLOW}Bitte wählen Sie eine Option:${NC}"
echo ""
echo -e "${GREEN}1)${NC} Abhängigkeiten installieren und System für manuelles Testen vorbereiten"
echo -e " ${BLUE}→ Python, Node.js, SSL-Zertifikate, Anwendung deployed, minimaler Test${NC}"
echo -e " ${BLUE}→ System bereit für manuelle Tests und Entwicklung${NC}"
echo ""
echo -e "${GREEN}2)${NC} Vollständige Kiosk-Installation mit Remote-Zugang"
echo -e " ${BLUE}→ Komplette Produktionsinstallation mit automatischem Kiosk-Start${NC}"
echo -e " ${BLUE}→ RDP (root:744563017196A), SSH (user:raspberry), Firewall${NC}"
echo -e " ${BLUE}→ Automatischer Login und Kiosk-Modus beim Boot${NC}"
echo ""
echo -e "${GREEN}3)${NC} Beenden"
echo ""
echo -e "${CYAN}=================================================================${NC}"
echo -n "Ihre Wahl [1-3]: "
}
# =========================== INSTALLATIONS-MODI ===========================
install_dependencies_only() {
log "=== MODUS: ABHÄNGIGKEITEN INSTALLIEREN FÜR MANUELLES TESTEN ==="
check_root
check_debian_system
check_internet_connection
configure_hostname
update_system
configure_network_security
install_python_dependencies
install_nodejs_npm
install_ssl_certificates
install_python_packages
deploy_application
install_npm_dependencies
generate_ssl_certificate
# Performance-Optimierungen auch für manuelles Testen
optimize_webapp_performance
optimize_static_assets
# Minimaler Test
progress "Starte minimalen Test..."
cd "$APP_DIR"
# Teste Python-Import
if python3 -c "import sys; sys.path.insert(0, '$APP_DIR'); from app import app; print('✅ Flask-App erfolgreich importiert')" 2>/dev/null; then
success "✅ Python-Abhängigkeiten funktionieren"
else
error "❌ Python-Import fehlgeschlagen"
fi
cd "$CURRENT_DIR"
success "✅ Abhängigkeiten-Installation abgeschlossen!"
info "Das System ist bereit für manuelle Tests und Entwicklung"
info "Hostname wurde auf 'raspberrypi' gesetzt"
info "HTTPS-Backend kann manuell gestartet werden mit:"
info " cd /opt/myp && python3 app.py"
}
install_full_production_system() {
log "=== MODUS: VOLLSTÄNDIGE KIOSK-INSTALLATION MIT REMOTE-ZUGANG ==="
check_root
check_debian_system
check_internet_connection
# Hostname zuerst setzen
configure_hostname
# Führe zuerst Abhängigkeiten-Installation durch (falls noch nicht geschehen)
if [ ! -d "$APP_DIR" ] || [ ! -f "$APP_DIR/app.py" ]; then
warning "Anwendung noch nicht deployed - führe Abhängigkeiten-Installation durch..."
update_system
configure_network_security
install_python_dependencies
install_nodejs_npm
install_ssl_certificates
install_python_packages
deploy_application
install_npm_dependencies
generate_ssl_certificate
else
# Netzwerk-Sicherheit auch bei bestehender Installation konfigurieren
configure_network_security
fi
# Desktop-Environments entfernen und minimale X11 installieren
remove_desktop_environments
install_minimal_x11
# Performance-Optimierungen für Raspberry Pi Webapp
optimize_webapp_performance
optimize_static_assets
# Remote-Zugang konfigurieren
install_remote_access
configure_firewall
# Kiosk-Benutzer und Autologin konfigurieren
create_kiosk_user
configure_autologin
configure_kiosk_autostart
# Services installieren und aktivieren
install_systemd_services
enable_and_start_services
# System-Test
test_application
test_remote_access
# Aufräumen
cleanup_old_files
success "✅ Vollständige Kiosk-Installation abgeschlossen!"
info "Das System ist vollständig konfiguriert:"
info " 🖥️ Hostname: raspberrypi"
info " 🖥️ Automatischer Kiosk-Modus beim Boot"
info " 📡 SSH: ssh user@<ip> (Passwort: raspberry)"
info " 🖥️ RDP: <ip>:3389 (Benutzer: root, Passwort: 744563017196A)"
info " 🔒 Firewall: 192.168.0.0/16 + localhost + raspberrypi + m040tbaraspi001"
warning "⚠️ Neustart erforderlich für automatischen Kiosk-Start: sudo reboot"
}
# =========================== RDP & SSH ZUGANG ===========================
install_remote_access() {
log "=== INSTALLIERE REMOTE-ZUGANG (RDP & SSH) ==="
# SSH-Server installieren und konfigurieren
progress "Installiere und konfiguriere SSH-Server..."
apt-get install -y openssh-server || error "SSH-Server Installation fehlgeschlagen"
# SSH-Service aktivieren
systemctl enable ssh
systemctl start ssh
# SSH-Benutzer 'user' erstellen (falls nicht vorhanden)
if ! id "user" &>/dev/null; then
progress "Erstelle SSH-Benutzer: user"
useradd -m -s /bin/bash user || error "Kann SSH-Benutzer nicht erstellen"
echo "user:raspberry" | chpasswd || error "Kann Passwort für SSH-Benutzer nicht setzen"
usermod -aG sudo user 2>/dev/null || true
log "✅ SSH-Benutzer 'user' erstellt mit Passwort 'raspberry'"
else
info "SSH-Benutzer 'user' existiert bereits"
echo "user:raspberry" | chpasswd || warning "Konnte Passwort für SSH-Benutzer nicht aktualisieren"
fi
# RDP-Server (xrdp) installieren - vereinfachter Ansatz
progress "Installiere RDP-Server (xrdp) - vereinfachte Installation..."
# Alle bestehenden xrdp-Installationen entfernen
progress "Entferne vorherige xrdp-Installationen..."
systemctl stop xrdp xrdp-sesman 2>/dev/null || true
systemctl disable xrdp xrdp-sesman 2>/dev/null || true
apt-get remove --purge -y xrdp 2>/dev/null || true
rm -rf /etc/xrdp /var/log/xrdp* 2>/dev/null || true
# XFCE Desktop installieren (minimal)
progress "Installiere minimale XFCE-Umgebung..."
if ! apt-get install -y xfce4-session xfce4-panel xfce4-terminal xfce4-settings xfdesktop4 dbus-x11; then
warning "Minimale XFCE-Installation fehlgeschlagen - verwende Fallback..."
apt-get install -y xfce4 dbus-x11 || error "XFCE Installation fehlgeschlagen"
fi
# xrdp neu installieren
progress "Installiere xrdp neu..."
apt-get update
apt-get install -y xrdp || error "xrdp Installation fehlgeschlagen"
# Benutzer zur xrdp-Gruppe hinzufügen
usermod -aG xrdp root 2>/dev/null || true
if id "user" &>/dev/null; then
usermod -aG xrdp user 2>/dev/null || true
fi
# Erstelle minimale xrdp-Konfiguration
progress "Erstelle minimale xrdp-Konfiguration..."
# Backup der Original-Konfiguration
cp /etc/xrdp/xrdp.ini /etc/xrdp/xrdp.ini.original 2>/dev/null || true
# Sehr einfache xrdp.ini
cat > /etc/xrdp/xrdp.ini << 'EOF'
[Globals]
ini_version=1
fork=true
port=3389
tcp_nodelay=true
tcp_keepalive=true
security_layer=rdp
autorun=
allow_channels=true
allow_multimon=false
bitmap_cache=true
bitmap_compression=true
bulk_compression=false
max_bpp=24
new_cursors=true
use_fastpath=both
require_credentials=true
ask_for_reconnect_reason=false
enable_token_login=false
[Xorg]
name=Xorg
lib=libxup.so
username=ask
password=ask
ip=127.0.0.1
port=-1
code=20
EOF
# Einfache sesman.ini
cp /etc/xrdp/sesman.ini /etc/xrdp/sesman.ini.original 2>/dev/null || true
cat > /etc/xrdp/sesman.ini << 'EOF'
[Globals]
ListenAddress=127.0.0.1
ListenPort=3350
EnableUserWindowManager=true
UserWindowManager=startxfce4
DefaultWindowManager=startxfce4
[Security]
AllowRootLogin=true
MaxLoginRetry=4
AlwaysGroupCheck=false
[Sessions]
X11DisplayOffset=10
MaxSessions=10
KillDisconnected=false
IdleTimeLimit=0
DisconnectedTimeLimit=0
[Logging]
LogFile=xrdp-sesman.log
LogLevel=INFO
EnableSyslog=true
SyslogLevel=INFO
[Xorg]
param1=-bs
param2=-nolisten
param3=tcp
param4=-dpi
param5=96
EOF
# Erstelle .xsession für XFCE
progress "Konfiguriere XFCE-Sessions..."
# Root .xsession
cat > /root/.xsession << 'EOF'
#!/bin/bash
export XDG_SESSION_DESKTOP=xfce
export XDG_DATA_DIRS=/usr/share/xfce4:/usr/local/share:/usr/share
export XDG_CONFIG_DIRS=/etc/xdg/xdg-xfce:/etc/xdg
exec startxfce4
EOF
chmod +x /root/.xsession
# User .xsession (falls user existiert)
if id "user" &>/dev/null; then
cat > /home/user/.xsession << 'EOF'
#!/bin/bash
export XDG_SESSION_DESKTOP=xfce
export XDG_DATA_DIRS=/usr/share/xfce4:/usr/local/share:/usr/share
export XDG_CONFIG_DIRS=/etc/xdg/xdg-xfce:/etc/xdg
exec startxfce4
EOF
chown user:user /home/user/.xsession
chmod +x /home/user/.xsession
fi
# Root-Passwort setzen
progress "Setze Root-Passwort für RDP..."
echo "root:744563017196A" | chpasswd || error "Kann Root-Passwort nicht setzen"
# Log-Verzeichnisse erstellen mit korrekten Berechtigungen
progress "Erstelle Log-Verzeichnisse..."
mkdir -p /var/log
touch /var/log/xrdp.log /var/log/xrdp-sesman.log 2>/dev/null || true
chown xrdp:xrdp /var/log/xrdp*.log 2>/dev/null || true
chmod 644 /var/log/xrdp*.log 2>/dev/null || true
# Erstelle xrdp-Konfigurationsverzeichnisse
mkdir -p /etc/xrdp/cert /var/run/xrdp
chown xrdp:xrdp /etc/xrdp/cert /var/run/xrdp 2>/dev/null || true
# Services aktivieren und starten
progress "Starte xrdp-Services..."
# systemd daemon reload
systemctl daemon-reload
# Services aktivieren
systemctl enable xrdp-sesman
systemctl enable xrdp
# Services starten (sesman zuerst)
systemctl start xrdp-sesman
sleep 3
# Prüfe sesman-Status
if systemctl is-active --quiet xrdp-sesman; then
success "✅ xrdp-sesman erfolgreich gestartet"
# Jetzt xrdp starten
systemctl start xrdp
sleep 3
if systemctl is-active --quiet xrdp; then
success "✅ xrdp erfolgreich gestartet"
else
warning "⚠️ xrdp konnte nicht gestartet werden"
journalctl -u xrdp --no-pager -l | tail -10
fi
else
warning "⚠️ xrdp-sesman konnte nicht gestartet werden"
journalctl -u xrdp-sesman --no-pager -l | tail -10
fi
cd "$CURRENT_DIR"
# Finaler Status-Check
if systemctl is-active --quiet xrdp && systemctl is-active --quiet xrdp-sesman; then
log "✅ Remote-Zugang vollständig konfiguriert:"
log " 📡 SSH: user:raspberry (Port 22)"
log " 🖥️ RDP: root:744563017196A (Port 3389)"
log " 🖥️ RDP: user:raspberry (Port 3389)"
elif systemctl is-active --quiet ssh; then
log "✅ SSH-Zugang konfiguriert:"
log " 📡 SSH: user:raspberry (Port 22)"
warning "⚠️ RDP-Installation unvollständig"
info "Manuelle Überprüfung erforderlich:"
info " systemctl status xrdp"
info " systemctl status xrdp-sesman"
info " journalctl -u xrdp -f"
else
error "❌ Weder SSH noch RDP konnten konfiguriert werden"
fi
}
# =========================== FIREWALL KONFIGURATION ===========================
configure_firewall() {
log "=== KONFIGURIERE FIREWALL (firewalld) ==="
# firewalld installieren
progress "Installiere firewalld..."
apt-get install -y firewalld || error "firewalld Installation fehlgeschlagen"
# firewalld aktivieren und starten
systemctl enable firewalld
systemctl start firewalld
# Warte kurz bis firewalld vollständig gestartet ist
sleep 5
progress "Konfiguriere firewalld-Zonen und -Regeln..."
# Firewall-Status prüfen
if ! firewall-cmd --state >/dev/null 2>&1; then
error "firewalld ist nicht aktiv oder reagiert nicht"
fi
# Bestehende Zone entfernen falls vorhanden
progress "Entferne bestehende myp-backend Zone falls vorhanden..."
if firewall-cmd --permanent --get-zones | grep -q "myp-backend"; then
log "Entferne bestehende myp-backend Zone..."
firewall-cmd --permanent --delete-zone=myp-backend 2>/dev/null || true
firewall-cmd --reload
sleep 2
fi
# Zone neu erstellen
progress "Erstelle neue myp-backend Zone..."
if ! firewall-cmd --permanent --new-zone=myp-backend; then
error "Fehler beim Erstellen der myp-backend Zone"
fi
# Konfiguration neu laden
firewall-cmd --reload
sleep 2
# Erweiterte Netzwerk-Quellen definieren (nur IPv4)
progress "Füge Netzwerk-Quellen hinzu..."
firewall-cmd --permanent --zone=myp-backend --add-source=192.168.0.0/16 || error "Fehler beim Hinzufügen des 192.168.0.0/16 Netzwerks"
firewall-cmd --permanent --zone=myp-backend --add-source=127.0.0.1/32 || error "Fehler beim Hinzufügen von localhost"
# Lokaler Hostname "raspberrypi" hinzufügen
local local_hostname="raspberrypi"
progress "Füge lokalen Hostname hinzu: $local_hostname"
local local_ip=$(getent hosts "$local_hostname" | awk '{print $1}' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -1 2>/dev/null || true)
if [ -n "$local_ip" ]; then
firewall-cmd --permanent --zone=myp-backend --add-source="$local_ip/32" 2>/dev/null || warning "Konnte lokalen Hostname nicht hinzufügen"
log "✅ Lokaler Hostname $local_hostname hinzugefügt: $local_ip"
else
info "Lokaler Hostname $local_hostname nicht auflösbar - wird beim nächsten Boot verfügbar sein"
fi
# Frontend-Server m040tbaraspi001 hinzufügen (falls auflösbar)
progress "Füge Frontend-Server hinzu: m040tbaraspi001"
local frontend_ip=$(getent hosts "m040tbaraspi001" | awk '{print $1}' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -1 2>/dev/null || true)
if [ -n "$frontend_ip" ]; then
firewall-cmd --permanent --zone=myp-backend --add-source="$frontend_ip/32" 2>/dev/null || warning "Konnte Frontend-Server IP nicht hinzufügen"
log "✅ Frontend-Server m040tbaraspi001 hinzugefügt: $frontend_ip"
else
# Versuche auch mit FQDN
local frontend_fqdn_ip=$(getent hosts "m040tbaraspi001.de040.corpintra.net" | awk '{print $1}' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | head -1 2>/dev/null || true)
if [ -n "$frontend_fqdn_ip" ]; then
firewall-cmd --permanent --zone=myp-backend --add-source="$frontend_fqdn_ip/32" 2>/dev/null || warning "Konnte Frontend-Server FQDN nicht hinzufügen"
log "✅ Frontend-Server m040tbaraspi001.de040.corpintra.net hinzugefügt: $frontend_fqdn_ip"
else
info "Frontend-Server m040tbaraspi001 nicht auflösbar - überspringe"
fi
fi
# Ports und Services hinzufügen
progress "Konfiguriere Ports und Services..."
# HTTPS für API & Kiosk zulassen
firewall-cmd --permanent --zone=myp-backend --add-port=443/tcp || error "Fehler beim Hinzufügen von Port 443"
# SSH für Wartung
firewall-cmd --permanent --zone=myp-backend --add-service=ssh || error "Fehler beim Hinzufügen des SSH-Service"
# RDP für Remote-Desktop
firewall-cmd --permanent --zone=myp-backend --add-port=3389/tcp || error "Fehler beim Hinzufügen von Port 3389"
# IPv6 in firewalld deaktivieren
progress "Deaktiviere IPv6 in firewalld..."
firewall-cmd --permanent --set-target=DROP --zone=public --family=ipv6 2>/dev/null || warning "IPv6 konnte nicht in public Zone deaktiviert werden"
firewall-cmd --permanent --set-target=DROP --zone=myp-backend --family=ipv6 2>/dev/null || warning "IPv6 konnte nicht in myp-backend Zone deaktiviert werden"
# Default-Zone setzen
progress "Setze Default-Zone..."
firewall-cmd --set-default-zone=myp-backend || error "Fehler beim Setzen der Default-Zone"
# Änderungen übernehmen
progress "Lade Firewall-Konfiguration neu..."
firewall-cmd --reload || error "Fehler beim Neuladen der Firewall-Konfiguration"
# Kurz warten und Status prüfen
sleep 3
# Firewall-Status anzeigen
progress "Firewall-Konfiguration:"
if firewall-cmd --list-all --zone=myp-backend 2>/dev/null; then
log "✅ Firewall-Konfiguration erfolgreich angezeigt"
else
warning "⚠️ Firewall-Status konnte nicht angezeigt werden"
fi
# Finale Validierung
progress "Validiere Firewall-Konfiguration..."
local validation_errors=0
# Prüfe ob Zone existiert
if ! firewall-cmd --get-zones | grep -q "myp-backend"; then
error "Zone myp-backend wurde nicht korrekt erstellt"
((validation_errors++))
fi
# Prüfe Default-Zone
if [ "$(firewall-cmd --get-default-zone)" != "myp-backend" ]; then
warning "Default-Zone ist nicht myp-backend"
((validation_errors++))
fi
# Prüfe Ports
if ! firewall-cmd --zone=myp-backend --query-port=443/tcp 2>/dev/null; then
warning "Port 443 nicht korrekt konfiguriert"
((validation_errors++))
fi
if ! firewall-cmd --zone=myp-backend --query-port=3389/tcp 2>/dev/null; then
warning "Port 3389 nicht korrekt konfiguriert"
((validation_errors++))
fi
if ! firewall-cmd --zone=myp-backend --query-service=ssh 2>/dev/null; then
warning "SSH-Service nicht korrekt konfiguriert"
((validation_errors++))
fi
if [ $validation_errors -eq 0 ]; then
log "✅ Firewall konfiguriert und validiert:"
log " 🔒 Zone: myp-backend (als Default gesetzt)"
log " 🌐 Netzwerk: 192.168.0.0/16 (nur IPv4)"
log " 🏠 Localhost: 127.0.0.1"
log " 🖥️ Lokaler Host: raspberrypi"
log " 📡 Frontend-Server: m040tbaraspi001"
log " 🔌 Ports: 443/tcp (HTTPS), 22/tcp (SSH), 3389/tcp (RDP)"
log " 🚫 IPv6 vollständig blockiert"
else
warning "⚠️ Firewall-Konfiguration mit $validation_errors Fehlern abgeschlossen"
info "System funktioniert möglicherweise trotzdem - manuelle Überprüfung empfohlen"
fi
}
# =========================== REMOTE-ZUGANG TESTEN ===========================
test_remote_access() {
log "=== TESTE REMOTE-ZUGANG ==="
# SSH-Service testen
progress "Teste SSH-Service..."
if systemctl is-active --quiet ssh; then
success "✅ SSH-Service läuft"
# SSH-Port testen
if ss -tlnp | grep -q ":22 "; then
success "✅ SSH-Port 22 ist offen"
else
warning "⚠️ SSH-Port 22 nicht erreichbar"
fi
else
warning "⚠️ SSH-Service läuft nicht"
fi
# RDP-Services testen
progress "Teste RDP-Services..."
local xrdp_sesman_status="❌"
local xrdp_status="❌"
if systemctl is-active --quiet xrdp-sesman; then
xrdp_sesman_status="✅"
success "✅ xrdp-sesman läuft"
else
warning "⚠️ xrdp-sesman läuft nicht"
fi
if systemctl is-active --quiet xrdp; then
xrdp_status="✅"
success "✅ xrdp läuft"
# RDP-Port testen
if ss -tlnp | grep -q ":3389 "; then
success "✅ RDP-Port 3389 ist offen"
else
warning "⚠️ RDP-Port 3389 nicht erreichbar"
fi
else
warning "⚠️ xrdp läuft nicht"
fi
# Firewall-Status testen
progress "Teste Firewall-Status..."
if systemctl is-active --quiet firewalld; then
success "✅ Firewall läuft"
# Prüfe ob Ports offen sind
if firewall-cmd --zone=myp-backend --query-port=22/tcp 2>/dev/null; then
success "✅ SSH-Port in Firewall freigegeben"
else
warning "⚠️ SSH-Port nicht in Firewall freigegeben"
fi
if firewall-cmd --zone=myp-backend --query-port=3389/tcp 2>/dev/null; then
success "✅ RDP-Port in Firewall freigegeben"
else
warning "⚠️ RDP-Port nicht in Firewall freigegeben"
fi
else
warning "⚠️ Firewall läuft nicht"
fi
# Netzwerk-Interface testen
progress "Teste Netzwerk-Konfiguration..."
local ip_address=$(ip route get 1.1.1.1 2>/dev/null | awk '{print $7}' | head -1 || echo "Unbekannt")
if [ "$ip_address" != "Unbekannt" ]; then
success "✅ Netzwerk-Interface aktiv: $ip_address"
info "Zugang-URLs:"
info " SSH: ssh user@$ip_address"
if [ "$xrdp_status" = "✅" ]; then
info " RDP: $ip_address:3389 (root:744563017196A oder user:raspberry)"
fi
else
warning "⚠️ Keine Netzwerk-IP ermittelt"
fi
# Status-Zusammenfassung
log "📊 Service-Status:"
log " SSH: $(systemctl is-active --quiet ssh && echo "✅ Aktiv" || echo "❌ Inaktiv")"
log " xrdp-sesman: $xrdp_sesman_status $(systemctl is-active --quiet xrdp-sesman && echo "Aktiv" || echo "Inaktiv")"
log " xrdp: $xrdp_status $(systemctl is-active --quiet xrdp && echo "Aktiv" || echo "Inaktiv")"
log "✅ Remote-Zugang-Test abgeschlossen"
}
# =========================== HOSTNAME KONFIGURATION ===========================
configure_hostname() {
log "=== KONFIGURIERE HOSTNAME ==="
local target_hostname="raspberrypi"
local current_hostname=$(hostname)
if [ "$current_hostname" != "$target_hostname" ]; then
progress "Setze Hostname von '$current_hostname' auf '$target_hostname'..."
# Hostname sofort setzen
hostnamectl set-hostname "$target_hostname" || error "Fehler beim Setzen des Hostnames"
# /etc/hostname aktualisieren
echo "$target_hostname" > /etc/hostname
# /etc/hosts aktualisieren
cp /etc/hosts /etc/hosts.backup
sed -i "s/127.0.1.1.*/127.0.1.1\t$target_hostname/" /etc/hosts
# Falls kein 127.0.1.1 Eintrag existiert, hinzufügen
if ! grep -q "127.0.1.1" /etc/hosts; then
echo "127.0.1.1 $target_hostname" >> /etc/hosts
fi
log "✅ Hostname erfolgreich auf '$target_hostname' gesetzt"
else
log "✅ Hostname bereits korrekt: '$target_hostname'"
fi
# Hostname-Auflösung testen
if getent hosts "$target_hostname" >/dev/null 2>&1; then
local resolved_ip=$(getent hosts "$target_hostname" | awk '{print $1}' | head -1)
log "✅ Hostname-Auflösung funktioniert: $target_hostname -> $resolved_ip"
else
warning "⚠️ Hostname-Auflösung für '$target_hostname' fehlgeschlagen"
fi
}
# =========================== WEBAPP PERFORMANCE-OPTIMIERUNG ===========================
optimize_webapp_performance() {
log "=== WEBAPP PERFORMANCE-OPTIMIERUNG FÜR RASPBERRY PI ==="
# Python/Flask spezifische Optimierungen
progress "Konfiguriere Python-Performance-Optimierungen..."
# Python Bytecode Optimierung aktivieren
cat > /etc/environment << 'EOF'
# Python Performance Optimierungen
PYTHONOPTIMIZE=2
PYTHONDONTWRITEBYTECODE=1
PYTHONUNBUFFERED=1
PYTHONHASHSEED=random
# Flask/SQLite Optimierungen
FLASK_ENV=production
FLASK_DEBUG=0
SQLITE_TMPDIR=/tmp
# Memory Optimierungen
MALLOC_ARENA_MAX=2
MALLOC_MMAP_THRESHOLD=131072
MALLOC_TRIM_THRESHOLD=131072
EOF
# Systemd Service-Optimierungen
progress "Optimiere Systemd-Services für bessere Performance..."
# Stoppe unnötige Services
local unnecessary_services=(
"bluetooth.service"
"hciuart.service"
"avahi-daemon.service"
"cups.service"
"cups-browsed.service"
"ModemManager.service"
"wpa_supplicant.service"
)
for service in "${unnecessary_services[@]}"; do
if systemctl is-enabled "$service" 2>/dev/null; then
systemctl disable "$service" 2>/dev/null || true
systemctl stop "$service" 2>/dev/null || true
log "✅ Service deaktiviert: $service"
fi
done
# Tmpfs für temporäre Dateien
progress "Konfiguriere tmpfs für bessere I/O Performance..."
cat >> /etc/fstab << 'EOF'
# MYP Performance Optimierungen - tmpfs für temporäre Dateien
tmpfs /tmp tmpfs defaults,noatime,nosuid,size=256m 0 0
tmpfs /var/tmp tmpfs defaults,noatime,nosuid,size=128m 0 0
tmpfs /var/log tmpfs defaults,noatime,nosuid,size=64m 0 0
EOF
# Logrotate für tmpfs-Logs konfigurieren
cat > /etc/logrotate.d/myp-tmpfs << 'EOF'
/var/log/*.log {
daily
missingok
rotate 2
compress
notifempty
create 0644 root root
copytruncate
}
EOF
# Systemd Journal Einstellungen optimieren
progress "Optimiere systemd Journal für bessere Performance..."
mkdir -p /etc/systemd/journald.conf.d
cat > /etc/systemd/journald.conf.d/myp-performance.conf << 'EOF'
[Journal]
# Journal Optimierungen für Raspberry Pi
Storage=volatile
RuntimeMaxUse=32M
RuntimeKeepFree=16M
RuntimeMaxFileSize=8M
RuntimeMaxFiles=4
MaxRetentionSec=1day
MaxFileSec=1hour
ForwardToSyslog=no
ForwardToKMsg=no
ForwardToConsole=no
ForwardToWall=no
EOF
# Crontab für regelmäßige Cache-Bereinigung
progress "Installiere automatische Cache-Bereinigung..."
cat > /etc/cron.d/myp-cache-cleanup << 'EOF'
# MYP Cache und Memory Cleanup
# Alle 6 Stunden Cache bereinigen
0 */6 * * * root /bin/echo 3 > /proc/sys/vm/drop_caches
# Täglich um 3 Uhr temporäre Dateien bereinigen
0 3 * * * root /usr/bin/find /tmp -type f -atime +1 -delete 2>/dev/null
# Wöchentlich Python Cache bereinigen
0 2 * * 0 root /usr/bin/find /opt/myp -name "*.pyc" -delete 2>/dev/null
0 2 * * 0 root /usr/bin/find /opt/myp -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null
EOF
# Limits für bessere Ressourcen-Verwaltung
progress "Konfiguriere System-Limits..."
cat >> /etc/security/limits.conf << 'EOF'
# MYP Performance Limits
* soft nofile 65536
* hard nofile 65536
* soft nproc 32768
* hard nproc 32768
root soft nofile 65536
root hard nofile 65536
EOF
# Apache/Nginx entfernen falls vorhanden (Konflikt mit Flask)
progress "Entferne konfliktbehaftete Webserver..."
local webservers=("apache2" "nginx" "lighttpd")
for webserver in "${webservers[@]}"; do
if systemctl is-enabled "$webserver" 2>/dev/null; then
systemctl stop "$webserver" 2>/dev/null || true
systemctl disable "$webserver" 2>/dev/null || true
apt-get remove --purge -y "$webserver" 2>/dev/null || true
log "✅ Webserver entfernt: $webserver"
fi
done
log "✅ Webapp Performance-Optimierung abgeschlossen:"
log " 🚀 Python Bytecode-Optimierung aktiviert"
log " 💾 tmpfs für temporäre Dateien konfiguriert"
log " 📝 Journal-Logging optimiert"
log " 🧹 Automatische Cache-Bereinigung installiert"
log " ⚡ Unnötige Services deaktiviert"
log " 📊 System-Limits für bessere Performance gesetzt"
}
# =========================== CSS/JS OPTIMIERUNG FÜR RASPBERRY PI ===========================
optimize_static_assets() {
log "=== RASPBERRY PI CSS/JS OPTIMIERUNG ==="
if [ ! -d "$APP_DIR/static" ]; then
warning "Static-Ordner nicht gefunden - überspringe Asset-Optimierung"
return
fi
progress "Validiere Raspberry Pi optimierte CSS-Dateien..."
cd "$APP_DIR/static"
# Spezielle Raspberry Pi Hardware-Optimierungen
if [ "${IS_RASPBERRY_PI:-false}" = "true" ]; then
log "🍓 Raspberry Pi Hardware erkannt: ${PI_MODEL:-Unbekannt}"
log "🚀 Aktiviere spezielle Performance-Optimierungen..."
else
info " Keine Raspberry Pi Hardware - verwende Standard-Optimierungen"
fi
# Prüfe ob optimierte CSS-Dateien existieren
local optimized_files=(
"css/glassmorphism.css"
"css/optimization-animations.css"
"css/professional-theme.css"
"css/caching-optimizations.css"
)
local missing_files=0
for file in "${optimized_files[@]}"; do
if [ ! -f "$file" ]; then
warning "Optimierte CSS-Datei fehlt: $file"
((missing_files++))
else
# Prüfe ob Datei Raspberry Pi Optimierungen enthält
if grep -q "Raspberry Pi" "$file" 2>/dev/null; then
log "✅ Raspberry Pi optimiert: $file"
else
warning "⚠️ Datei nicht für Raspberry Pi optimiert: $file"
fi
fi
done
if [ $missing_files -gt 0 ]; then
warning "⚠️ $missing_files CSS-Dateien fehlen oder sind nicht optimiert"
fi
# Erstelle kritische CSS-Datei für Above-the-fold Content
progress "Erstelle kritische CSS-Datei für Raspberry Pi..."
cat > css/critical-raspberry-pi.min.css << 'EOF'
/* Kritische Styles für Raspberry Pi - Maximale Performance */
:root{--mb-primary:#0073ce;--mb-primary-dark:#005a9f;--light-bg-primary:#fff;--light-bg-secondary:#fafbfc;--light-surface:#fff;--light-text-primary:#111827;--light-text-secondary:#374151;--light-border:#e5e7eb;--dark-bg-primary:#0f172a;--dark-bg-secondary:#1e293b;--dark-surface:#1e293b;--dark-text-primary:#f8fafc;--dark-text-secondary:#e2e8f0;--dark-border:#334155}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:system-ui,-apple-system,sans-serif;line-height:1.5;background:var(--light-bg-primary);color:var(--light-text-primary)}
.dark body{background:var(--dark-bg-primary);color:var(--dark-text-primary)}
.container{max-width:1200px;margin:0 auto;padding:0 1rem}
.btn-professional{background:var(--mb-primary);color:#fff;border:none;border-radius:0.5rem;padding:0.75rem 1.5rem;font-weight:600;cursor:pointer}
.btn-professional:hover{background:var(--mb-primary-dark)}
.card-professional{background:var(--light-surface);border:1px solid var(--light-border);border-radius:0.75rem;padding:1.5rem}
.dark .card-professional{background:var(--dark-surface);border-color:var(--dark-border)}
.professional-container{background:var(--light-surface);border:1px solid var(--light-border);border-radius:0.75rem}
.dark .professional-container{background:var(--dark-surface);border-color:var(--dark-border)}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}
.hidden{display:none}.block{display:block}.flex{display:flex}.items-center{align-items:center}
.w-full{width:100%}.h-full{height:100%}
@media(max-width:768px){.container{padding:0 0.5rem}.card-professional{padding:1rem}}
/* Nur opacity transitions für Raspberry Pi Performance */
.animate-fade-in{animation:fadeIn 0.2s ease-out}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
EOF
# Erstelle optimierten JavaScript-Loader ohne GPU-intensive Features
progress "Erstelle Raspberry Pi optimierten JavaScript-Loader..."
cat > js/raspberry-pi-loader.min.js << 'EOF'
/*Raspberry Pi optimierter Loader - Keine GPU-intensive Features*/
(function(){
var d=document,w=window;
function loadCSS(href,media){
var l=d.createElement('link');
l.rel='stylesheet';
l.href=href;
l.media=media||'all';
d.head.appendChild(l);
return l;
}
function loadJS(src,cb){
var s=d.createElement('script');
s.async=true;
s.src=src;
if(cb)s.onload=cb;
d.head.appendChild(s);
return s;
}
w.loadOptimizedAssets=function(){
if(w.assetsLoaded)return;
w.assetsLoaded=true;
loadCSS('/static/css/professional-theme.css');
loadCSS('/static/css/glassmorphism.css');
loadCSS('/static/css/optimization-animations.css');
loadCSS('/static/css/caching-optimizations.css');
if(d.querySelector('#app-js')){
loadJS('/static/js/app.min.js');
}
};
if(d.readyState==='loading'){
d.addEventListener('DOMContentLoaded',w.loadOptimizedAssets);
}else{
w.loadOptimizedAssets();
}
})();
EOF
# Service Worker für optimiertes Caching auf Raspberry Pi
progress "Erstelle Raspberry Pi optimierten Service Worker..."
cat > sw-raspberry-pi.js << 'EOF'
const CACHE_NAME = 'myp-raspberry-pi-v1';
const CRITICAL_ASSETS = [
'/',
'/static/css/critical-raspberry-pi.min.css',
'/static/js/raspberry-pi-loader.min.js',
'/static/css/professional-theme.css',
'/static/css/glassmorphism.css',
'/static/css/optimization-animations.css'
];
// Aggressive Caching für statische Assets
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
console.log('Raspberry Pi Cache wird geladen...');
return cache.addAll(CRITICAL_ASSETS);
})
);
self.skipWaiting();
});
// Cache-First Strategie für bessere Performance auf schwacher Hardware
self.addEventListener('fetch', event => {
if (event.request.url.includes('/static/')) {
event.respondWith(
caches.match(event.request)
.then(response => {
if (response) {
return response;
}
return fetch(event.request).then(fetchResponse => {
if (fetchResponse && fetchResponse.status === 200) {
const responseClone = fetchResponse.clone();
caches.open(CACHE_NAME)
.then(cache => {
cache.put(event.request, responseClone);
});
}
return fetchResponse;
});
})
);
}
});
// Cache-Bereinigung für alte Versionen
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheName !== CACHE_NAME) {
console.log('Entferne alte Cache-Version:', cacheName);
return caches.delete(cacheName);
}
})
);
})
);
});
EOF
# CSS-Minifikation für optimierte Dateien
progress "Minifiziere CSS-Dateien für bessere Performance..."
local css_files=("professional-theme.css" "glassmorphism.css" "optimization-animations.css" "caching-optimizations.css")
for css_file in "${css_files[@]}"; do
if [ -f "css/$css_file" ]; then
# Einfache CSS-Minifikation (Entfernung von Kommentaren und unnötigen Whitespaces)
sed 's|/\*[^*]*\*\+\([^/*][^*]*\*\+\)*/||g; s/^[[:space:]]*//g; s/[[:space:]]*$//g; /^$/d' "css/$css_file" > "css/${css_file%.css}.min.css" 2>/dev/null || true
if [ -f "css/${css_file%.css}.min.css" ]; then
log "✅ Minifiziert: ${css_file%.css}.min.css"
fi
fi
done
# Gzip-Kompression für alle CSS/JS-Dateien
progress "Komprimiere Dateien mit Gzip..."
find css js -name "*.css" -o -name "*.js" | while read file; do
if [ -f "$file" ] && [ ! -f "$file.gz" ]; then
gzip -9 -c "$file" > "$file.gz" 2>/dev/null || true
if [ -f "$file.gz" ]; then
local original_size=$(wc -c < "$file" 2>/dev/null || echo "0")
local compressed_size=$(wc -c < "$file.gz" 2>/dev/null || echo "0")
if [ "$original_size" -gt 0 ] && [ "$compressed_size" -gt 0 ]; then
local ratio=$((100 - (compressed_size * 100 / original_size)))
log "✅ Komprimiert: $file (${ratio}% kleiner)"
fi
fi
fi
done
# Performance-Hints für Browser
progress "Erstelle Performance-Hints für Raspberry Pi Browser..."
cat > performance-hints.txt << 'EOF'
# Performance-Optimierungen für Raspberry Pi Browser:
# 1. Alle backdrop-filter entfernt (GPU-intensiv)
# 2. Transform-Animationen eliminiert (Layout-Thrashing)
# 3. Box-shadows reduziert (Paint-Performance)
# 4. Will-change Properties entfernt (Memory-Management)
# 5. Gradient-Effekte vereinfacht (GPU-Berechnungen)
# 6. Nur Opacity/Color Transitions (CSS-Performance)
# 7. Kritische CSS inline geladen (Render-Blocking)
# 8. Service Worker für aggressives Caching
# 9. Gzip-Kompression für alle Assets
# 10. Cache-First Strategie für statische Dateien
EOF
cd "$CURRENT_DIR"
log "✅ Raspberry Pi CSS/JS-Optimierung abgeschlossen:"
log " 🚀 Backdrop-Filter und Transform-Animationen entfernt"
log " 📦 Kritische CSS für Above-the-fold Content erstellt"
log " ⚡ Raspberry Pi spezifischer Asset-Loader"
log " 🗜️ Aggressive Gzip-Kompression angewendet"
log " 🔄 Cache-First Service Worker installiert"
log " 📊 CSS-Minifikation für alle Dateien"
log " 💾 Performance-optimiert für schwache Hardware"
}
# =========================== HAUPTPROGRAMM ===========================
main() {
# Erstelle Log-Datei
touch "$INSTALL_LOG" || true
while true; do
show_menu
read -r choice
case $choice in
1)
install_dependencies_only
echo ""
echo -n "Drücken Sie Enter um fortzufahren..."
read -r
;;
2)
install_full_production_system
echo ""
echo -n "Drücken Sie Enter um fortzufahren..."
read -r
;;
3)
log "Setup-Skript beendet"
exit 0
;;
*)
error "Ungültige Auswahl. Bitte wählen Sie 1-3."
;;
esac
done
}
# Skript starten
main "$@"