#!/usr/bin/env bash # EasyMCP / SapB1Mcp — Setup auf dem Docker-Host (Pull-Deployment). # # Die einzige Datei, die ein Kunde braucht. Bezug: # curl -fsSLO https://git.kraemerweb.de/kraemerweb/easymcp-release/raw/branch/main/setup.sh # # Aufruf: # bash setup.sh # neueste Version (latest) # bash setup.sh # bestimmte Version (Tag im Release-Repo) # # Was das Skript tut: # 1. Holt die Deployment-Dateien (docker-compose.yml, hydra.yml, .env.example) # anonym aus dem öffentlichen Release-Repo — passend zur gewählten Version. # 2. Erzeugt secrets/creds_key (32 Byte base64, Verschlüsselung der SAP-Credentials). # 3. Legt .env aus .env.example an und generiert PG_PASSWORD + SECRETS_SYSTEM; # setzt APP_VERSION (= gewählte Version bzw. latest) und PROJECT_DIR. # 4. Pullt das Updater-Image (für die Update-Funktion des Admin-UI). # # Idempotent: eine vorhandene .env und ein vorhandener creds_key werden NIE # überschrieben — nur APP_VERSION und PROJECT_DIR werden nachgezogen. Die # Deployment-Dateien werden immer auf den Stand der gewählten Version gebracht. set -euo pipefail cd "$(dirname "$0")" RELEASE_BASE="${RELEASE_BASE:-https://git.kraemerweb.de/kraemerweb/easymcp-release}" REGISTRY_IMAGE_BASE="${REGISTRY_IMAGE_BASE:-git.kraemerweb.de/kraemerweb}" VERSION="${1:-}" if [ -n "$VERSION" ]; then REF="tag/${VERSION}" APP_VERSION="$VERSION" else REF="branch/main" APP_VERSION="latest" fi info() { printf '\033[1;34m==>\033[0m %s\n' "$*"; } ok() { printf '\033[1;32m ✓\033[0m %s\n' "$*"; } warn() { printf '\033[1;33m !\033[0m %s\n' "$*"; } fail() { printf '\033[1;31mFEHLER:\033[0m %s\n' "$*" >&2; exit 1; } # --- Zufallswerte (openssl bevorzugt, /dev/urandom als Fallback) ------------- rand_hex() { # $1 = Byte-Anzahl; Ausgabe hex (URL-sicher, auch für DSN-URLs) if command -v openssl >/dev/null 2>&1; then openssl rand -hex "$1" | tr -d ' \r\n' else od -An -N"$1" -tx1 /dev/urandom | tr -d ' \r\n' fi } rand_b64() { # $1 = Byte-Anzahl; Ausgabe base64 (eine Zeile) if command -v openssl >/dev/null 2>&1; then openssl rand -base64 "$1" | tr -d '\r\n' else head -c "$1" /dev/urandom | base64 | tr -d '\r\n' fi } set_env() { # $1 = Name, $2 = Wert — setzt bzw. ergänzt NAME=WERT in .env if grep -q "^$1=" .env; then sed -i "s|^$1=.*|$1=$2|" .env else printf '%s=%s\n' "$1" "$2" >> .env fi } fetch() { # $1 = Datei im Release-Repo, $2 = Zielname — atomar ersetzen curl -fsSL "$RELEASE_BASE/raw/$REF/$1" -o "$2.new" \ || fail "Download fehlgeschlagen: $RELEASE_BASE/raw/$REF/$1 (Version/Netzwerk prüfen)" mv "$2.new" "$2" } # --- Vorbedingungen ----------------------------------------------------------- command -v curl >/dev/null 2>&1 || fail "curl nicht gefunden — bitte installieren." command -v docker >/dev/null 2>&1 || fail "docker nicht gefunden — bitte Docker Engine installieren." docker info >/dev/null 2>&1 || fail "Docker-Daemon nicht erreichbar (läuft der Dienst? Rechte? Ggf. sudo verwenden)." if docker compose version >/dev/null 2>&1; then COMPOSE="docker compose" elif command -v docker-compose >/dev/null 2>&1; then COMPOSE="docker-compose" else fail "Weder 'docker compose' (Plugin v2) noch 'docker-compose' gefunden." fi # --- 1. Deployment-Dateien holen ----------------------------------------------- info "Hole Deployment-Dateien (${VERSION:-latest}) aus $RELEASE_BASE ..." fetch docker-compose.yml docker-compose.yml fetch hydra.yml hydra.yml fetch .env.example .env.example ok "docker-compose.yml, hydra.yml, .env.example aktualisiert." # --- 2. creds_key -------------------------------------------------------------- info "Prüfe secrets/creds_key ..." mkdir -p secrets if [ -f secrets/creds_key ]; then ok "secrets/creds_key existiert bereits — bleibt unverändert." else ( umask 077; rand_b64 32 > secrets/creds_key ) ok "secrets/creds_key erzeugt (chmod 600)." echo " WICHTIG: Diese Datei SICHERN. Ohne sie sind die gespeicherten SAP-Zugangsdaten unlesbar." fi # --- 3. .env ------------------------------------------------------------------- info "Prüfe .env ..." if [ -f .env ]; then ok ".env existiert bereits — Secrets/Werte bleiben unverändert." current="$(sed -n 's/^APP_VERSION=//p' .env | head -n1)" set_env APP_VERSION "$APP_VERSION" if [ -n "$current" ] && [ "$current" != "$APP_VERSION" ]; then ok "Update: APP_VERSION ${current} -> ${APP_VERSION} (wirkt nach '${COMPOSE} pull' + '${COMPOSE} up -d')." fi else cp .env.example .env chmod 600 .env PG_PASSWORD="$(rand_hex 24)" # nur [0-9a-f]: sicher für Hydras DSN-URL SECRETS_SYSTEM="$(rand_hex 32)" # Hydra-Systemschlüssel — nach Inbetriebnahme NIE mehr ändern set_env PG_PASSWORD "$PG_PASSWORD" set_env SECRETS_SYSTEM "$SECRETS_SYSTEM" set_env APP_VERSION "$APP_VERSION" ok ".env angelegt, PG_PASSWORD + SECRETS_SYSTEM generiert (chmod 600)." fi # Host-Pfad des Deployments — braucht die Update-Funktion des Admin-UI (der # Einweg-Updater mountet das Projektverzeichnis pfad-identisch). Bei jedem Lauf # aktualisieren, falls das Verzeichnis umgezogen ist. set_env PROJECT_DIR "$(pwd)" # --- 4. Updater-Image für die Admin-UI-Update-Funktion -------------------------- info "Pulle Updater-Image ..." if docker pull "$REGISTRY_IMAGE_BASE/sapb1mcp-updater:latest" >/dev/null; then ok "Updater-Image bereit." else warn "Updater-Image konnte nicht gepullt werden — Registry-Zugriff prüfen; das Admin-UI-Update funktioniert sonst nicht." fi # --- 5. Nächste Schritte --------------------------------------------------------- cat < Port 4444) LOGIN_URL öffentliche HTTPS-URL des Login-Dienstes (Reverse Proxy -> Port 8081) MCP_RESOURCE_URL öffentliche HTTPS-URL des MCP-Servers (Reverse Proxy -> Port 8080) SL_BASE_URL SAP Service Layer, z. B. https://sap-host:50000/b1s/ (trailing /b1s/ ist Pflicht) SL_COMPANYDB SAP-Firmendatenbank ADMIN_SAP_USER SAP-Benutzer, der das Admin-UI öffnen darf MCP_ALLOWED_USERS kommagetrennte SAP-Benutzer mit MCP-Dauerzugriff Optional: SL_INSECURE (self-signed SAP-Zertifikat), BIND_ADDR/ADMIN_BIND und *_HOST_PORT, falls der Reverse Proxy auf einem anderen Host läuft. Danach den Stack starten: ${COMPOSE} pull ${COMPOSE} up -d Status prüfen: ${COMPOSE} ps (alle Dauerläufer müssen "healthy" werden) Updates später: im Admin-UI unter „Update" — oder erneut 'bash setup.sh [version]' gefolgt von '${COMPOSE} pull' + '${COMPOSE} up -d'. Details: INSTALL.md ============================================================================ EOF