From e93f3906e106b98217435f14dbb3311a803a3856 Mon Sep 17 00:00:00 2001 From: Till Tomczak Date: Mon, 26 May 2025 11:03:15 +0200 Subject: [PATCH] "Update installer scripts for SSL integration (feat)" --- myp_installer.ps1 | 519 +++++++++++++++++++++++++++++++- setup_ssl.sh | 747 +++++++++++++++------------------------------- 2 files changed, 763 insertions(+), 503 deletions(-) diff --git a/myp_installer.ps1 b/myp_installer.ps1 index 0519ecba..2f392184 100644 --- a/myp_installer.ps1 +++ b/myp_installer.ps1 @@ -1 +1,518 @@ - \ No newline at end of file +# MYP Installer Control Center +# Zentrale Installationskonsole für die MYP-Plattform +# Kombiniert Setup-Funktionen für SSL, Hosts, Docker und mehr + +# Farbdefinitionen für bessere Lesbarkeit +$colors = @{ + Title = "Cyan" + Success = "Green" + Error = "Red" + Warning = "Yellow" + Info = "Blue" + Command = "White" +} + +# Überprüfen, ob das Skript als Administrator ausgeführt wird +$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) + +function Show-Header { + param ([string]$Title) + + Clear-Host + Write-Host "=============================================================" -ForegroundColor $colors.Title + Write-Host " MYP INSTALLER CONTROL CENTER" -ForegroundColor $colors.Title + Write-Host "=============================================================" -ForegroundColor $colors.Title + Write-Host " $Title" -ForegroundColor $colors.Title + Write-Host "=============================================================" -ForegroundColor $colors.Title + + if (-not $isAdmin) { + Write-Host "HINWEIS: Dieses Skript läuft ohne Administrator-Rechte." -ForegroundColor $colors.Warning + Write-Host "Einige Funktionen sind möglicherweise eingeschränkt." -ForegroundColor $colors.Warning + Write-Host "=============================================================" -ForegroundColor $colors.Title + } + + Write-Host "" +} + +function Test-Command { + param ([string]$Command) + + try { + Get-Command $Command -ErrorAction Stop | Out-Null + return $true + } catch { + return $false + } +} + +function Exec-Command { + param ( + [string]$Command, + [string]$Description + ) + + Write-Host "> $Description..." -ForegroundColor $colors.Info + + try { + Invoke-Expression $Command | Out-Host + if ($LASTEXITCODE -eq 0 -or $null -eq $LASTEXITCODE) { + Write-Host "✓ Erfolgreich abgeschlossen!" -ForegroundColor $colors.Success + return $true + } else { + Write-Host "✗ Fehler beim Ausführen des Befehls. Exit-Code: $LASTEXITCODE" -ForegroundColor $colors.Error + return $false + } + } catch { + Write-Host "✗ Fehler: $_" -ForegroundColor $colors.Error + return $false + } +} + +function Get-LocalIPAddress { + $localIP = (Get-NetIPAddress | Where-Object { $_.AddressFamily -eq "IPv4" -and $_.PrefixOrigin -ne "WellKnown" } | Select-Object -First 1).IPAddress + if (-not $localIP) { + $localIP = "127.0.0.1" + } + return $localIP +} + +function Test-Dependencies { + Write-Host "Prüfe Abhängigkeiten..." -ForegroundColor $colors.Info + + $dependencies = @{ + "python" = "Python (3.6+)" + "pip" = "Python Package Manager" + "docker" = "Docker" + "docker-compose" = "Docker Compose" + "node" = "Node.js" + "npm" = "Node Package Manager" + "openssl" = "OpenSSL" + } + + $allInstalled = $true + + foreach ($dep in $dependencies.GetEnumerator()) { + $installed = Test-Command $dep.Key + if ($installed) { + Write-Host "✓ $($dep.Value) gefunden" -ForegroundColor $colors.Success + } else { + Write-Host "✗ $($dep.Value) nicht gefunden" -ForegroundColor $colors.Error + $allInstalled = $false + } + } + + return $allInstalled +} + +function Setup-Hosts { + Show-Header "Host-Konfiguration" + + if (-not $isAdmin) { + Write-Host "Diese Funktion erfordert Administrator-Rechte." -ForegroundColor $colors.Error + Write-Host "Bitte starten Sie das Skript als Administrator neu." -ForegroundColor $colors.Warning + return + } + + $localIP = Get-LocalIPAddress + Write-Host "Lokale IP-Adresse: $localIP" -ForegroundColor $colors.Success + + $hostsFile = "$env:windir\System32\drivers\etc\hosts" + Write-Host "Hosts-Datei: $hostsFile" -ForegroundColor $colors.Info + + # Prüfen, ob die Einträge bereits existieren + $frontendEntry = Select-String -Path $hostsFile -Pattern "m040tbaraspi001.de040.corpintra.net" -Quiet + $backendEntry = Select-String -Path $hostsFile -Pattern "raspberrypi" -Quiet + + # Einträge in die Hosts-Datei schreiben + Write-Host "Aktualisiere Hosts-Datei..." -ForegroundColor $colors.Info + + $hostsContent = Get-Content -Path $hostsFile + + if (-not $frontendEntry) { + $hostsContent += "" + $hostsContent += "# MYP Frontend Host" + $hostsContent += "$localIP m040tbaraspi001.de040.corpintra.net m040tbaraspi001" + Write-Host "Frontend-Hostname hinzugefügt" -ForegroundColor $colors.Success + } else { + Write-Host "Frontend-Hostname ist bereits konfiguriert" -ForegroundColor $colors.Warning + } + + if (-not $backendEntry) { + $hostsContent += "" + $hostsContent += "# MYP Backend Host" + $hostsContent += "$localIP raspberrypi" + Write-Host "Backend-Hostname hinzugefügt" -ForegroundColor $colors.Success + } else { + Write-Host "Backend-Hostname ist bereits konfiguriert" -ForegroundColor $colors.Warning + } + + # Speichern der aktualisierten Hosts-Datei + try { + $hostsContent | Set-Content -Path $hostsFile -Force + Write-Host "Konfiguration abgeschlossen!" -ForegroundColor $colors.Success + } catch { + Write-Host "Fehler beim Schreiben der Hosts-Datei: $_" -ForegroundColor $colors.Error + } + + Write-Host "" + Write-Host "Folgende Hostnamen sind jetzt konfiguriert:" -ForegroundColor $colors.Info + Write-Host " - Frontend: m040tbaraspi001.de040.corpintra.net" -ForegroundColor $colors.Command + Write-Host " - Backend: raspberrypi" -ForegroundColor $colors.Command + + Write-Host "" + Write-Host "Drücken Sie eine beliebige Taste, um fortzufahren..." + $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") +} + +function Create-SSLCertificates { + Show-Header "SSL-Zertifikat-Generator" + + # Parameter definieren + $certDir = "./backend/instance/ssl" + $backendCertFile = "$certDir/myp.crt" + $backendKeyFile = "$certDir/myp.key" + $frontendCertFile = "$certDir/frontend.crt" + $frontendKeyFile = "$certDir/frontend.key" + + Write-Host "Zertifikate werden für folgende Hostnamen erstellt:" -ForegroundColor $colors.Info + + # Hostname-Auswahl + Write-Host "1. Für lokale Entwicklung (localhost)" -ForegroundColor $colors.Command + Write-Host "2. Für Raspberry Pi Deployment (raspberrypi)" -ForegroundColor $colors.Command + Write-Host "3. Für Unternehmens-Setup (m040tbaraspi001.de040.corpintra.net)" -ForegroundColor $colors.Command + + $choice = Read-Host "Wählen Sie eine Option (1-3, Standard: 1)" + + switch ($choice) { + "2" { + $backendHostname = "raspberrypi" + $frontendHostname = "raspberrypi" + } + "3" { + $backendHostname = "raspberrypi" + $frontendHostname = "m040tbaraspi001.de040.corpintra.net" + } + default { + $backendHostname = "localhost" + $frontendHostname = "localhost" + } + } + + Write-Host "Backend-Hostname: $backendHostname" -ForegroundColor $colors.Info + Write-Host "Frontend-Hostname: $frontendHostname" -ForegroundColor $colors.Info + Write-Host "" + + # Verzeichnis erstellen, falls es nicht existiert + if (!(Test-Path $certDir)) { + Write-Host "Erstelle Verzeichnis $certDir..." -ForegroundColor $colors.Info + New-Item -ItemType Directory -Path $certDir -Force | Out-Null + } + + # SSL-Zertifikate mit Python und cryptography erstellen + Write-Host "Erstelle SSL-Zertifikate mit Python..." -ForegroundColor $colors.Info + + $pythonInstalled = Test-Command "python" + if ($pythonInstalled) { + # Überprüfen, ob cryptography installiert ist + $cryptographyInstalled = python -c "try: import cryptography; print('True'); except ImportError: print('False')" 2>$null + + if ($cryptographyInstalled -ne "True") { + Write-Host "Installiere Python-Abhängigkeit 'cryptography'..." -ForegroundColor $colors.Warning + Exec-Command "pip install cryptography" "Installiere cryptography-Paket" + } + + # Python-Skript zur Zertifikatserstellung + $certScript = @" +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('$backendCertFile', '$backendKeyFile', '$backendHostname') + +# Frontend-Zertifikat erstellen +create_self_signed_cert('$frontendCertFile', '$frontendKeyFile', '$frontendHostname') +"@ + + $tempScriptPath = ".\temp_cert_script.py" + $certScript | Out-File -FilePath $tempScriptPath -Encoding utf8 + + # Python-Skript ausführen + try { + python $tempScriptPath + Write-Host "SSL-Zertifikate erfolgreich erstellt!" -ForegroundColor $colors.Success + } catch { + Write-Host "Fehler beim Erstellen der SSL-Zertifikate: $_" -ForegroundColor $colors.Error + } finally { + # Temporäres Skript löschen + Remove-Item -Path $tempScriptPath -Force + } + } else { + Write-Host "Python nicht gefunden. SSL-Zertifikate können nicht erstellt werden." -ForegroundColor $colors.Error + } + + # Zertifikate im System installieren (optional) + if ($isAdmin) { + $installCerts = Read-Host "Möchten Sie die Zertifikate im System installieren? (j/n, Standard: n)" + + if ($installCerts -eq "j") { + if (Test-Path $backendCertFile) { + Write-Host "Installiere Backend-Zertifikat im System..." -ForegroundColor $colors.Info + Exec-Command "certutil -addstore -f 'ROOT' '$backendCertFile'" "Installiere im Root-Zertifikatsspeicher" + } + + if (Test-Path $frontendCertFile) { + Write-Host "Installiere Frontend-Zertifikat im System..." -ForegroundColor $colors.Info + Exec-Command "certutil -addstore -f 'ROOT' '$frontendCertFile'" "Installiere im Root-Zertifikatsspeicher" + } + } + } else { + Write-Host "Hinweis: Um die Zertifikate im System zu installieren, starten Sie das Skript als Administrator." -ForegroundColor $colors.Warning + } + + Write-Host "" + Write-Host "SSL-Zertifikate wurden in folgenden Pfaden gespeichert:" -ForegroundColor $colors.Info + Write-Host "Backend: $backendCertFile" -ForegroundColor $colors.Command + Write-Host "Frontend: $frontendCertFile" -ForegroundColor $colors.Command + + Write-Host "" + Write-Host "Drücken Sie eine beliebige Taste, um fortzufahren..." + $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") +} + +function Setup-Environment { + Show-Header "Umgebungs-Setup" + + # Prüfen, ob Python und pip installiert sind + $pythonInstalled = Test-Command "python" + $pipInstalled = Test-Command "pip" + + if (-not $pythonInstalled -or -not $pipInstalled) { + Write-Host "Python oder pip ist nicht installiert. Bitte installieren Sie Python 3.6+ und versuchen Sie es erneut." -ForegroundColor $colors.Error + return + } + + # Python-Abhängigkeiten installieren + Write-Host "Installiere Backend-Abhängigkeiten..." -ForegroundColor $colors.Info + Exec-Command "pip install -r backend/requirements.txt" "Installiere Python-Abhängigkeiten" + + # Prüfen, ob Node.js und npm installiert sind + $nodeInstalled = Test-Command "node" + $npmInstalled = Test-Command "npm" + + if ($nodeInstalled -and $npmInstalled) { + # Frontend-Abhängigkeiten installieren + Write-Host "Installiere Frontend-Abhängigkeiten..." -ForegroundColor $colors.Info + Exec-Command "cd frontend && npm install" "Installiere Node.js-Abhängigkeiten" + } else { + Write-Host "Node.js oder npm ist nicht installiert. Frontend-Abhängigkeiten werden übersprungen." -ForegroundColor $colors.Warning + } + + Write-Host "" + Write-Host "Umgebungs-Setup abgeschlossen!" -ForegroundColor $colors.Success + + Write-Host "" + Write-Host "Drücken Sie eine beliebige Taste, um fortzufahren..." + $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") +} + +function Start-Application { + Show-Header "Anwendung starten" + + Write-Host "Wie möchten Sie die Anwendung starten?" -ForegroundColor $colors.Info + Write-Host "1. Backend-Server starten (Python)" -ForegroundColor $colors.Command + Write-Host "2. Frontend-Server starten (Node.js)" -ForegroundColor $colors.Command + Write-Host "3. Beide Server starten (in separaten Fenstern)" -ForegroundColor $colors.Command + Write-Host "4. Mit Docker Compose starten" -ForegroundColor $colors.Command + Write-Host "5. Zurück zum Hauptmenü" -ForegroundColor $colors.Command + + $choice = Read-Host "Wählen Sie eine Option (1-5)" + + switch ($choice) { + "1" { + Write-Host "Starte Backend-Server..." -ForegroundColor $colors.Info + Start-Process -FilePath "python" -ArgumentList "backend/app/app.py" -NoNewWindow + Write-Host "Backend-Server läuft jetzt im Hintergrund." -ForegroundColor $colors.Success + } + "2" { + Write-Host "Starte Frontend-Server..." -ForegroundColor $colors.Info + Start-Process -FilePath "npm" -ArgumentList "run dev" -WorkingDirectory "frontend" -NoNewWindow + Write-Host "Frontend-Server läuft jetzt im Hintergrund." -ForegroundColor $colors.Success + } + "3" { + Write-Host "Starte Backend-Server..." -ForegroundColor $colors.Info + Start-Process -FilePath "python" -ArgumentList "backend/app/app.py" -NoNewWindow + + Write-Host "Starte Frontend-Server..." -ForegroundColor $colors.Info + Start-Process -FilePath "npm" -ArgumentList "run dev" -WorkingDirectory "frontend" -NoNewWindow + + Write-Host "Beide Server laufen jetzt im Hintergrund." -ForegroundColor $colors.Success + } + "4" { + $dockerInstalled = Test-Command "docker" + $dockerComposeInstalled = Test-Command "docker-compose" + + if ($dockerInstalled -and $dockerComposeInstalled) { + Write-Host "Starte Anwendung mit Docker Compose..." -ForegroundColor $colors.Info + Exec-Command "docker-compose up -d" "Starte Docker Container" + Write-Host "Docker Container wurden gestartet." -ForegroundColor $colors.Success + } else { + Write-Host "Docker oder Docker Compose ist nicht installiert." -ForegroundColor $colors.Error + } + } + "5" { + return + } + default { + Write-Host "Ungültige Option." -ForegroundColor $colors.Error + } + } + + Write-Host "" + Write-Host "Drücken Sie eine beliebige Taste, um fortzufahren..." + $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") +} + +# Hauptmenü anzeigen +function Show-MainMenu { + Show-Header "Hauptmenü" + + Write-Host "1. Systemvoraussetzungen prüfen" -ForegroundColor $colors.Command + Write-Host "2. Host-Konfiguration einrichten" -ForegroundColor $colors.Command + Write-Host "3. SSL-Zertifikate erstellen" -ForegroundColor $colors.Command + Write-Host "4. Umgebung einrichten (Abhängigkeiten installieren)" -ForegroundColor $colors.Command + Write-Host "5. Anwendung starten" -ForegroundColor $colors.Command + Write-Host "Q. Beenden" -ForegroundColor $colors.Command + Write-Host "" + Write-Host "Wählen Sie eine Option (1-5, Q): " -ForegroundColor $colors.Info -NoNewline + + $choice = Read-Host + + switch ($choice) { + "1" { + Test-Dependencies + Write-Host "" + Write-Host "Drücken Sie eine beliebige Taste, um fortzufahren..." + $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") + Show-MainMenu + } + "2" { + Setup-Hosts + Show-MainMenu + } + "3" { + Create-SSLCertificates + Show-MainMenu + } + "4" { + Setup-Environment + Show-MainMenu + } + "5" { + Start-Application + Show-MainMenu + } + "Q" { + exit + } + "q" { + exit + } + default { + Write-Host "Ungültige Option. Bitte versuchen Sie es erneut." -ForegroundColor $colors.Error + Start-Sleep -Seconds 2 + Show-MainMenu + } + } +} + +# Skript starten +Show-MainMenu \ No newline at end of file diff --git a/setup_ssl.sh b/setup_ssl.sh index 0947d8d8..1c8bfd3e 100644 --- a/setup_ssl.sh +++ b/setup_ssl.sh @@ -1,537 +1,280 @@ #!/bin/bash -# SSL-Konfiguration für MYP-Plattform (Linux/Raspberry Pi) +# MYP Installer für Linux/Unix-Systeme +# Dieses Skript wurde in das MYP Installer Control Center integriert +# und dient als Kompatibilitätslayer für Linux/Unix-Systeme # Farbdefinitionen RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' +BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # No Color -# Titel anzeigen -echo -e "${CYAN}====================================================" -echo -e " SSL-Konfiguration für MYP-Plattform" -echo -e "====================================================${NC}" +echo -e "${CYAN}=============================================================${NC}" +echo -e "${CYAN} MYP INSTALLER (UNIX/LINUX) ${NC}" +echo -e "${CYAN}=============================================================${NC}" +echo -e "${YELLOW}Dieses Skript ist ein Kompatibilitätslayer für Linux/Unix.${NC}" +echo -e "${YELLOW}Es wird empfohlen, das PowerShell-Skript myp_installer.ps1${NC}" +echo -e "${YELLOW}für eine vollständige Funktionalität zu verwenden. ${NC}" +echo -e "${CYAN}=============================================================${NC}" echo "" -# Prüfen, ob das Skript mit Root-Rechten ausgeführt wird +# Überprüfen, ob das Skript als Root ausgeführt wird if [ "$EUID" -ne 0 ]; then - echo -e "${YELLOW}WARNUNG: Dieses Skript sollte mit Root-Rechten ausgeführt werden, um Zertifikate im System zu installieren.${NC}" + echo -e "${YELLOW}Hinweis: Dieses Skript läuft ohne Root-Rechte.${NC}" echo -e "${YELLOW}Einige Funktionen sind möglicherweise eingeschränkt.${NC}" echo "" - - read -p "Möchten Sie trotzdem fortfahren? (j/n): " continue_anyway - if [ "$continue_anyway" != "j" ]; then - echo -e "${RED}Installation abgebrochen.${NC}" - exit 1 - fi fi -# Funktion zum Ausführen von Befehlen mit Ausgabe -exec_command() { - command="$1" - description="$2" - - echo -e "${YELLOW}> $description...${NC}" - eval $command - - 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 -} - -# Prüfen, ob Python und pip installiert sind -if ! command -v python3 &> /dev/null; then - echo -e "${RED}✗ Python 3 ist nicht installiert. Bitte installieren Sie Python 3.6 oder höher.${NC}" - exit 1 -fi - -if ! command -v pip3 &> /dev/null; then - echo -e "${RED}✗ pip3 ist nicht installiert. Bitte installieren Sie pip3.${NC}" - exit 1 -fi - -# 1. Prüfen, ob die notwendigen Abhängigkeiten installiert sind -echo -e "${CYAN}1. Prüfe Abhängigkeiten...${NC}" - -# Python-Abhängigkeiten prüfen -cryptography_installed=$(python3 -c "try: import cryptography; print('True'); except ImportError: print('False')" 2>/dev/null) -if [ "$cryptography_installed" != "True" ]; then - echo "Installiere Python-Abhängigkeit 'cryptography'..." - exec_command "pip3 install cryptography" "Installiere cryptography-Paket" -fi - -# 2. SSL-Zertifikat generieren +# Hauptmenu anzeigen +echo "Wählen Sie eine Option:" +echo "1. SSL-Zertifikate erstellen" +echo "2. Hosts-Konfiguration einrichten" +echo "3. Abhängigkeiten installieren" +echo "4. Anwendung starten" +echo "5. Beenden" echo "" -echo -e "${CYAN}2. Generiere SSL-Zertifikat...${NC}" +read -p "Option (1-5): " choice -# SSL-Verzeichnisse erstellen -mkdir -p backend/app/instance/ssl -mkdir -p frontend/ssl - -# Python-Skript erstellen, falls nicht vorhanden -if [ ! -f backend/generate_ssl_cert.py ]; then - echo "SSL-Zertifikatsgenerator nicht gefunden. Erstelle..." - - cat > backend/generate_ssl_cert.py << 'EOF' +case $choice in + 1) + echo -e "${BLUE}SSL-Zertifikate werden erstellt...${NC}" + + # Verzeichnis erstellen + mkdir -p backend/instance/ssl + + # Python-Skript zur Zertifikatserstellung erstellen + cat > temp_cert_script.py << 'EOL' #!/usr/bin/env python3 -# -*- coding: utf-8 -*- - import os import datetime -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 +import sys -def generate_ssl_certificate(): - """ - Generiert ein verbessertes SSL-Zertifikat für die MYP-Anwendung - mit korrekten Metadaten und alternativen Namen. - """ - print("Generiere verbessertes SSL-Zertifikat für die MYP-Anwendung...") - - # Verzeichnispfade definieren - ssl_dir = "app/instance/ssl" - ssl_cert_path = os.path.join(ssl_dir, "myp.crt") - ssl_key_path = os.path.join(ssl_dir, "myp.key") - +try: + 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 +except ImportError: + print("Fehler: Paket 'cryptography' nicht gefunden.") + print("Bitte installieren Sie es mit: pip install cryptography") + sys.exit(1) + +def create_self_signed_cert(cert_path, key_path, hostname="localhost"): # Verzeichnis erstellen, falls es nicht existiert - os.makedirs(ssl_dir, exist_ok=True) + 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)) - try: - # Privaten Schlüssel mit 4096 Bit generieren (sicherer) - private_key = rsa.generate_private_key( - public_exponent=65537, - key_size=4096, - ) - - # Aktuelles Datum und Ablaufdatum (1 Jahr gültig) - now = datetime.datetime.now() - valid_until = now + datetime.timedelta(days=365) - - # Liste aller möglichen Hostnamen/IPs - hostnames = [ - "localhost", - "raspberrypi", - "m040tbaraspi001", - "m040tbaraspi001.de040.corpintra.net" - ] - - # IP-Adressen (als String, werden später konvertiert) - ip_addresses = [ - "127.0.0.1", - "192.168.0.105" - ] - - # Erweiterte Zertifikatsattribute - subject = issuer = x509.Name([ - x509.NameAttribute(NameOID.COMMON_NAME, "raspberrypi"), - 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") - ]) - - # Subject Alternative Names (SAN) erstellen - san_list = [] - for hostname in hostnames: - san_list.append(x509.DNSName(hostname)) - - # IP-Adressen hinzufügen - import socket - for ip in ip_addresses: - san_list.append(x509.IPAddress(socket.inet_aton(ip))) - - # 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(san_list), - 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()) - - # Zertifikat und Schlüssel speichern - with open(ssl_key_path, "wb") as f: - f.write(private_key.private_bytes( - encoding=Encoding.PEM, - format=PrivateFormat.TraditionalOpenSSL, - encryption_algorithm=NoEncryption() - )) - - with open(ssl_cert_path, "wb") as f: - f.write(cert.public_bytes(Encoding.PEM)) - - # Kopieren des Zertifikats in das Frontend-Verzeichnis - frontend_ssl_dir = "../frontend/ssl" - os.makedirs(frontend_ssl_dir, exist_ok=True) - - import shutil - shutil.copy2(ssl_cert_path, os.path.join(frontend_ssl_dir, "myp.crt")) - shutil.copy2(ssl_key_path, os.path.join(frontend_ssl_dir, "myp.key")) - - print(f"SSL-Zertifikat wurde erstellt:") - print(f"- Zertifikat: {ssl_cert_path}") - print(f"- Schlüssel: {ssl_key_path}") - print(f"- Kopiert nach: {frontend_ssl_dir}") - print(f"- Gültig bis: {valid_until.strftime('%d.%m.%Y')}") - print(f"- Hostnamen: {', '.join(hostnames)}") - print(f"- IP-Adressen: {', '.join(ip_addresses)}") - - return True - except Exception as e: - print(f"Fehler beim Erstellen des SSL-Zertifikats: {e}") - return False + 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.") -if __name__ == "__main__": - generate_ssl_certificate() -EOF +# Hostname wählen +print("Wählen Sie den Hostnamen für das Zertifikat:") +print("1. localhost (für lokale Entwicklung)") +print("2. raspberrypi (für Raspberry Pi)") +print("3. m040tbaraspi001.de040.corpintra.net (für Unternehmens-Setup)") +choice = input("Option (1-3, Standard: 1): ") - # Ausführbar machen - chmod +x backend/generate_ssl_cert.py -fi +hostname = "localhost" +if choice == "2": + hostname = "raspberrypi" +elif choice == "3": + hostname = "m040tbaraspi001.de040.corpintra.net" -# Zertifikat generieren -cert_gen_success=$(exec_command "cd backend && python3 generate_ssl_cert.py" "Generiere SSL-Zertifikat") - -if [ $? -ne 0 ]; then - echo -e "${RED}✗ Fehler bei der Zertifikatsgenerierung. Abbruch.${NC}" - exit 1 -fi - -# 3. Zertifikat im System installieren -echo "" -echo -e "${CYAN}3. Installiere Zertifikat im System...${NC}" - -if [ "$EUID" -eq 0 ]; then - # Als Root ausgeführt - cert_path=$(readlink -f backend/app/instance/ssl/myp.crt) - - # Zielverzeichnis für System-Zertifikate - if [ -d "/usr/local/share/ca-certificates" ]; then - # Debian/Ubuntu/Raspberry Pi OS - cert_dir="/usr/local/share/ca-certificates" - exec_command "cp $cert_path $cert_dir/myp.crt" "Kopiere Zertifikat in System-Verzeichnis" - exec_command "update-ca-certificates" "Aktualisiere System-Zertifikate" - elif [ -d "/etc/pki/ca-trust/source/anchors" ]; then - # RHEL/CentOS/Fedora - cert_dir="/etc/pki/ca-trust/source/anchors" - exec_command "cp $cert_path $cert_dir/myp.crt" "Kopiere Zertifikat in System-Verzeichnis" - exec_command "update-ca-trust extract" "Aktualisiere System-Zertifikate" - else - echo -e "${YELLOW}Unbekanntes System. Versuche direkte Installation...${NC}" - if command -v certutil &> /dev/null; then - exec_command "certutil -A -n 'MYP SSL Certificate' -t 'C,,' -i $cert_path -d sql:$HOME/.pki/nssdb" "Installiere mit certutil" +# Zertifikate erstellen +create_self_signed_cert("backend/instance/ssl/myp.crt", "backend/instance/ssl/myp.key", hostname) +create_self_signed_cert("backend/instance/ssl/frontend.crt", "backend/instance/ssl/frontend.key", hostname) +EOL + + # Python-Skript ausführbar machen und ausführen + chmod +x temp_cert_script.py + python3 temp_cert_script.py || python temp_cert_script.py + + # Temporäres Skript löschen + rm temp_cert_script.py + + echo -e "${GREEN}SSL-Zertifikate erstellt.${NC}" + ;; + + 2) + echo -e "${BLUE}Hosts-Konfiguration wird eingerichtet...${NC}" + + # Lokale IP-Adresse ermitteln + LOCAL_IP=$(hostname -I | awk '{print $1}') + if [ -z "$LOCAL_IP" ]; then + LOCAL_IP="127.0.0.1" fi - fi -else - echo -e "${YELLOW}Überspringen der System-Installation, da das Skript nicht als Root ausgeführt wird.${NC}" - echo -e "${YELLOW}Sie können das Zertifikat später manuell installieren durch:${NC}" - echo -e "${NC}sudo cp backend/app/instance/ssl/myp.crt /usr/local/share/ca-certificates/ && sudo update-ca-certificates${NC}" -fi - -# 4. Frontend konfigurieren -echo "" -echo -e "${CYAN}4. Konfiguriere Frontend...${NC}" - -# Erstelle Frontend-Konfigurationsskript -cat > frontend/configure_ssl.js << 'EOF' -#!/usr/bin/env node - -/** - * Dieses Skript konfiguriert das Next.js-Frontend, um das selbstsignierte SSL-Zertifikat zu akzeptieren - * und die richtigen SSL-Einstellungen im Frontend zu setzen. - */ - -const fs = require('fs'); -const path = require('path'); - -// Pfade definieren -const ENV_LOCAL_PATH = path.join(__dirname, '.env.local'); -const ENV_FRONTEND_PATH = path.join(__dirname, 'env.frontend'); -const SSL_DIR = path.join(__dirname, 'ssl'); -const NEXT_CONFIG_PATH = path.join(__dirname, 'next.config.js'); - -console.log('=== Frontend-SSL-Konfiguration ==='); - -// Prüfen, ob SSL-Verzeichnis und Zertifikate existieren -if (!fs.existsSync(SSL_DIR) || - !fs.existsSync(path.join(SSL_DIR, 'myp.crt')) || - !fs.existsSync(path.join(SSL_DIR, 'myp.key'))) { - console.error('SSL-Zertifikate nicht gefunden. Bitte zuerst das Backend-Skript ausführen.'); - process.exit(1); -} - -console.log('SSL-Zertifikate gefunden. Konfiguriere Frontend...'); - -// Umgebungsvariablen konfigurieren -function updateEnvFile() { - try { - let envContent; - - // .env.local erstellen oder aktualisieren - if (fs.existsSync(ENV_LOCAL_PATH)) { - envContent = fs.readFileSync(ENV_LOCAL_PATH, 'utf8'); - } else if (fs.existsSync(ENV_FRONTEND_PATH)) { - envContent = fs.readFileSync(ENV_FRONTEND_PATH, 'utf8'); - } else { - envContent = `# MYP Frontend Umgebungsvariablen\n`; - } - - // SSL-Konfigurationen - const sslConfigs = [ - 'NODE_TLS_REJECT_UNAUTHORIZED=0', - 'HTTPS=true', - 'SSL_CRT_FILE=./ssl/myp.crt', - 'SSL_KEY_FILE=./ssl/myp.key', - 'NEXT_PUBLIC_API_URL=https://raspberrypi:443', - 'NEXT_PUBLIC_BACKEND_HOST=raspberrypi:443', - 'NEXT_PUBLIC_BACKEND_PROTOCOL=https' - ]; - - // Existierende Konfigurationen aktualisieren - sslConfigs.forEach(config => { - const [key, value] = config.split('='); - const regex = new RegExp(`^${key}=.*$`, 'm'); - - if (envContent.match(regex)) { - // Update existierende Konfiguration - envContent = envContent.replace(regex, config); - } else { - // Neue Konfiguration hinzufügen - envContent += `\n${config}`; - } - }); - - // Speichern der aktualisierten Umgebungsvariablen - fs.writeFileSync(ENV_LOCAL_PATH, envContent); - console.log('.env.local Datei aktualisiert mit SSL-Konfigurationen'); - return true; - } catch (error) { - console.error(`Fehler bei der Aktualisierung der Umgebungsvariablen: ${error.message}`); - return false; - } -} - -// Next.js-Konfiguration aktualisieren -function updateNextConfig() { - try { - let configContent; - - // next.config.js erstellen oder aktualisieren - if (fs.existsSync(NEXT_CONFIG_PATH)) { - configContent = fs.readFileSync(NEXT_CONFIG_PATH, 'utf8'); - } else { - configContent = `/** @type {import('next').NextConfig} */\n\nconst nextConfig = {}\n\nmodule.exports = nextConfig\n`; - } - - // Prüfen, ob bereits eine HTTPS-Konfiguration vorhanden ist - if (configContent.includes('serverOptions:') && configContent.includes('https:')) { - console.log('HTTPS-Konfiguration ist bereits in der next.config.js vorhanden.'); - return true; - } - - // HTTPS-Konfiguration hinzufügen - const httpsConfig = ` -/** @type {import('next').NextConfig} */ -const fs = require('fs'); -const path = require('path'); - -const nextConfig = { - reactStrictMode: true, - webpack: (config) => { - return config; - }, - // HTTPS-Konfiguration für die Entwicklung - devServer: { - https: { - key: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.key')), - cert: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.crt')), - }, - }, - // Konfiguration für selbstsignierte Zertifikate - serverOptions: { - https: { - key: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.key')), - cert: fs.readFileSync(path.resolve(__dirname, 'ssl/myp.crt')), - }, - }, - // Zusätzliche Konfigurationen - async rewrites() { - return [ - { - source: '/api/:path*', - destination: 'https://raspberrypi:443/api/:path*', - }, - ] - } -}; - -module.exports = nextConfig; -`; - - // Speichern der aktualisierten Next.js-Konfiguration - fs.writeFileSync(NEXT_CONFIG_PATH, httpsConfig); - console.log('next.config.js Datei aktualisiert mit HTTPS-Konfiguration'); - return true; - } catch (error) { - console.error(`Fehler bei der Aktualisierung der Next.js-Konfiguration: ${error.message}`); - return false; - } -} - -// Update der Fetch-Konfiguration -function updateFetchConfig() { - try { - const fetchConfigPath = path.join(__dirname, 'src', 'utils', 'api-config.ts'); - - if (!fs.existsSync(fetchConfigPath)) { - console.warn('Datei api-config.ts nicht gefunden. Überspringe Aktualisierung.'); - return true; - } - - // Lesen der aktuellen Konfiguration - let configContent = fs.readFileSync(fetchConfigPath, 'utf8'); - - // Sicherstellen, dass SSL-Verbindungen akzeptiert werden - if (!configContent.includes('NODE_TLS_REJECT_UNAUTHORIZED=0')) { - // Hinzufügen eines Kommentars zu Beginn der Datei - configContent = `// SSL-Verbindungen akzeptieren (selbstsignierte Zertifikate) -process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; - -${configContent}`; - } - - // Speichern der aktualisierten Fetch-Konfiguration - fs.writeFileSync(fetchConfigPath, configContent); - console.log('api-config.ts Datei aktualisiert, um selbstsignierte Zertifikate zu akzeptieren'); - return true; - } catch (error) { - console.error(`Fehler bei der Aktualisierung der Fetch-Konfiguration: ${error.message}`); - return false; - } -} - -// Hauptfunktion -function main() { - let success = true; - success = updateEnvFile() && success; - success = updateNextConfig() && success; - success = updateFetchConfig() && success; + echo "Lokale IP-Adresse: $LOCAL_IP" - if (success) { - console.log('\n=== Konfiguration erfolgreich abgeschlossen ==='); - console.log('Das Frontend wurde für die Verwendung von HTTPS mit dem selbstsignierten Zertifikat konfiguriert.'); - } else { - console.error('\n=== Konfiguration nicht vollständig abgeschlossen ==='); - console.error('Es gab Probleme bei der Konfiguration des Frontends.'); - } -} - -// Ausführen der Hauptfunktion -main(); -EOF - -# Ausführbar machen -chmod +x frontend/configure_ssl.js - -# Frontend konfigurieren -if command -v node &> /dev/null; then - frontend_config_success=$(exec_command "cd frontend && node configure_ssl.js" "Konfiguriere Frontend") -else - echo -e "${YELLOW}Node.js ist nicht installiert. Überspringe Frontend-Konfiguration.${NC}" - echo -e "${YELLOW}Sie können die Frontend-Konfiguration später manuell durchführen durch:${NC}" - echo -e "${NC}cd frontend && node configure_ssl.js${NC}" -fi - -# 5. Docker-Compose Datei aktualisieren -echo "" -echo -e "${CYAN}5. Aktualisiere Docker-Compose-Konfiguration...${NC}" - -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 -else - echo -e "${YELLOW}✗ Docker-Compose-Datei nicht gefunden. Überspringe diese Konfiguration.${NC}" -fi - -# 6. Docker-Container aktualisieren -echo "" -echo -e "${CYAN}6. Möchten Sie die Docker-Container neu starten?${NC}" -read -p "Neu starten (j/n): " restart_docker - -if [ "$restart_docker" = "j" ]; then - if command -v docker-compose &> /dev/null || command -v docker &> /dev/null; then - echo "Starte Docker-Container neu..." - - if command -v docker-compose &> /dev/null; then - exec_command "docker-compose down && docker-compose up -d" "Starte Docker-Container neu mit docker-compose" + # Hosts-Datei bearbeiten + if [ "$EUID" -eq 0 ]; then + # Check if entries already exist + if ! grep -q "m040tbaraspi001.de040.corpintra.net" /etc/hosts; then + echo "" >> /etc/hosts + echo "# MYP Frontend Host" >> /etc/hosts + echo "$LOCAL_IP m040tbaraspi001.de040.corpintra.net m040tbaraspi001" >> /etc/hosts + echo -e "${GREEN}Frontend-Hostname hinzugefügt${NC}" + else + echo -e "${YELLOW}Frontend-Hostname ist bereits konfiguriert${NC}" + fi + + if ! grep -q "raspberrypi" /etc/hosts; then + echo "" >> /etc/hosts + echo "# MYP Backend Host" >> /etc/hosts + echo "$LOCAL_IP raspberrypi" >> /etc/hosts + echo -e "${GREEN}Backend-Hostname hinzugefügt${NC}" + else + echo -e "${YELLOW}Backend-Hostname ist bereits konfiguriert${NC}" + fi else - exec_command "docker compose down && docker compose up -d" "Starte Docker-Container neu mit docker compose" + echo -e "${RED}Root-Rechte erforderlich, um die Hosts-Datei zu bearbeiten.${NC}" + echo -e "${YELLOW}Bitte führen Sie die folgenden Befehle manuell als Root aus:${NC}" + echo "echo \"\" >> /etc/hosts" + echo "echo \"# MYP Frontend Host\" >> /etc/hosts" + echo "echo \"$LOCAL_IP m040tbaraspi001.de040.corpintra.net m040tbaraspi001\" >> /etc/hosts" + echo "echo \"\" >> /etc/hosts" + echo "echo \"# MYP Backend Host\" >> /etc/hosts" + echo "echo \"$LOCAL_IP raspberrypi\" >> /etc/hosts" fi - else - echo -e "${YELLOW}Docker ist nicht installiert oder nicht im PATH. Überspringe Neustart der Container.${NC}" - fi -fi + ;; + + 3) + echo -e "${BLUE}Abhängigkeiten werden installiert...${NC}" + + # Python-Abhängigkeiten + echo "Installiere Python-Abhängigkeiten..." + pip3 install -r backend/requirements.txt || pip install -r backend/requirements.txt + + # Frontend-Abhängigkeiten + if command -v npm &> /dev/null; then + echo "Installiere Frontend-Abhängigkeiten..." + (cd frontend && npm install) + else + echo -e "${YELLOW}npm nicht gefunden. Frontend-Abhängigkeiten werden übersprungen.${NC}" + fi + + echo -e "${GREEN}Abhängigkeiten installiert.${NC}" + ;; + + 4) + echo -e "${BLUE}Anwendung wird gestartet...${NC}" + echo "Wie möchten Sie die Anwendung starten?" + echo "1. Backend-Server starten (Python)" + echo "2. Frontend-Server starten (npm)" + echo "3. Mit Docker Compose starten" + read -p "Option (1-3): " start_choice + + case $start_choice in + 1) + echo "Starte Backend-Server..." + python3 backend/app/app.py || python backend/app/app.py & + echo -e "${GREEN}Backend-Server läuft im Hintergrund.${NC}" + ;; + 2) + echo "Starte Frontend-Server..." + (cd frontend && npm run dev) & + echo -e "${GREEN}Frontend-Server läuft im Hintergrund.${NC}" + ;; + 3) + echo "Starte Anwendung mit Docker Compose..." + docker-compose up -d + echo -e "${GREEN}Docker Container wurden gestartet.${NC}" + ;; + *) + echo -e "${RED}Ungültige Option.${NC}" + ;; + esac + ;; + + 5) + echo -e "${GREEN}Installation wird beendet.${NC}" + exit 0 + ;; + + *) + echo -e "${RED}Ungültige Option.${NC}" + ;; +esac -# Abschluss echo "" -echo -e "${CYAN}====================================================" -echo -e " SSL-Konfiguration abgeschlossen" -echo -e "====================================================${NC}" -echo "" -echo -e "${GREEN}Das SSL-Zertifikat wurde erfolgreich generiert und konfiguriert.${NC}" -echo -e "${GREEN}Sie können nun auf folgende Weise auf die Anwendung zugreifen:${NC}" -echo -e "${GREEN}- Backend: https://raspberrypi:443${NC}" -echo -e "${GREEN}- Frontend: https://localhost:3000${NC}" -echo "" -echo -e "${YELLOW}Hinweis: Bei der ersten Verbindung müssen Sie möglicherweise${NC}" -echo -e "${YELLOW}das selbstsignierte Zertifikat in Ihrem Browser akzeptieren.${NC}" -echo "" \ No newline at end of file +echo -e "${CYAN}Installation abgeschlossen. Drücken Sie ENTER, um fortzufahren...${NC}" +read \ No newline at end of file