#!/bin/bash # MYP Installer Control Center für Linux/Unix-Systeme # Konsolidiertes Installationsskript für die MYP-Plattform # Version 2.0 # Farbdefinitionen RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' WHITE='\033[1;37m' NC='\033[0m' # No Color # Überprüfen, ob das Skript als Root ausgeführt wird is_root=0 if [ "$EUID" -eq 0 ]; then is_root=1 fi # Funktionen show_header() { local title="$1" clear echo -e "${CYAN}=============================================================${NC}" echo -e "${CYAN} MYP INSTALLER CONTROL CENTER ${NC}" echo -e "${CYAN}=============================================================${NC}" echo -e "${CYAN} $title${NC}" echo -e "${CYAN}=============================================================${NC}" if [ $is_root -eq 0 ]; then echo -e "${YELLOW}HINWEIS: Dieses Skript läuft ohne Root-Rechte.${NC}" echo -e "${YELLOW}Einige Funktionen sind möglicherweise eingeschränkt.${NC}" echo -e "${CYAN}=============================================================${NC}" fi echo "" } check_command() { command -v "$1" >/dev/null 2>&1 } exec_command() { local cmd="$1" local description="$2" echo -e "${BLUE}> $description...${NC}" eval $cmd if [ $? -eq 0 ]; then echo -e "${GREEN}✓ Erfolgreich abgeschlossen!${NC}" return 0 else echo -e "${RED}✗ Fehler beim Ausführen des Befehls. Exit-Code: $?${NC}" return 1 fi } get_local_ip() { local ip=$(hostname -I | awk '{print $1}') if [ -z "$ip" ]; then ip="127.0.0.1" fi echo "$ip" } test_dependencies() { echo -e "${BLUE}Prüfe Abhängigkeiten...${NC}" local all_installed=1 # Python if check_command python3; then echo -e "${GREEN}✓ Python 3 gefunden${NC}" elif check_command python; then echo -e "${GREEN}✓ Python gefunden${NC}" else echo -e "${RED}✗ Python nicht gefunden${NC}" all_installed=0 fi # Pip if check_command pip3; then echo -e "${GREEN}✓ Python Package Manager (pip3) gefunden${NC}" elif check_command pip; then echo -e "${GREEN}✓ Python Package Manager (pip) gefunden${NC}" else echo -e "${RED}✗ Python Package Manager (pip) nicht gefunden${NC}" all_installed=0 fi # Docker if check_command docker; then echo -e "${GREEN}✓ Docker gefunden${NC}" else echo -e "${RED}✗ Docker nicht gefunden${NC}" all_installed=0 fi # Docker Compose if check_command docker-compose; then echo -e "${GREEN}✓ Docker Compose gefunden${NC}" else echo -e "${RED}✗ Docker Compose nicht gefunden${NC}" all_installed=0 fi # Node.js if check_command node; then echo -e "${GREEN}✓ Node.js gefunden${NC}" else echo -e "${RED}✗ Node.js nicht gefunden${NC}" all_installed=0 fi # npm if check_command npm; then echo -e "${GREEN}✓ Node Package Manager (npm) gefunden${NC}" else echo -e "${RED}✗ Node Package Manager (npm) nicht gefunden${NC}" all_installed=0 fi # OpenSSL if check_command openssl; then echo -e "${GREEN}✓ OpenSSL gefunden${NC}" else echo -e "${RED}✗ OpenSSL nicht gefunden${NC}" all_installed=0 fi return $all_installed } setup_hosts() { show_header "Host-Konfiguration" if [ $is_root -eq 0 ]; then echo -e "${RED}Diese Funktion erfordert Root-Rechte.${NC}" echo -e "${YELLOW}Bitte starten Sie das Skript mit sudo oder als Root neu.${NC}" read -p "Drücken Sie ENTER, um fortzufahren..." return 1 fi local_ip=$(get_local_ip) echo -e "${GREEN}Lokale IP-Adresse: $local_ip${NC}" hosts_file="/etc/hosts" echo -e "${BLUE}Hosts-Datei: $hosts_file${NC}" # Prüfen, ob die Einträge bereits existieren frontend_entry=$(grep "m040tbaraspi001.de040.corpintra.net" $hosts_file) backend_entry=$(grep "raspberrypi" $hosts_file) # Einträge in die Hosts-Datei schreiben echo -e "${BLUE}Aktualisiere Hosts-Datei...${NC}" if [ -z "$frontend_entry" ]; then echo "" >> $hosts_file echo "# MYP Frontend Host" >> $hosts_file echo "$local_ip m040tbaraspi001.de040.corpintra.net m040tbaraspi001" >> $hosts_file echo -e "${GREEN}Frontend-Hostname hinzugefügt${NC}" else echo -e "${YELLOW}Frontend-Hostname ist bereits konfiguriert${NC}" fi if [ -z "$backend_entry" ]; then echo "" >> $hosts_file echo "# MYP Backend Host" >> $hosts_file echo "$local_ip raspberrypi" >> $hosts_file echo -e "${GREEN}Backend-Hostname hinzugefügt${NC}" else echo -e "${YELLOW}Backend-Hostname ist bereits konfiguriert${NC}" fi echo -e "${GREEN}Konfiguration abgeschlossen!${NC}" echo "" echo -e "${BLUE}Folgende Hostnamen sind jetzt konfiguriert:${NC}" echo -e "${WHITE} - Frontend: m040tbaraspi001.de040.corpintra.net${NC}" echo -e "${WHITE} - Backend: raspberrypi${NC}" echo "" read -p "Drücken Sie ENTER, um fortzufahren..." } create_ssl_certificates() { show_header "SSL-Zertifikat-Generator" # Parameter definieren cert_dir="./backend/instance/ssl" backend_cert_file="$cert_dir/myp.crt" backend_key_file="$cert_dir/myp.key" frontend_cert_file="$cert_dir/frontend.crt" frontend_key_file="$cert_dir/frontend.key" echo -e "${BLUE}Zertifikate werden für folgende Hostnamen erstellt:${NC}" # Hostname-Auswahl echo -e "${WHITE}1. Für lokale Entwicklung (localhost)${NC}" echo -e "${WHITE}2. Für Raspberry Pi Deployment (raspberrypi)${NC}" echo -e "${WHITE}3. Für Unternehmens-Setup (m040tbaraspi001.de040.corpintra.net)${NC}" read -p "Wählen Sie eine Option (1-3, Standard: 1): " choice backend_hostname="localhost" frontend_hostname="localhost" case $choice in 2) backend_hostname="raspberrypi" frontend_hostname="raspberrypi" ;; 3) backend_hostname="raspberrypi" frontend_hostname="m040tbaraspi001.de040.corpintra.net" ;; esac echo -e "${BLUE}Backend-Hostname: $backend_hostname${NC}" echo -e "${BLUE}Frontend-Hostname: $frontend_hostname${NC}" echo "" # Verzeichnis erstellen, falls es nicht existiert if [ ! -d "$cert_dir" ]; then echo -e "${BLUE}Erstelle Verzeichnis $cert_dir...${NC}" mkdir -p "$cert_dir" fi # SSL-Zertifikate mit Python und cryptography erstellen echo -e "${BLUE}Erstelle SSL-Zertifikate mit Python...${NC}" if check_command python3 || check_command python; then # Überprüfen, ob cryptography installiert ist python_cmd="python3" if ! check_command python3; then python_cmd="python" fi cryptography_installed=$($python_cmd -c "try: import cryptography; print('True'); except ImportError: print('False')" 2>/dev/null) if [ "$cryptography_installed" != "True" ]; then echo -e "${YELLOW}Installiere Python-Abhängigkeit 'cryptography'...${NC}" if check_command pip3; then exec_command "pip3 install cryptography" "Installiere cryptography-Paket" else exec_command "pip install cryptography" "Installiere cryptography-Paket" fi fi # Python-Skript zur Zertifikatserstellung cat > temp_cert_script.py << EOF #!/usr/bin/env python3 import os import datetime import sys from cryptography import x509 from cryptography.x509.oid import NameOID from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption def create_self_signed_cert(cert_path, key_path, hostname="localhost"): # Verzeichnis erstellen, falls es nicht existiert cert_dir = os.path.dirname(cert_path) if cert_dir and not os.path.exists(cert_dir): os.makedirs(cert_dir, exist_ok=True) # Privaten Schlüssel generieren private_key = rsa.generate_private_key( public_exponent=65537, key_size=4096, ) # Schlüsseldatei schreiben with open(key_path, "wb") as key_file: key_file.write(private_key.private_bytes( encoding=Encoding.PEM, format=PrivateFormat.TraditionalOpenSSL, encryption_algorithm=NoEncryption() )) # Aktuelles Datum und Ablaufdatum berechnen now = datetime.datetime.now() valid_until = now + datetime.timedelta(days=3650) # 10 Jahre gültig # Name für das Zertifikat erstellen subject = issuer = x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, hostname), x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Mercedes-Benz AG"), x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, "Werk 040 Berlin"), x509.NameAttribute(NameOID.COUNTRY_NAME, "DE"), x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Berlin"), x509.NameAttribute(NameOID.LOCALITY_NAME, "Berlin") ]) # Zertifikat erstellen cert = x509.CertificateBuilder().subject_name( subject ).issuer_name( issuer ).public_key( private_key.public_key() ).serial_number( x509.random_serial_number() ).not_valid_before( now ).not_valid_after( valid_until ).add_extension( x509.SubjectAlternativeName([ x509.DNSName(hostname), x509.DNSName("localhost") ]), critical=False, ).add_extension( x509.BasicConstraints(ca=True, path_length=None), critical=True ).add_extension( x509.KeyUsage( digital_signature=True, content_commitment=False, key_encipherment=True, data_encipherment=False, key_agreement=False, key_cert_sign=True, crl_sign=True, encipher_only=False, decipher_only=False ), critical=True ).add_extension( x509.ExtendedKeyUsage([ x509.oid.ExtendedKeyUsageOID.SERVER_AUTH, x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH ]), critical=False ).sign(private_key, hashes.SHA256()) # Zertifikatsdatei schreiben with open(cert_path, "wb") as cert_file: cert_file.write(cert.public_bytes(Encoding.PEM)) print(f"Selbstsigniertes SSL-Zertifikat für '{hostname}' erstellt:") print(f"Zertifikat: {cert_path}") print(f"Schlüssel: {key_path}") print(f"Gültig für 10 Jahre.") # Backend-Zertifikat erstellen create_self_signed_cert('$backend_cert_file', '$backend_key_file', '$backend_hostname') # Frontend-Zertifikat erstellen create_self_signed_cert('$frontend_cert_file', '$frontend_key_file', '$frontend_hostname') EOF # Python-Skript ausführbar machen und ausführen chmod +x temp_cert_script.py if $python_cmd temp_cert_script.py; then echo -e "${GREEN}SSL-Zertifikate erfolgreich erstellt!${NC}" else echo -e "${RED}Fehler beim Erstellen der SSL-Zertifikate.${NC}" fi # Temporäres Skript löschen rm temp_cert_script.py else echo -e "${RED}Python nicht gefunden. SSL-Zertifikate können nicht erstellt werden.${NC}" fi # Zertifikate im System installieren (optional) if [ $is_root -eq 1 ]; then read -p "Möchten Sie die Zertifikate im System installieren? (j/n, Standard: n): " install_certs if [ "$install_certs" = "j" ]; then if [ -f "$backend_cert_file" ]; then echo -e "${BLUE}Installiere Backend-Zertifikat im System...${NC}" # Für verschiedene Linux-Distributionen if [ -d "/usr/local/share/ca-certificates" ]; then # Debian/Ubuntu/Raspberry Pi OS cp "$backend_cert_file" /usr/local/share/ca-certificates/myp.crt update-ca-certificates echo -e "${GREEN}Zertifikat installiert (Debian/Ubuntu)${NC}" elif [ -d "/etc/pki/ca-trust/source/anchors" ]; then # RHEL/CentOS/Fedora cp "$backend_cert_file" /etc/pki/ca-trust/source/anchors/myp.crt update-ca-trust extract echo -e "${GREEN}Zertifikat installiert (RHEL/CentOS/Fedora)${NC}" else echo -e "${YELLOW}Unbekanntes System. Zertifikatinstallation übersprungen.${NC}" fi fi fi else echo -e "${YELLOW}Hinweis: Um die Zertifikate im System zu installieren, starten Sie das Skript als Root.${NC}" fi # Frontend für HTTPS konfigurieren echo "" read -p "Möchten Sie das Frontend für HTTPS konfigurieren? (j/n, Standard: j): " configure_frontend if [ "$configure_frontend" != "n" ]; then echo -e "${BLUE}Konfiguriere Frontend für HTTPS...${NC}" # Kopiere Zertifikate ins Frontend-Verzeichnis frontend_ssl_dir="./frontend/ssl" if [ ! -d "$frontend_ssl_dir" ]; then mkdir -p "$frontend_ssl_dir" fi cp "$backend_cert_file" "$frontend_ssl_dir/myp.crt" cp "$backend_key_file" "$frontend_ssl_dir/myp.key" echo -e "${GREEN}Zertifikate ins Frontend-Verzeichnis kopiert.${NC}" # Prüfen, ob .env.local existiert und aktualisieren env_local_path="./frontend/.env.local" if [ -f "$env_local_path" ]; then # Datei existiert, mache Backup cp "$env_local_path" "${env_local_path}.bak" else # Datei erstellen echo "# MYP Frontend Umgebungsvariablen" > "$env_local_path" fi # SSL-Konfigurationen hinzufügen/aktualisieren declare -a ssl_configs=( "NODE_TLS_REJECT_UNAUTHORIZED=0" "HTTPS=true" "SSL_CRT_FILE=./ssl/myp.crt" "SSL_KEY_FILE=./ssl/myp.key" "NEXT_PUBLIC_API_URL=https://${backend_hostname}" "NEXT_PUBLIC_BACKEND_HOST=${backend_hostname}" "NEXT_PUBLIC_BACKEND_PROTOCOL=https" ) for config in "${ssl_configs[@]}"; do key=$(echo "$config" | cut -d'=' -f1) # Prüfen, ob die Konfiguration bereits existiert if grep -q "^${key}=" "$env_local_path"; then # Existierende Konfiguration aktualisieren sed -i "s|^${key}=.*|${config}|" "$env_local_path" else # Neue Konfiguration hinzufügen echo "$config" >> "$env_local_path" fi done echo -e "${GREEN}.env.local Datei mit SSL-Konfigurationen aktualisiert.${NC}" fi echo "" echo -e "${BLUE}SSL-Zertifikate wurden in folgenden Pfaden gespeichert:${NC}" echo -e "${WHITE}Backend: $backend_cert_file${NC}" echo -e "${WHITE}Frontend: $frontend_cert_file${NC}" echo "" read -p "Drücken Sie ENTER, um fortzufahren..." } setup_environment() { show_header "Umgebungs-Setup" # Prüfen, ob Python und pip installiert sind python_cmd="python3" pip_cmd="pip3" if ! check_command python3; then if check_command python; then python_cmd="python" else echo -e "${RED}Python ist nicht installiert.${NC}" read -p "Drücken Sie ENTER, um fortzufahren..." return 1 fi fi if ! check_command pip3; then if check_command pip; then pip_cmd="pip" else echo -e "${RED}pip ist nicht installiert.${NC}" read -p "Drücken Sie ENTER, um fortzufahren..." return 1 fi fi # Python-Abhängigkeiten installieren echo -e "${BLUE}Installiere Backend-Abhängigkeiten...${NC}" exec_command "$pip_cmd install -r backend/requirements.txt" "Installiere Python-Abhängigkeiten" # Prüfen, ob Node.js und npm installiert sind if check_command node && check_command npm; then # Frontend-Abhängigkeiten installieren echo -e "${BLUE}Installiere Frontend-Abhängigkeiten...${NC}" exec_command "cd frontend && npm install" "Installiere Node.js-Abhängigkeiten" else echo -e "${YELLOW}Node.js oder npm ist nicht installiert. Frontend-Abhängigkeiten werden übersprungen.${NC}" fi # Docker-Compose Datei aktualisieren docker_compose_file="docker-compose.yml" if [ -f "$docker_compose_file" ]; then if ! grep -q -- "--dual-protocol" "$docker_compose_file"; then # Backup erstellen cp "$docker_compose_file" "${docker_compose_file}.bak" # Konfiguration aktualisieren sed -i 's/command: python -m app\.app/command: python -m app.app --dual-protocol/g' "$docker_compose_file" echo -e "${GREEN}Docker-Compose-Datei wurde aktualisiert, um den dual-protocol-Modus zu aktivieren.${NC}" else echo -e "${GREEN}Docker-Compose-Datei ist bereits korrekt konfiguriert.${NC}" fi fi echo "" echo -e "${GREEN}Umgebungs-Setup abgeschlossen!${NC}" echo "" read -p "Drücken Sie ENTER, um fortzufahren..." } start_application() { show_header "Anwendung starten" echo -e "${BLUE}Wie möchten Sie die Anwendung starten?${NC}" echo -e "${WHITE}1. Backend-Server starten (Python)${NC}" echo -e "${WHITE}2. Frontend-Server starten (Node.js)${NC}" echo -e "${WHITE}3. Beide Server starten${NC}" echo -e "${WHITE}4. Mit Docker Compose starten${NC}" echo -e "${WHITE}5. Zurück zum Hauptmenü${NC}" read -p "Wählen Sie eine Option (1-5): " choice case $choice in 1) echo -e "${BLUE}Starte Backend-Server...${NC}" python_cmd="python3" if ! check_command python3; then python_cmd="python" fi $python_cmd backend/app/app.py & echo -e "${GREEN}Backend-Server läuft jetzt im Hintergrund.${NC}" echo -e "${YELLOW}PID: $!${NC}" ;; 2) echo -e "${BLUE}Starte Frontend-Server...${NC}" if check_command npm; then (cd frontend && npm run dev) & echo -e "${GREEN}Frontend-Server läuft jetzt im Hintergrund.${NC}" echo -e "${YELLOW}PID: $!${NC}" else echo -e "${RED}npm ist nicht installiert.${NC}" fi ;; 3) echo -e "${BLUE}Starte Backend-Server...${NC}" python_cmd="python3" if ! check_command python3; then python_cmd="python" fi $python_cmd backend/app/app.py & backend_pid=$! echo -e "${BLUE}Starte Frontend-Server...${NC}" if check_command npm; then (cd frontend && npm run dev) & frontend_pid=$! echo -e "${GREEN}Beide Server laufen jetzt im Hintergrund.${NC}" echo -e "${YELLOW}Backend PID: $backend_pid${NC}" echo -e "${YELLOW}Frontend PID: $frontend_pid${NC}" else echo -e "${RED}npm ist nicht installiert. Nur Backend wurde gestartet.${NC}" echo -e "${YELLOW}Backend PID: $backend_pid${NC}" fi ;; 4) if check_command docker && check_command docker-compose; then echo -e "${BLUE}Starte Anwendung mit Docker Compose...${NC}" exec_command "docker-compose up -d" "Starte Docker Container" echo -e "${GREEN}Docker Container wurden gestartet.${NC}" else echo -e "${RED}Docker oder Docker Compose ist nicht installiert.${NC}" fi ;; 5) return ;; *) echo -e "${RED}Ungültige Option.${NC}" ;; esac echo "" read -p "Drücken Sie ENTER, um fortzufahren..." } clean_old_scripts() { show_header "Alte Skripte bereinigen" old_scripts=( "setup_ssl.sh" "setup_hosts.sh" "generate_ssl_certs.sh" "setup_ssl.ps1" "setup_hosts.ps1" "setup_hosts_copy.ps1" "generate_ssl_certs.ps1" "generate_ssl_certs_copy.ps1" ) echo -e "${BLUE}Folgende Skripte werden gelöscht:${NC}" for script in "${old_scripts[@]}"; do if [ -f "$script" ]; then echo -e "${WHITE} - $script${NC}" fi done echo "" read -p "Möchten Sie fortfahren? (j/n, Standard: j): " confirm if [ "$confirm" != "n" ]; then for script in "${old_scripts[@]}"; do if [ -f "$script" ]; then if rm "$script"; then echo -e "${GREEN}✓ $script wurde gelöscht.${NC}" else echo -e "${RED}✗ Fehler beim Löschen von $script.${NC}" fi fi done echo "" echo -e "${GREEN}Bereinigung abgeschlossen.${NC}" else echo -e "${YELLOW}Bereinigung abgebrochen.${NC}" fi echo "" read -p "Drücken Sie ENTER, um fortzufahren..." } # Hauptmenü anzeigen show_main_menu() { show_header "Hauptmenü" echo -e "${WHITE}1. Systemvoraussetzungen prüfen${NC}" echo -e "${WHITE}2. Host-Konfiguration einrichten${NC}" echo -e "${WHITE}3. SSL-Zertifikate erstellen${NC}" echo -e "${WHITE}4. Umgebung einrichten (Abhängigkeiten installieren)${NC}" echo -e "${WHITE}5. Anwendung starten${NC}" echo -e "${WHITE}6. Alte Skripte bereinigen${NC}" echo -e "${WHITE}Q. Beenden${NC}" echo "" read -p "Wählen Sie eine Option (1-6, Q): " choice case $choice in 1) test_dependencies echo "" read -p "Drücken Sie ENTER, um fortzufahren..." show_main_menu ;; 2) setup_hosts show_main_menu ;; 3) create_ssl_certificates show_main_menu ;; 4) setup_environment show_main_menu ;; 5) start_application show_main_menu ;; 6) clean_old_scripts show_main_menu ;; [Qq]) exit 0 ;; *) echo -e "${RED}Ungültige Option. Bitte versuchen Sie es erneut.${NC}" sleep 2 show_main_menu ;; esac } # Skript starten show_main_menu