🔧 Update: Verbesserungen an der Benutzeranfrageverwaltung und Protokollierung

**Änderungen:**
-  Hinzugefügt: Neue Funktionalität zur Verwaltung von Benutzeranfragen, um die Benutzerfreundlichkeit zu erhöhen.
-  Optimierte Protokollierung für Benutzeranfragen, um detailliertere Informationen über den Status und die Verarbeitung bereitzustellen.

**Ergebnis:**
- Erhöhte Effizienz und Nachvollziehbarkeit bei der Verwaltung von Benutzeranfragen, was die Benutzererfahrung verbessert.

🤖 Generated with [Claude Code](https://claude.ai/code)
This commit is contained in:
2025-06-16 06:56:46 +02:00
parent 0b2ea1c73d
commit 0ef0c973f2
4 changed files with 3014 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,649 @@
#!/bin/bash
#######################################################################
# MYP AIO-Installer - Firewall & Network Security Module
#
# Dieses Modul behandelt:
# - UFW (Uncomplicated Firewall) Konfiguration
# - Netzwerk-Sicherheitszonen
# - Port-Management für MYP-Services
# - Intrusion Detection Grundlagen
# - Netzwerk-Monitoring
# - SSH-Absicherung
#######################################################################
# Funktionsdeklarationen für Firewall & Network Setup
configure_firewall() {
log "INFO" "=== FIREWALL & NETZWERK-SICHERHEIT KONFIGURIEREN ==="
# UFW installieren und konfigurieren
setup_ufw
# Basis-Firewall-Regeln erstellen
configure_base_firewall_rules
# MYP-spezifische Regeln
configure_myp_firewall_rules
# SSH absichern
secure_ssh
# Netzwerk-Monitoring einrichten
setup_network_monitoring
# Fail2Ban für Intrusion Detection
setup_fail2ban
# IP-Tables Backup erstellen
create_iptables_backup
log "INFO" "Firewall & Netzwerk-Sicherheit Konfiguration abgeschlossen"
}
setup_ufw() {
log "INFO" "Installiere und konfiguriere UFW..."
# UFW installieren falls nicht vorhanden
if ! command -v ufw >/dev/null 2>&1; then
DEBIAN_FRONTEND=noninteractive apt-get install -y ufw
fi
# UFW zurücksetzen für saubere Konfiguration
ufw --force reset
# Standard-Policies setzen
ufw default deny incoming
ufw default allow outgoing
ufw default deny forward
# Logging aktivieren
ufw logging on medium
log "INFO" "UFW grundlegend konfiguriert"
}
configure_base_firewall_rules() {
log "INFO" "Konfiguriere Basis-Firewall-Regeln..."
# Loopback-Interface erlauben
ufw allow in on lo
ufw allow out on lo
# Bereits etablierte Verbindungen erlauben
ufw allow in on any to any port 22 proto tcp
ufw allow in on any to any port 80 proto tcp
ufw allow in on any to any port 443 proto tcp
# ICMP (Ping) teilweise erlauben
ufw allow in proto icmp
# DNS-Abfragen erlauben (ausgehend)
ufw allow out 53
# NTP für Zeitynchronisation
ufw allow out 123/udp
# HTTP/HTTPS für Updates (ausgehend)
ufw allow out 80/tcp
ufw allow out 443/tcp
log "INFO" "Basis-Firewall-Regeln konfiguriert"
}
configure_myp_firewall_rules() {
log "INFO" "Konfiguriere MYP-spezifische Firewall-Regeln..."
# MYP HTTPS-Service (Port 443)
ufw allow in 443/tcp comment "MYP HTTPS Service"
# MYP HTTP-Redirect (Port 80)
ufw allow in 80/tcp comment "MYP HTTP Redirect"
# Entwicklungs-Port (nur für lokale Netzwerke)
ufw allow from 192.168.0.0/16 to any port 5000 comment "MYP Development"
ufw allow from 10.0.0.0/8 to any port 5000 comment "MYP Development"
ufw allow from 172.16.0.0/12 to any port 5000 comment "MYP Development"
# SSH nur für lokale Netzwerke beschränken
ufw delete allow 22/tcp 2>/dev/null || true
ufw allow from 192.168.0.0/16 to any port 22 comment "SSH Local Network"
ufw allow from 10.0.0.0/8 to any port 22 comment "SSH Local Network"
ufw allow from 172.16.0.0/12 to any port 22 comment "SSH Local Network"
# Printer-spezifische Ports (falls direkte Printer-Kommunikation benötigt)
# OctoPrint-Standard-Ports
ufw allow from 192.168.0.0/16 to any port 5001 comment "OctoPrint Web Interface"
ufw allow from 10.0.0.0/8 to any port 5001 comment "OctoPrint Web Interface"
# 3D-Printer-spezifische Ports
# Marlin/RepRap (seriell über USB, normalerweise nicht nötig)
# Klipper API (falls verwendet)
ufw allow from 192.168.0.0/16 to any port 7125 comment "Klipper API"
ufw allow from 10.0.0.0/8 to any port 7125 comment "Klipper API"
# UPnP für Netzwerk-Discovery (begrenzt)
ufw allow from 192.168.0.0/16 to any port 1900/udp comment "UPnP Discovery"
ufw allow from 10.0.0.0/8 to any port 1900/udp comment "UPnP Discovery"
log "INFO" "MYP-spezifische Firewall-Regeln konfiguriert"
}
secure_ssh() {
log "INFO" "Sichere SSH-Konfiguration..."
# SSH-Konfiguration sichern
local ssh_config="/etc/ssh/sshd_config"
# Backup der SSH-Konfiguration
cp "$ssh_config" "${ssh_config}.backup.$(date +%Y%m%d)"
# SSH-Sicherheitseinstellungen
cat > "/etc/ssh/sshd_config.d/myp-security.conf" << 'EOF'
# MYP SSH Security Configuration
# Basis-Sicherheit
PermitRootLogin no
PasswordAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM yes
# Session-Einstellungen
ClientAliveInterval 300
ClientAliveCountMax 2
LoginGraceTime 60
MaxAuthTries 3
MaxSessions 2
MaxStartups 2
# Protokoll-Einstellungen
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
# Verschlüsselung
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512
# Banner
Banner /etc/ssh/ssh_banner
EOF
# SSH-Banner erstellen
cat > "/etc/ssh/ssh_banner" << 'EOF'
================================================================================
MYP SYSTEM - AUTORISIERTER ZUGANG
================================================================================
WARNUNG: Dieses System ist nur für autorisierte Benutzer bestimmt.
Alle Aktivitäten werden überwacht und protokolliert.
Unbefugter Zugang ist strengstens untersagt und wird strafrechtlich verfolgt.
Mercedes-Benz 3D-Drucker-Management-System
================================================================================
EOF
# SSH-Host-Keys regenerieren für bessere Sicherheit
log "INFO" "Regeneriere SSH-Host-Keys..."
rm -f /etc/ssh/ssh_host_*
ssh-keygen -A
# SSH-Service neu starten
systemctl restart ssh
# SSH-Service Status prüfen
if systemctl is-active --quiet ssh; then
log "INFO" "SSH erfolgreich gesichert und neu gestartet"
else
log "ERROR" "SSH-Service konnte nicht neu gestartet werden"
return 1
fi
log "INFO" "SSH-Sicherheit konfiguriert"
}
setup_network_monitoring() {
log "INFO" "Richte Netzwerk-Monitoring ein..."
# Netstat-Monitoring-Script
cat > "/usr/local/bin/myp-netmon.sh" << 'EOF'
#!/bin/bash
# MYP Network Monitor
LOG_FILE="/var/log/myp/network-monitor.log"
ALERT_FILE="/var/log/myp/network-alerts.log"
exec >> "$LOG_FILE" 2>&1
echo "$(date): Network Monitor Scan gestartet"
# Prüfe offene Ports
OPEN_PORTS=$(ss -tlnp | grep LISTEN)
echo "Offene Ports:"
echo "$OPEN_PORTS"
# Prüfe verdächtige Verbindungen
SUSPICIOUS_CONNECTIONS=$(ss -tn | awk '$1=="ESTAB" {print $4, $5}' | grep -v "127.0.0.1\|::1" | sort | uniq -c | sort -nr | head -10)
if [[ -n "$SUSPICIOUS_CONNECTIONS" ]]; then
echo "Top-Verbindungen:"
echo "$SUSPICIOUS_CONNECTIONS"
fi
# Prüfe Firewall-Status
UFW_STATUS=$(ufw status)
echo "Firewall-Status:"
echo "$UFW_STATUS"
# Prüfe auf Port-Scans (einfache Heuristik)
RECENT_CONNECTIONS=$(journalctl --since="5 minutes ago" -u ssh | grep "Failed\|Invalid" | wc -l)
if [[ $RECENT_CONNECTIONS -gt 10 ]]; then
echo "$(date): ALERT - Möglicher SSH-Angriff erkannt ($RECENT_CONNECTIONS Fehlversuche)" >> "$ALERT_FILE"
fi
echo "$(date): Network Monitor Scan abgeschlossen"
echo "----------------------------------------"
EOF
chmod +x "/usr/local/bin/myp-netmon.sh"
# Network Monitor Service
cat > "/etc/systemd/system/myp-netmon.service" << 'EOF'
[Unit]
Description=MYP Network Monitor
Documentation=https://github.com/mercedes-benz/myp
[Service]
Type=oneshot
ExecStart=/usr/local/bin/myp-netmon.sh
EOF
# Network Monitor Timer
cat > "/etc/systemd/system/myp-netmon.timer" << 'EOF'
[Unit]
Description=MYP Network Monitor Timer
Documentation=https://github.com/mercedes-benz/myp
[Timer]
OnCalendar=*:0/10
Persistent=true
[Install]
WantedBy=timers.target
EOF
systemctl enable myp-netmon.timer
log "INFO" "Netzwerk-Monitoring eingerichtet"
}
setup_fail2ban() {
log "INFO" "Installiere und konfiguriere Fail2Ban..."
# Fail2Ban installieren
if ! command -v fail2ban-server >/dev/null 2>&1; then
DEBIAN_FRONTEND=noninteractive apt-get install -y fail2ban
fi
# Fail2Ban lokale Konfiguration
cat > "/etc/fail2ban/jail.local" << 'EOF'
[DEFAULT]
# Basis-Konfiguration
ignoreip = 127.0.0.1/8 ::1 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12
bantime = 3600
findtime = 600
maxretry = 3
backend = systemd
# E-Mail-Benachrichtigungen (optional)
# destemail = admin@example.com
# sendername = Fail2Ban
# mta = sendmail
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 7200
[nginx-http-auth]
enabled = false
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
[nginx-noscript]
enabled = false
port = http,https
filter = nginx-noscript
logpath = /var/log/nginx/access.log
[nginx-badbots]
enabled = false
port = http,https
filter = nginx-badbots
logpath = /var/log/nginx/access.log
[apache-auth]
enabled = false
port = http,https
filter = apache-auth
logpath = /var/log/apache*/*error.log
[myp-https]
enabled = true
port = https
filter = myp-https
logpath = /var/log/myp/app.log
maxretry = 5
bantime = 1800
EOF
# MYP-spezifischer Fail2Ban-Filter
cat > "/etc/fail2ban/filter.d/myp-https.conf" << 'EOF'
# MYP HTTPS Fail2Ban Filter
[Definition]
failregex = ^.*\[.*\] ".*" 401 .* ".*" ".*" "<HOST>".*$
^.*\[.*\] ".*" 403 .* ".*" ".*" "<HOST>".*$
^.*Authentication failed.*<HOST>.*$
^.*Invalid login attempt.*<HOST>.*$
ignoreregex =
[Init]
journalmatch = _SYSTEMD_UNIT=myp-https.service
EOF
# Fail2Ban aktivieren und starten
systemctl enable fail2ban
systemctl restart fail2ban
# Status prüfen
if systemctl is-active --quiet fail2ban; then
log "INFO" "Fail2Ban erfolgreich konfiguriert und gestartet"
else
log "WARN" "Fail2Ban konnte nicht gestartet werden"
fi
log "INFO" "Fail2Ban konfiguriert"
}
create_iptables_backup() {
log "INFO" "Erstelle IPTables-Backup..."
# Backup-Verzeichnis erstellen
mkdir -p "/etc/myp/firewall-backups"
# IPTables-Regeln sichern
iptables-save > "/etc/myp/firewall-backups/iptables-$(date +%Y%m%d-%H%M%S).rules"
ip6tables-save > "/etc/myp/firewall-backups/ip6tables-$(date +%Y%m%d-%H%M%S).rules"
# UFW-Status sichern
ufw status verbose > "/etc/myp/firewall-backups/ufw-status-$(date +%Y%m%d-%H%M%S).txt"
# Backup-Script für regelmäßige Sicherungen
cat > "/usr/local/bin/myp-firewall-backup.sh" << 'EOF'
#!/bin/bash
# MYP Firewall Backup Script
BACKUP_DIR="/etc/myp/firewall-backups"
DATE=$(date +%Y%m%d-%H%M%S)
# Aktuelle Regeln sichern
iptables-save > "$BACKUP_DIR/iptables-$DATE.rules"
ip6tables-save > "$BACKUP_DIR/ip6tables-$DATE.rules"
ufw status verbose > "$BACKUP_DIR/ufw-status-$DATE.txt"
# Alte Backups bereinigen (behalte nur die letzten 30)
find "$BACKUP_DIR" -name "*.rules" -mtime +30 -delete
find "$BACKUP_DIR" -name "*.txt" -mtime +30 -delete
echo "$(date): Firewall-Backup erstellt: $DATE"
EOF
chmod +x "/usr/local/bin/myp-firewall-backup.sh"
# Backup-Service
cat > "/etc/systemd/system/myp-firewall-backup.service" << 'EOF'
[Unit]
Description=MYP Firewall Backup
Documentation=https://github.com/mercedes-benz/myp
[Service]
Type=oneshot
ExecStart=/usr/local/bin/myp-firewall-backup.sh
StandardOutput=append:/var/log/myp/firewall-backup.log
StandardError=append:/var/log/myp/firewall-backup.log
EOF
# Backup-Timer
cat > "/etc/systemd/system/myp-firewall-backup.timer" << 'EOF'
[Unit]
Description=MYP Firewall Backup Timer
Documentation=https://github.com/mercedes-benz/myp
[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=30m
[Install]
WantedBy=timers.target
EOF
systemctl enable myp-firewall-backup.timer
log "INFO" "IPTables-Backup erstellt und Backup-System eingerichtet"
}
configure_network_zones() {
log "INFO" "Konfiguriere Netzwerk-Sicherheitszonen..."
# Erstelle Netzwerk-Zonen-Konfiguration
cat > "/etc/myp/network-zones.conf" << 'EOF'
# MYP Network Security Zones Configuration
# Trusted Networks (Management, Admin-Zugang)
TRUSTED_NETWORKS=(
"192.168.1.0/24" # Management-Netz
"10.10.0.0/16" # Admin-Netz
)
# Production Networks (Standard-Benutzer)
PRODUCTION_NETWORKS=(
"192.168.0.0/16" # Produktions-Netz
"10.0.0.0/8" # Firmen-Netz
"172.16.0.0/12" # DMZ
)
# Restricted Networks (Gäste, IoT)
RESTRICTED_NETWORKS=(
"192.168.100.0/24" # Gäste-Netz
"10.99.0.0/16" # IoT-Netz
)
# Blocked Networks
BLOCKED_NETWORKS=(
"0.0.0.0/8" # Invalid
"169.254.0.0/16" # Link-local
"224.0.0.0/4" # Multicast
)
EOF
# Zonen-Management-Script
cat > "/usr/local/bin/myp-zones.sh" << 'EOF'
#!/bin/bash
# MYP Network Zones Management
source /etc/myp/network-zones.conf
case "$1" in
"apply")
echo "Wende Netzwerk-Zonen an..."
# Trusted Networks - Vollzugriff
for network in "${TRUSTED_NETWORKS[@]}"; do
ufw allow from "$network" comment "Trusted Zone"
done
# Production Networks - Limitierter Zugriff
for network in "${PRODUCTION_NETWORKS[@]}"; do
ufw allow from "$network" to any port 443 comment "Production Zone HTTPS"
ufw allow from "$network" to any port 80 comment "Production Zone HTTP"
done
# Restricted Networks - Sehr limitiert
for network in "${RESTRICTED_NETWORKS[@]}"; do
ufw allow from "$network" to any port 443 comment "Restricted Zone HTTPS"
done
# Blocked Networks
for network in "${BLOCKED_NETWORKS[@]}"; do
ufw deny from "$network" comment "Blocked Zone"
done
;;
"status")
echo "Netzwerk-Zonen Status:"
ufw status numbered
;;
"reset")
echo "Setze Netzwerk-Zonen zurück..."
ufw --force reset
;;
*)
echo "Verwendung: $0 {apply|status|reset}"
exit 1
;;
esac
EOF
chmod +x "/usr/local/bin/myp-zones.sh"
log "INFO" "Netzwerk-Sicherheitszonen konfiguriert"
}
activate_firewall() {
log "INFO" "Aktiviere Firewall..."
# UFW aktivieren
echo "y" | ufw enable
# Status prüfen
if ufw status | grep -q "Status: active"; then
log "INFO" "UFW erfolgreich aktiviert"
else
log "ERROR" "UFW konnte nicht aktiviert werden"
return 1
fi
# Firewall-Status loggen
ufw status verbose > "/var/log/myp/firewall-status.log"
log "INFO" "Firewall aktiviert"
}
verify_firewall() {
log "INFO" "Überprüfe Firewall-Konfiguration..."
local errors=0
# UFW Status prüfen
if ! ufw status | grep -q "Status: active"; then
log "ERROR" "UFW ist nicht aktiv"
errors=$((errors + 1))
fi
# Wichtige Ports prüfen
local required_ports=("443/tcp" "80/tcp" "22/tcp")
for port in "${required_ports[@]}"; do
if ! ufw status | grep -q "$port"; then
log "ERROR" "Port-Regel fehlt: $port"
errors=$((errors + 1))
fi
done
# SSH-Service prüfen
if ! systemctl is-active --quiet ssh; then
log "ERROR" "SSH-Service nicht aktiv"
errors=$((errors + 1))
fi
# Fail2Ban prüfen
if command -v fail2ban-server >/dev/null 2>&1; then
if ! systemctl is-active --quiet fail2ban; then
log "WARN" "Fail2Ban nicht aktiv"
fi
fi
# Netzwerk-Konnektivität testen
if ! ping -c 1 8.8.8.8 >/dev/null 2>&1; then
log "ERROR" "Externe Netzwerk-Konnektivität fehlgeschlagen"
errors=$((errors + 1))
fi
if [[ $errors -eq 0 ]]; then
log "INFO" "Firewall-Verifikation erfolgreich"
# Firewall-Status-Report erstellen
create_firewall_report
return 0
else
log "ERROR" "Firewall-Verifikation fehlgeschlagen ($errors Fehler)"
return 1
fi
}
create_firewall_report() {
log "INFO" "Erstelle Firewall-Status-Report..."
local report_file="/var/log/myp/firewall-report-$(date +%Y%m%d-%H%M%S).txt"
cat > "$report_file" << EOF
================================================================================
MYP FIREWALL-KONFIGURATION REPORT
================================================================================
Erstellt: $(date)
System: $(uname -a)
Hostname: $(hostname)
=== UFW STATUS ===
$(ufw status verbose)
=== IPTABLES RULES ===
$(iptables -L -n)
=== OPEN PORTS ===
$(ss -tlnp)
=== SSH CONFIGURATION ===
SSH-Service: $(systemctl is-active ssh)
SSH-Port: $(grep -E "^Port|^#Port" /etc/ssh/sshd_config | head -1)
=== FAIL2BAN STATUS ===
$(if command -v fail2ban-client >/dev/null 2>&1; then fail2ban-client status; else echo "Fail2Ban nicht installiert"; fi)
=== NETWORK INTERFACES ===
$(ip addr show)
=== ROUTING TABLE ===
$(ip route show)
=== DNS CONFIGURATION ===
$(cat /etc/resolv.conf)
================================================================================
ENDE REPORT
================================================================================
EOF
log "INFO" "Firewall-Report erstellt: $report_file"
}

View File

@ -0,0 +1,571 @@
#!/bin/bash
#######################################################################
# MYP AIO-Installer - Python & Node.js Module
#
# Dieses Modul behandelt die Installation von:
# - Python und pip mit --break-system-packages
# - Node.js und npm
# - Python-Abhängigkeiten aus requirements.txt
# - Node.js-Abhängigkeiten aus package.json
# - Build-Prozess für Frontend-Assets
#######################################################################
# Funktionsdeklarationen für Python & Node.js Setup
install_python_dependencies() {
log "INFO" "=== PYTHON-ABHÄNGIGKEITEN INSTALLIEREN ==="
# Python-Version überprüfen
verify_python_installation
# pip konfigurieren
configure_pip
# Virtuelle Umgebung erstellen (optional)
# create_python_venv
# Requirements installieren
install_python_requirements
# Python-Installation verifizieren
verify_python_dependencies
log "INFO" "Python-Abhängigkeiten Installation abgeschlossen"
}
install_node_dependencies() {
log "INFO" "=== NODE.JS-ABHÄNGIGKEITEN INSTALLIEREN ==="
# Node.js installieren
install_nodejs
# npm konfigurieren
configure_npm
# Package-Dependencies installieren
install_npm_packages
# Build-Prozess durchführen
build_frontend_assets
# Node.js-Installation verifizieren
verify_node_dependencies
log "INFO" "Node.js-Abhängigkeiten Installation abgeschlossen"
}
verify_python_installation() {
log "INFO" "Überprüfe Python-Installation..."
# Python3 Version prüfen
if ! command -v python3 >/dev/null 2>&1; then
log "ERROR" "Python3 ist nicht installiert"
return 1
fi
local python_version=$(python3 --version | cut -d' ' -f2)
log "INFO" "Python-Version: $python_version"
# Mindestversion prüfen (Python 3.8+)
if ! python3 -c "import sys; sys.exit(0 if sys.version_info >= (3, 8) else 1)"; then
log "ERROR" "Python-Version zu alt (mindestens 3.8 erforderlich)"
return 1
fi
# pip überprüfen
if ! command -v pip3 >/dev/null 2>&1; then
log "INFO" "pip3 nicht gefunden, installiere pip..."
apt-get install -y python3-pip
fi
local pip_version=$(pip3 --version | cut -d' ' -f2)
log "INFO" "pip-Version: $pip_version"
log "INFO" "Python-Installation verifiziert"
}
configure_pip() {
log "INFO" "Konfiguriere pip..."
# pip Konfigurationsverzeichnis erstellen
mkdir -p "/home/$PROJECT_USER/.config/pip"
mkdir -p "/root/.config/pip"
# pip.conf für bessere Performance und Sicherheit
cat > "/home/$PROJECT_USER/.config/pip/pip.conf" << 'EOF'
[global]
timeout = 60
retries = 5
trusted-host = pypi.org
pypi.python.org
files.pythonhosted.org
[install]
upgrade-strategy = only-if-needed
break-system-packages = true
EOF
# Kopiere für root
cp "/home/$PROJECT_USER/.config/pip/pip.conf" "/root/.config/pip/pip.conf"
# Berechtigungen setzen
chown -R "$PROJECT_USER:$PROJECT_GROUP" "/home/$PROJECT_USER/.config"
# pip auf neueste Version aktualisieren
log "INFO" "Aktualisiere pip auf neueste Version..."
pip3 install --upgrade pip --break-system-packages || {
log "WARN" "pip-Update hatte Probleme"
}
log "INFO" "pip konfiguriert"
}
create_python_venv() {
log "INFO" "Erstelle Python Virtual Environment..."
local venv_path="$INSTALL_PATH/venv"
# Virtual Environment erstellen
python3 -m venv "$venv_path" || {
log "ERROR" "Virtual Environment konnte nicht erstellt werden"
return 1
}
# Aktivierungsscript für systemd erstellen
cat > "$INSTALL_PATH/activate_venv.sh" << EOF
#!/bin/bash
source "$venv_path/bin/activate"
exec "\$@"
EOF
chmod +x "$INSTALL_PATH/activate_venv.sh"
# Virtual Environment in systemd-Service nutzen
export PYTHON_VENV_PATH="$venv_path"
log "INFO" "Python Virtual Environment erstellt: $venv_path"
}
install_python_requirements() {
log "INFO" "Installiere Python-Requirements..."
# Requirements-Datei prüfen
local requirements_file="$INSTALL_PATH/requirements.txt"
if [[ ! -f "$requirements_file" ]]; then
log "ERROR" "Requirements-Datei nicht gefunden: $requirements_file"
return 1
fi
log "INFO" "Gefundene Requirements-Datei: $requirements_file"
# Anzahl der Requirements anzeigen
local req_count=$(grep -v '^#' "$requirements_file" | grep -v '^$' | wc -l)
log "INFO" "Installiere $req_count Python-Packages..."
# Installation mit --break-system-packages
log "INFO" "Führe pip install mit --break-system-packages aus..."
# Erstelle temporäres Install-Script für bessere Kontrolle
cat > "/tmp/pip_install.sh" << EOF
#!/bin/bash
set -e
cd "$INSTALL_PATH"
# Upgrade pip falls nötig
pip3 install --upgrade pip --break-system-packages
# Installiere Requirements
pip3 install -r requirements.txt --break-system-packages --no-cache-dir
# Erstelle Freeze-Liste für Debugging
pip3 freeze --break-system-packages > installed_packages.txt
EOF
chmod +x "/tmp/pip_install.sh"
# Installation ausführen
if /tmp/pip_install.sh; then
log "INFO" "Python-Requirements erfolgreich installiert"
else
log "ERROR" "Python-Requirements Installation fehlgeschlagen"
# Versuche einzelne Installation bei Fehlern
log "INFO" "Versuche einzelne Package-Installation..."
install_requirements_individually "$requirements_file"
fi
# Cleanup
rm -f "/tmp/pip_install.sh"
log "INFO" "Python-Requirements Installation abgeschlossen"
}
install_requirements_individually() {
local requirements_file="$1"
log "INFO" "Installiere Requirements einzeln..."
# Lese Requirements und installiere einzeln
while IFS= read -r line; do
# Überspringe Kommentare und leere Zeilen
[[ "$line" =~ ^#.*$ ]] && continue
[[ -z "$line" ]] && continue
# Package-Name extrahieren
local package=$(echo "$line" | cut -d'=' -f1 | cut -d'>' -f1 | cut -d'<' -f1 | tr -d ' ')
if [[ -n "$package" ]]; then
log "INFO" "Installiere: $package"
if pip3 install "$line" --break-system-packages --no-cache-dir; then
log "INFO" "$package installiert"
else
log "WARN" "$package Installation fehlgeschlagen"
fi
fi
done < "$requirements_file"
}
install_nodejs() {
log "INFO" "Installiere Node.js..."
# Prüfe ob Node.js bereits installiert ist
if command -v node >/dev/null 2>&1; then
local current_version=$(node --version)
log "INFO" "Node.js bereits installiert: $current_version"
# Prüfe Version (mindestens v16)
if node -e "process.exit(parseInt(process.version.slice(1)) >= 16 ? 0 : 1)"; then
log "INFO" "Node.js Version ist ausreichend"
return 0
else
log "WARN" "Node.js Version zu alt, aktualisiere..."
fi
fi
# Versuche Installation über APT (NodeSource Repository)
if install_nodejs_apt; then
log "INFO" "Node.js über APT installiert"
return 0
fi
# Fallback: Installation über NodeSource Script
if install_nodejs_nodesource; then
log "INFO" "Node.js über NodeSource installiert"
return 0
fi
# Letzter Fallback: Snap
if install_nodejs_snap; then
log "INFO" "Node.js über Snap installiert"
return 0
fi
log "ERROR" "Node.js Installation fehlgeschlagen"
return 1
}
install_nodejs_apt() {
log "INFO" "Versuche Node.js Installation über APT..."
# APT-Cache aktualisieren
apt-get update -y
# Node.js installieren
if DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs npm; then
# Version prüfen
local node_version=$(node --version 2>/dev/null || echo "v0.0.0")
local npm_version=$(npm --version 2>/dev/null || echo "0.0.0")
log "INFO" "Node.js installiert: $node_version"
log "INFO" "npm installiert: $npm_version"
return 0
else
log "WARN" "APT Node.js Installation fehlgeschlagen"
return 1
fi
}
install_nodejs_nodesource() {
log "INFO" "Versuche Node.js Installation über NodeSource..."
# NodeSource Setup-Script herunterladen und ausführen
if curl -fsSL https://deb.nodesource.com/setup_18.x | bash -; then
# Node.js installieren
if DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs; then
log "INFO" "Node.js über NodeSource erfolgreich installiert"
return 0
fi
fi
log "WARN" "NodeSource Installation fehlgeschlagen"
return 1
}
install_nodejs_snap() {
log "INFO" "Versuche Node.js Installation über Snap..."
# Snap installieren falls nicht vorhanden
if ! command -v snap >/dev/null 2>&1; then
DEBIAN_FRONTEND=noninteractive apt-get install -y snapd
systemctl enable --now snapd.socket
sleep 5
fi
# Node.js über Snap installieren
if snap install node --classic; then
# Symlinks erstellen
ln -sf /snap/bin/node /usr/local/bin/node
ln -sf /snap/bin/npm /usr/local/bin/npm
log "INFO" "Node.js über Snap erfolgreich installiert"
return 0
fi
log "WARN" "Snap Node.js Installation fehlgeschlagen"
return 1
}
configure_npm() {
log "INFO" "Konfiguriere npm..."
# npm Konfiguration für bessere Performance
npm config set audit-level moderate
npm config set fund false
npm config set update-notifier false
npm config set prefer-offline true
# Cache-Verzeichnis setzen
npm config set cache "/home/$PROJECT_USER/.npm"
# Registry auf https setzen
npm config set registry https://registry.npmjs.org/
# Timeout erhöhen
npm config set timeout 300000
# npm auf neueste Version aktualisieren
log "INFO" "Aktualisiere npm auf neueste Version..."
npm install -g npm@latest || {
log "WARN" "npm-Update hatte Probleme"
}
# Berechtigungen für npm-Cache
chown -R "$PROJECT_USER:$PROJECT_GROUP" "/home/$PROJECT_USER/.npm" 2>/dev/null || true
log "INFO" "npm konfiguriert"
}
install_npm_packages() {
log "INFO" "Installiere npm-Packages..."
# Package.json prüfen
local package_json="$INSTALL_PATH/package.json"
if [[ ! -f "$package_json" ]]; then
log "WARN" "package.json nicht gefunden: $package_json"
log "INFO" "Erstelle minimale package.json..."
create_minimal_package_json
fi
# Wechsle ins Installationsverzeichnis
cd "$INSTALL_PATH"
# npm install ausführen
log "INFO" "Führe npm install aus..."
if npm install --production; then
log "INFO" "npm-Packages erfolgreich installiert"
else
log "WARN" "npm install hatte Probleme, versuche --force..."
if npm install --production --force; then
log "INFO" "npm-Packages mit --force installiert"
else
log "ERROR" "npm install fehlgeschlagen"
return 1
fi
fi
# Package-Liste für Debugging
npm list --depth=0 > npm_packages.txt 2>/dev/null || true
log "INFO" "npm-Packages Installation abgeschlossen"
}
create_minimal_package_json() {
log "INFO" "Erstelle minimale package.json..."
cat > "$INSTALL_PATH/package.json" << 'EOF'
{
"name": "myp-system",
"version": "1.0.0",
"description": "Mercedes-Benz 3D Printer Management System",
"main": "app.py",
"scripts": {
"build:css": "tailwindcss -i static/css/input.css -o static/css/output.css --minify",
"watch:css": "tailwindcss -i static/css/input.css -o static/css/output.css --watch",
"dev": "npm run watch:css",
"build": "npm run build:css"
},
"dependencies": {
"tailwindcss": "^3.3.0",
"@tailwindcss/forms": "^0.5.0",
"@tailwindcss/typography": "^0.5.0",
"autoprefixer": "^10.4.0",
"postcss": "^8.4.0"
},
"keywords": ["3d-printing", "management", "mercedes-benz"],
"author": "Till Tomczak",
"license": "Proprietary"
}
EOF
log "INFO" "Minimale package.json erstellt"
}
build_frontend_assets() {
log "INFO" "Baue Frontend-Assets..."
cd "$INSTALL_PATH"
# Prüfe ob build-Script verfügbar ist
if npm run build --silent 2>/dev/null; then
log "INFO" "Frontend-Assets mit npm run build erstellt"
elif command -v tailwindcss >/dev/null 2>&1; then
log "INFO" "Verwende direkte TailwindCSS-Kommandos..."
build_tailwind_directly
else
log "WARN" "Kein Build-System verfügbar, überspringe Asset-Build"
return 0
fi
# Komprimiere Assets für Produktionsumgebung
compress_assets
log "INFO" "Frontend-Assets Build abgeschlossen"
}
build_tailwind_directly() {
log "INFO" "Baue TailwindCSS direkt..."
# Input-CSS erstellen falls nicht vorhanden
if [[ ! -f "static/css/input.css" ]]; then
mkdir -p "static/css"
cat > "static/css/input.css" << 'EOF'
@tailwind base;
@tailwind components;
@tailwind utilities;
/* Custom MYP Styles */
.btn-primary {
@apply bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 transition-colors;
}
.card {
@apply bg-white rounded-lg shadow-md p-6;
}
.form-input {
@apply border border-gray-300 rounded px-3 py-2 focus:outline-none focus:border-blue-500;
}
EOF
fi
# TailwindCSS Build
npx tailwindcss -i static/css/input.css -o static/css/output.css --minify || {
log "WARN" "TailwindCSS Build fehlgeschlagen"
}
}
compress_assets() {
log "INFO" "Komprimiere Assets..."
# CSS-Dateien komprimieren
find "$INSTALL_PATH/static/css" -name "*.css" -type f | while read -r css_file; do
if command -v gzip >/dev/null 2>&1; then
gzip -c "$css_file" > "${css_file}.gz"
log "INFO" "Komprimiert: $(basename "$css_file")"
fi
done
# JavaScript-Dateien komprimieren
find "$INSTALL_PATH/static/js" -name "*.js" -type f | while read -r js_file; do
if command -v gzip >/dev/null 2>&1; then
gzip -c "$js_file" > "${js_file}.gz"
log "INFO" "Komprimiert: $(basename "$js_file")"
fi
done
log "INFO" "Asset-Komprimierung abgeschlossen"
}
verify_python_dependencies() {
log "INFO" "Überprüfe Python-Dependencies..."
local errors=0
# Wichtige Packages prüfen
local critical_packages=(
"flask"
"flask-sqlalchemy"
"flask-login"
"flask-wtf"
"werkzeug"
"gunicorn"
)
for package in "${critical_packages[@]}"; do
if ! python3 -c "import $package" 2>/dev/null; then
log "ERROR" "Kritisches Python-Package fehlt: $package"
errors=$((errors + 1))
fi
done
# Erstelle Package-Report
python3 -c "import pkg_resources; print('\n'.join([str(d) for d in pkg_resources.working_set]))" > "$INSTALL_PATH/python_packages_installed.txt"
if [[ $errors -eq 0 ]]; then
log "INFO" "Python-Dependencies Verifikation erfolgreich"
return 0
else
log "ERROR" "Python-Dependencies Verifikation fehlgeschlagen ($errors Fehler)"
return 1
fi
}
verify_node_dependencies() {
log "INFO" "Überprüfe Node.js-Dependencies..."
local errors=0
# Node.js Version prüfen
if ! command -v node >/dev/null 2>&1; then
log "ERROR" "Node.js nicht verfügbar"
errors=$((errors + 1))
else
local node_version=$(node --version)
log "INFO" "Node.js Version: $node_version"
fi
# npm Version prüfen
if ! command -v npm >/dev/null 2>&1; then
log "ERROR" "npm nicht verfügbar"
errors=$((errors + 1))
else
local npm_version=$(npm --version)
log "INFO" "npm Version: $npm_version"
fi
# TailwindCSS prüfen
if ! npx tailwindcss --help >/dev/null 2>&1; then
log "WARN" "TailwindCSS nicht verfügbar"
fi
if [[ $errors -eq 0 ]]; then
log "INFO" "Node.js-Dependencies Verifikation erfolgreich"
return 0
else
log "ERROR" "Node.js-Dependencies Verifikation fehlgeschlagen ($errors Fehler)"
return 1
fi
}

View File

@ -0,0 +1,790 @@
#!/bin/bash
#######################################################################
# MYP AIO-Installer - User & Services Module
#
# Dieses Modul behandelt:
# - Erstellung des System-Benutzers
# - Konfiguration von systemd Services
# - Service-Abhängigkeiten und Targets
# - User-Session-Management
# - Service-Monitoring und Restart-Policies
#######################################################################
# Funktionsdeklarationen für User & Services Setup
create_system_user() {
log "INFO" "=== SYSTEM-BENUTZER ERSTELLEN ==="
# MYP-Benutzer erstellen
create_myp_user
# Benutzer-Verzeichnisse einrichten
setup_user_directories
# Benutzer-Berechtigungen konfigurieren
configure_user_permissions
# Benutzer-Umgebung konfigurieren
configure_user_environment
log "INFO" "System-Benutzer Erstellung abgeschlossen"
}
setup_systemd_services() {
log "INFO" "=== SYSTEMD SERVICES EINRICHTEN ==="
# Haupt-MYP-Service erstellen
create_myp_main_service
# Zusätzliche Services erstellen
create_auxiliary_services
# Service-Abhängigkeiten konfigurieren
configure_service_dependencies
# Services aktivieren
enable_services
# Service-Monitoring einrichten
setup_service_monitoring
log "INFO" "SystemD Services Einrichtung abgeschlossen"
}
create_myp_user() {
log "INFO" "Erstelle MYP-Systembenutzer..."
# Prüfe ob Benutzer bereits existiert
if id "$PROJECT_USER" &>/dev/null; then
log "INFO" "Benutzer '$PROJECT_USER' existiert bereits"
# Prüfe Gruppe
if getent group "$PROJECT_GROUP" >/dev/null; then
log "INFO" "Gruppe '$PROJECT_GROUP' existiert bereits"
else
log "INFO" "Erstelle Gruppe '$PROJECT_GROUP'..."
groupadd "$PROJECT_GROUP"
fi
# Benutzer zur Gruppe hinzufügen falls nötig
usermod -g "$PROJECT_GROUP" "$PROJECT_USER"
return 0
fi
# Erstelle Gruppe
log "INFO" "Erstelle Gruppe '$PROJECT_GROUP'..."
groupadd "$PROJECT_GROUP"
# Erstelle Benutzer
log "INFO" "Erstelle Benutzer '$PROJECT_USER'..."
useradd \
--system \
--create-home \
--home-dir "/home/$PROJECT_USER" \
--shell "/bin/bash" \
--gid "$PROJECT_GROUP" \
--comment "MYP System User" \
"$PROJECT_USER"
# Zusätzliche Gruppen zuweisen
local additional_groups=(
"sudo" # Admin-Rechte
"www-data" # Web-Server
"dialout" # Serielle Schnittstellen
"plugdev" # USB-Geräte
"gpio" # GPIO (Raspberry Pi)
"i2c" # I2C-Bus (Raspberry Pi)
"spi" # SPI-Bus (Raspberry Pi)
"video" # Video-Zugriff
"audio" # Audio-Zugriff
"users" # Standard-Benutzergruppe
)
for group in "${additional_groups[@]}"; do
if getent group "$group" >/dev/null 2>&1; then
usermod -a -G "$group" "$PROJECT_USER"
log "INFO" "Benutzer '$PROJECT_USER' zur Gruppe '$group' hinzugefügt"
fi
done
# Passwort setzen (für Sicherheit)
local password=$(openssl rand -base64 32)
echo "$PROJECT_USER:$password" | chpasswd
# Passwort in sichere Datei speichern
echo "Benutzer: $PROJECT_USER" > "/etc/myp/credentials.txt"
echo "Passwort: $password" >> "/etc/myp/credentials.txt"
chmod 600 "/etc/myp/credentials.txt"
log "INFO" "MYP-Systembenutzer '$PROJECT_USER' erstellt"
log "INFO" "Passwort gespeichert in: /etc/myp/credentials.txt"
}
setup_user_directories() {
log "INFO" "Richte Benutzer-Verzeichnisse ein..."
local user_home="/home/$PROJECT_USER"
# Standard-Verzeichnisse erstellen
local user_dirs=(
"$user_home/.config"
"$user_home/.local/bin"
"$user_home/.local/share"
"$user_home/.cache"
"$user_home/Desktop"
"$user_home/Documents"
"$user_home/Downloads"
"$user_home/Pictures"
"$user_home/scripts"
)
for dir in "${user_dirs[@]}"; do
mkdir -p "$dir"
done
# Spezielle MYP-Verzeichnisse
mkdir -p "$user_home/.myp"
mkdir -p "$user_home/.myp/logs"
mkdir -p "$user_home/.myp/backups"
mkdir -p "$user_home/.myp/config"
# Symlinks zu wichtigen Systempfaden
ln -sf "$INSTALL_PATH" "$user_home/myp-system"
ln -sf "/var/log/myp" "$user_home/system-logs"
ln -sf "/etc/myp" "$user_home/system-config"
# Berechtigungen setzen
chown -R "$PROJECT_USER:$PROJECT_GROUP" "$user_home"
chmod 755 "$user_home"
chmod 700 "$user_home/.myp"
log "INFO" "Benutzer-Verzeichnisse eingerichtet"
}
configure_user_permissions() {
log "INFO" "Konfiguriere Benutzer-Berechtigungen..."
# Sudo-Berechtigungen für MYP-Benutzer
cat > "/etc/sudoers.d/myp-user" << EOF
# MYP System User Permissions
$PROJECT_USER ALL=(ALL) NOPASSWD: /bin/systemctl restart myp-*
$PROJECT_USER ALL=(ALL) NOPASSWD: /bin/systemctl start myp-*
$PROJECT_USER ALL=(ALL) NOPASSWD: /bin/systemctl stop myp-*
$PROJECT_USER ALL=(ALL) NOPASSWD: /bin/systemctl status myp-*
$PROJECT_USER ALL=(ALL) NOPASSWD: /bin/systemctl reload myp-*
$PROJECT_USER ALL=(ALL) NOPASSWD: /usr/bin/tail -f /var/log/myp/*
$PROJECT_USER ALL=(ALL) NOPASSWD: /bin/journalctl -u myp-*
$PROJECT_USER ALL=(ALL) NOPASSWD: /usr/bin/nginx -s reload
$PROJECT_USER ALL=(ALL) NOPASSWD: /usr/sbin/ufw enable
$PROJECT_USER ALL=(ALL) NOPASSWD: /usr/sbin/ufw disable
$PROJECT_USER ALL=(ALL) NOPASSWD: /usr/sbin/ufw reload
EOF
chmod 440 "/etc/sudoers.d/myp-user"
# Raspberry Pi GPIO-Berechtigungen
if [[ -f /proc/device-tree/model ]] && grep -q "Raspberry Pi" /proc/device-tree/model; then
log "INFO" "Konfiguriere Raspberry Pi Berechtigungen..."
# GPIO-Gruppe erstellen falls nicht vorhanden
groupadd -f gpio
usermod -a -G gpio "$PROJECT_USER"
# udev-Regeln für GPIO
cat > "/etc/udev/rules.d/99-myp-gpio.rules" << 'EOF'
# MYP GPIO Permissions
SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c 'chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio'"
SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c 'chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/virtual/gpio'"
EOF
# I2C/SPI Berechtigungen
cat > "/etc/udev/rules.d/99-myp-i2c-spi.rules" << 'EOF'
# MYP I2C/SPI Permissions
KERNEL=="i2c-[0-9]*", GROUP="i2c", MODE="0660"
KERNEL=="spidev[0-9]*", GROUP="spi", MODE="0660"
EOF
udevadm control --reload-rules
fi
log "INFO" "Benutzer-Berechtigungen konfiguriert"
}
configure_user_environment() {
log "INFO" "Konfiguriere Benutzer-Umgebung..."
local user_home="/home/$PROJECT_USER"
# .bashrc für MYP-Benutzer
cat > "$user_home/.bashrc" << 'EOF'
# MYP System User .bashrc
# Grundlegende Bash-Konfiguration
if [ -f /etc/bash.bashrc ]; then
. /etc/bash.bashrc
fi
# Umgebungsvariablen
export PATH="$HOME/.local/bin:$PATH"
export EDITOR=nano
export BROWSER=chromium-browser
export MYP_INSTALL_PATH="/opt/myp"
export MYP_LOG_PATH="/var/log/myp"
# Aliases für MYP-Management
alias myp-status='sudo systemctl status myp-https'
alias myp-start='sudo systemctl start myp-https'
alias myp-stop='sudo systemctl stop myp-https'
alias myp-restart='sudo systemctl restart myp-https'
alias myp-logs='sudo journalctl -u myp-https -f'
alias myp-kiosk-status='sudo systemctl status myp-kiosk'
alias myp-kiosk-restart='sudo systemctl restart myp-kiosk'
# System-Aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias grep='grep --color=auto'
alias df='df -h'
alias du='du -h'
alias free='free -h'
# MYP-spezifische Funktionen
myp-quick-status() {
echo "=== MYP System Status ==="
echo "Haupt-Service: $(systemctl is-active myp-https)"
echo "Kiosk-Service: $(systemctl is-active myp-kiosk)"
echo "System-Load: $(uptime | cut -d, -f4-)"
echo "Speicher: $(free -h | grep Mem | awk '{print $3"/"$2}')"
echo "Festplatte: $(df -h / | tail -1 | awk '{print $3"/"$2" ("$5" verwendet)"}')"
}
myp-backup() {
local backup_dir="/home/myp/.myp/backups/backup-$(date +%Y%m%d-%H%M%S)"
echo "Erstelle Backup in: $backup_dir"
mkdir -p "$backup_dir"
cp -r "$MYP_INSTALL_PATH/database" "$backup_dir/"
cp -r "$MYP_INSTALL_PATH/config" "$backup_dir/"
cp -r "$MYP_INSTALL_PATH/uploads" "$backup_dir/"
echo "Backup erstellt: $backup_dir"
}
# Willkommensnachricht
if [[ $- == *i* ]]; then
echo "Willkommen im MYP System!"
echo "Verwende 'myp-quick-status' für einen Systemüberblick"
echo "Verwende 'myp-logs' für Live-Logs"
fi
EOF
# .profile für Desktop-Umgebung
cat > "$user_home/.profile" << 'EOF'
# MYP System User .profile
# Standard PATH
PATH="$HOME/.local/bin:$PATH"
# MYP Umgebungsvariablen
export MYP_INSTALL_PATH="/opt/myp"
export MYP_LOG_PATH="/var/log/myp"
export MYP_USER="myp"
# Desktop-Umgebung
export XDG_CURRENT_DESKTOP=LXDE
export XDG_SESSION_DESKTOP=LXDE
export DESKTOP_SESSION=LXDE
# Browser-Konfiguration
export BROWSER=chromium-browser
# Locale
export LANG=de_DE.UTF-8
export LC_ALL=de_DE.UTF-8
EOF
# .bash_logout
cat > "$user_home/.bash_logout" << 'EOF'
# MYP System User .bash_logout
# Bereinigung bei Logout
clear
EOF
# Berechtigungen setzen
chown "$PROJECT_USER:$PROJECT_GROUP" "$user_home/.bashrc"
chown "$PROJECT_USER:$PROJECT_GROUP" "$user_home/.profile"
chown "$PROJECT_USER:$PROJECT_GROUP" "$user_home/.bash_logout"
chmod 644 "$user_home/.bashrc"
chmod 644 "$user_home/.profile"
chmod 644 "$user_home/.bash_logout"
log "INFO" "Benutzer-Umgebung konfiguriert"
}
create_myp_main_service() {
log "INFO" "Erstelle Haupt-MYP-Service..."
cat > "/etc/systemd/system/${SERVICE_NAME}.service" << EOF
[Unit]
Description=MYP HTTPS Server
Documentation=https://github.com/mercedes-benz/myp
After=network-online.target
After=systemd-resolved.service
Wants=network-online.target
PartOf=multi-user.target
[Service]
Type=exec
User=$PROJECT_USER
Group=$PROJECT_GROUP
WorkingDirectory=$INSTALL_PATH
Environment=PYTHONPATH=$INSTALL_PATH
Environment=FLASK_APP=app.py
Environment=FLASK_ENV=production
Environment=MYP_CONFIG_PATH=/etc/myp
Environment=MYP_LOG_PATH=/var/log/myp
ExecStartPre=/bin/sleep 5
ExecStart=/usr/bin/python3 app.py
ExecReload=/bin/kill -HUP \$MAINPID
KillMode=mixed
KillSignal=SIGTERM
TimeoutStopSec=30
Restart=always
RestartSec=10
StartLimitInterval=300
StartLimitBurst=5
# Sicherheits-Einstellungen
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=false
ProtectSystem=strict
ReadWritePaths=$INSTALL_PATH
ReadWritePaths=/var/log/myp
ReadWritePaths=/etc/myp
ReadWritePaths=/tmp
# Resource-Limits (für Raspberry Pi optimiert)
MemoryLimit=512M
TasksMax=256
# Logging
StandardOutput=append:/var/log/myp/app.log
StandardError=append:/var/log/myp/app-error.log
SyslogIdentifier=myp-https
# Watchdog
WatchdogSec=60
[Install]
WantedBy=multi-user.target
EOF
log "INFO" "Haupt-MYP-Service erstellt"
}
create_auxiliary_services() {
log "INFO" "Erstelle zusätzliche Services..."
# MYP Database Cleanup Service
create_cleanup_service
# MYP Backup Service
create_backup_service
# MYP Health Check Service
create_healthcheck_service
# MYP Log Rotation Service
create_logrotation_service
log "INFO" "Zusätzliche Services erstellt"
}
create_cleanup_service() {
log "INFO" "Erstelle Database Cleanup Service..."
# Service
cat > "/etc/systemd/system/myp-cleanup.service" << EOF
[Unit]
Description=MYP Database Cleanup
Documentation=https://github.com/mercedes-benz/myp
After=myp-https.service
[Service]
Type=oneshot
User=$PROJECT_USER
Group=$PROJECT_GROUP
WorkingDirectory=$INSTALL_PATH
Environment=PYTHONPATH=$INSTALL_PATH
ExecStart=/usr/bin/python3 utils/database_cleanup.py
StandardOutput=append:/var/log/myp/cleanup.log
StandardError=append:/var/log/myp/cleanup-error.log
EOF
# Timer
cat > "/etc/systemd/system/myp-cleanup.timer" << 'EOF'
[Unit]
Description=MYP Database Cleanup Timer
Documentation=https://github.com/mercedes-benz/myp
[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=30m
[Install]
WantedBy=timers.target
EOF
systemctl enable myp-cleanup.timer
log "INFO" "Database Cleanup Service erstellt"
}
create_backup_service() {
log "INFO" "Erstelle Backup Service..."
# Service
cat > "/etc/systemd/system/myp-backup.service" << EOF
[Unit]
Description=MYP System Backup
Documentation=https://github.com/mercedes-benz/myp
After=myp-https.service
[Service]
Type=oneshot
User=$PROJECT_USER
Group=$PROJECT_GROUP
WorkingDirectory=$INSTALL_PATH
Environment=PYTHONPATH=$INSTALL_PATH
ExecStart=/bin/bash -c 'python3 -c "from utils.backup_manager import BackupManager; BackupManager().create_backup()"'
StandardOutput=append:/var/log/myp/backup.log
StandardError=append:/var/log/myp/backup-error.log
EOF
# Timer
cat > "/etc/systemd/system/myp-backup.timer" << 'EOF'
[Unit]
Description=MYP System Backup Timer
Documentation=https://github.com/mercedes-benz/myp
[Timer]
OnCalendar=weekly
Persistent=true
RandomizedDelaySec=1h
[Install]
WantedBy=timers.target
EOF
systemctl enable myp-backup.timer
log "INFO" "Backup Service erstellt"
}
create_healthcheck_service() {
log "INFO" "Erstelle Health Check Service..."
# Health Check Script
cat > "/usr/local/bin/myp-healthcheck.sh" << 'EOF'
#!/bin/bash
# MYP System Health Check
set -euo pipefail
LOG_FILE="/var/log/myp/healthcheck.log"
exec >> "$LOG_FILE" 2>&1
echo "$(date): MYP Health Check gestartet"
# Prüfe MYP-Service
if ! systemctl is-active --quiet myp-https; then
echo "$(date): WARNUNG - MYP-Service nicht aktiv"
systemctl start myp-https
fi
# Prüfe Festplattenspeicher
DISK_USAGE=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
if [[ $DISK_USAGE -gt 90 ]]; then
echo "$(date): WARNUNG - Festplatte zu voll ($DISK_USAGE%)"
fi
# Prüfe Speicherverbrauch
MEM_USAGE=$(free | grep Mem | awk '{print int($3/$2 * 100.0)}')
if [[ $MEM_USAGE -gt 90 ]]; then
echo "$(date): WARNUNG - Speicher zu voll ($MEM_USAGE%)"
fi
# Prüfe HTTP-Antwort
if ! curl -f -s -k https://localhost >/dev/null; then
echo "$(date): WARNUNG - HTTP-Service nicht erreichbar"
systemctl restart myp-https
fi
echo "$(date): MYP Health Check abgeschlossen"
EOF
chmod +x "/usr/local/bin/myp-healthcheck.sh"
# Service
cat > "/etc/systemd/system/myp-healthcheck.service" << 'EOF'
[Unit]
Description=MYP System Health Check
Documentation=https://github.com/mercedes-benz/myp
[Service]
Type=oneshot
ExecStart=/usr/local/bin/myp-healthcheck.sh
EOF
# Timer
cat > "/etc/systemd/system/myp-healthcheck.timer" << 'EOF'
[Unit]
Description=MYP System Health Check Timer
Documentation=https://github.com/mercedes-benz/myp
[Timer]
OnCalendar=*:0/15
Persistent=true
[Install]
WantedBy=timers.target
EOF
systemctl enable myp-healthcheck.timer
log "INFO" "Health Check Service erstellt"
}
create_logrotation_service() {
log "INFO" "Erstelle Log Rotation Service..."
# Logrotate-Konfiguration
cat > "/etc/logrotate.d/myp" << 'EOF'
/var/log/myp/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 myp myp
postrotate
systemctl reload myp-https 2>/dev/null || true
endscript
}
/var/log/myp-kiosk.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 644 myp myp
}
EOF
log "INFO" "Log Rotation Service erstellt"
}
configure_service_dependencies() {
log "INFO" "Konfiguriere Service-Abhängigkeiten..."
# Erstelle Drop-In-Directory für Service-Overrides
mkdir -p "/etc/systemd/system/${SERVICE_NAME}.service.d"
# Service-Abhängigkeiten
cat > "/etc/systemd/system/${SERVICE_NAME}.service.d/dependencies.conf" << 'EOF'
[Unit]
# Netzwerk-Abhängigkeiten
After=network-online.target
After=systemd-networkd.service
After=NetworkManager.service
Wants=network-online.target
# DNS-Abhängigkeiten
After=systemd-resolved.service
Wants=systemd-resolved.service
# System-Abhängigkeiten
After=systemd-tmpfiles-setup.service
After=local-fs.target
[Service]
# Erweiterte Restart-Policy
RestartPreventExitStatus=SIGKILL
SuccessExitStatus=143
EOF
# Kiosk-Service-Abhängigkeiten
if [[ -f "/etc/systemd/system/${KIOSK_SERVICE}.service" ]]; then
mkdir -p "/etc/systemd/system/${KIOSK_SERVICE}.service.d"
cat > "/etc/systemd/system/${KIOSK_SERVICE}.service.d/dependencies.conf" << EOF
[Unit]
# MYP-Service-Abhängigkeit
After=${SERVICE_NAME}.service
Wants=${SERVICE_NAME}.service
# Desktop-Abhängigkeiten
After=graphical-session.target
After=lightdm.service
PartOf=graphical-session.target
[Service]
# Erweiterte Kiosk-Konfiguration
Environment=DISPLAY=:0
Environment=XAUTHORITY=/home/$PROJECT_USER/.Xauthority
EOF
fi
systemctl daemon-reload
log "INFO" "Service-Abhängigkeiten konfiguriert"
}
enable_services() {
log "INFO" "Aktiviere Services..."
# Haupt-Services aktivieren
systemctl enable "$SERVICE_NAME"
systemctl enable "$KIOSK_SERVICE" 2>/dev/null || true
# Timer-Services aktivieren
systemctl enable myp-cleanup.timer 2>/dev/null || true
systemctl enable myp-backup.timer 2>/dev/null || true
systemctl enable myp-healthcheck.timer 2>/dev/null || true
# System-Services aktivieren
systemctl enable ssh
systemctl enable systemd-resolved
systemctl enable lightdm 2>/dev/null || true
log "INFO" "Services aktiviert"
}
setup_service_monitoring() {
log "INFO" "Richte Service-Monitoring ein..."
# Monitoring-Script
cat > "/usr/local/bin/myp-monitor.sh" << 'EOF'
#!/bin/bash
# MYP Service Monitor
SERVICES=("myp-https" "myp-kiosk")
LOG_FILE="/var/log/myp/monitor.log"
for service in "${SERVICES[@]}"; do
if systemctl is-failed --quiet "$service"; then
echo "$(date): Service $service ist fehlgeschlagen, starte neu..." >> "$LOG_FILE"
systemctl restart "$service"
fi
done
EOF
chmod +x "/usr/local/bin/myp-monitor.sh"
# Monitor-Service
cat > "/etc/systemd/system/myp-monitor.service" << 'EOF'
[Unit]
Description=MYP Service Monitor
Documentation=https://github.com/mercedes-benz/myp
[Service]
Type=oneshot
ExecStart=/usr/local/bin/myp-monitor.sh
EOF
# Monitor-Timer
cat > "/etc/systemd/system/myp-monitor.timer" << 'EOF'
[Unit]
Description=MYP Service Monitor Timer
Documentation=https://github.com/mercedes-benz/myp
[Timer]
OnCalendar=*:0/5
Persistent=true
[Install]
WantedBy=timers.target
EOF
systemctl enable myp-monitor.timer
log "INFO" "Service-Monitoring eingerichtet"
}
restart_services() {
log "INFO" "Starte Services neu..."
# Stoppe alle MYP-Services
systemctl stop "$KIOSK_SERVICE" 2>/dev/null || true
systemctl stop "$SERVICE_NAME" 2>/dev/null || true
# Warte kurz
sleep 3
# Starte Services
if systemctl start "$SERVICE_NAME"; then
log "INFO" "Haupt-Service gestartet"
else
log "ERROR" "Haupt-Service konnte nicht gestartet werden"
return 1
fi
# Kiosk-Service nur starten wenn Desktop verfügbar
if systemctl is-active --quiet lightdm 2>/dev/null; then
if systemctl start "$KIOSK_SERVICE" 2>/dev/null; then
log "INFO" "Kiosk-Service gestartet"
else
log "WARN" "Kiosk-Service konnte nicht gestartet werden"
fi
fi
log "INFO" "Services neugestartet"
}
verify_services() {
log "INFO" "Überprüfe Services..."
local errors=0
# Prüfe Service-Dateien
local service_files=(
"/etc/systemd/system/${SERVICE_NAME}.service"
"/etc/systemd/system/${KIOSK_SERVICE}.service"
"/etc/systemd/system/myp-cleanup.service"
"/etc/systemd/system/myp-backup.service"
"/etc/systemd/system/myp-healthcheck.service"
)
for file in "${service_files[@]}"; do
if [[ ! -f "$file" ]]; then
log "ERROR" "Service-Datei fehlt: $file"
errors=$((errors + 1))
fi
done
# Prüfe Service-Status
if ! systemctl is-enabled --quiet "$SERVICE_NAME"; then
log "ERROR" "Haupt-Service nicht aktiviert"
errors=$((errors + 1))
fi
# Prüfe Benutzer
if ! id "$PROJECT_USER" &>/dev/null; then
log "ERROR" "MYP-Benutzer existiert nicht"
errors=$((errors + 1))
fi
if [[ $errors -eq 0 ]]; then
log "INFO" "Services Verifikation erfolgreich"
return 0
else
log "ERROR" "Services Verifikation fehlgeschlagen ($errors Fehler)"
return 1
fi
}