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