spawner/install.sh
2026-01-30 18:00:41 +01:00

314 lines
10 KiB
Bash

#!/bin/bash
set -e
# ============================================================
# Container Spawner - Installationsskript
# https://gitea.iotxs.de/RainerWieland/spawner
# ============================================================
REPO_URL="https://gitea.iotxs.de/RainerWieland/spawner.git"
RAW_URL="https://gitea.iotxs.de/RainerWieland/spawner/raw/branch/main"
INSTALL_DIR="${PWD}"
VERSION="0.1.0"
# Farben fuer Output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo ""
echo "============================================================"
echo " Container Spawner Installation v${VERSION}"
echo "============================================================"
echo ""
# ============================================================
# 1. Pruefe .env
# ============================================================
if [ ! -f "${INSTALL_DIR}/.env" ]; then
echo -e "${YELLOW}HINWEIS: Keine .env-Datei gefunden!${NC}"
echo ""
# Erstelle .env.example aus Repository
echo "Lade .env.example herunter..."
if command -v curl >/dev/null 2>&1; then
curl -sSL "${RAW_URL}/.env.example" -o "${INSTALL_DIR}/.env.example"
elif command -v wget >/dev/null 2>&1; then
wget -q "${RAW_URL}/.env.example" -O "${INSTALL_DIR}/.env.example"
else
echo -e "${RED}Fehler: Weder curl noch wget gefunden!${NC}"
exit 1
fi
echo -e "${GREEN}Vorlage erstellt: .env.example${NC}"
echo ""
echo "Naechste Schritte:"
echo " 1. Kopiere die Vorlage: cp .env.example .env"
echo " 2. Passe die Werte an: nano .env"
echo " - SECRET_KEY generieren (siehe Kommentar in .env)"
echo " - BASE_DOMAIN setzen"
echo " - TRAEFIK_NETWORK pruefen"
echo " 3. Fuehre erneut aus: bash install.sh"
echo ""
exit 0
fi
echo -e "${GREEN}.env-Datei gefunden${NC}"
# Lade .env Variablen
set -a
source "${INSTALL_DIR}/.env"
set +a
# ============================================================
# 2. Pruefe Voraussetzungen
# ============================================================
echo ""
echo "Pruefe Voraussetzungen..."
# Docker
if ! command -v docker >/dev/null 2>&1; then
echo -e "${RED}Fehler: Docker nicht gefunden!${NC}"
echo "Installiere Docker: https://docs.docker.com/get-docker/"
exit 1
fi
echo -e " Docker: ${GREEN}OK${NC}"
# Docker Compose
if command -v docker-compose >/dev/null 2>&1; then
COMPOSE_CMD="docker-compose"
elif docker compose version >/dev/null 2>&1; then
COMPOSE_CMD="docker compose"
else
echo -e "${RED}Fehler: docker-compose nicht gefunden!${NC}"
exit 1
fi
echo -e " Docker Compose: ${GREEN}OK${NC} (${COMPOSE_CMD})"
# Git
if ! command -v git >/dev/null 2>&1; then
echo -e "${RED}Fehler: Git nicht gefunden!${NC}"
exit 1
fi
echo -e " Git: ${GREEN}OK${NC}"
# ============================================================
# 3. Pruefe ob bereits installiert (Update vs. Neuinstallation)
# ============================================================
echo ""
if [ -d "${INSTALL_DIR}/.git" ]; then
echo -e "${YELLOW}Update erkannt - hole neueste Aenderungen...${NC}"
# Sichere lokale Aenderungen
if ! git diff --quiet 2>/dev/null; then
echo "Lokale Aenderungen gefunden, erstelle Stash..."
git stash
fi
git fetch origin
git pull origin main
echo -e "${GREEN}Repository aktualisiert${NC}"
else
echo "Neuinstallation - klone Repository..."
# Temporaeres Verzeichnis fuer Clone
TEMP_DIR=$(mktemp -d)
git clone "${REPO_URL}" "${TEMP_DIR}"
# Kopiere Dateien (ueberschreibt nicht .env)
shopt -s dotglob
for item in "${TEMP_DIR}"/*; do
basename_item=$(basename "$item")
if [ "$basename_item" != ".env" ] && [ "$basename_item" != ".git" ]; then
cp -r "$item" "${INSTALL_DIR}/"
fi
done
# .git Verzeichnis kopieren fuer Updates
cp -r "${TEMP_DIR}/.git" "${INSTALL_DIR}/"
rm -rf "${TEMP_DIR}"
echo -e "${GREEN}Repository geklont${NC}"
fi
# ============================================================
# 4. Verzeichnisse und Rechte setzen
# ============================================================
echo ""
echo "Setze Verzeichnisse und Berechtigungen..."
# Verzeichnisse erstellen falls nicht vorhanden
mkdir -p "${INSTALL_DIR}/data"
mkdir -p "${INSTALL_DIR}/logs"
# Berechtigungen setzen (rwx fuer Owner, rx fuer Group/Other)
chmod 755 "${INSTALL_DIR}/data"
chmod 755 "${INSTALL_DIR}/logs"
# Fuer Docker: Verzeichnisse muessen vom Container beschreibbar sein
# Option 1: Wenn Container als root laeuft (Standard) - 755 reicht
# Option 2: Wenn Container als non-root laeuft - 777 oder chown noetig
# Pruefen ob wir als root laufen (fuer chown)
if [ "$(id -u)" = "0" ]; then
# Als root: Owner auf aktuellen User setzen (oder Docker-User)
# Standard: belassen wie es ist (root kann alles)
echo -e " data/: ${GREEN}OK${NC} (755, root)"
echo -e " logs/: ${GREEN}OK${NC} (755, root)"
else
# Als normaler User: Verzeichnisse muessen beschreibbar sein
# Docker-Container laeuft meist als root, daher 755 ausreichend
# Falls Container als non-root laeuft, auf 777 setzen:
# chmod 777 "${INSTALL_DIR}/data" "${INSTALL_DIR}/logs"
echo -e " data/: ${GREEN}OK${NC} (755)"
echo -e " logs/: ${GREEN}OK${NC} (755)"
fi
# .env Datei schuetzen (nur Owner kann lesen/schreiben)
if [ -f "${INSTALL_DIR}/.env" ]; then
chmod 600 "${INSTALL_DIR}/.env"
echo -e " .env: ${GREEN}OK${NC} (600, nur Owner)"
fi
# install.sh ausfuehrbar machen
if [ -f "${INSTALL_DIR}/install.sh" ]; then
chmod +x "${INSTALL_DIR}/install.sh"
fi
# ============================================================
# 5. Docker-Netzwerk pruefen/erstellen
# ============================================================
echo ""
NETWORK="${TRAEFIK_NETWORK:-web}"
echo "Pruefe Docker-Netzwerk: ${NETWORK}"
if docker network inspect "${NETWORK}" >/dev/null 2>&1; then
echo -e " Netzwerk '${NETWORK}': ${GREEN}existiert${NC}"
else
echo -e " ${YELLOW}Netzwerk '${NETWORK}' nicht gefunden - erstelle...${NC}"
docker network create "${NETWORK}"
echo -e " Netzwerk '${NETWORK}': ${GREEN}erstellt${NC}"
fi
# ============================================================
# 6. Docker-Images bauen
# ============================================================
echo ""
echo "Baue Docker-Images..."
# Stoppe laufende Container
${COMPOSE_CMD} down 2>/dev/null || true
# User-Template Image bauen (fuer User-Container)
if [ -d "${INSTALL_DIR}/user-template" ]; then
echo " [1/4] Baue user-service-template (User-Container)..."
if docker build --no-cache -t user-service-template:latest "${INSTALL_DIR}/user-template/" > /dev/null 2>&1; then
echo -e " user-service-template: ${GREEN}OK${NC}"
else
echo -e " user-service-template: ${RED}FEHLER${NC}"
echo " Versuche mit detaillierter Ausgabe..."
docker build --no-cache -t user-service-template:latest "${INSTALL_DIR}/user-template/"
exit 1
fi
fi
# User-Template-Next Image bauen (alternatives Template, optional)
if [ -d "${INSTALL_DIR}/user-template-next" ]; then
echo " [2/4] Baue user-template-next (alternatives Template)..."
if docker build -t user-template-next:latest "${INSTALL_DIR}/user-template-next/" > /dev/null 2>&1; then
echo -e " user-template-next: ${GREEN}OK${NC}"
else
echo -e " user-template-next: ${YELLOW}WARNUNG - Build fehlgeschlagen (optional)${NC}"
fi
fi
# Spawner Backend Image bauen
echo " [3/4] Baue Spawner API (Flask Backend)..."
if docker build -t spawner:latest "${INSTALL_DIR}/" > /dev/null 2>&1; then
echo -e " spawner-api: ${GREEN}OK${NC}"
else
echo -e " spawner-api: ${RED}FEHLER${NC}"
docker build -t spawner:latest "${INSTALL_DIR}/"
exit 1
fi
# Frontend Image bauen
if [ -d "${INSTALL_DIR}/frontend" ]; then
echo " [4/4] Baue Frontend (Next.js)..."
echo " Dies kann einige Minuten dauern (npm install + build)..."
if docker build -t spawner-frontend:latest "${INSTALL_DIR}/frontend/" 2>&1 | grep -E "(error|Error|ERROR)" > /dev/null; then
echo -e " spawner-frontend: ${RED}FEHLER${NC}"
echo " Versuche mit detaillierter Ausgabe..."
docker build -t spawner-frontend:latest "${INSTALL_DIR}/frontend/"
exit 1
else
docker build -t spawner-frontend:latest "${INSTALL_DIR}/frontend/" > /dev/null 2>&1
echo -e " spawner-frontend: ${GREEN}OK${NC}"
fi
fi
echo ""
echo "Alle Images erfolgreich gebaut."
# ============================================================
# 7. Container starten
# ============================================================
echo ""
echo "Starte Container..."
${COMPOSE_CMD} up -d
# Warte auf Health-Check
echo ""
echo "Warte auf Spawner-Start..."
sleep 5
# Health-Check fuer API
SPAWNER_URL="http://localhost:${SPAWNER_PORT:-5000}/health"
if curl -sf "${SPAWNER_URL}" >/dev/null 2>&1; then
echo -e " API Health-Check: ${GREEN}OK${NC}"
else
echo -e " API Health-Check: ${YELLOW}Noch nicht bereit (normal beim ersten Start)${NC}"
fi
# Health-Check fuer Frontend
if curl -sf "http://localhost:3000/" >/dev/null 2>&1; then
echo -e " Frontend Health-Check: ${GREEN}OK${NC}"
else
echo -e " Frontend Health-Check: ${YELLOW}Noch nicht bereit (normal beim ersten Start)${NC}"
fi
# ============================================================
# 8. Fertig
# ============================================================
echo ""
echo "============================================================"
echo -e " ${GREEN}Installation abgeschlossen!${NC}"
echo "============================================================"
echo ""
# URLs anzeigen
SCHEME="https"
if [ "${BASE_DOMAIN:-localhost}" = "localhost" ]; then
SCHEME="http"
fi
FULL_URL="${SCHEME}://${SPAWNER_SUBDOMAIN:-coder}.${BASE_DOMAIN:-localhost}"
echo "Zugriff:"
echo " Frontend: ${FULL_URL}"
echo " API: ${FULL_URL}/api"
echo " Health: ${FULL_URL}/health"
echo ""
echo "Lokaler Zugriff (ohne Traefik):"
echo " API: http://localhost:${SPAWNER_PORT:-5000}"
echo " Frontend: http://localhost:3000"
echo ""
echo "Nuetzliche Befehle:"
echo " Status: ${COMPOSE_CMD} ps"
echo " Logs API: ${COMPOSE_CMD} logs -f spawner"
echo " Logs FE: ${COMPOSE_CMD} logs -f frontend"
echo " Neustart: ${COMPOSE_CMD} restart"
echo " Stoppen: ${COMPOSE_CMD} down"
echo ""