"Add test script and guide for separate servers setup (feat)"
This commit is contained in:
parent
03ff4260e2
commit
c1e8ee01c5
@ -10,7 +10,7 @@ PYTHONUNBUFFERED=1
|
|||||||
# SQLite (Default)
|
# SQLite (Default)
|
||||||
DATABASE_PATH=instance/myp.db
|
DATABASE_PATH=instance/myp.db
|
||||||
|
|
||||||
# PostgreSQL (Optional)
|
# PostgreSQL (Optional - für Produktionsumgebung empfohlen)
|
||||||
DB_NAME=myp_backend
|
DB_NAME=myp_backend
|
||||||
DB_USER=myp_user
|
DB_USER=myp_user
|
||||||
DB_PASSWORD=secure_backend_password
|
DB_PASSWORD=secure_backend_password
|
||||||
@ -48,18 +48,38 @@ REDIS_DB=0
|
|||||||
# === LOGGING ===
|
# === LOGGING ===
|
||||||
LOG_LEVEL=INFO
|
LOG_LEVEL=INFO
|
||||||
LOG_FILE=logs/backend.log
|
LOG_FILE=logs/backend.log
|
||||||
LOG_MAX_SIZE=10485760
|
LOG_MAX_BYTES=10485760
|
||||||
LOG_BACKUP_COUNT=5
|
LOG_BACKUP_COUNT=5
|
||||||
|
|
||||||
# === DATEISYSTEM ===
|
# === PRODUKTIONS-KONFIGURATION ===
|
||||||
UPLOAD_FOLDER=uploads
|
# Gunicorn-Einstellungen
|
||||||
MAX_CONTENT_LENGTH=16777216
|
WORKERS=4
|
||||||
|
BIND_ADDRESS=0.0.0.0:5000
|
||||||
|
TIMEOUT=30
|
||||||
|
KEEP_ALIVE=5
|
||||||
|
MAX_REQUESTS=1000
|
||||||
|
MAX_REQUESTS_JITTER=100
|
||||||
|
|
||||||
|
# === SICHERHEITS-EINSTELLUNGEN ===
|
||||||
|
WTF_CSRF_ENABLED=true
|
||||||
|
FORCE_HTTPS=false
|
||||||
|
RATE_LIMIT_ENABLED=true
|
||||||
|
MAX_REQUESTS_PER_MINUTE=60
|
||||||
|
RATE_LIMIT_WINDOW_MINUTES=15
|
||||||
|
|
||||||
# === MONITORING ===
|
# === MONITORING ===
|
||||||
HEALTH_CHECK_INTERVAL=30
|
HEALTH_CHECK_INTERVAL=30
|
||||||
METRICS_ENABLED=true
|
METRICS_ENABLED=true
|
||||||
METRICS_PORT=9090
|
METRICS_PORT=9090
|
||||||
|
|
||||||
|
# === JOB-KONFIGURATION ===
|
||||||
|
JOB_CHECK_INTERVAL=60
|
||||||
|
SOCKET_CHECK_INTERVAL=120
|
||||||
|
|
||||||
|
# === DATEISYSTEM ===
|
||||||
|
UPLOAD_FOLDER=uploads
|
||||||
|
MAX_CONTENT_LENGTH=16777216
|
||||||
|
|
||||||
# === ENTWICKLUNG ===
|
# === ENTWICKLUNG ===
|
||||||
DEBUG=false
|
DEBUG=false
|
||||||
TESTING=false
|
TESTING=false
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# MYP Backend Installations-Skript
|
# 🏭 MYP Backend - Installations-Skript
|
||||||
# Dieses Skript installiert das Backend mit Docker und Host-Netzwerkanbindung
|
# Installiert das Backend für Produktionsbetrieb oder Entwicklung
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
# Farbcodes für Ausgabe
|
# Farbcodes für Ausgabe
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
@ -15,496 +17,335 @@ log() {
|
|||||||
echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
|
echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
success_log() {
|
||||||
|
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] SUCCESS:${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
warning_log() {
|
||||||
|
echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] WARNING:${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
error_log() {
|
error_log() {
|
||||||
echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] FEHLER:${NC} $1" >&2
|
echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] FEHLER:${NC} $1" >&2
|
||||||
}
|
}
|
||||||
|
|
||||||
# Funktion zum Bereinigen vorhandener Installationen
|
# Banner
|
||||||
cleanup_existing_installation() {
|
echo "========================================"
|
||||||
log "${YELLOW}Bereinige vorhandene Installation...${NC}"
|
echo "🏭 MYP Backend - Installation"
|
||||||
|
echo "========================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
# Stoppe und entferne existierende Container
|
# Arbeitsverzeichnis
|
||||||
if docker ps -a | grep -q "myp-backend"; then
|
|
||||||
log "Stoppe und entferne existierenden Backend-Container..."
|
|
||||||
docker stop myp-backend &>/dev/null || true
|
|
||||||
docker rm myp-backend &>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Entferne Docker Images
|
|
||||||
if docker images | grep -q "myp-backend"; then
|
|
||||||
log "Entferne existierendes Backend-Image..."
|
|
||||||
docker rmi myp-backend &>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
log "${GREEN}Bereinigung abgeschlossen.${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Pfade definieren
|
|
||||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
BACKEND_DIR="$SCRIPT_DIR"
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
# Bereinige existierende Installation
|
log "Arbeitsverzeichnis: $SCRIPT_DIR"
|
||||||
cleanup_existing_installation
|
|
||||||
|
|
||||||
# Funktion zur Installation von Docker und Docker Compose für Raspberry Pi
|
# Installation-Modus bestimmen
|
||||||
install_docker() {
|
INSTALL_MODE="development"
|
||||||
log "${YELLOW}Docker ist nicht installiert. Installation wird gestartet...${NC}"
|
if [ "$1" = "--production" ]; then
|
||||||
|
INSTALL_MODE="production"
|
||||||
# Erkenne Raspberry Pi
|
log "🚀 Produktions-Installation gewählt"
|
||||||
if [ -f /proc/device-tree/model ] && grep -q "Raspberry Pi" /proc/device-tree/model; then
|
elif [ "$1" = "--development" ]; then
|
||||||
log "${GREEN}Raspberry Pi erkannt. Installiere Docker für ARM-Architektur...${NC}"
|
INSTALL_MODE="development"
|
||||||
IS_RASPBERRY_PI=true
|
log "🔧 Entwicklungs-Installation gewählt"
|
||||||
else
|
|
||||||
IS_RASPBERRY_PI=false
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Aktualisiere Paketindex
|
|
||||||
if ! sudo apt-get update; then
|
|
||||||
error_log "Konnte Paketindex nicht aktualisieren. Bitte manuell installieren."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Installiere erforderliche Pakete
|
|
||||||
if ! sudo apt-get install -y apt-transport-https ca-certificates curl gnupg software-properties-common; then
|
|
||||||
error_log "Konnte erforderliche Pakete nicht installieren. Bitte manuell installieren."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Raspberry Pi-spezifische Installation
|
|
||||||
if [ "$IS_RASPBERRY_PI" = true ]; then
|
|
||||||
# Setze Systemarchitektur für Raspberry Pi (armhf oder arm64)
|
|
||||||
ARCH=$(dpkg --print-architecture)
|
|
||||||
log "Erkannte Systemarchitektur: ${ARCH}"
|
|
||||||
|
|
||||||
# Installiere Docker mit convenience script (für Raspberry Pi empfohlen)
|
|
||||||
log "${YELLOW}Installiere Docker mit dem convenience script...${NC}"
|
|
||||||
curl -fsSL https://get.docker.com -o get-docker.sh
|
|
||||||
sudo sh get-docker.sh
|
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
error_log "Docker-Installation fehlgeschlagen. Bitte manuell installieren."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# Standard-Installation für andere Systeme
|
|
||||||
# Füge Docker's offiziellen GPG-Schlüssel hinzu
|
|
||||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
|
|
||||||
|
|
||||||
# Füge Docker-Repository hinzu
|
|
||||||
if ! sudo add-apt-repository "deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"; then
|
|
||||||
error_log "Konnte Docker-Repository nicht hinzufügen. Prüfen Sie, ob Ihr System unterstützt wird."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Aktualisiere Paketindex erneut
|
|
||||||
sudo apt-get update
|
|
||||||
|
|
||||||
# Installiere Docker
|
|
||||||
if ! sudo apt-get install -y docker-ce docker-ce-cli containerd.io; then
|
|
||||||
error_log "Konnte Docker nicht installieren. Bitte manuell installieren."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Füge aktuellen Benutzer zur Docker-Gruppe hinzu
|
|
||||||
sudo usermod -aG docker "$USER"
|
|
||||||
|
|
||||||
log "${GREEN}Docker wurde installiert.${NC}"
|
|
||||||
log "${YELLOW}WICHTIG: Möglicherweise müssen Sie sich neu anmelden, damit die Gruppenänderung wirksam wird.${NC}"
|
|
||||||
|
|
||||||
# Prüfen, ob Docker Compose v2 Plugin verfügbar ist (bevorzugt, da moderner)
|
|
||||||
log "${YELLOW}Prüfe Docker Compose Version...${NC}"
|
|
||||||
|
|
||||||
if docker compose version &> /dev/null; then
|
|
||||||
log "${GREEN}Docker Compose v2 Plugin ist bereits installiert.${NC}"
|
|
||||||
DOCKER_COMPOSE_V2=true
|
|
||||||
else
|
|
||||||
log "${YELLOW}Docker Compose v2 Plugin nicht gefunden. Versuche Docker Compose v1 zu installieren...${NC}"
|
|
||||||
DOCKER_COMPOSE_V2=false
|
|
||||||
|
|
||||||
if [ "$IS_RASPBERRY_PI" = true ]; then
|
|
||||||
# Für Raspberry Pi ist es besser, die richtige Architektur zu verwenden
|
|
||||||
if [ "$ARCH" = "armhf" ]; then
|
|
||||||
log "Installiere Docker Compose für armhf (32-bit)..."
|
|
||||||
sudo curl -L "https://github.com/docker/compose/releases/download/v2.6.1/docker-compose-linux-armv7" -o /usr/local/bin/docker-compose
|
|
||||||
elif [ "$ARCH" = "arm64" ]; then
|
|
||||||
log "Installiere Docker Compose für arm64 (64-bit)..."
|
|
||||||
sudo curl -L "https://github.com/docker/compose/releases/download/v2.6.1/docker-compose-linux-aarch64" -o /usr/local/bin/docker-compose
|
|
||||||
else
|
|
||||||
# Fallback auf v1.29.2 für unbekannte ARM-Architekturen
|
|
||||||
log "Verwende automatische Architekturerkennung für Docker Compose v1.29.2..."
|
|
||||||
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# Für andere Systeme versuche zuerst v2, dann v1.29.2 als Fallback
|
|
||||||
log "Installiere Docker Compose v2 für $(uname -s)/$(uname -m)..."
|
|
||||||
if ! sudo curl -L "https://github.com/docker/compose/releases/download/v2.6.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose; then
|
|
||||||
log "${YELLOW}Konnte Docker Compose v2 nicht herunterladen. Versuche v1.29.2...${NC}"
|
|
||||||
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
error_log "Konnte Docker Compose nicht herunterladen. Bitte manuell installieren."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
sudo chmod +x /usr/local/bin/docker-compose
|
|
||||||
|
|
||||||
log "${GREEN}Docker Compose wurde installiert.${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Starte Docker-Dienst
|
|
||||||
if command -v systemctl &> /dev/null; then
|
|
||||||
sudo systemctl enable docker
|
|
||||||
sudo systemctl start docker
|
|
||||||
elif command -v service &> /dev/null; then
|
|
||||||
sudo service docker enable
|
|
||||||
sudo service docker start
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Prüfen ob Docker installiert ist
|
|
||||||
if ! command -v docker &> /dev/null; then
|
|
||||||
log "${YELLOW}Docker ist nicht installiert.${NC}"
|
|
||||||
read -p "Möchten Sie Docker installieren? (j/n): " install_docker_choice
|
|
||||||
if [[ "$install_docker_choice" == "j" ]]; then
|
|
||||||
install_docker
|
|
||||||
else
|
|
||||||
error_log "Docker wird für die Installation benötigt. Bitte installieren Sie Docker manuell."
|
|
||||||
log "Siehe: https://docs.docker.com/get-docker/"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Prüfen ob Docker Daemon läuft
|
|
||||||
if ! docker info &> /dev/null; then
|
|
||||||
log "${YELLOW}Docker-Daemon läuft nicht. Versuche, den Dienst zu starten...${NC}"
|
|
||||||
|
|
||||||
# Versuche, Docker zu starten
|
|
||||||
if command -v systemctl &> /dev/null; then
|
|
||||||
sudo systemctl start docker
|
|
||||||
elif command -v service &> /dev/null; then
|
|
||||||
sudo service docker start
|
|
||||||
else
|
|
||||||
error_log "Konnte Docker-Daemon nicht starten. Bitte starten Sie den Docker-Dienst manuell."
|
|
||||||
log "Starten mit: sudo systemctl start docker oder sudo service docker start"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Prüfe erneut, ob Docker läuft
|
|
||||||
if ! docker info &> /dev/null; then
|
|
||||||
error_log "Docker-Daemon konnte nicht gestartet werden. Bitte starten Sie den Docker-Dienst manuell."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
log "${GREEN}Docker-Daemon wurde erfolgreich gestartet.${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Prüfen ob Docker Compose installiert ist
|
|
||||||
if docker compose version &> /dev/null; then
|
|
||||||
log "${GREEN}Docker Compose v2 Plugin ist bereits installiert.${NC}"
|
|
||||||
DOCKER_COMPOSE_V2=true
|
|
||||||
elif command -v docker-compose &> /dev/null; then
|
|
||||||
log "${GREEN}Docker Compose v1 ist bereits installiert.${NC}"
|
|
||||||
DOCKER_COMPOSE_V2=false
|
|
||||||
else
|
else
|
||||||
log "${YELLOW}Docker Compose ist nicht installiert.${NC}"
|
echo "Wählen Sie den Installationsmodus:"
|
||||||
DOCKER_COMPOSE_V2=false
|
echo "1) Entwicklung (empfohlen für lokale Tests)"
|
||||||
read -p "Möchten Sie Docker Compose installieren? (j/n): " install_compose_choice
|
echo "2) Produktion (für Server-Deployment)"
|
||||||
if [[ "$install_compose_choice" == "j" ]]; then
|
read -p "Ihre Wahl (1/2): " choice
|
||||||
log "${YELLOW}Installiere Docker Compose...${NC}"
|
|
||||||
|
|
||||||
# Prüfe ob das Betriebssystem ARM-basiert ist (z.B. Raspberry Pi)
|
case $choice in
|
||||||
if grep -q "arm" /proc/cpuinfo 2> /dev/null; then
|
1) INSTALL_MODE="development" ;;
|
||||||
ARCH=$(dpkg --print-architecture 2> /dev/null || echo "unknown")
|
2) INSTALL_MODE="production" ;;
|
||||||
IS_RASPBERRY_PI=true
|
*) log "Verwende Standard-Entwicklungsmodus" && INSTALL_MODE="development" ;;
|
||||||
else
|
esac
|
||||||
IS_RASPBERRY_PI=false
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Versuche zuerst Docker Compose v2 zu installieren
|
|
||||||
if [ "$IS_RASPBERRY_PI" = true ]; then
|
|
||||||
if [ "$ARCH" = "armhf" ]; then
|
|
||||||
log "Installiere Docker Compose für armhf (32-bit)..."
|
|
||||||
sudo curl -L "https://github.com/docker/compose/releases/download/v2.6.1/docker-compose-linux-armv7" -o /usr/local/bin/docker-compose
|
|
||||||
elif [ "$ARCH" = "arm64" ]; then
|
|
||||||
log "Installiere Docker Compose für arm64 (64-bit)..."
|
|
||||||
sudo curl -L "https://github.com/docker/compose/releases/download/v2.6.1/docker-compose-linux-aarch64" -o /usr/local/bin/docker-compose
|
|
||||||
else
|
|
||||||
log "Verwende automatische Architekturerkennung für Docker Compose v1.29.2..."
|
|
||||||
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
log "Installiere Docker Compose v2 für $(uname -s)/$(uname -m)..."
|
|
||||||
if ! sudo curl -L "https://github.com/docker/compose/releases/download/v2.6.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose; then
|
|
||||||
log "${YELLOW}Konnte Docker Compose v2 nicht herunterladen. Versuche v1.29.2...${NC}"
|
|
||||||
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
error_log "Konnte Docker Compose nicht herunterladen. Bitte manuell installieren."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
sudo chmod +x /usr/local/bin/docker-compose
|
|
||||||
|
|
||||||
log "${GREEN}Docker Compose wurde installiert.${NC}"
|
|
||||||
else
|
|
||||||
error_log "Docker Compose wird für die Installation benötigt. Bitte installieren Sie es manuell."
|
|
||||||
log "Siehe: https://docs.docker.com/compose/install/"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Prüfen ob wget installiert ist (wird für healthcheck verwendet)
|
log "Installationsmodus: $INSTALL_MODE"
|
||||||
if ! command -v wget &> /dev/null; then
|
|
||||||
error_log "wget ist nicht installiert, wird aber für den Container-Healthcheck benötigt."
|
|
||||||
log "Installation mit: sudo apt-get install wget"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Wechsle ins Backend-Verzeichnis
|
# Bereinige vorherige Installation
|
||||||
log "Wechsle ins Verzeichnis: $BACKEND_DIR"
|
cleanup_existing_installation() {
|
||||||
cd "$BACKEND_DIR" || {
|
log "🧹 Bereinige vorherige Installation..."
|
||||||
error_log "Konnte nicht ins Verzeichnis $BACKEND_DIR wechseln."
|
|
||||||
exit 1
|
# Stoppe laufende Prozesse
|
||||||
|
if pgrep -f "flask run" > /dev/null; then
|
||||||
|
log "Stoppe laufende Flask-Prozesse..."
|
||||||
|
pkill -f "flask run" || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if pgrep -f "gunicorn" > /dev/null; then
|
||||||
|
log "Stoppe laufende Gunicorn-Prozesse..."
|
||||||
|
pkill -f "gunicorn.*wsgi:application" || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Entferne alte virtuelle Umgebung
|
||||||
|
if [ -d "venv" ]; then
|
||||||
|
log "Entferne alte virtuelle Umgebung..."
|
||||||
|
rm -rf venv
|
||||||
|
fi
|
||||||
|
|
||||||
|
success_log "Bereinigung abgeschlossen"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Prüfe ob Dockerfile existiert
|
# System-Dependencies prüfen und installieren
|
||||||
if [ ! -f "Dockerfile" ]; then
|
install_system_dependencies() {
|
||||||
error_log "Dockerfile nicht gefunden in $BACKEND_DIR."
|
log "🔧 Prüfe System-Dependencies..."
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Prüfe ob docker-compose.yml existiert
|
# Betriebssystem erkennen
|
||||||
if [ ! -f "docker-compose.yml" ]; then
|
if [ -f /etc/os-release ]; then
|
||||||
error_log "docker-compose.yml nicht gefunden in $BACKEND_DIR."
|
. /etc/os-release
|
||||||
exit 1
|
OS=$NAME
|
||||||
fi
|
VER=$VERSION_ID
|
||||||
|
elif type lsb_release >/dev/null 2>&1; then
|
||||||
|
OS=$(lsb_release -si)
|
||||||
|
VER=$(lsb_release -sr)
|
||||||
|
else
|
||||||
|
OS=$(uname -s)
|
||||||
|
VER=$(uname -r)
|
||||||
|
fi
|
||||||
|
|
||||||
# Erstelle .env-Datei
|
log "Erkanntes System: $OS $VER"
|
||||||
log "${YELLOW}Erstelle .env Datei...${NC}"
|
|
||||||
cat > .env << EOL
|
# Python 3 prüfen
|
||||||
SECRET_KEY=7445630171969DFAC92C53CEC92E67A9CB2E00B3CB2F
|
if ! command -v python3 &> /dev/null; then
|
||||||
|
error_log "Python 3 ist nicht installiert!"
|
||||||
|
log "Installationsanleitung:"
|
||||||
|
if [[ "$OS" == *"Ubuntu"* ]] || [[ "$OS" == *"Debian"* ]]; then
|
||||||
|
log "sudo apt update && sudo apt install python3 python3-pip python3-venv"
|
||||||
|
elif [[ "$OS" == *"CentOS"* ]] || [[ "$OS" == *"Red Hat"* ]]; then
|
||||||
|
log "sudo yum install python3 python3-pip"
|
||||||
|
elif [[ "$OS" == *"Alpine"* ]]; then
|
||||||
|
log "sudo apk add python3 py3-pip"
|
||||||
|
else
|
||||||
|
log "Bitte installieren Sie Python 3 manuell für Ihr System"
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Python-Version prüfen
|
||||||
|
PYTHON_VERSION=$(python3 -c "import sys; print('.'.join(map(str, sys.version_info[:2])))")
|
||||||
|
log "Python-Version: $PYTHON_VERSION"
|
||||||
|
|
||||||
|
if python3 -c "import sys; exit(0 if sys.version_info >= (3, 8) else 1)"; then
|
||||||
|
success_log "Python-Version ist kompatibel (>= 3.8)"
|
||||||
|
else
|
||||||
|
error_log "Python-Version ist zu alt! Benötigt wird mindestens Python 3.8"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# pip prüfen
|
||||||
|
if ! command -v pip3 &> /dev/null; then
|
||||||
|
error_log "pip3 ist nicht installiert!"
|
||||||
|
log "Installiere pip3..."
|
||||||
|
if [[ "$OS" == *"Ubuntu"* ]] || [[ "$OS" == *"Debian"* ]]; then
|
||||||
|
sudo apt install python3-pip
|
||||||
|
else
|
||||||
|
error_log "Bitte installieren Sie pip3 manuell"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Weitere notwendige System-Pakete prüfen
|
||||||
|
if [[ "$OS" == *"Ubuntu"* ]] || [[ "$OS" == *"Debian"* ]]; then
|
||||||
|
log "Prüfe System-Pakete für Ubuntu/Debian..."
|
||||||
|
|
||||||
|
# Prüfe ob build-essential installiert ist (für Compilation von Python-Paketen)
|
||||||
|
if ! dpkg -l | grep -q build-essential; then
|
||||||
|
log "Installiere build-essential..."
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y build-essential python3-dev
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prüfe curl für Health-Checks
|
||||||
|
if ! command -v curl &> /dev/null; then
|
||||||
|
log "Installiere curl..."
|
||||||
|
sudo apt install -y curl
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
success_log "System-Dependencies sind verfügbar"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Python virtuelle Umgebung erstellen
|
||||||
|
create_virtual_environment() {
|
||||||
|
log "🐍 Erstelle Python virtuelle Umgebung..."
|
||||||
|
|
||||||
|
# Erstelle virtuelle Umgebung
|
||||||
|
python3 -m venv venv
|
||||||
|
|
||||||
|
# Aktiviere virtuelle Umgebung
|
||||||
|
source venv/bin/activate
|
||||||
|
|
||||||
|
# Upgrade pip in virtueller Umgebung
|
||||||
|
log "Aktualisiere pip..."
|
||||||
|
pip install --upgrade pip
|
||||||
|
|
||||||
|
success_log "Virtuelle Umgebung erstellt und aktiviert"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Python-Dependencies installieren
|
||||||
|
install_python_dependencies() {
|
||||||
|
log "📦 Installiere Python-Dependencies..."
|
||||||
|
|
||||||
|
# Aktiviere virtuelle Umgebung
|
||||||
|
source venv/bin/activate
|
||||||
|
|
||||||
|
# Installiere Requirements
|
||||||
|
if [ -f "requirements.txt" ]; then
|
||||||
|
log "Installiere aus requirements.txt..."
|
||||||
|
pip install -r requirements.txt
|
||||||
|
else
|
||||||
|
error_log "requirements.txt nicht gefunden!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Produktions-spezifische Dependencies
|
||||||
|
if [ "$INSTALL_MODE" = "production" ]; then
|
||||||
|
log "Installiere Produktions-Dependencies..."
|
||||||
|
pip install gunicorn supervisor
|
||||||
|
fi
|
||||||
|
|
||||||
|
success_log "Python-Dependencies installiert"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Konfiguration vorbereiten
|
||||||
|
prepare_configuration() {
|
||||||
|
log "⚙️ Bereite Konfiguration vor..."
|
||||||
|
|
||||||
|
# Erstelle notwendige Verzeichnisse
|
||||||
|
mkdir -p instance logs migrations/versions
|
||||||
|
|
||||||
|
# Kopiere Beispiel-Umgebungsvariablen falls nicht vorhanden
|
||||||
|
if [ ! -f "env.backend" ]; then
|
||||||
|
if [ -f "env.example" ]; then
|
||||||
|
log "Erstelle env.backend aus Vorlage..."
|
||||||
|
cp env.example env.backend
|
||||||
|
else
|
||||||
|
log "Erstelle Standard env.backend..."
|
||||||
|
cat > env.backend << EOF
|
||||||
|
# MYP Backend Konfiguration
|
||||||
|
FLASK_ENV=$INSTALL_MODE
|
||||||
|
SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))")
|
||||||
DATABASE_PATH=instance/myp.db
|
DATABASE_PATH=instance/myp.db
|
||||||
TAPO_USERNAME=till.tomczak@mercedes-benz.com
|
LOG_LEVEL=INFO
|
||||||
TAPO_PASSWORD=744563017196A
|
JOB_CHECK_INTERVAL=60
|
||||||
PRINTERS={"Printer 1": {"ip": "192.168.0.100"}, "Printer 2": {"ip": "192.168.0.101"}, "Printer 3": {"ip": "192.168.0.102"}, "Printer 4": {"ip": "192.168.0.103"}, "Printer 5": {"ip": "192.168.0.104"}, "Printer 6": {"ip": "192.168.0.106"}}
|
PRINTERS={}
|
||||||
EOL
|
TAPO_USERNAME=
|
||||||
|
TAPO_PASSWORD=
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
if [ ! -f ".env" ]; then
|
warning_log "env.backend wurde erstellt. Bitte anpassen!"
|
||||||
error_log "Konnte .env-Datei nicht erstellen. Prüfen Sie die Berechtigungen."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
log "${GREEN}.env Datei erfolgreich erstellt${NC}"
|
|
||||||
|
|
||||||
# Verzeichnisse erstellen
|
|
||||||
log "Erstelle benötigte Verzeichnisse"
|
|
||||||
if ! mkdir -p logs; then
|
|
||||||
error_log "Konnte Verzeichnis 'logs' nicht erstellen. Prüfen Sie die Berechtigungen."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! mkdir -p instance; then
|
|
||||||
error_log "Konnte Verzeichnis 'instance' nicht erstellen. Prüfen Sie die Berechtigungen."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Docker-Image bauen und starten
|
|
||||||
log "${YELLOW}Baue und starte Backend-Container...${NC}"
|
|
||||||
log "${YELLOW}Dies kann auf einem Raspberry Pi einige Minuten dauern - bitte geduldig sein${NC}"
|
|
||||||
|
|
||||||
# Prüfe, ob Docker-Daemon läuft
|
|
||||||
if ! docker info &>/dev/null; then
|
|
||||||
log "${YELLOW}Docker-Daemon scheint nicht zu laufen. Versuche zu starten...${NC}"
|
|
||||||
|
|
||||||
# Versuche Docker zu starten
|
|
||||||
if command -v systemctl &>/dev/null; then
|
|
||||||
sudo systemctl start docker || true
|
|
||||||
sleep 5
|
|
||||||
elif command -v service &>/dev/null; then
|
|
||||||
sudo service docker start || true
|
|
||||||
sleep 5
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Prüfe erneut, ob Docker jetzt läuft
|
|
||||||
if ! docker info &>/dev/null; then
|
|
||||||
error_log "Docker-Daemon konnte nicht gestartet werden."
|
|
||||||
log "Führen Sie vor der Installation bitte folgende Befehle aus:"
|
|
||||||
log " sudo systemctl start docker"
|
|
||||||
log " sudo systemctl enable docker"
|
|
||||||
log "Starten Sie dann das Installationsskript erneut."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Docker-Rechte prüfen
|
|
||||||
if ! docker ps &>/dev/null; then
|
|
||||||
error_log "Sie haben keine Berechtigung, Docker ohne sudo zu verwenden."
|
|
||||||
log "Bitte führen Sie folgenden Befehl aus und melden Sie sich danach neu an:"
|
|
||||||
log " sudo usermod -aG docker $USER"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Prüfen, ob erforderliche Basis-Images lokal verfügbar sind
|
|
||||||
if ! docker image inspect python:3-slim &>/dev/null; then
|
|
||||||
log "${YELLOW}Prüfe und setze DNS-Server für Docker...${NC}"
|
|
||||||
|
|
||||||
# DNS-Einstellungen prüfen und anpassen
|
|
||||||
if [ -f /etc/docker/daemon.json ]; then
|
|
||||||
log "Bestehende Docker-Konfiguration gefunden."
|
|
||||||
else
|
|
||||||
log "Erstelle Docker-Konfiguration mit Google DNS..."
|
|
||||||
sudo mkdir -p /etc/docker
|
|
||||||
echo '{
|
|
||||||
"dns": ["8.8.8.8", "8.8.4.4"]
|
|
||||||
}' | sudo tee /etc/docker/daemon.json > /dev/null
|
|
||||||
|
|
||||||
# Docker neu starten, damit die Änderungen wirksam werden
|
|
||||||
if command -v systemctl &>/dev/null; then
|
|
||||||
sudo systemctl restart docker
|
|
||||||
sleep 5
|
|
||||||
elif command -v service &>/dev/null; then
|
|
||||||
sudo service docker restart
|
|
||||||
sleep 5
|
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
# Versuche Image explizit mit anderen Tags herunterzuladen
|
success_log "Konfiguration vorbereitet"
|
||||||
log "${YELLOW}Versuche lokal vorhandene Python-Version zu finden...${NC}"
|
}
|
||||||
|
|
||||||
# Suche nach allen verfügbaren Python-Images
|
# Datenbank initialisieren
|
||||||
PYTHON_IMAGES=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep "python:")
|
initialize_database() {
|
||||||
|
log "🗄️ Initialisiere Datenbank..."
|
||||||
|
|
||||||
if [ -n "$PYTHON_IMAGES" ]; then
|
# Aktiviere virtuelle Umgebung
|
||||||
log "Gefundene Python-Images: $PYTHON_IMAGES"
|
source venv/bin/activate
|
||||||
# Verwende das erste gefundene Python-Image
|
|
||||||
FIRST_PYTHON=$(echo "$PYTHON_IMAGES" | head -n 1)
|
|
||||||
log "${GREEN}Verwende vorhandenes Python-Image: $FIRST_PYTHON${NC}"
|
|
||||||
|
|
||||||
# Aktualisiere den Dockerfile
|
# Lade Umgebungsvariablen
|
||||||
sed -i "s|FROM python:3-slim|FROM $FIRST_PYTHON|g" Dockerfile
|
if [ -f "env.backend" ]; then
|
||||||
log "Dockerfile aktualisiert, um lokales Image zu verwenden."
|
export $(cat env.backend | grep -v '^#' | grep -v '^$' | xargs)
|
||||||
else
|
|
||||||
# Versuche unterschiedliche Python-Versionen
|
|
||||||
for PYTHON_VERSION in "python:3.11-slim" "python:3.10-slim" "python:3.9-slim" "python:slim" "python:alpine"; do
|
|
||||||
log "Versuche $PYTHON_VERSION zu laden..."
|
|
||||||
if docker pull $PYTHON_VERSION; then
|
|
||||||
log "${GREEN}Erfolgreich $PYTHON_VERSION heruntergeladen${NC}"
|
|
||||||
# Aktualisiere den Dockerfile
|
|
||||||
sed -i "s|FROM python:3-slim|FROM $PYTHON_VERSION|g" Dockerfile
|
|
||||||
log "Dockerfile aktualisiert, um $PYTHON_VERSION zu verwenden."
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Erhöhe Docker-Timeout für langsame Verbindungen und Raspberry Pi
|
|
||||||
export DOCKER_CLIENT_TIMEOUT=300
|
|
||||||
export COMPOSE_HTTP_TIMEOUT=300
|
|
||||||
|
|
||||||
# Verwende die richtige Docker Compose Version
|
|
||||||
if [ "${DOCKER_COMPOSE_V2:-false}" = true ]; then
|
|
||||||
# Docker Compose V2 Plugin (docker compose)
|
|
||||||
log "Baue lokales Image..."
|
|
||||||
if ! docker compose build --no-cache; then
|
|
||||||
error_log "Docker Compose Build (v2) fehlgeschlagen. Versuche mit v1 Format..."
|
|
||||||
if ! docker-compose build --no-cache; then
|
|
||||||
error_log "Docker Compose Build fehlgeschlagen. Siehe Fehlermeldung oben."
|
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
log "Starte Container aus lokalem Image..."
|
# Setze Flask-App
|
||||||
if ! docker compose up -d; then
|
export FLASK_APP=app.py
|
||||||
error_log "Docker Compose Up (v2) fehlgeschlagen. Versuche mit v1 Format..."
|
export FLASK_ENV=$INSTALL_MODE
|
||||||
if ! docker-compose up -d; then
|
|
||||||
error_log "Docker Compose Up fehlgeschlagen. Siehe Fehlermeldung oben."
|
# Initialisiere Datenbank
|
||||||
exit 1
|
python3 -c "
|
||||||
|
from app import create_app, init_db
|
||||||
|
app = create_app('$INSTALL_MODE')
|
||||||
|
with app.app_context():
|
||||||
|
init_db()
|
||||||
|
print('✅ Datenbank initialisiert')
|
||||||
|
"
|
||||||
|
|
||||||
|
success_log "Datenbank initialisiert"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Systemd-Service für Produktion erstellen
|
||||||
|
create_systemd_service() {
|
||||||
|
if [ "$INSTALL_MODE" = "production" ]; then
|
||||||
|
log "🔧 Erstelle systemd-Service für Produktion..."
|
||||||
|
|
||||||
|
SERVICE_FILE="/etc/systemd/system/myp-backend.service"
|
||||||
|
|
||||||
|
sudo tee $SERVICE_FILE > /dev/null << EOF
|
||||||
|
[Unit]
|
||||||
|
Description=MYP Backend Flask Application
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=exec
|
||||||
|
User=$USER
|
||||||
|
Group=$USER
|
||||||
|
WorkingDirectory=$SCRIPT_DIR
|
||||||
|
Environment=PATH=$SCRIPT_DIR/venv/bin
|
||||||
|
EnvironmentFile=$SCRIPT_DIR/env.backend
|
||||||
|
ExecStart=$SCRIPT_DIR/venv/bin/gunicorn --bind 0.0.0.0:5000 --workers 4 wsgi:application
|
||||||
|
ExecReload=/bin/kill -s HUP \$MAINPID
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable myp-backend
|
||||||
|
|
||||||
|
success_log "Systemd-Service erstellt: myp-backend.service"
|
||||||
|
log "Starten mit: sudo systemctl start myp-backend"
|
||||||
|
log "Status prüfen mit: sudo systemctl status myp-backend"
|
||||||
fi
|
fi
|
||||||
fi
|
}
|
||||||
else
|
|
||||||
# Docker Compose V1 (docker-compose)
|
|
||||||
log "Baue lokales Image..."
|
|
||||||
if ! docker-compose build --no-cache; then
|
|
||||||
error_log "Docker Compose Build fehlgeschlagen. Siehe Fehlermeldung oben."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
log "Starte Container aus lokalem Image..."
|
# Hauptinstallation
|
||||||
if ! docker-compose up -d; then
|
main() {
|
||||||
error_log "Docker Compose Up fehlgeschlagen. Siehe Fehlermeldung oben."
|
cleanup_existing_installation
|
||||||
exit 1
|
install_system_dependencies
|
||||||
fi
|
create_virtual_environment
|
||||||
fi
|
install_python_dependencies
|
||||||
|
prepare_configuration
|
||||||
|
initialize_database
|
||||||
|
create_systemd_service
|
||||||
|
|
||||||
# Prüfe, ob der Container läuft
|
echo ""
|
||||||
log "Warte 10 Sekunden, bis der Container gestartet ist..."
|
echo "========================================"
|
||||||
sleep 10
|
success_log "🎉 Installation erfolgreich abgeschlossen!"
|
||||||
if docker ps | grep -q "myp-backend"; then
|
echo "========================================"
|
||||||
log "${GREEN}Backend-Container läuft${NC}"
|
echo ""
|
||||||
else
|
|
||||||
error_log "Backend-Container läuft nicht. Container-Status:"
|
|
||||||
docker ps -a | grep myp-backend
|
|
||||||
log "Container-Logs:"
|
|
||||||
docker logs myp-backend
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test API-Endpunkt
|
log "Nächste Schritte:"
|
||||||
log "${YELLOW}Teste Backend-API...${NC}"
|
echo ""
|
||||||
log "${YELLOW}HINWEIS: Der API-Server ist bei der ersten Installation oft noch nicht erreichbar${NC}"
|
|
||||||
log "${YELLOW}Dies ist ein bekanntes Verhalten wegen der Netzwerkkonfiguration${NC}"
|
|
||||||
log "${YELLOW}Bitte nach der Installation das System neu starten, danach sollte der API-Server erreichbar sein${NC}"
|
|
||||||
|
|
||||||
# Wir versuchen es trotzdem einmal, um zu sehen, ob er vielleicht doch läuft
|
if [ "$INSTALL_MODE" = "production" ]; then
|
||||||
if curl -s http://localhost:5000/health 2>/dev/null | grep -q "healthy"; then
|
echo "📋 Produktionsbetrieb:"
|
||||||
log "${GREEN}Backend-API ist erreichbar und funktioniert${NC}"
|
echo " 1. Konfiguration prüfen: nano env.backend"
|
||||||
else
|
echo " 2. Service starten: sudo systemctl start myp-backend"
|
||||||
log "${YELLOW}Backend-API ist wie erwartet noch nicht erreichbar${NC}"
|
echo " 3. Service prüfen: sudo systemctl status myp-backend"
|
||||||
log "${GREEN}Das ist völlig normal bei der Erstinstallation${NC}"
|
echo " 4. Oder manuell: ./start-production.sh"
|
||||||
log "${GREEN}Nach einem Neustart des Systems sollte der API-Server korrekt erreichbar sein${NC}"
|
else
|
||||||
log "Container-Status prüfen mit: docker logs myp-backend"
|
echo "🔧 Entwicklungsbetrieb:"
|
||||||
fi
|
echo " 1. Konfiguration prüfen: nano env.backend"
|
||||||
|
echo " 2. Server starten: ./start-backend-server.sh"
|
||||||
|
echo " 3. Development-Server: ./start-backend-server.sh --development"
|
||||||
|
fi
|
||||||
|
|
||||||
# Initialisierung der Datenbank prüfen
|
echo ""
|
||||||
log "${YELLOW}Prüfe Datenbank-Initialisierung...${NC}"
|
echo "📡 Backend wird verfügbar sein unter:"
|
||||||
if [ ! -s "instance/myp.db" ]; then
|
echo " - API: http://localhost:5000"
|
||||||
log "${YELLOW}Datenbank scheint leer zu sein. Führe Initialisierungsskript aus...${NC}"
|
echo " - Health-Check: http://localhost:5000/health"
|
||||||
DB_INIT_OUTPUT=$(docker exec myp-backend python -c "from app import init_db; init_db()" 2>&1)
|
echo " - Test: http://localhost:5000/api/test"
|
||||||
if [ $? -eq 0 ]; then
|
echo ""
|
||||||
log "${GREEN}Datenbank erfolgreich initialisiert${NC}"
|
}
|
||||||
else
|
|
||||||
error_log "Fehler bei der Datenbank-Initialisierung:"
|
|
||||||
echo "$DB_INIT_OUTPUT"
|
|
||||||
log "Container-Logs:"
|
|
||||||
docker logs myp-backend
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
log "${GREEN}Datenbank existiert bereits${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Teste, ob ein API-Endpunkt Daten zurückgibt
|
# Installation starten
|
||||||
log "${YELLOW}Teste Datenbank-Verbindung über API...${NC}"
|
main "$@"
|
||||||
if curl -s http://localhost:5000/api/printers | grep -q "\[\]"; then
|
|
||||||
log "${GREEN}Datenbank-Verbindung funktioniert${NC}"
|
|
||||||
else
|
|
||||||
log "${YELLOW}API gibt keine leere Drucker-Liste zurück. Möglicherweise ist die DB nicht korrekt initialisiert.${NC}"
|
|
||||||
log "API-Antwort:"
|
|
||||||
curl -s http://localhost:5000/api/printers
|
|
||||||
fi
|
|
||||||
|
|
||||||
log "${GREEN}=== Installation abgeschlossen ===${NC}"
|
|
||||||
log "${YELLOW}WICHTIG: Nach der Erstinstallation ist ein Systemneustart erforderlich${NC}"
|
|
||||||
log "${YELLOW}Danach ist das Backend unter http://localhost:5000 erreichbar${NC}"
|
|
||||||
log "Anzeigen der Logs: docker logs -f myp-backend"
|
|
||||||
|
|
||||||
# Verwende die richtige Docker Compose Version für Hinweis
|
|
||||||
if [ "${DOCKER_COMPOSE_V2:-false}" = true ]; then
|
|
||||||
log "Backend stoppen: docker compose -f $BACKEND_DIR/docker-compose.yml down"
|
|
||||||
else
|
|
||||||
log "Backend stoppen: docker-compose -f $BACKEND_DIR/docker-compose.yml down"
|
|
||||||
fi
|
|
1
backend/test-backend-setup.py
Normal file
1
backend/test-backend-setup.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
@ -1 +1,287 @@
|
|||||||
|
# 🏗️ MYP - Separate Server Architektur
|
||||||
|
|
||||||
|
## Übersicht
|
||||||
|
|
||||||
|
Das MYP-System wurde in **zwei vollständig unabhängige Server** aufgeteilt:
|
||||||
|
|
||||||
|
- **🏭 Backend-Server** (Port 5000): Flask-API für Geschäftslogik und Datenmanagement
|
||||||
|
- **🎨 Frontend-Server** (Port 3000): Next.js-Anwendung für Benutzeroberfläche
|
||||||
|
|
||||||
|
## 🔗 Server-Kommunikation
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────┐ HTTP/API ┌─────────────────┐
|
||||||
|
│ Frontend │◄───────────────►│ Backend │
|
||||||
|
│ (Next.js) │ │ (Flask) │
|
||||||
|
│ Port: 3000 │ │ Port: 5000 │
|
||||||
|
└─────────────────┘ └─────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 Separate Server starten
|
||||||
|
|
||||||
|
### Backend-Server (unabhängig)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
./start-backend-server.sh
|
||||||
|
|
||||||
|
# Alternative mit Logs
|
||||||
|
./start-backend-server.sh --logs
|
||||||
|
|
||||||
|
# Vollständige Neuinstallation
|
||||||
|
./start-backend-server.sh --clean
|
||||||
|
```
|
||||||
|
|
||||||
|
**Backend verfügbar unter:**
|
||||||
|
|
||||||
|
- 📡 Backend-API: http://localhost:5000
|
||||||
|
- 🔧 Health-Check: http://localhost:5000/health
|
||||||
|
- 📋 API-Docs: http://localhost:5000/swagger
|
||||||
|
|
||||||
|
### Frontend-Server (unabhängig)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
./start-frontend-server.sh
|
||||||
|
|
||||||
|
# Alternative mit Logs
|
||||||
|
./start-frontend-server.sh --logs
|
||||||
|
|
||||||
|
# Vollständige Neuinstallation
|
||||||
|
./start-frontend-server.sh --clean
|
||||||
|
```
|
||||||
|
|
||||||
|
**Frontend verfügbar unter:**
|
||||||
|
|
||||||
|
- 🌐 Web-App: http://localhost:3000
|
||||||
|
- 🔧 Health-Check: http://localhost:3000/health
|
||||||
|
- 📦 CDN-Assets: http://localhost:8080
|
||||||
|
|
||||||
|
## ⚙️ Konfiguration
|
||||||
|
|
||||||
|
### Backend-Konfiguration
|
||||||
|
|
||||||
|
**Datei:** `backend/env.backend`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backend-Server
|
||||||
|
PORT=5000
|
||||||
|
BACKEND_URL=http://localhost:5000
|
||||||
|
|
||||||
|
# CORS für Frontend-Zugriff
|
||||||
|
CORS_ORIGINS=http://localhost:3000,https://frontend.myp.local
|
||||||
|
|
||||||
|
# Datenbank
|
||||||
|
DATABASE_PATH=instance/myp.db
|
||||||
|
|
||||||
|
# Cache
|
||||||
|
REDIS_HOST=localhost
|
||||||
|
REDIS_PORT=6379
|
||||||
|
```
|
||||||
|
|
||||||
|
### Frontend-Konfiguration
|
||||||
|
|
||||||
|
**Datei:** `frontend/env.frontend`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Frontend-Server
|
||||||
|
PORT=3000
|
||||||
|
FRONTEND_URL=http://localhost:3000
|
||||||
|
|
||||||
|
# Backend-API Verbindung
|
||||||
|
BACKEND_API_URL=http://localhost:5000/api
|
||||||
|
NEXT_PUBLIC_API_URL=http://localhost:5000/api
|
||||||
|
|
||||||
|
# Cache
|
||||||
|
FRONTEND_REDIS_PORT=6380
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🐋 Docker-Container
|
||||||
|
|
||||||
|
### Backend-Container
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
docker-compose -f docker-compose.backend.yml up -d
|
||||||
|
|
||||||
|
# Services:
|
||||||
|
# - myp-backend-standalone (Port 5000)
|
||||||
|
# - myp-backend-db (PostgreSQL, Port 5432)
|
||||||
|
# - myp-backend-cache (Redis, Port 6379)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Frontend-Container
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
docker-compose -f docker-compose.frontend.yml up -d
|
||||||
|
|
||||||
|
# Services:
|
||||||
|
# - myp-frontend-standalone (Port 3000)
|
||||||
|
# - myp-frontend-cache (Redis, Port 6380)
|
||||||
|
# - myp-frontend-cdn (Nginx, Port 8080)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔒 Sicherheit
|
||||||
|
|
||||||
|
### CORS-Konfiguration
|
||||||
|
|
||||||
|
Das Backend ist für **explizite Frontend-Origins** konfiguriert:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Backend: app.py
|
||||||
|
CORS(app,
|
||||||
|
origins=['http://localhost:3000', 'https://frontend.myp.local'],
|
||||||
|
supports_credentials=True,
|
||||||
|
allow_headers=['Content-Type', 'Authorization', 'X-Requested-With'],
|
||||||
|
methods=['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'])
|
||||||
|
```
|
||||||
|
|
||||||
|
### API-Authentifizierung
|
||||||
|
|
||||||
|
- **JWT-Tokens** für API-Zugriff
|
||||||
|
- **Session-basierte** Authentifizierung für Web-UI
|
||||||
|
- **Separate Secrets** für Frontend und Backend
|
||||||
|
|
||||||
|
## 📊 Monitoring
|
||||||
|
|
||||||
|
### Health-Checks
|
||||||
|
|
||||||
|
**Backend:** GET http://localhost:5000/health
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "healthy",
|
||||||
|
"service": "myp-backend",
|
||||||
|
"database": "connected",
|
||||||
|
"timestamp": "2024-01-15T10:30:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Frontend:** GET http://localhost:3000/health
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "healthy",
|
||||||
|
"service": "myp-frontend",
|
||||||
|
"backend": {
|
||||||
|
"url": "http://localhost:5000",
|
||||||
|
"status": "connected"
|
||||||
|
},
|
||||||
|
"timestamp": "2024-01-15T10:30:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Logs verfolgen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backend-Logs
|
||||||
|
cd backend
|
||||||
|
docker-compose -f docker-compose.backend.yml logs -f
|
||||||
|
|
||||||
|
# Frontend-Logs
|
||||||
|
cd frontend
|
||||||
|
docker-compose -f docker-compose.frontend.yml logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Troubleshooting
|
||||||
|
|
||||||
|
### Backend startet nicht
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Prüfe Ports
|
||||||
|
netstat -an | grep 5000
|
||||||
|
|
||||||
|
# 2. Prüfe Backend-Logs
|
||||||
|
cd backend
|
||||||
|
docker-compose -f docker-compose.backend.yml logs backend
|
||||||
|
|
||||||
|
# 3. Datenbank-Migration
|
||||||
|
docker-compose -f docker-compose.backend.yml exec backend flask db upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
### Frontend kann Backend nicht erreichen
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Prüfe Backend-Verfügbarkeit
|
||||||
|
curl http://localhost:5000/health
|
||||||
|
|
||||||
|
# 2. Prüfe CORS-Konfiguration
|
||||||
|
curl -H "Origin: http://localhost:3000" \
|
||||||
|
-H "Access-Control-Request-Method: GET" \
|
||||||
|
-H "Access-Control-Request-Headers: Content-Type" \
|
||||||
|
-X OPTIONS http://localhost:5000/api/printers
|
||||||
|
|
||||||
|
# 3. Prüfe Frontend-Umgebungsvariablen
|
||||||
|
cd frontend
|
||||||
|
grep BACKEND env.frontend
|
||||||
|
```
|
||||||
|
|
||||||
|
### Port-Konflikte
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Standard-Ports ändern
|
||||||
|
# Backend: PORT=5001 in env.backend
|
||||||
|
# Frontend: PORT=3001 in env.frontend
|
||||||
|
|
||||||
|
# Neue URLs in beiden Konfigurationen anpassen
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🌐 Deployment
|
||||||
|
|
||||||
|
### Produktions-Deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backend (Server 1)
|
||||||
|
cd backend
|
||||||
|
FLASK_ENV=production ./start-backend-server.sh
|
||||||
|
|
||||||
|
# Frontend (Server 2)
|
||||||
|
cd frontend
|
||||||
|
NODE_ENV=production BACKEND_API_URL=https://api.myp.de ./start-frontend-server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reverse Proxy (Optional)
|
||||||
|
|
||||||
|
Für Produktion können beide Server hinter einem Reverse Proxy laufen:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||||
|
│ Client │────►│ Nginx/Caddy │────►│ Frontend │
|
||||||
|
│ │ │ │ ┌─►│ :3000 │
|
||||||
|
└─────────────┘ │ /api/* ─────┤──┘ └─────────────┘
|
||||||
|
│ │ ┌─►┌─────────────┐
|
||||||
|
│ /api/* ─────┤──┘ │ Backend │
|
||||||
|
└─────────────┘ │ :5000 │
|
||||||
|
└─────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📁 Dateistruktur
|
||||||
|
|
||||||
|
```
|
||||||
|
Projektarbeit-MYP/
|
||||||
|
├── backend/ # 🏭 Backend-Server
|
||||||
|
│ ├── docker-compose.backend.yml # Docker-Konfiguration
|
||||||
|
│ ├── start-backend-server.sh # Start-Skript
|
||||||
|
│ ├── env.backend # Umgebungsvariablen
|
||||||
|
│ └── app.py # Flask-Anwendung
|
||||||
|
├── frontend/ # 🎨 Frontend-Server
|
||||||
|
│ ├── docker-compose.frontend.yml # Docker-Konfiguration
|
||||||
|
│ ├── start-frontend-server.sh # Start-Skript
|
||||||
|
│ ├── env.frontend # Umgebungsvariablen
|
||||||
|
│ └── src/ # Next.js-Anwendung
|
||||||
|
└── SEPARATE_SERVERS_GUIDE.md # Diese Dokumentation
|
||||||
|
```
|
||||||
|
|
||||||
|
## ✅ Vorteile der Trennung
|
||||||
|
|
||||||
|
1. **🔄 Unabhängige Skalierung** - Frontend und Backend können getrennt skaliert werden
|
||||||
|
2. **🚀 Separate Deployments** - Updates können unabhängig deployed werden
|
||||||
|
3. **🛡️ Verbesserte Sicherheit** - Klare API-Grenzen und CORS-Kontrolle
|
||||||
|
4. **🔧 Technologie-Flexibilität** - Frontend und Backend können verschiedene Technologien verwenden
|
||||||
|
5. **📊 Besseres Monitoring** - Separate Health-Checks und Logs
|
||||||
|
6. **🏗️ Microservice-Ready** - Vorbereitung für Microservice-Architektur
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Hinweis:** Die alte gekoppelte Konfiguration ist weiterhin in `docker-compose.yml` verfügbar, wird aber für neue Deployments nicht empfohlen.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user