[Unit] Description=MYP Kiosk Watchdog Service - Intelligente Überwachung für HTTPS Backend und Kiosk-Browser Documentation=https://github.com/MYP-Druckerverwaltung After=multi-user.target myp-https.service Wants=myp-https.service [Service] Type=simple User=root Restart=always RestartSec=30 TimeoutStartSec=60 TimeoutStopSec=30 # Intelligentes Watchdog-Skript mit modularer Struktur ExecStart=/bin/bash -c '\ # === KONFIGURATION === \ readonly HTTPS_SERVICE="myp-https" \ readonly KIOSK_SERVICE="myp-kiosk" \ readonly KIOSK_USER="kiosk" \ readonly HTTPS_URL="https://localhost:443" \ readonly APP_DIR="/opt/myp" \ readonly LOG_FILE="/var/log/kiosk-watchdog.log" \ readonly CHECK_INTERVAL=30 \ readonly HTTPS_TIMEOUT=10 \ readonly RESTART_DELAY=15 \ readonly MAX_MEMORY_PERCENT=85 \ readonly CERT_EXPIRE_DAYS=7 \ \ # === LOGGING-FUNKTIONEN === \ log_info() { echo "$(date "+%Y-%m-%d %H:%M:%S") [INFO] $1" >> "$LOG_FILE"; } \ log_warn() { echo "$(date "+%Y-%m-%d %H:%M:%S") [WARN] $1" >> "$LOG_FILE"; } \ log_error() { echo "$(date "+%Y-%m-%d %H:%M:%S") [ERROR] $1" >> "$LOG_FILE"; } \ \ # === HILFSFUNKTIONEN === \ is_service_active() { systemctl is-active --quiet "$1"; } \ is_service_enabled() { systemctl is-enabled --quiet "$1"; } \ restart_service() { \ log_info "Starte Service neu: $1"; \ systemctl restart "$1" && sleep "$RESTART_DELAY" || log_error "Service-Neustart fehlgeschlagen: $1"; \ } \ \ check_https_connectivity() { \ curl -k -s --connect-timeout "$HTTPS_TIMEOUT" --max-time "$HTTPS_TIMEOUT" "$HTTPS_URL" >/dev/null 2>&1; \ } \ \ check_ssl_certificate() { \ local cert_file="$APP_DIR/certs/localhost/localhost.crt" \ [ -f "$cert_file" ] && openssl x509 -in "$cert_file" -noout -checkend $((86400 * CERT_EXPIRE_DAYS)) >/dev/null 2>&1; \ } \ \ regenerate_ssl_certificate() { \ log_warn "Regeneriere SSL-Zertifikat..."; \ if python3 -c "import sys; sys.path.insert(0, \"$APP_DIR\"); from utils.ssl_config import ensure_ssl_certificates; ensure_ssl_certificates(\"$APP_DIR\", True)" 2>/dev/null; then \ log_info "SSL-Zertifikat erfolgreich regeneriert"; \ restart_service "$HTTPS_SERVICE"; \ else \ log_error "SSL-Zertifikat-Regenerierung fehlgeschlagen"; \ fi \ } \ \ check_kiosk_user_session() { \ pgrep -u "$KIOSK_USER" >/dev/null 2>&1; \ } \ \ check_chromium_process() { \ pgrep -u "$KIOSK_USER" -f "chromium.*kiosk" >/dev/null 2>&1; \ } \ \ check_x_server() { \ pgrep -f "X.*:0" >/dev/null 2>&1; \ } \ \ check_display_availability() { \ [ -n "$(DISPLAY=:0 xdpyinfo 2>/dev/null)" ]; \ } \ \ get_memory_usage() { \ free | awk "/^Mem:/ {printf \"%.1f\", \$3/\$2 * 100.0}"; \ } \ \ cleanup_system_resources() { \ log_info "Bereinige Systemressourcen (Speichernutzung: $(get_memory_usage)%)"; \ \ # Browser-Cache bereinigen \ rm -rf "/home/$KIOSK_USER/.chromium-kiosk/Default/Cache"/* 2>/dev/null || true; \ rm -rf "/home/$KIOSK_USER/.cache"/* 2>/dev/null || true; \ \ # Temporäre Dateien bereinigen \ find "/tmp" -type f -atime +1 -delete 2>/dev/null || true; \ find "$APP_DIR/uploads/temp" -type f -mtime +1 -delete 2>/dev/null || true; \ \ # System-Cache leeren \ sync; \ echo 3 > /proc/sys/vm/drop_caches 2>/dev/null || true; \ \ log_info "Systemressourcen bereinigt - neue Speichernutzung: $(get_memory_usage)%"; \ } \ \ restart_kiosk_session() { \ log_warn "Starte Kiosk-Session neu..."; \ \ # Beende alle Kiosk-Prozesse sanft \ pkill -u "$KIOSK_USER" -TERM 2>/dev/null || true; \ sleep 5; \ \ # Erzwinge Beendigung falls nötig \ pkill -u "$KIOSK_USER" -KILL 2>/dev/null || true; \ sleep 2; \ \ # Starte Getty-Service neu für Autologin \ systemctl restart getty@tty1.service; \ sleep "$RESTART_DELAY"; \ \ log_info "Kiosk-Session neugestartet"; \ } \ \ # === HAUPTÜBERWACHUNGSSCHLEIFE === \ log_info "Kiosk-Watchdog gestartet (PID: $$)"; \ \ while true; do \ # === HTTPS BACKEND ÜBERWACHUNG === \ if ! is_service_active "$HTTPS_SERVICE"; then \ log_error "HTTPS-Service nicht aktiv"; \ restart_service "$HTTPS_SERVICE"; \ elif ! check_https_connectivity; then \ log_error "HTTPS Backend nicht erreichbar"; \ restart_service "$HTTPS_SERVICE"; \ fi; \ \ # === SSL-ZERTIFIKAT ÜBERWACHUNG === \ if ! check_ssl_certificate; then \ if [ -f "$APP_DIR/certs/localhost/localhost.crt" ]; then \ log_warn "SSL-Zertifikat läuft in $CERT_EXPIRE_DAYS Tagen ab"; \ else \ log_error "SSL-Zertifikat fehlt"; \ fi; \ regenerate_ssl_certificate; \ fi; \ \ # === KIOSK-SESSION ÜBERWACHUNG === \ if ! check_kiosk_user_session; then \ log_error "Kiosk-Benutzer-Session nicht aktiv"; \ restart_kiosk_session; \ elif ! check_x_server; then \ log_error "X-Server nicht verfügbar"; \ restart_kiosk_session; \ elif ! check_display_availability; then \ log_error "Display :0 nicht verfügbar"; \ restart_kiosk_session; \ elif ! check_chromium_process; then \ log_warn "Chromium-Kiosk-Prozess nicht gefunden"; \ if is_service_enabled "$KIOSK_SERVICE"; then \ systemctl --user start "$KIOSK_SERVICE" 2>/dev/null || true; \ else \ sudo -u "$KIOSK_USER" DISPLAY=:0 chromium --kiosk --no-sandbox --ignore-certificate-errors "$HTTPS_URL" >/dev/null 2>&1 & \ fi; \ sleep "$RESTART_DELAY"; \ fi; \ \ # === SYSTEMRESSOURCEN ÜBERWACHUNG === \ memory_usage=$(get_memory_usage); \ if (( $(echo "$memory_usage > $MAX_MEMORY_PERCENT" | bc -l 2>/dev/null || echo 0) )); then \ log_warn "Hohe Speichernutzung: ${memory_usage}%"; \ cleanup_system_resources; \ fi; \ \ # === LOG-ROTATION === \ if [ -f "$LOG_FILE" ] && [ $(stat -c%s "$LOG_FILE" 2>/dev/null || echo 0) -gt 10485760 ]; then \ tail -n 1000 "$LOG_FILE" > "${LOG_FILE}.tmp" && mv "${LOG_FILE}.tmp" "$LOG_FILE"; \ log_info "Log-Datei rotiert (>10MB)"; \ fi; \ \ # Warte bis zur nächsten Prüfung \ sleep "$CHECK_INTERVAL"; \ done' # Umgebungsvariablen für optimierte Überwachung Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin Environment=DISPLAY=:0 Environment=PYTHONPATH=/opt/myp Environment=SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt Environment=LC_ALL=C.UTF-8 Environment=LANG=C.UTF-8 # Logging-Konfiguration StandardOutput=append:/var/log/kiosk-watchdog.log StandardError=append:/var/log/kiosk-watchdog.log # Sicherheitseinstellungen NoNewPrivileges=false PrivateTmp=false ProtectSystem=strict ReadWritePaths=/var/log ReadWritePaths=/opt/myp ReadWritePaths=/home/kiosk ReadWritePaths=/proc/sys/vm ReadWritePaths=/tmp # Resource-Limits MemoryMax=256M CPUQuota=25% [Install] WantedBy=multi-user.target