#!/bin/bash
# ===================================================================
# MYP Druckerverwaltung - Raspberry Pi Kiosk Installation
# Vollautomatische Installation für echten Kiosk-Modus ohne Escape
# Designed für Raspberry Pi OS, Ubuntu Server, Debian minimal
# ===================================================================
set -e # Bei Fehlern sofort beenden
# =========================== KONFIGURATION ===========================
KIOSK_USER="kiosk"
APP_USER="myp"
APP_DIR="/opt/myp-druckerverwaltung"
BACKUP_DIR="/opt/myp-backups"
CURRENT_DIR=""
INSTALL_LOG="/var/log/myp-kiosk-install.log"
CHROMIUM_BIN="" # Global verfügbar machen
# NEUE KONFIGURATION - Erweiterte Anforderungen
ROOT_PASSWORD="744563017196A"
HOSTNAME="raspberrypi"
# Desktop Environment Pakete die entfernt werden sollen
REMOVE_PACKAGES=(
"gnome*" "kde*" "xfce*" "lxde*" "mate*" "cinnamon*"
"lightdm" "gdm*" "xdm" "nodm"
"firefox*" "thunderbird*" "libreoffice*" "wolfram-engine"
"scratch*" "minecraft-pi" "sonic-pi" "idle*"
"vlc" "smplayer" "totem" "rhythmbox"
"gedit" "mousepad" "leafpad" "pluma"
"file-roller" "xarchiver" "ark"
"gimp" "inkscape" "blender"
"chromium-browser" # Alte Version entfernen
)
# Farben für Ausgabe
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m'
# ========================== LOGGING-SYSTEM ==========================
log() {
echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}" | tee -a "$INSTALL_LOG"
}
error() {
echo -e "${RED}[FEHLER] $1${NC}" | tee -a "$INSTALL_LOG"
exit 1
}
warning() {
echo -e "${YELLOW}[WARNUNG] $1${NC}" | tee -a "$INSTALL_LOG"
}
info() {
echo -e "${BLUE}[INFO] $1${NC}" | tee -a "$INSTALL_LOG"
}
progress() {
echo -e "${PURPLE}[FORTSCHRITT] $1${NC}" | tee -a "$INSTALL_LOG"
}
# ========================== SYSTEM-CHECKS ==========================
check_root() {
if [ "$EUID" -ne 0 ]; then
error "Dieses Skript muss als Root ausgeführt werden: sudo $0"
fi
export PATH="/usr/sbin:/sbin:/usr/bin:/bin:/usr/local/bin:$PATH"
}
detect_system() {
log "Erkenne System-Umgebung..."
# Aktuelle Position ermitteln
CURRENT_DIR="$(pwd)"
log "Aktuelles Verzeichnis: $CURRENT_DIR"
# Prüfe ob wir uns im richtigen Verzeichnis befinden
if [ ! -f "$CURRENT_DIR/app.py" ]; then
error "app.py nicht gefunden in $CURRENT_DIR - Bitte im MYP-Projektverzeichnis ausführen!"
fi
# System-Info sammeln
info "System: $(uname -a)"
info "Distribution: $(lsb_release -d 2>/dev/null || cat /etc/os-release | head -1 || echo 'Unbekannt')"
info "Speicher: $(free -h | head -2 | tail -1)"
info "Festplatte: $(df -h / | tail -1)"
# Internetverbindung testen
if ! ping -c 1 google.com &> /dev/null; then
error "Keine Internetverbindung verfügbar!"
fi
# Minimal 2GB freier Speicher erforderlich
available_kb=$(df / | awk 'NR==2 {print $4}')
if [ "$available_kb" -lt 2000000 ]; then
error "Nicht genügend Speicherplatz! Mindestens 2GB erforderlich."
fi
log "✅ System-Checks erfolgreich"
}
# ========================== SYSTEM-GRUNDKONFIGURATION ==========================
setup_system_basics() {
log "=== PHASE 0: SYSTEM-GRUNDKONFIGURATION ==="
# Hostname setzen
progress "Setze Hostname auf '$HOSTNAME'..."
echo "$HOSTNAME" > /etc/hostname
sed -i "s/127.0.1.1.*/127.0.1.1\t$HOSTNAME/" /etc/hosts
hostnamectl set-hostname "$HOSTNAME" 2>/dev/null || true
# Root-Passwort setzen
progress "Setze Root-Passwort..."
echo "root:$ROOT_PASSWORD" | chpasswd
# Root-SSH-Zugang aktivieren (für Wartung)
if [ -f "/etc/ssh/sshd_config" ]; then
sed -i 's/#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
sed -i 's/#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
fi
# Zeitzone setzen
progress "Setze Zeitzone auf Europe/Berlin..."
timedatectl set-timezone Europe/Berlin 2>/dev/null || true
# Locales konfigurieren
progress "Konfiguriere deutsche Locales..."
if [ -f "/etc/locale.gen" ]; then
sed -i 's/# de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/' /etc/locale.gen
locale-gen || true
update-locale LANG=de_DE.UTF-8 || true
fi
# Deutsche Tastaturlayout konfigurieren - VERBESSERTE VERSION
progress "Konfiguriere deutsches Tastaturlayout..."
# Sicherstellen dass keyboard-configuration installiert ist
if ! dpkg -l | grep -q keyboard-configuration; then
apt-get install -y keyboard-configuration console-setup console-data kbd
fi
# Debconf-Konfiguration für keyboard-configuration
echo "keyboard-configuration keyboard-configuration/layout select German" | debconf-set-selections
echo "keyboard-configuration keyboard-configuration/layoutcode string de" | debconf-set-selections
echo "keyboard-configuration keyboard-configuration/model select Generic 105-key (Intl) PC" | debconf-set-selections
echo "keyboard-configuration keyboard-configuration/modelcode string pc105" | debconf-set-selections
echo "keyboard-configuration keyboard-configuration/variant select German" | debconf-set-selections
echo "keyboard-configuration keyboard-configuration/variantcode string" | debconf-set-selections
# Rekonfiguriere keyboard-configuration
dpkg-reconfigure -f noninteractive keyboard-configuration
# /etc/default/keyboard für Console und X11
cat > "/etc/default/keyboard" << EOF
# Keyboard configuration file for Debian
# Deutsches Tastaturlayout
XKBMODEL="pc105"
XKBLAYOUT="de"
XKBVARIANT=""
XKBOPTIONS=""
BACKSPACE="guess"
EOF
# Console-Setup konfigurieren
cat > "/etc/default/console-setup" << EOF
# CONFIGURATION FILE FOR SETUPCON
ACTIVE_CONSOLES="/dev/tty[1-6]"
CHARMAP="UTF-8"
CODESET="guess"
FONTFACE="Fixed"
FONTSIZE="8x16"
VIDEOMODE=
EOF
# Console-Tastaturlayout sofort aktivieren
if command -v loadkeys &> /dev/null; then
loadkeys de 2>/dev/null || true
info "Console-Tastaturlayout auf Deutsch gesetzt"
fi
# Setupcon ausführen für Console-Setup
if command -v setupcon &> /dev/null; then
setupcon --force --save 2>/dev/null || true
info "Console-Setup konfiguriert"
fi
# X11-Tastaturlayout für Kiosk-Session vorbereiten
mkdir -p /etc/X11/xorg.conf.d
cat > "/etc/X11/xorg.conf.d/00-keyboard.conf" << EOF
# Deutsches Tastaturlayout für X11
Section "InputClass"
Identifier "system-keyboard"
MatchIsKeyboard "on"
Option "XkbLayout" "de"
Option "XkbModel" "pc105"
Option "XkbVariant" ""
Option "XkbOptions" ""
EndSection
EOF
# Systemd localectl für moderne Debian-Systeme (mit Fehlerbehandlung)
if command -v localectl &> /dev/null; then
# Prüfe ob localectl funktioniert
if localectl status &> /dev/null; then
localectl set-keymap de 2>/dev/null || warning "localectl set-keymap fehlgeschlagen"
localectl set-x11-keymap de 2>/dev/null || warning "localectl set-x11-keymap fehlgeschlagen"
info "Tastaturlayout via localectl auf Deutsch gesetzt"
else
warning "localectl nicht funktional - verwende alternative Methoden"
# Alternative: Direkte Keymap-Datei setzen
echo "KEYMAP=de" > /etc/vconsole.conf 2>/dev/null || true
fi
else
warning "localectl nicht verfügbar - verwende legacy-Methoden"
# Legacy-Methode für ältere Systeme
echo "KEYMAP=de" > /etc/vconsole.conf 2>/dev/null || true
fi
# Keyboard-Services neu laden
systemctl reload-or-restart keyboard-setup 2>/dev/null || true
systemctl reload-or-restart console-setup 2>/dev/null || true
# Keymap-Dateien manuell prüfen und erstellen falls nötig
if [ ! -f "/usr/share/keymaps/i386/qwertz/de.kmap.gz" ] && [ ! -f "/usr/share/kbd/keymaps/i386/qwertz/de.map.gz" ]; then
warning "Deutsche Keymap-Dateien fehlen - installiere kbd-Paket"
apt-get install -y kbd console-data || true
fi
info "Deutsches Tastaturlayout global konfiguriert (Console + X11)"
log "✅ System-Grundkonfiguration abgeschlossen"
}
# ========================== SYSTEM-UPDATE ==========================
update_system() {
log "=== PHASE 0.5: SYSTEM-UPDATE ==="
progress "Aktualisiere Paketlisten..."
apt-get update -y || error "APT Update fehlgeschlagen"
progress "Upgrade bestehender Pakete..."
apt-get upgrade -y || warning "APT Upgrade teilweise fehlgeschlagen"
progress "Installiere essenzielle System-Tools..."
apt-get install -y \
ca-certificates \
gnupg \
lsb-release \
software-properties-common \
apt-transport-https \
curl \
wget \
git \
unzip \
nano \
htop \
rsync \
sudo \
cron \
logrotate \
tree \
zip \
keyboard-configuration \
console-setup \
console-data \
kbd \
locales \
|| error "Essenzielle Pakete Installation fehlgeschlagen"
# Dist-upgrade für Kernel-Updates
progress "Führe Distribution-Upgrade durch..."
apt-get dist-upgrade -y || warning "Dist-upgrade teilweise fehlgeschlagen"
log "✅ System-Update abgeschlossen"
}
# ========================== ZERTIFIKATE INSTALLIEREN ==========================
install_certificates() {
log "=== PHASE 0.8: ZERTIFIKATE-INSTALLATION ==="
progress "Aktualisiere CA-Zertifikate..."
apt-get install -y ca-certificates
update-ca-certificates
# Mozilla CA Bundle
progress "Installiere erweiterte Zertifikate..."
if ! wget -O /usr/local/share/ca-certificates/cacert.pem https://curl.se/ca/cacert.pem; then
warning "Mozilla CA Bundle Download fehlgeschlagen"
else
update-ca-certificates
fi
# SSL-Zertifikate für Python requests
if command -v python3 &> /dev/null; then
python3 -m pip install --upgrade certifi --break-system-packages 2>/dev/null || true
fi
log "✅ Zertifikate installiert und aktualisiert"
}
# ========================== VERZEICHNISSTRUKTUR ERSTELLEN ==========================
create_directory_structure() {
log "=== PHASE 1.5: VERZEICHNISSTRUKTUR ERSTELLEN ==="
progress "Erstelle MYP-Verzeichnisstruktur..."
# Hauptverzeichnisse
mkdir -p "$APP_DIR"
mkdir -p "$BACKUP_DIR"
# Upload-Ordner-Struktur
progress "Erstelle Upload-Verzeichnisse..."
UPLOAD_BASE="$APP_DIR/uploads"
CURRENT_YEAR=$(date +%Y)
CURRENT_MONTH=$(date +%m)
# Upload-Kategorien mit Jahres-/Monats-Struktur
for category in assets avatars backups guests jobs logs temp; do
mkdir -p "$UPLOAD_BASE/$category/$CURRENT_YEAR/$CURRENT_MONTH"
info "Erstellt: $UPLOAD_BASE/$category/$CURRENT_YEAR/$CURRENT_MONTH"
done
# Database-Verzeichnis
mkdir -p "$APP_DIR/database/backups"
# Log-Verzeichnisse
progress "Erstelle Log-Verzeichnisse..."
for log_cat in app auth errors jobs printers scheduler; do
mkdir -p "$APP_DIR/logs/$log_cat"
mkdir -p "/var/log/myp-$log_cat"
done
# Config-Verzeichnis
mkdir -p "$APP_DIR/config"
# Static Assets
mkdir -p "$APP_DIR/static/css"
mkdir -p "$APP_DIR/static/js"
mkdir -p "$APP_DIR/static/icons"
# Certificates
mkdir -p "$APP_DIR/certs"
log "✅ Verzeichnisstruktur erstellt"
}
# ========================== SYSTEM-BEREINIGUNG ==========================
cleanup_system() {
log "=== PHASE 1: SYSTEM-BEREINIGUNG ==="
# APT-Cache aktualisieren
progress "Aktualisiere Paketlisten..."
apt-get update -y || warning "APT Update teilweise fehlgeschlagen"
# Entferne unnötige Desktop-Umgebungen
progress "Entferne Desktop-Umgebungen und unnötige Software..."
for package in "${REMOVE_PACKAGES[@]}"; do
if dpkg -l | grep -q "^ii.*$package"; then
info "Entferne: $package"
apt-get purge -y "$package" 2>/dev/null || true
fi
done
# Aggressive Bereinigung
apt-get autoremove -y --purge
apt-get autoclean
# Stoppe unnötige Services
progress "Stoppe Desktop-Services..."
for service in gdm lightdm xdm nodm plymouth; do
systemctl stop "$service" 2>/dev/null || true
systemctl disable "$service" 2>/dev/null || true
done
log "✅ System-Bereinigung abgeschlossen"
}
# ========================== PAKETE INSTALLIEREN ==========================
install_packages() {
log "=== PHASE 2: SYSTEM-PAKETE INSTALLATION ==="
progress "Installiere Basis-Pakete..."
apt-get install -y \
curl wget git unzip \
python3 python3-pip python3-venv python3-dev \
build-essential libssl-dev libffi-dev \
sqlite3 nginx supervisor \
xorg xinit openbox \
xserver-xorg-video-all \
x11-xserver-utils xdotool unclutter \
pulseaudio alsa-utils \
fonts-liberation fonts-dejavu \
ca-certificates apt-transport-https \
systemd-timesyncd \
ufw fail2ban \
htop nano \
|| error "Basis-Pakete Installation fehlgeschlagen"
# Node.js installieren - VERBESSERTE VERSION
progress "Installiere Node.js mit mehreren Fallback-Methoden..."
# Prüfe ob Node.js bereits verfügbar ist
if command -v node &> /dev/null && command -v npm &> /dev/null; then
info "Node.js bereits verfügbar: $(node --version)"
info "NPM bereits verfügbar: $(npm --version)"
else
# Methode 1: NodeSource Repository (LTS)
progress "Versuche NodeSource LTS Repository..."
if curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && apt-get install -y nodejs; then
log "✅ Node.js via NodeSource LTS installiert"
else
warning "NodeSource LTS fehlgeschlagen, versuche NodeSource 18.x..."
# Methode 2: NodeSource 18.x (stabil)
if curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && apt-get install -y nodejs; then
log "✅ Node.js via NodeSource 18.x installiert"
else
warning "NodeSource fehlgeschlagen, versuche Standard-Repository..."
# Methode 3: Standard Repository
apt-get update && apt-get install -y nodejs npm || true
# Methode 4: Snap als Fallback
if ! command -v node &> /dev/null; then
warning "Standard-Repository fehlgeschlagen, versuche Snap..."
if command -v snap &> /dev/null || apt-get install -y snapd; then
snap install node --classic || true
fi
fi
# Methode 5: Manual Download als letzter Ausweg
if ! command -v node &> /dev/null; then
warning "Alle Repository-Methoden fehlgeschlagen, lade Node.js manuell herunter..."
NODE_VERSION="18.17.0"
ARCH=$(uname -m)
case $ARCH in
x86_64) NODE_ARCH="x64" ;;
armv7l) NODE_ARCH="armv7l" ;;
aarch64) NODE_ARCH="arm64" ;;
*) NODE_ARCH="x64" ;;
esac
cd /tmp
wget "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.xz" -O node.tar.xz || true
if [ -f "node.tar.xz" ]; then
tar -xf node.tar.xz
cp -r "node-v${NODE_VERSION}-linux-${NODE_ARCH}"/* /usr/local/
log "✅ Node.js manuell installiert"
fi
fi
fi
fi
# Finale Validierung
if command -v node &> /dev/null && command -v npm &> /dev/null; then
log "✅ Node.js erfolgreich installiert: $(node --version)"
log "✅ NPM erfolgreich installiert: $(npm --version)"
# NPM Global-Verzeichnis konfigurieren für bessere Berechtigungen
mkdir -p /usr/local/lib/npm-global
npm config set prefix '/usr/local/lib/npm-global'
echo 'export PATH=/usr/local/lib/npm-global/bin:$PATH' >> /etc/profile
export PATH=/usr/local/lib/npm-global/bin:$PATH
else
warning "⚠️ Node.js/NPM-Installation fehlgeschlagen - Node.js-Features werden übersprungen"
# Erstelle Dummy-npm-Kommando um Skript-Fehler zu vermeiden
cat > /usr/local/bin/npm << 'EOF'
#!/bin/bash
echo "NPM nicht verfügbar - Node.js-Installation fehlgeschlagen"
echo "Node.js-Abhängigkeiten werden übersprungen"
exit 0
EOF
chmod +x /usr/local/bin/npm
fi
fi
log "✅ System-Pakete installiert"
}
# ========================== CHROMIUM INSTALLATION ==========================
install_chromium() {
log "=== PHASE 3: CHROMIUM INSTALLATION ==="
progress "Installiere Chromium Browser..."
# Versuche verschiedene Installationsmethoden
if apt-get install -y chromium 2>/dev/null; then
CHROMIUM_BIN="/usr/bin/chromium"
log "✅ Chromium via APT installiert"
elif apt-get install -y chromium-browser 2>/dev/null; then
CHROMIUM_BIN="/usr/bin/chromium-browser"
log "✅ Chromium-Browser via APT installiert"
else
# Snap-Installation versuchen
warning "APT-Installation fehlgeschlagen, versuche Snap..."
if command -v snap &> /dev/null || (apt-get install -y snapd && systemctl enable --now snapd); then
snap install chromium
CHROMIUM_BIN="/snap/bin/chromium"
log "✅ Chromium via Snap installiert"
else
# Flatpak als letzter Ausweg
warning "Snap fehlgeschlagen, versuche Flatpak..."
if apt-get install -y flatpak && flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo; then
flatpak install -y flathub org.chromium.Chromium
CHROMIUM_BIN="flatpak run org.chromium.Chromium"
log "✅ Chromium via Flatpak installiert"
else
error "❌ Chromium konnte nicht installiert werden! Bitte manuell installieren."
fi
fi
fi
# Chromium-Binary validieren
if [[ "$CHROMIUM_BIN" == "flatpak"* ]]; then
# Flatpak-Spezialbehandlung
log "Chromium via Flatpak verfügbar"
elif [ ! -x "$CHROMIUM_BIN" ]; then
error "Chromium-Binary nicht ausführbar: $CHROMIUM_BIN"
fi
log "✅ Chromium-Installation abgeschlossen: $CHROMIUM_BIN"
}
# ========================== BENUTZER ERSTELLEN ==========================
create_users() {
log "=== PHASE 4: BENUTZER-ERSTELLUNG ==="
# App-Benutzer erstellen
progress "Erstelle App-Benutzer: $APP_USER"
if ! id "$APP_USER" &>/dev/null; then
if ! useradd -m -s /bin/bash "$APP_USER" 2>/dev/null; then
adduser --disabled-password --gecos "" "$APP_USER" || error "Kann App-Benutzer nicht erstellen"
fi
usermod -aG sudo "$APP_USER" 2>/dev/null || true
fi
# Kiosk-Benutzer erstellen
progress "Erstelle Kiosk-Benutzer: $KIOSK_USER"
if ! id "$KIOSK_USER" &>/dev/null; then
if ! useradd -m -s /bin/bash "$KIOSK_USER" 2>/dev/null; then
adduser --disabled-password --gecos "" "$KIOSK_USER" || error "Kann Kiosk-Benutzer nicht erstellen"
fi
# Kiosk-Benutzer zu Audio/Video-Gruppen hinzufügen
usermod -aG audio,video,input "$KIOSK_USER" 2>/dev/null || true
fi
log "✅ Benutzer erstellt: $APP_USER, $KIOSK_USER"
}
# ========================== ANWENDUNG INSTALLIEREN ==========================
install_application() {
log "=== PHASE 5: ANWENDUNGS-INSTALLATION ==="
# Anwendung kopieren
progress "Kopiere Anwendung von $CURRENT_DIR nach $APP_DIR"
rsync -av --exclude='.git' --exclude='__pycache__' --exclude='node_modules' "$CURRENT_DIR"/ "$APP_DIR/"
chown -R "$APP_USER:$APP_USER" "$APP_DIR"
# Wechsel ins Anwendungsverzeichnis
cd "$APP_DIR"
# DIREKTER PYTHON-PACKAGE INSTALL OHNE VENV - NEU!
progress "Installiere Python-Dependencies DIREKT (ohne Virtual Environment)..."
# Pip aktualisieren
python3 -m pip install --upgrade pip --break-system-packages
# Requirements installieren
if [ -f "requirements.txt" ]; then
info "Installiere aus requirements.txt..."
python3 -m pip install -r requirements.txt --break-system-packages
else
# Basis-Pakete installieren
info "Installiere Basis-Python-Pakete..."
python3 -m pip install --break-system-packages \
flask \
flask-login \
flask-wtf \
flask-limiter \
sqlalchemy \
werkzeug \
requests \
gunicorn \
bcrypt \
cryptography \
PyP100 \
python-dotenv \
Pillow \
schedule
fi
# ENGINE-IMPORT-FEHLER BEHEBEN
progress "Behebe Engine-Import-Problem..."
# Prüfe und korrigiere models.py
if [ -f "models.py" ]; then
# Backup erstellen
cp models.py models.py.backup
# Sicherstellen dass engine richtig importiert wird
if ! grep -q "from sqlalchemy import create_engine" models.py; then
sed -i '1i from sqlalchemy import create_engine' models.py
fi
# engine Variable definieren falls fehlt
if ! grep -q "^engine = " models.py; then
echo "" >> models.py
echo "# Engine für direkten Zugriff" >> models.py
echo "try:" >> models.py
echo " engine = create_optimized_engine()" >> models.py
echo "except:" >> models.py
echo " from sqlalchemy import create_engine" >> models.py
echo " engine = create_engine('sqlite:///database.db')" >> models.py
fi
fi
# app.py für engine-Kompatibilität erweitern
if [ -f "app.py" ]; then
# Backup erstellen
cp app.py app.py.backup
# Engine-Import sicherstellen
if ! grep -q "from models import.*engine" app.py; then
# Versuche engine zu importieren
if grep -q "from models import" app.py; then
sed -i '/from models import/s/$/,engine/' app.py 2>/dev/null || true
else
# Falls keine from models import Zeile existiert
if grep -q "import models" app.py; then
sed -i '/import models/a from models import engine' app.py
fi
fi
fi
# db-Variable für Kompatibilität
if ! grep -q "^db = engine" app.py; then
echo "" >> app.py
echo "# DB-Engine für Kompatibilität" >> app.py
echo "try:" >> app.py
echo " from models import engine" >> app.py
echo " db = engine" >> app.py
echo "except ImportError:" >> app.py
echo " from sqlalchemy import create_engine" >> app.py
echo " db = create_engine('sqlite:///database.db')" >> app.py
fi
fi
# Node.js Dependencies - VERBESSERTE VERSION
if [ -f "package.json" ]; then
progress "Installiere Node.js Dependencies..."
# Prüfe ob npm verfügbar ist
if command -v npm &> /dev/null && npm --version &> /dev/null; then
info "NPM verfügbar: $(npm --version)"
# Versuche npm install mit verschiedenen Methoden
if sudo -u "$APP_USER" npm install; then
log "✅ Node.js Dependencies installiert"
# Versuche CSS-Build falls Tailwind vorhanden
if [ -f "tailwind.config.js" ]; then
info "Tailwind-Konfiguration gefunden, versuche CSS-Build..."
if sudo -u "$APP_USER" npm run build:css; then
log "✅ CSS erfolgreich gebaut"
else
warning "⚠️ CSS-Build fehlgeschlagen - wird übersprungen"
# Fallback: Erstelle leere CSS-Datei
mkdir -p "$APP_DIR/static/css" || true
touch "$APP_DIR/static/css/tailwind.css" || true
chown "$APP_USER:$APP_USER" "$APP_DIR/static/css/tailwind.css" 2>/dev/null || true
fi
fi
else
warning "⚠️ npm install fehlgeschlagen, versuche Alternativen..."
# Alternative 1: npm install ohne Cache
if sudo -u "$APP_USER" npm install --no-cache; then
log "✅ Node.js Dependencies installiert (ohne Cache)"
elif sudo -u "$APP_USER" npm install --force; then
log "✅ Node.js Dependencies installiert (forciert)"
else
warning "⚠️ Alle npm-Installationsmethoden fehlgeschlagen"
warning "Node.js-Abhängigkeiten werden übersprungen"
# Erstelle leere CSS-Datei als Fallback
mkdir -p "$APP_DIR/static/css" || true
cat > "$APP_DIR/static/css/tailwind.css" << 'EOF'
/* Fallback CSS - NPM-Installation fehlgeschlagen */
body { font-family: system-ui, sans-serif; margin: 0; padding: 0; }
EOF
chown "$APP_USER:$APP_USER" "$APP_DIR/static/css/tailwind.css" 2>/dev/null || true
fi
fi
else
warning "⚠️ NPM nicht verfügbar - Node.js-Dependencies werden übersprungen"
info "Die Anwendung funktioniert auch ohne Node.js-Dependencies"
# Erstelle Fallback CSS-Datei
mkdir -p "$APP_DIR/static/css" || true
cat > "$APP_DIR/static/css/tailwind.css" << 'EOF'
/* Fallback CSS - NPM nicht verfügbar */
/* Basis-Styling für MYP-Anwendung */
body {
font-family: system-ui, -apple-system, sans-serif;
margin: 0;
padding: 0;
background: #f8f9fa;
}
.container { max-width: 1200px; margin: 0 auto; padding: 20px; }
.btn {
display: inline-block;
padding: 8px 16px;
background: #007bff;
color: white;
text-decoration: none;
border-radius: 4px;
border: none;
cursor: pointer;
}
.btn:hover { background: #0056b3; }
.alert {
padding: 12px;
margin: 10px 0;
border-radius: 4px;
background: #d4edda;
border: 1px solid #c3e6cb;
color: #155724;
}
.alert-danger { background: #f8d7da; border-color: #f5c6cb; color: #721c24; }
.table { width: 100%; border-collapse: collapse; margin: 20px 0; }
.table th, .table td { padding: 12px; text-align: left; border-bottom: 1px solid #dee2e6; }
.table th { background: #e9ecef; font-weight: 600; }
.form-control {
width: 100%;
padding: 8px 12px;
border: 1px solid #ced4da;
border-radius: 4px;
font-size: 14px;
max-width: 400px;
}
.card {
background: white;
border: 1px solid #dee2e6;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.text-center { text-align: center; }
.mt-4 { margin-top: 24px; }
.mb-4 { margin-bottom: 24px; }
.navbar {
background: #343a40;
color: white;
padding: 15px 0;
margin-bottom: 20px;
}
.navbar a { color: white; text-decoration: none; margin: 0 15px; }
.navbar a:hover { color: #adb5bd; }
EOF
chown "$APP_USER:$APP_USER" "$APP_DIR/static/css/tailwind.css" 2>/dev/null || true
log "✅ Fallback CSS-Datei erstellt"
fi
else
info "Keine package.json gefunden - Node.js-Dependencies werden übersprungen"
fi
# Datenbank initialisieren (DB-Import-Fehler behoben)
progress "Initialisiere Datenbank..."
python3 -c "
import sys
sys.path.insert(0, '$APP_DIR')
try:
from models import init_database, create_initial_admin
init_database()
create_initial_admin()
print('✅ Datenbank erfolgreich initialisiert')
except Exception as e:
print(f'⚠️ Datenbank-Initialisierung fehlgeschlagen: {str(e)}')
# Fallback: Erstelle leere Datenbank
import sqlite3
conn = sqlite3.connect('$APP_DIR/database.db')
conn.close()
print('✅ Fallback-Datenbank erstellt')
" || warning "Datenbank-Initialisierung fehlgeschlagen"
# Konfiguration erstellen
progress "Erstelle Anwendungskonfiguration..."
cat > "$APP_DIR/.env" << EOF
FLASK_ENV=production
SECRET_KEY=$(openssl rand -hex 32)
DATABASE_URL=sqlite:///database.db
HOST=0.0.0.0
PORT=5000
DEBUG=False
KIOSK_MODE=true
KIOSK_URL=http://localhost
EOF
chown "$APP_USER:$APP_USER" "$APP_DIR/.env"
log "✅ Anwendung installiert"
}
# ========================== DATEIBERECHTIGUNGEN SETZEN ==========================
set_file_permissions() {
log "=== PHASE 5.5: DATEIBERECHTIGUNGEN SETZEN ==="
progress "Setze korrekte Dateiberechtigungen..."
# Basis-Anwendungsverzeichnis
chown -R "$APP_USER:$APP_USER" "$APP_DIR"
chown -R "$APP_USER:$APP_USER" "$BACKUP_DIR"
# Verzeichnis-Berechtigungen
find "$APP_DIR" -type d -exec chmod 755 {} \;
find "$BACKUP_DIR" -type d -exec chmod 755 {} \;
# Datei-Berechtigungen
find "$APP_DIR" -type f -exec chmod 644 {} \;
# Ausführbare Dateien
if [ -f "$APP_DIR/app.py" ]; then
chmod 755 "$APP_DIR/app.py"
fi
# Upload-Ordner spezielle Berechtigungen
if [ -d "$APP_DIR/uploads" ]; then
chmod 755 "$APP_DIR/uploads"
find "$APP_DIR/uploads" -type d -exec chmod 755 {} \;
find "$APP_DIR/uploads" -type f -exec chmod 644 {} \;
# Prüfe ob www-data existiert, sonst verwende APP_USER
if id "www-data" &>/dev/null; then
chown -R "$APP_USER:www-data" "$APP_DIR/uploads"
else
warning "www-data-Benutzer nicht verfügbar - verwende $APP_USER:$APP_USER"
chown -R "$APP_USER:$APP_USER" "$APP_DIR/uploads"
fi
fi
# Log-Verzeichnisse
if [ -d "$APP_DIR/logs" ]; then
chmod 755 "$APP_DIR/logs"
find "$APP_DIR/logs" -type d -exec chmod 755 {} \;
find "$APP_DIR/logs" -type f -exec chmod 644 {} \;
chown -R "$APP_USER:$APP_USER" "$APP_DIR/logs"
fi
# Database-Verzeichnis
if [ -d "$APP_DIR/database" ]; then
chmod 755 "$APP_DIR/database"
find "$APP_DIR/database" -type f -exec chmod 644 {} \;
chown -R "$APP_USER:$APP_USER" "$APP_DIR/database"
fi
# Config-Dateien
if [ -f "$APP_DIR/.env" ]; then
chmod 600 "$APP_DIR/.env"
chown "$APP_USER:$APP_USER" "$APP_DIR/.env"
fi
# Static-Verzeichnis
if [ -d "$APP_DIR/static" ]; then
chmod 755 "$APP_DIR/static"
find "$APP_DIR/static" -type d -exec chmod 755 {} \;
find "$APP_DIR/static" -type f -exec chmod 644 {} \;
# Prüfe ob www-data existiert, sonst verwende APP_USER
if id "www-data" &>/dev/null; then
chown -R "$APP_USER:www-data" "$APP_DIR/static"
else
chown -R "$APP_USER:$APP_USER" "$APP_DIR/static"
fi
fi
# Templates-Verzeichnis
if [ -d "$APP_DIR/templates" ]; then
chmod 755 "$APP_DIR/templates"
find "$APP_DIR/templates" -type f -exec chmod 644 {} \;
chown -R "$APP_USER:$APP_USER" "$APP_DIR/templates"
fi
# System-Log-Verzeichnisse
for log_cat in app auth errors jobs printers scheduler; do
if [ -d "/var/log/myp-$log_cat" ]; then
chmod 755 "/var/log/myp-$log_cat"
fi
done
log "✅ Dateiberechtigungen gesetzt"
}
# ========================== KIOSK-KONFIGURATION ==========================
configure_kiosk() {
log "=== PHASE 6: ERWEITERTE KIOSK-KONFIGURATION ==="
# Sicherer Kiosk-Benutzer-Setup
KIOSK_HOME="/home/$KIOSK_USER"
progress "Konfiguriere Openbox für Kiosk..."
sudo -u "$KIOSK_USER" mkdir -p "$KIOSK_HOME/.config/openbox"
# Openbox-Konfiguration für maximale Sicherheit
cat > "$KIOSK_HOME/.config/openbox/rc.xml" << 'EOF'
Bitte warten Sie einen Moment.
" > /tmp/loading.html break fi done # ===== CHROMIUM KIOSK-MODUS MIT RASPBERRY PI OPTIMIERUNGEN ===== # Raspberry Pi spezifische Chromium-Flags CHROMIUM_FLAGS=" --kiosk --no-sandbox --disable-web-security --disable-features=TranslateUI,BlinkGenPropertyTrees --disable-ipc-flooding-protection --disable-renderer-backgrounding --disable-backgrounding-occluded-windows --disable-background-timer-throttling --disable-background-networking --disable-breakpad --disable-component-extensions-with-background-pages --disable-dev-shm-usage --disable-extensions --disable-hang-monitor --disable-popup-blocking --disable-prompt-on-repost --disable-sync --disable-translate --disable-infobars --disable-session-crashed-bubble --disable-restore-session-state --disable-crash-reporter --noerrdialogs --no-first-run --no-default-browser-check --autoplay-policy=no-user-gesture-required --start-fullscreen --window-position=0,0 --window-size=1920,1080 --user-data-dir=$KIOSK_HOME/.chromium-kiosk --disable-features=VizDisplayCompositor --enable-features=OverlayScrollbar --disable-gpu-sandbox --disable-software-rasterizer --ignore-certificate-errors --ignore-ssl-errors --ignore-certificate-errors-spki-list --ignore-ssl-errors-list --disable-logging --silent-debugger-extension-api --disable-default-apps --disable-background-mode --app-auto-launched --no-startup-window --force-device-scale-factor=1.0 --disable-pinch --overscroll-history-navigation=0 " # Raspberry Pi Hardware-spezifische Optimierungen if grep -q "Raspberry Pi" /proc/cpuinfo 2>/dev/null; then echo "Raspberry Pi erkannt - aktiviere Hardware-Optimierungen" CHROMIUM_FLAGS="\$CHROMIUM_FLAGS --disable-gpu-compositing --enable-gpu-rasterization --disable-smooth-scrolling --disable-2d-canvas-image-chromium --disable-accelerated-2d-canvas --num-raster-threads=2 --enable-zero-copy " fi # URL bestimmen if curl -s http://localhost:5000 > /dev/null; then KIOSK_URL="http://localhost:5000" else KIOSK_URL="file:///tmp/loading.html" fi echo "Starte Chromium im Kiosk-Modus mit URL: \$KIOSK_URL" # Chromium mit Restart-Loop starten (wichtig für Stabilität) while true; do echo "\$(date): Starte Chromium..." \$CHROMIUM_BIN \$CHROMIUM_FLAGS "\$KIOSK_URL" EXIT_CODE=\$? echo "\$(date): Chromium beendet mit Exit-Code: \$EXIT_CODE" # Bei normalem Exit (0) oder Kiosk-Exit (15) nicht neustarten if [ \$EXIT_CODE -eq 0 ] || [ \$EXIT_CODE -eq 15 ]; then echo "Chromium normal beendet - Kiosk-Modus verlassen" break fi # Bei Crash: Kurz warten und neustarten echo "Chromium-Crash erkannt - Neustart in 3 Sekunden..." sleep 3 # Bereinige Chromium-Prozesse pkill -f chromium 2>/dev/null || true sleep 1 done echo "\$(date): Kiosk-Session beendet" EOF # LXDE Autostart-Konfiguration (Alternative Methode) progress "Konfiguriere LXDE Autostart..." sudo -u "$KIOSK_USER" mkdir -p "$KIOSK_HOME/.config/lxsession/LXDE-pi" cat > "$KIOSK_HOME/.config/lxsession/LXDE-pi/autostart" << EOF ################################################# # LXDE-pi autostart script für MYP Kiosk # # Basierend auf: https://mpascucci.github.io/tutorial/rpi/ ################################################# # Bildschirmschoner deaktivieren @xset s noblank @xset s off @xset -dpms # Mauszeiger verstecken @unclutter -idle 0.5 -root # Kiosk-Anwendung starten @bash $KIOSK_HOME/start-kiosk.sh EOF # Desktop-Autostart-Datei (systemd-kompatibel) progress "Erstelle Desktop-Autostart-Datei..." sudo -u "$KIOSK_USER" mkdir -p "$KIOSK_HOME/.config/autostart" cat > "$KIOSK_HOME/.config/autostart/myp-kiosk.desktop" << EOF [Desktop Entry] Type=Application Name=MYP Kiosk Application Comment=Startet die MYP Kiosk-Anwendung automatisch Exec=/bin/bash $KIOSK_HOME/start-kiosk.sh Hidden=false NoDisplay=false X-GNOME-Autostart-enabled=true StartupNotify=false Categories=System; EOF # Skripte ausführbar machen chmod +x "$KIOSK_HOME/start-kiosk.sh" chmod +x "$KIOSK_HOME/.config/lxsession/LXDE-pi/autostart" chown -R "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.config" chown "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/start-kiosk.sh" log "✅ Erweiterte Kiosk-Konfiguration erstellt" } # ========================== RASPBERRY PI OPTIMIERUNGEN ========================== optimize_raspberry_pi() { log "=== PHASE 6.2: RASPBERRY PI OPTIMIERUNGEN ===" # Prüfe ob es sich um einen Raspberry Pi handelt if ! grep -q "Raspberry Pi" /proc/cpuinfo 2>/dev/null; then info "Kein Raspberry Pi erkannt - überspringe Pi-spezifische Optimierungen" return 0 fi progress "Raspberry Pi erkannt - aktiviere Hardware-Optimierungen..." # ===== BOOT-KONFIGURATION OPTIMIEREN ===== progress "Optimiere Boot-Konfiguration..." # /boot/config.txt Optimierungen if [ -f "/boot/config.txt" ]; then # Backup erstellen cp /boot/config.txt /boot/config.txt.backup # GPU Memory Split für bessere Browser-Performance if ! grep -q "gpu_mem=" /boot/config.txt; then echo "" >> /boot/config.txt echo "# MYP Kiosk Optimierungen" >> /boot/config.txt echo "gpu_mem=128" >> /boot/config.txt info "GPU Memory Split auf 128MB gesetzt" fi # Disable Rainbow Splash if ! grep -q "disable_splash=1" /boot/config.txt; then echo "disable_splash=1" >> /boot/config.txt fi # HDMI Force Hotplug für bessere Display-Kompatibilität if ! grep -q "hdmi_force_hotplug=1" /boot/config.txt; then echo "hdmi_force_hotplug=1" >> /boot/config.txt fi # Disable Overscan für Kiosk-Displays if ! grep -q "disable_overscan=1" /boot/config.txt; then echo "disable_overscan=1" >> /boot/config.txt fi # Audio über HDMI aktivieren if ! grep -q "hdmi_drive=2" /boot/config.txt; then echo "hdmi_drive=2" >> /boot/config.txt fi info "Boot-Konfiguration optimiert" fi # /boot/cmdline.txt Optimierungen if [ -f "/boot/cmdline.txt" ]; then # Backup erstellen cp /boot/cmdline.txt /boot/cmdline.txt.backup # Console Blanking deaktivieren if ! grep -q "consoleblank=0" /boot/cmdline.txt; then sed -i 's/$/ consoleblank=0/' /boot/cmdline.txt info "Console Blanking deaktiviert" fi # Logo deaktivieren für schnelleren Boot if ! grep -q "logo.nologo" /boot/cmdline.txt; then sed -i 's/$/ logo.nologo/' /boot/cmdline.txt fi # Quiet Boot für saubere Kiosk-Erfahrung if ! grep -q "quiet" /boot/cmdline.txt; then sed -i 's/$/ quiet/' /boot/cmdline.txt fi fi # ===== WLAN POWER MANAGEMENT DEAKTIVIEREN ===== progress "Deaktiviere WLAN Power Management..." # Systemd-Service für WLAN Power Management cat > "/etc/systemd/system/disable-wifi-power-management.service" << 'EOF' [Unit] Description=Disable WiFi Power Management After=multi-user.target [Service] Type=oneshot RemainAfterExit=yes ExecStart=/bin/bash -c 'iwconfig wlan0 power off 2>/dev/null || true' [Install] WantedBy=multi-user.target EOF systemctl enable disable-wifi-power-management.service # NetworkManager Konfiguration (falls vorhanden) if [ -d "/etc/NetworkManager/conf.d" ]; then cat > "/etc/NetworkManager/conf.d/default-wifi-powersave-on.conf" << 'EOF' [connection] wifi.powersave = 2 EOF info "NetworkManager WLAN Power Save deaktiviert" fi # ===== ENERGIESPARMODUS KOMPLETT DEAKTIVIEREN ===== progress "Deaktiviere Energiesparmodus..." # LightDM Konfiguration erweitern if [ -f "/etc/lightdm/lightdm.conf" ]; then # Backup erstellen cp /etc/lightdm/lightdm.conf /etc/lightdm/lightdm.conf.backup # X-Server Kommando mit DPMS-Deaktivierung if ! grep -q "xserver-command=X -s 0 -dpms" /etc/lightdm/lightdm.conf; then sed -i '/^\[Seat:\*\]/a xserver-command=X -s 0 -dpms' /etc/lightdm/lightdm.conf info "X-Server Energiesparmodus deaktiviert" fi fi # ===== SYSTEMD POWER MANAGEMENT ===== progress "Konfiguriere systemd Power Management..." # Logind-Konfiguration für Kiosk mkdir -p /etc/systemd/logind.conf.d cat > "/etc/systemd/logind.conf.d/kiosk-power.conf" << 'EOF' [Login] # Verhindere Suspend/Hibernate im Kiosk-Modus HandlePowerKey=ignore HandleSuspendKey=ignore HandleHibernateKey=ignore HandleLidSwitch=ignore HandleLidSwitchExternalPower=ignore HandleLidSwitchDocked=ignore # Idle-Verhalten für Kiosk IdleAction=ignore IdleActionSec=infinity # Session-Management KillUserProcesses=no UserStopDelaySec=10 EOF # ===== RASPBERRY PI SPEZIFISCHE PAKETE ===== progress "Installiere Raspberry Pi spezifische Tools..." # Raspberry Pi Tools (falls verfügbar) apt-get install -y \ libraspberrypi-bin \ raspberrypi-kernel-headers \ wireless-tools \ bc \ 2>/dev/null || warning "Einige Pi-spezifische Pakete nicht verfügbar" # ===== TEMPERATUR-MONITORING ===== progress "Konfiguriere Temperatur-Monitoring..." # Temperatur-Check-Skript cat > "/usr/local/bin/pi-temp-check" << 'EOF' #!/bin/bash # Raspberry Pi Temperatur-Check für Kiosk-System TEMP=$(vcgencmd measure_temp 2>/dev/null | cut -d= -f2 | cut -d"'" -f1) if [ -n "$TEMP" ]; then echo "$(date): CPU Temperatur: ${TEMP}°C" >> /var/log/pi-temperature.log # Warnung bei hoher Temperatur if (( $(echo "$TEMP > 70" | bc -l) )); then echo "$(date): WARNUNG - Hohe CPU Temperatur: ${TEMP}°C" >> /var/log/pi-temperature.log logger "Raspberry Pi: Hohe CPU Temperatur: ${TEMP}°C" fi # Kritische Temperatur if (( $(echo "$TEMP > 80" | bc -l) )); then echo "$(date): KRITISCH - Sehr hohe CPU Temperatur: ${TEMP}°C" >> /var/log/pi-temperature.log logger "Raspberry Pi: KRITISCHE Temperatur: ${TEMP}°C" fi fi EOF chmod +x /usr/local/bin/pi-temp-check # Cron-Job für Temperatur-Monitoring cat > "/etc/cron.d/pi-temperature" << 'EOF' # Raspberry Pi Temperatur-Monitoring alle 5 Minuten */5 * * * * root /usr/local/bin/pi-temp-check EOF # ===== PERFORMANCE-OPTIMIERUNGEN ===== progress "Aktiviere Performance-Optimierungen..." # Swappiness reduzieren für bessere Performance echo "vm.swappiness=10" >> /etc/sysctl.conf # Dirty Ratio optimieren echo "vm.dirty_ratio=15" >> /etc/sysctl.conf echo "vm.dirty_background_ratio=5" >> /etc/sysctl.conf # ===== UNCLUTTER INSTALLATION ===== progress "Installiere unclutter für Mauszeiger-Verstecken..." apt-get install -y unclutter || warning "unclutter Installation fehlgeschlagen" # ===== CHROMIUM OPTIMIERUNGEN FÜR RASPBERRY PI ===== progress "Konfiguriere Chromium für Raspberry Pi..." # Chromium GPU-Konfiguration mkdir -p /etc/chromium-browser/policies/managed cat > "/etc/chromium-browser/policies/managed/kiosk-policy.json" << 'EOF' { "DefaultBrowserSettingEnabled": false, "BackgroundModeEnabled": false, "BookmarkBarEnabled": false, "BrowserSignin": 0, "DefaultNotificationsSetting": 2, "DefaultGeolocationSetting": 2, "DefaultMediaStreamSetting": 2, "PasswordManagerEnabled": false, "AutofillAddressEnabled": false, "AutofillCreditCardEnabled": false, "TranslateEnabled": false, "SpellCheckServiceEnabled": false, "SearchSuggestEnabled": false, "ImportBookmarks": false, "ImportHistory": false, "ImportSavedPasswords": false, "ImportSearchEngine": false, "MetricsReportingEnabled": false, "UserFeedbackAllowed": false } EOF info "Chromium-Richtlinien für Kiosk-Modus konfiguriert" log "✅ Raspberry Pi Optimierungen abgeschlossen" } # ========================== DNS UND NETZWERK OPTIMIERUNG ========================== configure_dns_and_network() { log "=== PHASE 6.3: DNS UND NETZWERK OPTIMIERUNG ===" progress "Konfiguriere intelligente DNS-Auflösung..." # ===== IPv6 DEAKTIVIEREN ===== progress "Deaktiviere IPv6 systemweit..." # Kernel-Parameter für IPv6-Deaktivierung cat >> /etc/sysctl.conf << 'EOF' # IPv6 deaktivieren für Kiosk-System net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 net.ipv6.conf.lo.disable_ipv6 = 1 EOF # IPv6 sofort deaktivieren sysctl -w net.ipv6.conf.all.disable_ipv6=1 sysctl -w net.ipv6.conf.default.disable_ipv6=1 sysctl -w net.ipv6.conf.lo.disable_ipv6=1 # IPv6 in GRUB deaktivieren (falls vorhanden) if [ -f "/etc/default/grub" ]; then if ! grep -q "ipv6.disable=1" /etc/default/grub; then sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="/GRUB_CMDLINE_LINUX_DEFAULT="ipv6.disable=1 /' /etc/default/grub update-grub 2>/dev/null || true fi fi # IPv6 in /boot/cmdline.txt deaktivieren (Raspberry Pi) if [ -f "/boot/cmdline.txt" ]; then if ! grep -q "ipv6.disable=1" /boot/cmdline.txt; then sed -i 's/$/ ipv6.disable=1/' /boot/cmdline.txt fi fi info "IPv6 systemweit deaktiviert" # ===== UNBOUND DNS RESOLVER INSTALLIEREN ===== progress "Installiere Unbound DNS Resolver..." apt-get install -y unbound unbound-host dnsutils || error "Unbound Installation fehlgeschlagen" # ===== DNS KONFIGURATION MIT PRIORITÄTEN ===== progress "Konfiguriere DNS mit intelligenten Prioritäten..." # Unbound Hauptkonfiguration cat > "/etc/unbound/unbound.conf" << 'EOF' # Unbound DNS Resolver Konfiguration für MYP Kiosk # Intelligente DNS-Auflösung mit Fallback-Mechanismen server: # Basis-Konfiguration verbosity: 1 interface: 127.0.0.1 port: 53 do-ip4: yes do-ip6: no do-udp: yes do-tcp: yes # Sicherheit chroot: "" username: "unbound" directory: "/etc/unbound" logfile: "/var/log/unbound.log" use-syslog: yes log-queries: no log-replies: no # Performance num-threads: 2 msg-cache-slabs: 4 rrset-cache-slabs: 4 infra-cache-slabs: 4 key-cache-slabs: 4 msg-cache-size: 64m rrset-cache-size: 128m cache-max-ttl: 86400 cache-min-ttl: 300 # Netzwerk-Einstellungen outgoing-range: 4096 num-queries-per-thread: 2048 so-rcvbuf: 4m so-sndbuf: 4m # Lokale Netzwerke erlauben access-control: 127.0.0.0/8 allow access-control: 192.168.0.0/16 allow access-control: 10.0.0.0/8 allow access-control: 172.16.0.0/12 allow # Root Hints root-hints: "/var/lib/unbound/root.hints" # DNSSEC auto-trust-anchor-file: "/var/lib/unbound/root.key" # Lokale Auflösung private-address: 192.168.0.0/16 private-address: 172.16.0.0/12 private-address: 10.0.0.0/8 private-address: 127.0.0.0/8 # Upstream DNS Server mit Prioritäten # 1. Prio: Router DNS (wird dynamisch gesetzt) # 2. Prio: Google DNS # 3. Prio: Cloudflare DNS # 4. Prio: Custom DNS Server forward-zone: name: "." # Fallback DNS Server (werden durch Skript überschrieben) forward-addr: 8.8.8.8 forward-addr: 8.8.4.4 forward-addr: 1.1.1.1 forward-addr: 1.0.0.1 forward-addr: 163.116.178.73 forward-addr: 163.116.178.74 EOF # ===== DYNAMISCHE DNS-KONFIGURATION ===== progress "Erstelle dynamisches DNS-Konfigurationsskript..." cat > "/usr/local/bin/configure-dns-priority" << 'EOF' #!/bin/bash # Dynamische DNS-Konfiguration mit Router-Priorität # Automatische Erkennung und Konfiguration der besten DNS-Server LOG_FILE="/var/log/dns-configuration.log" UNBOUND_CONF="/etc/unbound/unbound.conf" RESOLV_CONF="/etc/resolv.conf" log_dns() { echo "$(date): $1" >> "$LOG_FILE" } # Erkenne Router-DNS get_router_dns() { local router_dns="" # Methode 1: DHCP Lease-Datei if [ -f "/var/lib/dhcp/dhclient.leases" ]; then router_dns=$(grep "domain-name-servers" /var/lib/dhcp/dhclient.leases | tail -1 | cut -d' ' -f3- | tr -d ';' | tr ',' ' ') fi # Methode 2: systemd-resolved if [ -z "$router_dns" ] && command -v systemd-resolve &> /dev/null; then router_dns=$(systemd-resolve --status | grep "DNS Servers" | head -1 | cut -d: -f2 | xargs) fi # Methode 3: NetworkManager if [ -z "$router_dns" ] && command -v nmcli &> /dev/null; then router_dns=$(nmcli dev show | grep "IP4.DNS" | head -1 | cut -d: -f2 | xargs) fi # Methode 4: Route-basierte Erkennung if [ -z "$router_dns" ]; then local gateway=$(ip route | grep default | head -1 | awk '{print $3}') if [ -n "$gateway" ]; then # Versuche Gateway als DNS if nslookup google.com "$gateway" &> /dev/null; then router_dns="$gateway" fi fi fi echo "$router_dns" } # Teste DNS-Server test_dns_server() { local dns_server="$1" local timeout=3 if [ -z "$dns_server" ]; then return 1 fi # Teste mit nslookup if timeout "$timeout" nslookup google.com "$dns_server" &> /dev/null; then return 0 fi # Teste mit dig (falls verfügbar) if command -v dig &> /dev/null; then if timeout "$timeout" dig @"$dns_server" google.com &> /dev/null; then return 0 fi fi return 1 } # Konfiguriere Unbound mit priorisierten DNS-Servern configure_unbound() { local router_dns="$1" local config_section="" log_dns "Konfiguriere Unbound mit Router-DNS: $router_dns" # Erstelle Forward-Zone-Konfiguration config_section="forward-zone:\n name: \".\"\n" # 1. Priorität: Router DNS (falls verfügbar und funktional) if [ -n "$router_dns" ]; then for dns in $router_dns; do if test_dns_server "$dns"; then config_section="${config_section} forward-addr: $dns\n" log_dns "Router DNS hinzugefügt: $dns" else log_dns "Router DNS nicht erreichbar: $dns" fi done fi # 2. Priorität: Google DNS config_section="${config_section} forward-addr: 8.8.8.8\n" config_section="${config_section} forward-addr: 8.8.4.4\n" # 3. Priorität: Cloudflare DNS config_section="${config_section} forward-addr: 1.1.1.1\n" config_section="${config_section} forward-addr: 1.0.0.1\n" # 4. Priorität: Custom DNS Server config_section="${config_section} forward-addr: 163.116.178.73\n" config_section="${config_section} forward-addr: 163.116.178.74\n" # Ersetze Forward-Zone in Unbound-Konfiguration sed -i '/^forward-zone:/,$d' "$UNBOUND_CONF" echo -e "$config_section" >> "$UNBOUND_CONF" # Unbound neu laden systemctl reload unbound || systemctl restart unbound log_dns "Unbound-Konfiguration aktualisiert und neu geladen" } # Konfiguriere /etc/resolv.conf configure_resolv_conf() { log_dns "Konfiguriere /etc/resolv.conf für lokalen Unbound" # Backup erstellen cp "$RESOLV_CONF" "${RESOLV_CONF}.backup" 2>/dev/null || true # Neue resolv.conf erstellen cat > "$RESOLV_CONF" << 'RESOLV_EOF' # MYP Kiosk DNS-Konfiguration # Lokaler Unbound DNS Resolver mit intelligenten Fallbacks nameserver 127.0.0.1 # Fallback DNS Server (falls Unbound nicht verfügbar) nameserver 8.8.8.8 nameserver 8.8.4.4 # Suchdomänen search local # Optionen options timeout:2 options attempts:3 options rotate RESOLV_EOF # Schreibschutz setzen (verhindert Überschreibung durch DHCP) chattr +i "$RESOLV_CONF" 2>/dev/null || true log_dns "/etc/resolv.conf konfiguriert und geschützt" } # Hauptfunktion main() { log_dns "=== DNS-Konfiguration gestartet ===" # Router-DNS ermitteln router_dns=$(get_router_dns) log_dns "Erkannte Router-DNS: ${router_dns:-'Keine gefunden'}" # Unbound konfigurieren configure_unbound "$router_dns" # resolv.conf konfigurieren configure_resolv_conf # DNS-Test if nslookup google.com 127.0.0.1 &> /dev/null; then log_dns "✅ DNS-Konfiguration erfolgreich - Test bestanden" else log_dns "⚠️ DNS-Test fehlgeschlagen - Fallback aktiv" fi log_dns "=== DNS-Konfiguration abgeschlossen ===" } # Skript ausführen main "$@" EOF chmod +x /usr/local/bin/configure-dns-priority # ===== SYSTEMD-SERVICE FÜR DNS-KONFIGURATION ===== progress "Erstelle systemd-Service für DNS-Konfiguration..." cat > "/etc/systemd/system/dns-priority-config.service" << 'EOF' [Unit] Description=Configure DNS Priority with Router Detection After=network-online.target unbound.service Wants=network-online.target Before=myp-druckerverwaltung.service [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/local/bin/configure-dns-priority StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target EOF systemctl enable dns-priority-config.service # ===== DHCP-CLIENT KONFIGURATION ===== progress "Konfiguriere DHCP-Client für DNS-Schutz..." # dhclient-Konfiguration (verhindert DNS-Überschreibung) if [ -f "/etc/dhcp/dhclient.conf" ]; then # Backup erstellen cp /etc/dhcp/dhclient.conf /etc/dhcp/dhclient.conf.backup # DNS-Überschreibung verhindern if ! grep -q "supersede domain-name-servers" /etc/dhcp/dhclient.conf; then echo "" >> /etc/dhcp/dhclient.conf echo "# MYP Kiosk: Verhindere DNS-Überschreibung durch DHCP" >> /etc/dhcp/dhclient.conf echo "supersede domain-name-servers 127.0.0.1;" >> /etc/dhcp/dhclient.conf fi fi # NetworkManager-Konfiguration (falls vorhanden) if [ -d "/etc/NetworkManager/conf.d" ]; then cat > "/etc/NetworkManager/conf.d/dns-priority.conf" << 'EOF' [main] dns=none [connection] ipv6.method=ignore EOF info "NetworkManager DNS-Überschreibung deaktiviert" fi # ===== UNBOUND STARTEN UND KONFIGURIEREN ===== progress "Starte und konfiguriere Unbound..." # Root Hints herunterladen curl -o /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache 2>/dev/null || \ wget -O /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache 2>/dev/null || \ warning "Root Hints Download fehlgeschlagen" # Unbound-Benutzer Berechtigungen # Prüfe ob unbound-Benutzer existiert, sonst erstelle ihn oder verwende root if ! id "unbound" &>/dev/null; then warning "unbound-Benutzer nicht gefunden - versuche Erstellung..." if ! useradd --system --no-create-home --shell /bin/false unbound 2>/dev/null; then warning "unbound-Benutzer konnte nicht erstellt werden - verwende root" chown -R root:root /var/lib/unbound 2>/dev/null || true chown root:root /etc/unbound/unbound.conf 2>/dev/null || true else chown -R unbound:unbound /var/lib/unbound 2>/dev/null || true chown unbound:unbound /etc/unbound/unbound.conf 2>/dev/null || true fi else chown -R unbound:unbound /var/lib/unbound 2>/dev/null || true chown unbound:unbound /etc/unbound/unbound.conf 2>/dev/null || true fi # Unbound aktivieren und starten systemctl enable unbound systemctl start unbound # DNS-Konfiguration ausführen /usr/local/bin/configure-dns-priority # ===== CRON-JOB FÜR REGELMÄSSIGE DNS-UPDATES ===== progress "Konfiguriere automatische DNS-Updates..." cat > "/etc/cron.d/dns-priority-update" << 'EOF' # DNS-Priorität alle 30 Minuten aktualisieren */30 * * * * root /usr/local/bin/configure-dns-priority >/dev/null 2>&1 # Root Hints wöchentlich aktualisieren 0 3 * * 0 root curl -s -o /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache && systemctl reload unbound EOF # ===== DNS-MONITORING SKRIPT ===== progress "Erstelle DNS-Monitoring..." cat > "/usr/local/bin/dns-health-check" << 'EOF' #!/bin/bash # DNS-Gesundheitscheck für MYP Kiosk LOG_FILE="/var/log/dns-health.log" log_health() { echo "$(date): $1" >> "$LOG_FILE" } # Teste DNS-Auflösung test_dns_resolution() { local test_domains=("google.com" "github.com" "debian.org") local failed_count=0 for domain in "${test_domains[@]}"; do if ! nslookup "$domain" 127.0.0.1 &> /dev/null; then ((failed_count++)) log_health "DNS-Auflösung fehlgeschlagen für: $domain" fi done if [ $failed_count -eq 0 ]; then log_health "✅ DNS-Gesundheitscheck bestanden" return 0 elif [ $failed_count -lt ${#test_domains[@]} ]; then log_health "⚠️ DNS-Gesundheitscheck teilweise fehlgeschlagen ($failed_count/${#test_domains[@]})" return 1 else log_health "❌ DNS-Gesundheitscheck komplett fehlgeschlagen" return 2 fi } # Unbound-Status prüfen check_unbound_status() { if systemctl is-active --quiet unbound; then log_health "✅ Unbound läuft" return 0 else log_health "❌ Unbound läuft nicht - versuche Neustart" systemctl restart unbound sleep 3 if systemctl is-active --quiet unbound; then log_health "✅ Unbound erfolgreich neu gestartet" return 0 else log_health "❌ Unbound-Neustart fehlgeschlagen" return 1 fi fi } # Hauptfunktion main() { check_unbound_status test_dns_resolution local exit_code=$? # Bei kritischen Fehlern: DNS-Konfiguration neu laden if [ $exit_code -eq 2 ]; then log_health "Kritischer DNS-Fehler - lade Konfiguration neu" /usr/local/bin/configure-dns-priority fi return $exit_code } main "$@" EOF chmod +x /usr/local/bin/dns-health-check # DNS-Health-Check zu Cron hinzufügen cat >> "/etc/cron.d/dns-priority-update" << 'EOF' # DNS-Gesundheitscheck alle 10 Minuten */10 * * * * root /usr/local/bin/dns-health-check >/dev/null 2>&1 EOF log "✅ DNS und Netzwerk-Optimierung abgeschlossen" } # ========================== AUTO-LOGIN KONFIGURATION ========================== configure_autologin() { log "=== PHASE 6.5: AUTO-LOGIN KONFIGURATION ===" progress "Installiere und konfiguriere Display Manager..." # LightDM installieren für besseres Auto-Login-Management apt-get install -y lightdm lightdm-gtk-greeter || true # Stoppe andere Display Manager for dm in gdm gdm3 sddm xdm nodm; do systemctl stop "$dm" 2>/dev/null || true systemctl disable "$dm" 2>/dev/null || true done progress "Konfiguriere LightDM für Auto-Login..." # LightDM-Konfiguration für automatischen Login cat > "/etc/lightdm/lightdm.conf" << EOF [Seat:*] # Automatischer Login für Kiosk-Benutzer autologin-user=$KIOSK_USER autologin-user-timeout=0 autologin-session=openbox user-session=openbox session-wrapper=/etc/X11/Xsession greeter-session=lightdm-gtk-greeter allow-guest=false # Kein Benutzer-Wechsel möglich greeter-hide-users=true greeter-show-manual-login=false # Automatischer Start ohne Verzögerung autologin-in-background=false # Session-Setup session-setup-script=/usr/share/lightdm/setup-kiosk-session.sh [SeatDefaults] # Zusätzliche Sicherheitseinstellungen autologin-user=$KIOSK_USER autologin-user-timeout=0 autologin-session=openbox greeter-hide-users=true greeter-show-manual-login=false allow-user-switching=false EOF progress "Erstelle Session-Setup-Skript..." # Session-Setup-Skript für zusätzliche Sicherheit cat > "/usr/share/lightdm/setup-kiosk-session.sh" << EOF #!/bin/bash # Session-Setup für Kiosk-Modus # Stelle sicher, dass X11-Display verfügbar ist export DISPLAY=:0 # Deaktiviere Bildschirmschoner und Power Management xset s off xset s noblank xset s noexpose xset -dpms # Verstecke Mauszeiger unclutter -idle 0.5 -root & # Logge Session-Start echo "\$(date): Kiosk-Session für Benutzer $KIOSK_USER gestartet" >> /var/log/kiosk-session.log EOF chmod +x "/usr/share/lightdm/setup-kiosk-session.sh" progress "Konfiguriere Getty Auto-Login als Fallback..." # Getty Auto-Login als Fallback konfigurieren (falls LightDM fehlschlägt) mkdir -p "/etc/systemd/system/getty@tty1.service.d" cat > "/etc/systemd/system/getty@tty1.service.d/autologin.conf" << EOF [Service] ExecStart= ExecStart=-/sbin/agetty --autologin $KIOSK_USER --noclear %I \$TERM Type=simple EOF # Aktiviere getty@tty1 Service für automatischen Login systemctl enable getty@tty1.service progress "Konfiguriere systemd für automatischen grafischen Start..." # Setze graphical.target als Standard systemctl set-default graphical.target # Erstelle systemd-Override für LightDM mkdir -p "/etc/systemd/system/lightdm.service.d" cat > "/etc/systemd/system/lightdm.service.d/autologin-override.conf" << EOF [Unit] After=multi-user.target network.target myp-druckerverwaltung.service Wants=myp-druckerverwaltung.service [Service] # Automatischer Restart bei Fehlern Restart=always RestartSec=3 # Umgebungsvariablen für Kiosk Environment=DISPLAY=:0 Environment=KIOSK_MODE=1 # Verzögerung für Backend-Start ExecStartPre=/bin/bash -c 'for i in {1..30}; do if curl -s http://localhost:5000 >/dev/null 2>&1; then break; fi; sleep 2; done' EOF # Aktiviere LightDM Service systemctl enable lightdm.service progress "Erstelle Desktop-Session für Openbox..." # Desktop-Session-Datei für Openbox mkdir -p "/usr/share/xsessions" cat > "/usr/share/xsessions/openbox.desktop" << EOF [Desktop Entry] Name=Openbox Comment=A lightweight window manager Exec=openbox-session Type=XSession DesktopNames=OPENBOX EOF # Kiosk-Benutzer Desktop-Umgebung konfigurieren progress "Konfiguriere Desktop-Umgebung für Kiosk-Benutzer..." KIOSK_HOME="/home/$KIOSK_USER" # .xsessionrc für X-Session-Setup cat > "$KIOSK_HOME/.xsessionrc" << EOF #!/bin/bash # X-Session-Setup für Kiosk-Modus # Export Display export DISPLAY=:0 # Starte Session-Log echo "\$(date): X-Session gestartet für Kiosk-Benutzer" >> /var/log/kiosk-session.log # Führe Kiosk-Setup aus exec openbox-session EOF # .xinitrc für xinit/startx cat > "$KIOSK_HOME/.xinitrc" << EOF #!/bin/bash # Xinit-Konfiguration für Kiosk-Modus # Export Display export DISPLAY=:0 # Session-Setup xset s off xset s noblank xset s noexpose xset -dpms # Verstecke Mauszeiger unclutter -idle 0.5 -root & # Starte Openbox exec openbox-session EOF chmod +x "$KIOSK_HOME/.xsessionrc" chmod +x "$KIOSK_HOME/.xinitrc" # Konfiguriere PAM für automatischen Login progress "Konfiguriere PAM für automatischen Login..." # PAM-Konfiguration für LightDM autologin cat > "/etc/pam.d/lightdm-autologin" << EOF # PAM configuration for LightDM autologin auth required pam_env.so auth required pam_permit.so @include common-account session required pam_limits.so @include common-session @include common-password EOF # Zusätzliche Autostart-Mechanismen für maximale Zuverlässigkeit progress "Konfiguriere mehrfache Autostart-Absicherung..." # 1. BASHRC AUTOSTART cat >> "$KIOSK_HOME/.bashrc" << 'EOF' # ===== KIOSK AUTOSTART (BASHRC) ===== if [ -z "$SSH_CLIENT" ] && [ -z "$SSH_TTY" ] && [ -z "$KIOSK_STARTED" ]; then export KIOSK_STARTED=1 # Prüfe ob wir auf tty1 sind und X noch nicht läuft if [ "$(tty)" = "/dev/tty1" ] && [ -z "$DISPLAY" ]; then echo "Starte X-Session automatisch..." exec startx fi # Falls X läuft aber Kiosk-App nicht, starte sie if [ -n "$DISPLAY" ] && ! pgrep -f "chromium.*kiosk" > /dev/null; then echo "Starte Kiosk-Anwendung..." exec $HOME/start-kiosk.sh fi fi EOF # 2. PROFILE AUTOSTART cat >> "$KIOSK_HOME/.profile" << 'EOF' # ===== KIOSK AUTOSTART (PROFILE) ===== if [ -z "$SSH_CLIENT" ] && [ -z "$SSH_TTY" ] && [ -z "$KIOSK_STARTED" ]; then export KIOSK_STARTED=1 # Starte X-Session falls nicht vorhanden if [ -z "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ] && [ "$(tty)" = "/dev/tty1" ]; then echo "Starte X-Session via .profile" exec startx fi fi EOF # 3. DESKTOP AUTOSTART progress "Konfiguriere XDG autostart..." sudo -u "$KIOSK_USER" mkdir -p "$KIOSK_HOME/.config/autostart" cat > "$KIOSK_HOME/.config/autostart/kiosk-app.desktop" << EOF [Desktop Entry] Type=Application Name=MYP Kiosk Application Comment=Startet die MYP Kiosk-Anwendung Exec=$KIOSK_HOME/start-kiosk.sh Hidden=false NoDisplay=false X-GNOME-Autostart-enabled=true StartupNotify=false EOF chown "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.config/autostart/kiosk-app.desktop" # 4. CRON AUTOSTART (ÜBERWACHUNG) progress "Konfiguriere Cron-Überwachung..." cat > "/etc/cron.d/kiosk-watchdog" << EOF # Kiosk-Überwachung: Startet Kiosk neu falls nicht läuft */2 * * * * $KIOSK_USER /bin/bash -c 'if ! pgrep -f "chromium.*kiosk" > /dev/null; then echo "\$(date): Kiosk-Watchdog startet Anwendung neu" >> /var/log/kiosk-watchdog.log; DISPLAY=:0 $HOME/start-kiosk.sh & fi' EOF # 5. RC.LOCAL FALLBACK progress "Konfiguriere rc.local Fallback..." cat > "/etc/rc.local" << EOF #!/bin/bash # rc.local - Kiosk-Fallback # Warte auf System-Initialisierung sleep 15 # Starte Backend-Service falls nicht läuft if ! systemctl is-active --quiet myp-druckerverwaltung; then systemctl start myp-druckerverwaltung sleep 5 fi # Starte LightDM falls nicht läuft if ! systemctl is-active --quiet lightdm; then systemctl start lightdm sleep 3 fi # Prüfe ob Kiosk-Benutzer angemeldet ist, falls nicht, starte LightDM neu sleep 10 if ! pgrep -u $KIOSK_USER > /dev/null; then echo "\$(date): Kiosk-Benutzer nicht angemeldet - starte LightDM neu" >> /var/log/kiosk-fallback.log systemctl restart lightdm fi # Logge Start echo "\$(date): rc.local Kiosk-Fallback ausgeführt" >> /var/log/kiosk-fallback.log exit 0 EOF chmod +x "/etc/rc.local" # 6. SYSTEMD SERVICE ÜBERWACHUNG progress "Konfiguriere Service-Überwachung..." cat > "/etc/systemd/system/kiosk-watchdog.service" << EOF [Unit] Description=Kiosk Watchdog Service After=multi-user.target lightdm.service Wants=lightdm.service [Service] Type=simple User=root ExecStart=/bin/bash -c 'while true; do if ! systemctl is-active --quiet lightdm; then echo "\$(date): LightDM nicht aktiv - starte neu" >> /var/log/kiosk-watchdog.log; systemctl start lightdm; fi; if ! pgrep -u $KIOSK_USER > /dev/null; then echo "\$(date): Kiosk-Benutzer nicht angemeldet - starte LightDM neu" >> /var/log/kiosk-watchdog.log; systemctl restart lightdm; fi; sleep 30; done' Restart=always RestartSec=10 [Install] WantedBy=multi-user.target EOF systemctl enable kiosk-watchdog.service # 7. BOOT-PARAMETER OPTIMIERUNG progress "Optimiere Boot-Parameter für automatischen Start..." # Raspberry Pi spezifische Boot-Konfiguration if [ -f "/boot/config.txt" ]; then # GPU Memory für bessere Grafik-Performance if ! grep -q "gpu_mem=" /boot/config.txt; then echo "gpu_mem=128" >> /boot/config.txt fi # Disable Boot-Splash für schnelleren Start if ! grep -q "disable_splash=" /boot/config.txt; then echo "disable_splash=1" >> /boot/config.txt fi # Boot-Delay reduzieren if ! grep -q "boot_delay=" /boot/config.txt; then echo "boot_delay=0" >> /boot/config.txt fi fi # Kernel-Parameter für schnelleren Boot if [ -f "/boot/cmdline.txt" ]; then # Entferne Boot-Splash und füge quiet hinzu sed -i 's/splash//g' /boot/cmdline.txt if ! grep -q "quiet" /boot/cmdline.txt; then sed -i 's/$/ quiet/' /boot/cmdline.txt fi if ! grep -q "loglevel=3" /boot/cmdline.txt; then sed -i 's/$/ loglevel=3/' /boot/cmdline.txt fi fi # Berechtigungen finalisieren chown -R "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.config" chown "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.bashrc" chown "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.profile" chown "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.xsessionrc" chown "$KIOSK_USER:$KIOSK_USER" "$KIOSK_HOME/.xinitrc" log "✅ Mehrfache Autostart-Absicherung mit Boot-Optimierung implementiert" } # ========================== SICHERHEIT ========================== configure_security() { log "=== PHASE 8: SICHERHEITS-KONFIGURATION ===" progress "Konfiguriere Firewall..." ufw --force enable ufw default deny incoming ufw default allow outgoing ufw allow 22/tcp # SSH ufw allow 80/tcp # HTTP progress "Konfiguriere Fail2Ban..." cat > "/etc/fail2ban/jail.local" << EOF [DEFAULT] bantime = 600 findtime = 600 maxretry = 3 [sshd] enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 3 [nginx-http-auth] enabled = true filter = nginx-http-auth port = http,https logpath = /var/log/nginx/error.log maxretry = 5 EOF # Automatische Updates progress "Konfiguriere automatische Updates..." apt-get install -y unattended-upgrades echo 'Unattended-Upgrade::Automatic-Reboot "false";' > /etc/apt/apt.conf.d/50unattended-upgrades-local # Kiosk-Benutzer Einschränkungen progress "Beschränke Kiosk-Benutzer..." # Kein sudo für kiosk-Benutzer gpasswd -d "$KIOSK_USER" sudo 2>/dev/null || true # Shell auf /bin/false für bessere Sicherheit (aber X11 muss funktionieren) # usermod -s /bin/false "$KIOSK_USER" # Erstmal nicht, da X11 funktionieren muss log "✅ Sicherheit konfiguriert" } # ========================== WARTUNGSTOOLS ========================== create_maintenance_tools() { log "=== PHASE 9: WARTUNGSTOOLS ===" # Wartungsskript cat > "/usr/local/bin/myp-maintenance" << 'EOF' #!/bin/bash case "$1" in start) echo "Starte alle MYP-Services..." systemctl start myp-druckerverwaltung systemctl start nginx systemctl start myp-display systemctl start myp-kiosk-monitor echo "Services gestartet." ;; stop) echo "Stoppe alle MYP-Services..." systemctl stop myp-kiosk-monitor systemctl stop myp-display systemctl stop lightdm systemctl stop nginx systemctl stop myp-druckerverwaltung echo "Services gestoppt." ;; restart) echo "Starte alle MYP-Services neu..." systemctl restart myp-druckerverwaltung sleep 3 systemctl restart nginx systemctl restart myp-display systemctl restart myp-kiosk-monitor echo "Services neugestartet." ;; status) echo "=== MYP SYSTEM STATUS ===" echo echo "📱 Anwendung:" systemctl status myp-druckerverwaltung --no-pager -l echo echo "🌐 Nginx Proxy:" systemctl status nginx --no-pager -l echo echo "🖥️ Display Manager:" systemctl status lightdm --no-pager -l echo echo "🔍 Kiosk Monitor:" systemctl status myp-kiosk-monitor --no-pager -l echo echo "👤 Kiosk-Benutzer-Sessions:" who | grep kiosk || echo "Kein Kiosk-Benutzer angemeldet" echo echo "🌐 Anwendung erreichbar:" if curl -s http://localhost:5000 > /dev/null; then echo "✅ http://localhost:5000 erreichbar" else echo "❌ http://localhost:5000 NICHT erreichbar" fi ;; logs) echo "=== ANWENDUNGS-LOGS (Strg+C zum Beenden) ===" journalctl -u myp-druckerverwaltung -f ;; kiosk-logs) echo "=== KIOSK-LOGS (Strg+C zum Beenden) ===" echo "Monitor-Logs:" journalctl -u myp-kiosk-monitor -f & echo "LightDM-Logs:" journalctl -u lightdm -f & echo "Session-Logs:" tail -f /var/log/kiosk-session.log 2>/dev/null & wait ;; app-restart) echo "Starte nur Anwendung neu..." systemctl restart myp-druckerverwaltung echo "Anwendung neugestartet." ;; kiosk-restart) echo "Starte nur Kiosk-Display neu..." systemctl restart lightdm echo "Kiosk-Display neugestartet." ;; monitor-restart) echo "Starte Kiosk-Monitor neu..." systemctl restart myp-kiosk-monitor echo "Kiosk-Monitor neugestartet." ;; enable-ssh) echo "Aktiviere SSH für Wartung..." systemctl enable ssh systemctl start ssh echo "✅ SSH aktiviert für Remote-Wartung" echo "SSH-Status: $(systemctl is-active ssh)" echo "IP-Adresse: $(hostname -I | awk '{print $1}')" ;; disable-ssh) echo "Deaktiviere SSH für Sicherheit..." systemctl stop ssh systemctl disable ssh echo "✅ SSH deaktiviert" ;; exit-kiosk) echo "🔐 KIOSK-MODUS BEENDEN" echo "WARNUNG: Stoppt den Kiosk und aktiviert Wartungsmodus!" echo "Passwort erforderlich für Sicherheit." read -s -p "Kiosk-Passwort: " password echo if [ "$password" = "744563017196A" ]; then echo "✅ Passwort korrekt - beende Kiosk-Modus..." systemctl stop myp-kiosk-monitor systemctl stop lightdm systemctl enable ssh systemctl start ssh echo "🔧 Wartungsmodus aktiviert:" echo " • Kiosk gestoppt" echo " • SSH aktiviert" echo " • Console verfügbar" echo "Kiosk-Neustart mit: myp-maintenance start" else echo "❌ Falsches Passwort! Kiosk bleibt aktiv." exit 1 fi ;; enter-kiosk) echo "Aktiviere Kiosk-Modus..." systemctl disable ssh 2>/dev/null || true systemctl stop ssh 2>/dev/null || true systemctl start myp-druckerverwaltung systemctl start nginx systemctl start myp-display systemctl start myp-kiosk-monitor echo "✅ Kiosk-Modus aktiviert" ;; check-health) echo "=== SYSTEM-GESUNDHEITSCHECK ===" echo # Services-Check echo "📋 Service-Status:" for service in myp-druckerverwaltung nginx lightdm myp-kiosk-monitor; do if systemctl is-active --quiet $service; then echo " ✅ $service: aktiv" else echo " ❌ $service: INAKTIV" fi done # DNS-Service-Check if systemctl is-active --quiet unbound; then echo " ✅ unbound: aktiv" else echo " ❌ unbound: INAKTIV" fi echo # Netzwerk-Check echo "🌐 Netzwerk-Status:" if curl -s http://localhost:5000 > /dev/null; then echo " ✅ Anwendung erreichbar" else echo " ❌ Anwendung NICHT erreichbar" fi # DNS-Check if nslookup google.com 127.0.0.1 &> /dev/null; then echo " ✅ DNS-Auflösung funktional" else echo " ❌ DNS-Auflösung FEHLERHAFT" fi # IPv6-Check if [ "$(sysctl -n net.ipv6.conf.all.disable_ipv6)" = "1" ]; then echo " ✅ IPv6 deaktiviert (gewünscht)" else echo " ⚠️ IPv6 noch aktiv" fi echo # Kiosk-Check echo "🖥️ Kiosk-Status:" if pgrep -u kiosk > /dev/null; then echo " ✅ Kiosk-Benutzer angemeldet" else echo " ❌ Kiosk-Benutzer NICHT angemeldet" fi if pgrep -f "chromium.*kiosk" > /dev/null; then echo " ✅ Chromium-Kiosk läuft" else echo " ❌ Chromium-Kiosk läuft NICHT" fi echo # Ressourcen-Check echo "💾 System-Ressourcen:" echo " CPU: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)% belegt" echo " RAM: $(free | grep Mem | awk '{printf "%.1f%%", $3/$2 * 100.0}')" echo " Disk: $(df / | tail -1 | awk '{print $5}')" ;; auto-fix) echo "🔧 AUTOMATISCHE REPARATUR" echo "Versuche häufige Probleme zu beheben..." # Services neu starten echo "1. Starte Services neu..." systemctl restart myp-druckerverwaltung sleep 3 systemctl restart nginx systemctl restart lightdm systemctl restart myp-kiosk-monitor # DNS-Services reparieren echo "2. Repariere DNS-Services..." systemctl restart unbound systemctl restart dns-priority-config /usr/local/bin/configure-dns-priority # Berechtigungen reparieren echo "3. Repariere Berechtigungen..." chown -R kiosk:kiosk /home/kiosk chown -R myp:myp /opt/myp-druckerverwaltung # Logs bereinigen echo "4. Bereinige alte Logs..." journalctl --rotate journalctl --vacuum-time=7d echo "✅ Automatische Reparatur abgeschlossen" echo "Prüfe Status mit: myp-maintenance check-health" ;; dns-status) echo "=== DNS-KONFIGURATION STATUS ===" echo echo "🔍 Unbound Service:" systemctl status unbound --no-pager -l echo echo "📋 Aktuelle DNS-Server:" cat /etc/resolv.conf | grep nameserver echo echo "🌐 Router-DNS (erkannt):" /usr/local/bin/configure-dns-priority 2>/dev/null | grep "Erkannte Router-DNS" | tail -1 || echo "Keine Router-DNS erkannt" echo echo "📊 DNS-Statistiken:" if command -v unbound-control &> /dev/null; then unbound-control stats_noreset 2>/dev/null | head -10 || echo "Unbound-Control nicht verfügbar" fi echo echo "📝 Letzte DNS-Logs:" tail -10 /var/log/dns-configuration.log 2>/dev/null || echo "Keine DNS-Logs verfügbar" ;; dns-test) echo "=== DNS-AUFLÖSUNGSTEST ===" echo test_domains=("google.com" "github.com" "debian.org" "cloudflare.com") for domain in "${test_domains[@]}"; do echo -n "Testing $domain: " if nslookup "$domain" 127.0.0.1 &> /dev/null; then echo "✅ OK" else echo "❌ FEHLER" fi done echo echo "🔍 DNS-Gesundheitscheck:" /usr/local/bin/dns-health-check ;; dns-reconfigure) echo "=== DNS-KONFIGURATION NEU LADEN ===" echo "Lade DNS-Konfiguration mit Router-Erkennung neu..." /usr/local/bin/configure-dns-priority echo "✅ DNS-Konfiguration neu geladen" echo "Test mit: myp-maintenance dns-test" ;; ipv6-status) echo "=== IPv6-STATUS ===" echo echo "🔍 IPv6 Kernel-Parameter:" sysctl net.ipv6.conf.all.disable_ipv6 sysctl net.ipv6.conf.default.disable_ipv6 echo echo "🌐 IPv6-Adressen:" ip -6 addr show | grep inet6 || echo "Keine IPv6-Adressen (deaktiviert)" echo echo "📋 IPv6-Routen:" ip -6 route show 2>/dev/null || echo "Keine IPv6-Routen (deaktiviert)" ;; *) echo "MYP Druckerverwaltung - Wartungstool" echo echo "VERWENDUNG: $0 BEFEHL" echo echo "SERVICE-MANAGEMENT:" echo " start Alle Services starten" echo " stop Alle Services stoppen" echo " restart Alle Services neustarten" echo " status Detaillierter Status aller Services" echo echo "EINZELNE SERVICES:" echo " app-restart Nur Anwendung neustarten" echo " kiosk-restart Nur Kiosk-Display neustarten" echo " monitor-restart Nur Kiosk-Monitor neustarten" echo echo "LOGS & MONITORING:" echo " logs Live Anwendungs-Logs anzeigen" echo " kiosk-logs Live Kiosk-Logs anzeigen" echo " check-health System-Gesundheitscheck" echo echo "KIOSK-KONTROLLE:" echo " exit-kiosk Kiosk beenden (Passwort: 744563017196A)" echo " enter-kiosk Kiosk-Modus aktivieren" echo echo "DNS & NETZWERK:" echo " dns-status DNS-Konfiguration anzeigen" echo " dns-test DNS-Auflösung testen" echo " dns-reconfigure DNS-Konfiguration neu laden" echo " ipv6-status IPv6-Status prüfen" echo echo "WARTUNG:" echo " enable-ssh SSH für Remote-Wartung aktivieren" echo " disable-ssh SSH wieder deaktivieren" echo " auto-fix Automatische Problemreparatur" echo echo "BEISPIELE:" echo " $0 status # System-Status anzeigen" echo " $0 logs # Live-Logs verfolgen" echo " $0 exit-kiosk # Wartungsmodus aktivieren" ;; esac EOF chmod +x /usr/local/bin/myp-maintenance # Backup-Skript cat > "/usr/local/bin/myp-backup" << EOF #!/bin/bash BACKUP_DIR="$BACKUP_DIR" DATE=\$(date +%Y%m%d_%H%M%S) mkdir -p "\$BACKUP_DIR" echo "Erstelle MYP-System-Backup..." # Services kurz stoppen für konsistentes Backup systemctl stop myp-druckerverwaltung # Erstelle Backup tar -czf "\$BACKUP_DIR/myp_backup_\$DATE.tar.gz" \\ -C "$APP_DIR" \\ --exclude='node_modules' \\ --exclude='__pycache__' \\ --exclude='venv' \\ --exclude='*.log' \\ database.db .env uploads/ config/ 2>/dev/null || true # Backup der Kiosk-Konfiguration tar -czf "\$BACKUP_DIR/kiosk_config_\$DATE.tar.gz" \\ /home/kiosk/.config \\ /etc/lightdm/lightdm.conf \\ /usr/share/lightdm/setup-kiosk-session.sh \\ /etc/systemd/system/myp-*.service \\ /usr/local/bin/myp-* 2>/dev/null || true # Services wieder starten systemctl start myp-druckerverwaltung echo "✅ Backup erstellt:" echo " Anwendung: \$BACKUP_DIR/myp_backup_\$DATE.tar.gz" echo " Kiosk-Config: \$BACKUP_DIR/kiosk_config_\$DATE.tar.gz" # Alte Backups löschen (älter als 30 Tage) find "\$BACKUP_DIR" -name "myp_backup_*.tar.gz" -mtime +30 -delete 2>/dev/null || true find "\$BACKUP_DIR" -name "kiosk_config_*.tar.gz" -mtime +30 -delete 2>/dev/null || true echo "🧹 Alte Backups (>30 Tage) entfernt" EOF chmod +x /usr/local/bin/myp-backup # Notfall-Reset cat > "/usr/local/bin/myp-emergency-reset" << 'EOF' #!/bin/bash echo "🚨 NOTFALL-RESET für MYP Kiosk-System" echo "======================================" echo echo "WARNUNG: Dieser Befehl wird:" echo " • Alle Kiosk-Services stoppen" echo " • SSH für Remote-Wartung aktivieren" echo " • Console-Zugang ermöglichen" echo " • System in Wartungsmodus versetzen" echo echo "Nur bei kritischen Problemen verwenden!" echo read -p "Notfall-Reset durchführen? (RESET eingeben): " confirm if [ "$confirm" = "RESET" ]; then echo echo "🔧 Führe Notfall-Reset durch..." # Stoppe alle Kiosk-Services systemctl stop myp-kiosk-monitor 2>/dev/null || true systemctl stop lightdm 2>/dev/null || true # Aktiviere SSH systemctl enable ssh 2>/dev/null || true systemctl start ssh 2>/dev/null || true # Logge Reset echo "$(date): Notfall-Reset durchgeführt" >> /var/log/emergency-reset.log echo "✅ Notfall-Reset abgeschlossen!" echo echo "📋 AKTUELLE SITUATION:" echo " • Kiosk-Modus: GESTOPPT" echo " • SSH: AKTIVIERT für Remote-Wartung" echo " • Console: Verfügbar auf TTY1-6 (Strg+Alt+F1-F6)" echo " • IP-Adresse: $(hostname -I | awk '{print $1}')" echo echo "🔧 WARTUNGSOPTIONEN:" echo " • Status prüfen: myp-maintenance status" echo " • Gesundheitscheck: myp-maintenance check-health" echo " • Automatische Fix: myp-maintenance auto-fix" echo " • Kiosk reaktivieren: myp-maintenance enter-kiosk" echo else echo "❌ Abgebrochen. System bleibt unverändert." fi EOF chmod +x /usr/local/bin/myp-emergency-reset # Erweiterte Cron-Jobs cat > "/etc/cron.d/myp-system" << EOF # MYP System Maintenance Cron Jobs # Tägliches Backup um 2:00 Uhr 0 2 * * * root /usr/local/bin/myp-backup >> /var/log/myp-backup.log 2>&1 # Gesundheitscheck alle 10 Minuten */10 * * * * root /usr/local/bin/myp-maintenance check-health > /dev/null 2>&1 || echo "\$(date): Health check failed" >> /var/log/myp-health.log # Log-Rotation wöchentlich (Sonntags um 3:00) 0 3 * * 0 root journalctl --rotate && journalctl --vacuum-time=30d # System-Ressourcen-Log alle 5 Minuten */5 * * * * root echo "\$(date),\$(cat /proc/loadavg | cut -d' ' -f1-3),\$(free | grep Mem | awk '{printf \"%.1f\", \$3/\$2 * 100.0}')" >> /var/log/system-resources.log EOF log "✅ Erweiterte Wartungstools erstellt" } # ========================== FINALE KONFIGURATION ========================== finalize_installation() { log "=== PHASE 10: FINALISIERUNG ===" # Services starten progress "Starte Services..." systemctl start myp-druckerverwaltung sleep 3 systemctl start nginx # Warte und prüfe Services sleep 5 if systemctl is-active --quiet myp-druckerverwaltung; then log "✅ MYP-Anwendung läuft" else warning "⚠️ MYP-Anwendung nicht aktiv" fi if systemctl is-active --quiet nginx; then log "✅ Nginx läuft" else warning "⚠️ Nginx nicht aktiv" fi # Test ob Anwendung erreichbar ist progress "Teste Anwendung..." for i in {1..30}; do if curl -s http://localhost:5000 > /dev/null; then log "✅ Anwendung erreichbar unter http://localhost:5000" break else if [ $i -eq 30 ]; then warning "⚠️ Anwendung nach 30 Versuchen nicht erreichbar" else sleep 2 fi fi done # Chromium-Test progress "Teste Chromium-Installation..." if [[ "$CHROMIUM_BIN" == "flatpak"* ]]; then sudo -u "$KIOSK_USER" flatpak run org.chromium.Chromium --version > /dev/null 2>&1 && log "✅ Chromium (Flatpak) funktional" || warning "⚠️ Chromium (Flatpak) Test fehlgeschlagen" else sudo -u "$KIOSK_USER" "$CHROMIUM_BIN" --version > /dev/null 2>&1 && log "✅ Chromium funktional" || warning "⚠️ Chromium-Test fehlgeschlagen" fi # Teste Auto-Login-Konfiguration progress "Teste Auto-Login-Konfiguration..." if [ -f "/etc/lightdm/lightdm.conf" ] && grep -q "autologin-user=$KIOSK_USER" "/etc/lightdm/lightdm.conf"; then log "✅ Auto-Login für $KIOSK_USER konfiguriert" else warning "⚠️ Auto-Login-Konfiguration unvollständig" fi # Teste Systemd-Services progress "Teste Service-Konfiguration..." for service in myp-druckerverwaltung myp-display myp-kiosk-monitor; do if systemctl is-enabled --quiet "$service" 2>/dev/null; then log "✅ Service $service aktiviert" else warning "⚠️ Service $service nicht aktiviert" fi done # Teste Wartungstools progress "Teste Wartungstools..." if [ -x "/usr/local/bin/myp-maintenance" ]; then log "✅ myp-maintenance verfügbar" else warning "⚠️ myp-maintenance nicht verfügbar" fi if [ -x "/usr/local/bin/myp-backup" ]; then log "✅ myp-backup verfügbar" else warning "⚠️ myp-backup nicht verfügbar" fi if [ -x "/usr/local/bin/myp-emergency-reset" ]; then log "✅ myp-emergency-reset verfügbar" else warning "⚠️ myp-emergency-reset nicht verfügbar" fi # Erstelle erste Logs progress "Initialisiere Logging..." touch /var/log/kiosk-session.log touch /var/log/kiosk-monitor.log touch /var/log/kiosk-watchdog.log touch /var/log/emergency-reset.log touch /var/log/myp-backup.log touch /var/log/myp-health.log touch /var/log/system-resources.log # Setze einfache root:root Berechtigungen für alle Log-Dateien (maximale Kompatibilität) progress "Setze Log-Dateiberechtigungen..." chown root:root /var/log/kiosk-session.log 2>/dev/null || true chown root:root /var/log/kiosk-monitor.log 2>/dev/null || true chown root:root /var/log/kiosk-watchdog.log 2>/dev/null || true chown root:root /var/log/emergency-reset.log 2>/dev/null || true chown root:root /var/log/myp-backup.log 2>/dev/null || true chown root:root /var/log/myp-health.log 2>/dev/null || true chown root:root /var/log/system-resources.log 2>/dev/null || true # Setze Lese-/Schreibberechtigungen chmod 644 /var/log/kiosk-session.log 2>/dev/null || true chmod 644 /var/log/kiosk-monitor.log 2>/dev/null || true chmod 644 /var/log/kiosk-watchdog.log 2>/dev/null || true chmod 644 /var/log/emergency-reset.log 2>/dev/null || true chmod 644 /var/log/myp-backup.log 2>/dev/null || true chmod 644 /var/log/myp-health.log 2>/dev/null || true chmod 644 /var/log/system-resources.log 2>/dev/null || true # Log-Dateiberechtigungen sind bereits korrekt gesetzt (root:root) info "Log-Dateiberechtigungen erfolgreich konfiguriert" # Finale Berechtigungen chown -R "$APP_USER:$APP_USER" "$APP_DIR" chown -R "$KIOSK_USER:$KIOSK_USER" "/home/$KIOSK_USER" # System-Target finalisieren systemctl set-default graphical.target log "✅ Installation finalisiert" } # ========================== INSTALLATIONS-BERICHT ========================== show_installation_report() { local ip_address=$(hostname -I | awk '{print $1}') cat << EOF ╔══════════════════════════════════════════════════════════════╗ ║ 🎉 KIOSK-INSTALLATION ERFOLGREICH! 🎉 ║ ╚══════════════════════════════════════════════════════════════╝ 📋 INSTALLATIONS-ZUSAMMENFASSUNG: • System-Typ: Vollautomatischer Sicherheits-Kiosk • Anwendung: $APP_DIR • Kiosk-URL: http://$ip_address (nach Neustart) • Chromium: $CHROMIUM_BIN • Display Manager: LightDM mit Auto-Login • Kiosk-Benutzer: $KIOSK_USER (automatisch angemeldet) • App-Benutzer: $APP_USER 🛡️ SICHERHEITS-FEATURES: • Desktop-Flucht: Vollständig verhindert • Tastatur-Shortcuts: Alle deaktiviert • Browser-Escape: Unmöglich (Kiosk-Flags) • SSH: Standardmäßig deaktiviert • Firewall: Aktiv mit Fail2Ban-Schutz • Auto-Login: Sicher konfiguriert • Session-Isolation: Kiosk-Benutzer ohne sudo • IPv6: Systemweit deaktiviert • DNS: Lokaler Unbound-Resolver mit Router-Priorität 🔧 AUTOSTART-ABSICHERUNG (7-fach): ✅ 1. LightDM Auto-Login ✅ 2. Systemd User-Service ✅ 3. Bashrc Autostart ✅ 4. Profile Autostart ✅ 5. XDG Desktop Autostart ✅ 6. Cron Watchdog ✅ 7. RC.Local Fallback 🚀 SYSTEMD-SERVICES: • myp-druckerverwaltung.service → Flask-Anwendung • myp-display.service → LightDM-Management • myp-kiosk-monitor.service → Kiosk-Überwachung + Recovery • nginx.service → Reverse-Proxy • lightdm.service → Display Manager mit Auto-Login • unbound.service → Lokaler DNS-Resolver • dns-priority-config.service → Intelligente DNS-Konfiguration 🌐 DNS & NETZWERK-FEATURES: ✅ Router-DNS automatisch erkannt und priorisiert ✅ Fallback-DNS: Google → Cloudflare → Custom ✅ IPv6 systemweit deaktiviert ✅ DHCP-DNS-Überschreibung verhindert ✅ Unbound lokaler Resolver mit DNSSEC ✅ Automatische DNS-Updates alle 30 Min ✅ DNS-Gesundheitscheck alle 10 Min ✅ Intelligente Router-Erkennung (4 Methoden) 🔧 WARTUNGSTOOLS: 📱 myp-maintenance: • status - Detaillierter System-Status • restart - Alle Services neustarten • exit-kiosk - Wartungsmodus (Passwort: 744563017196A) • enable-ssh - SSH für Remote-Wartung • check-health - Automatischer Gesundheitscheck • auto-fix - Automatische Problemreparatur • dns-status - DNS-Konfiguration anzeigen • dns-test - DNS-Auflösung testen • dns-reconfigure - DNS-Konfiguration neu laden • ipv6-status - IPv6-Status prüfen 💾 myp-backup: • Automatisch: Täglich 2:00 Uhr • Manuell: myp-backup • Aufbewahrung: 30 Tage 🚨 myp-emergency-reset: • Notfall-Tool bei kritischen Problemen • Stoppt Kiosk, aktiviert SSH 📊 MONITORING & LOGS: • System-Health: Alle 10 Minuten automatisch • Resource-Logs: Alle 5 Minuten • Service-Überwachung: Kontinuierlich mit Auto-Recovery • Log-Rotation: Wöchentlich (30 Tage Aufbewahrung) ⚠️ WICHTIGE HINWEISE: • System bootet automatisch in VOLLBILD-KIOSK ohne Escape • Kein Desktop verfügbar - nur MYP-Anwendung sichtbar • SSH deaktiviert für maximale Sicherheit • Bei Problemen: Console-Zugang via Strg+Alt+F1-F6 🔐 NOTFALL-ZUGANG: 1. Console: Strg+Alt+F1 bis F6 → Login als Root/sudo-User 2. Emergency: myp-emergency-reset → RESET eingeben 3. Remote: myp-maintenance enable-ssh → SSH verfügbar 🚀 NÄCHSTE SCHRITTE: 1. System neustarten: sudo reboot 2. ⏱️ System bootet in ~2 Minuten automatisch in Kiosk-Modus 3. 🖥️ Chromium startet automatisch im Vollbild 4. 📱 MYP-Anwendung verfügbar unter http://$ip_address 5. 🔒 Kein Escape möglich - echtes Kiosk-System 📞 WARTUNG & SUPPORT: • Live Status: myp-maintenance status • Logs verfolgen: myp-maintenance logs • Kiosk beenden: myp-maintenance exit-kiosk • Gesundheitscheck: myp-maintenance check-health • Backup erstellen: myp-backup 🎯 LEISTUNGS-FEATURES: ✅ Multi-Browser-Fallback (APT → Snap → Flatpak) ✅ Service-Recovery bei Fehlern ✅ Session-Monitoring mit Auto-Restart ✅ Resource-Monitoring und Logging ✅ Automatische Backups mit Rotation ✅ Health-Checks mit Auto-Fix ✅ Emergency-Recovery-System ══════════════════════════════════════════════════════════════ Installation abgeschlossen: $(date) Installationslog: $INSTALL_LOG SYSTEM BEREIT FÜR PRODUKTIONS-KIOSK-BETRIEB! 🚀 ══════════════════════════════════════════════════════════════ EOF } # ========================== KEYMAP-PROBLEM BEHEBEN ========================== fix_keymap_issues() { log "=== PHASE 0.3: KEYMAP-PROBLEME BEHEBEN ===" progress "Behebe bekannte Keymap-Probleme..." # Installiere alle keyboard-bezogenen Pakete progress "Installiere vollständige Keyboard-Unterstützung..." apt-get install -y \ keyboard-configuration \ console-setup \ console-data \ kbd \ console-common \ xkb-data \ locales \ 2>/dev/null || warning "Einige Keyboard-Pakete konnten nicht installiert werden" # Generiere Locales falls noch nicht vorhanden progress "Generiere deutsche Locales..." if [ -f "/etc/locale.gen" ]; then sed -i 's/# de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/' /etc/locale.gen sed -i 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen locale-gen 2>/dev/null || warning "Locale-Generierung teilweise fehlgeschlagen" update-locale LANG=de_DE.UTF-8 2>/dev/null || true fi # Prüfe und repariere Keymap-Verzeichnisse progress "Prüfe Keymap-Verzeichnisse..." # Erstelle Keymap-Verzeichnisse falls sie fehlen mkdir -p /usr/share/keymaps/i386/qwertz 2>/dev/null || true mkdir -p /usr/share/kbd/keymaps/i386/qwertz 2>/dev/null || true mkdir -p /lib/kbd/keymaps/i386/qwertz 2>/dev/null || true # Prüfe ob deutsche Keymap verfügbar ist KEYMAP_FOUND=false for keymap_path in \ "/usr/share/keymaps/i386/qwertz/de.kmap.gz" \ "/usr/share/kbd/keymaps/i386/qwertz/de.map.gz" \ "/lib/kbd/keymaps/i386/qwertz/de.map.gz" \ "/usr/share/keymaps/i386/qwertz/de-latin1.kmap.gz" \ "/usr/share/kbd/keymaps/i386/qwertz/de-latin1.map.gz"; do if [ -f "$keymap_path" ]; then KEYMAP_FOUND=true info "Deutsche Keymap gefunden: $keymap_path" break fi done if [ "$KEYMAP_FOUND" = false ]; then warning "Keine deutsche Keymap gefunden - versuche Reparatur..." # Versuche console-data zu rekonfigurieren if dpkg -l | grep -q console-data; then dpkg-reconfigure -f noninteractive console-data 2>/dev/null || true fi # Versuche kbd zu rekonfigurieren if dpkg -l | grep -q "^ii.*kbd"; then dpkg-reconfigure -f noninteractive kbd 2>/dev/null || true fi # Fallback: Erstelle minimale deutsche Keymap if [ ! -f "/usr/share/keymaps/i386/qwertz/de.kmap.gz" ]; then warning "Erstelle Fallback-Keymap..." mkdir -p /usr/share/keymaps/i386/qwertz # Erstelle einfache deutsche Keymap cat > /tmp/de.kmap << 'EOF' # German keyboard layout keymaps 0-15 keycode 1 = Escape keycode 2 = one exclam keycode 3 = two quotedbl keycode 4 = three section keycode 5 = four dollar keycode 6 = five percent keycode 7 = six ampersand keycode 8 = seven slash keycode 9 = eight parenleft keycode 10 = nine parenright keycode 11 = zero equal keycode 12 = ssharp question keycode 13 = dead_acute dead_grave keycode 14 = BackSpace keycode 15 = Tab keycode 16 = q Q keycode 17 = w W keycode 18 = e E keycode 19 = r R keycode 20 = t T keycode 21 = z Z keycode 22 = u U keycode 23 = i I keycode 24 = o O keycode 25 = p P keycode 26 = udiaeresis Udiaeresis keycode 27 = plus asterisk keycode 28 = Return keycode 29 = Control keycode 30 = a A keycode 31 = s S keycode 32 = d D keycode 33 = f F keycode 34 = g G keycode 35 = h H keycode 36 = j J keycode 37 = k K keycode 38 = l L keycode 39 = odiaeresis Odiaeresis keycode 40 = adiaeresis Adiaeresis keycode 41 = dead_circumflex degree keycode 42 = Shift keycode 43 = numbersign apostrophe keycode 44 = y Y keycode 45 = x X keycode 46 = c C keycode 47 = v V keycode 48 = b B keycode 49 = n N keycode 50 = m M keycode 51 = comma semicolon keycode 52 = period colon keycode 53 = minus underscore keycode 54 = Shift keycode 57 = space EOF gzip /tmp/de.kmap mv /tmp/de.kmap.gz /usr/share/keymaps/i386/qwertz/de.kmap.gz 2>/dev/null || true info "Fallback deutsche Keymap erstellt" fi fi # Teste Keymap-Funktionalität progress "Teste Keymap-Funktionalität..." if command -v loadkeys &> /dev/null; then if loadkeys de 2>/dev/null; then info "✅ Deutsche Keymap erfolgreich geladen" else warning "⚠️ Deutsche Keymap konnte nicht geladen werden" # Versuche alternative Keymaps for alt_keymap in de-latin1 de_DE german; do if loadkeys "$alt_keymap" 2>/dev/null; then info "✅ Alternative Keymap '$alt_keymap' geladen" break fi done fi fi # Repariere localectl falls verfügbar if command -v localectl &> /dev/null; then progress "Repariere localectl-Konfiguration..." # Erstelle systemd-localed Verzeichnis falls es fehlt mkdir -p /etc/systemd/system/systemd-localed.service.d 2>/dev/null || true # Versuche localectl zu reparieren if ! localectl status &> /dev/null; then warning "localectl nicht funktional - versuche Reparatur..." # Starte systemd-localed Service systemctl start systemd-localed 2>/dev/null || true systemctl enable systemd-localed 2>/dev/null || true # Warte kurz und versuche erneut sleep 2 if localectl status &> /dev/null; then info "✅ localectl repariert" localectl set-keymap de 2>/dev/null || true localectl set-x11-keymap de 2>/dev/null || true else warning "localectl bleibt nicht funktional - verwende alternative Methoden" fi else info "✅ localectl funktional" fi fi # Erstelle vconsole.conf für systemd-Systeme progress "Konfiguriere vconsole.conf..." cat > /etc/vconsole.conf << EOF KEYMAP=de FONT=eurlatgr EOF # Aktualisiere initramfs mit neuen Keymap-Einstellungen if command -v update-initramfs &> /dev/null; then progress "Aktualisiere initramfs..." update-initramfs -u 2>/dev/null || warning "initramfs-Update fehlgeschlagen" fi log "✅ Keymap-Probleme behoben" } # ========================== HAUPTPROGRAMM ========================== main() { log "🚀 MYP Kiosk-Installation gestartet: $(date)" check_root detect_system setup_system_basics fix_keymap_issues update_system install_certificates create_directory_structure cleanup_system install_packages install_chromium create_users install_application set_file_permissions configure_kiosk optimize_raspberry_pi configure_dns_and_network configure_autologin configure_multiple_autostart configure_autostart configure_security create_maintenance_tools finalize_installation show_installation_report # Abschließende Frage echo read -p "🔄 System jetzt neustarten für Kiosk-Modus? (j/N): " reboot_choice if [[ "$reboot_choice" =~ ^[jJ]$ ]]; then log "🚀 Neustart für Kiosk-Modus..." sleep 3 reboot else log "⚠️ Manueller Neustart erforderlich: sudo reboot" fi } # ========================== PROGRAMMSTART ========================== # Starte Installation main "$@" chmod +x /usr/local/bin/dns-health-check