Projektarbeit-MYP/myp_installer.sh

701 lines
21 KiB
Bash

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