#!/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 }