Some checks failed
Tests / Go Tests (push) Has been cancelled
Tests / Python Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Go Lint (push) Has been cancelled
Tests / Python Lint (push) Has been cancelled
Tests / Security Scan (push) Has been cancelled
Tests / All Checks Passed (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Go Security Scan (push) Has been cancelled
Security Scanning / Python Security Scan (push) Has been cancelled
Security Scanning / Node.js Security Scan (push) Has been cancelled
Security Scanning / Docker Image Security (push) Has been cancelled
Security Scanning / Security Summary (push) Has been cancelled
CI/CD Pipeline / Go Tests (push) Has been cancelled
CI/CD Pipeline / Python Tests (push) Has been cancelled
CI/CD Pipeline / Website Tests (push) Has been cancelled
CI/CD Pipeline / Linting (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Docker Build & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / CI Summary (push) Has been cancelled
ci/woodpecker/manual/build-ci-image Pipeline was successful
ci/woodpecker/manual/main Pipeline failed
All services: admin-v2, studio-v2, website, ai-compliance-sdk, consent-service, klausur-service, voice-service, and infrastructure. Large PDFs and compiled binaries excluded via .gitignore.
1833 lines
60 KiB
YAML
1833 lines
60 KiB
YAML
services:
|
|
# ============================================
|
|
# Nginx HTTPS Reverse Proxy
|
|
# Enables secure context for microphone/crypto
|
|
# Access via HTTPS on same ports as HTTP was before
|
|
# ============================================
|
|
nginx:
|
|
image: nginx:alpine
|
|
container_name: breakpilot-pwa-nginx
|
|
ports:
|
|
- "443:443" # HTTPS Studio v2 (https://macmini/)
|
|
- "80:80" # HTTP -> HTTPS redirect
|
|
- "3000:3000" # HTTPS Admin Website (https://macmini:3000/)
|
|
- "3002:3002" # HTTPS Admin v2 (https://macmini:3002/)
|
|
- "8091:8091" # HTTPS Voice Service (wss://macmini:8091/)
|
|
- "8000:8000" # HTTPS Backend API
|
|
- "8086:8086" # HTTPS Klausur Service
|
|
- "8089:8089" # HTTPS Edu-Search proxy (edu-search runs on 8088)
|
|
- "8093:8093" # HTTPS AI Compliance SDK
|
|
- "8443:8443" # HTTPS Jitsi Meet (https://macmini:8443/)
|
|
- "3006:3006" # HTTPS Developer Portal (https://macmini:3006/)
|
|
volumes:
|
|
- ./nginx/conf.d:/etc/nginx/conf.d:ro
|
|
- vault_certs:/etc/nginx/certs:ro
|
|
depends_on:
|
|
vault-agent:
|
|
condition: service_started
|
|
studio-v2:
|
|
condition: service_started
|
|
voice-service:
|
|
condition: service_started
|
|
backend:
|
|
condition: service_started
|
|
klausur-service:
|
|
condition: service_started
|
|
website:
|
|
condition: service_started
|
|
ai-compliance-sdk:
|
|
condition: service_started
|
|
admin-v2:
|
|
condition: service_started
|
|
jitsi-web:
|
|
condition: service_started
|
|
developer-portal:
|
|
condition: service_started
|
|
extra_hosts:
|
|
- "breakpilot-edu-search:host-gateway"
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# ============================================
|
|
# HashiCorp Vault - Secrets Management
|
|
# Web UI: http://localhost:8200/ui
|
|
# ============================================
|
|
vault:
|
|
image: hashicorp/vault:1.15
|
|
container_name: breakpilot-pwa-vault
|
|
cap_add:
|
|
- IPC_LOCK
|
|
ports:
|
|
- "8200:8200"
|
|
environment:
|
|
- VAULT_DEV_ROOT_TOKEN_ID=${VAULT_DEV_TOKEN:-breakpilot-dev-token}
|
|
- VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200
|
|
- VAULT_ADDR=http://127.0.0.1:8200
|
|
volumes:
|
|
- vault_data:/vault/data
|
|
healthcheck:
|
|
test: ["CMD", "vault", "status"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 5s
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# Vault PKI Initialization - runs once to set up PKI and issue initial certs
|
|
vault-init:
|
|
image: hashicorp/vault:1.15
|
|
container_name: breakpilot-pwa-vault-init
|
|
environment:
|
|
- VAULT_ADDR=http://vault:8200
|
|
- VAULT_TOKEN=${VAULT_DEV_TOKEN:-breakpilot-dev-token}
|
|
volumes:
|
|
- ./vault/init-pki.sh:/init-pki.sh:ro
|
|
- vault_agent_config:/vault/agent/data
|
|
- vault_certs:/vault/certs
|
|
entrypoint: ["/bin/sh", "-c"]
|
|
command:
|
|
- |
|
|
echo "Waiting for Vault to be ready..."
|
|
until vault status > /dev/null 2>&1; do sleep 1; done
|
|
echo "Vault is ready. Running PKI initialization..."
|
|
chmod +x /init-pki.sh
|
|
/init-pki.sh
|
|
echo "PKI initialization complete. Exiting."
|
|
depends_on:
|
|
vault:
|
|
condition: service_healthy
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: "no"
|
|
|
|
# Vault Agent - manages certificate renewal for nginx
|
|
vault-agent:
|
|
image: hashicorp/vault:1.15
|
|
container_name: breakpilot-pwa-vault-agent
|
|
environment:
|
|
- VAULT_ADDR=http://vault:8200
|
|
volumes:
|
|
- ./vault/agent/config.hcl:/vault/agent/config.hcl:ro
|
|
- ./vault/agent/templates:/vault/agent/templates:ro
|
|
- ./vault/agent/split-certs.sh:/vault/agent/split-certs.sh:ro
|
|
- vault_agent_config:/vault/agent/data
|
|
- vault_certs:/vault/certs
|
|
entrypoint: ["vault", "agent", "-config=/vault/agent/config.hcl"]
|
|
depends_on:
|
|
vault:
|
|
condition: service_healthy
|
|
vault-init:
|
|
condition: service_completed_successfully
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# PostgreSQL Database with PostGIS Extension
|
|
# PostGIS is required for geo-service (OSM/Terrain features)
|
|
postgres:
|
|
image: postgis/postgis:16-3.4-alpine
|
|
container_name: breakpilot-pwa-postgres
|
|
ports:
|
|
- "5432:5432"
|
|
environment:
|
|
POSTGRES_USER: breakpilot
|
|
POSTGRES_PASSWORD: breakpilot123
|
|
POSTGRES_DB: breakpilot_db
|
|
volumes:
|
|
- breakpilot_pwa_data:/var/lib/postgresql/data
|
|
- ./geo-service/scripts/init_postgis.sql:/docker-entrypoint-initdb.d/10-init-postgis.sql:ro
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U breakpilot -d breakpilot_db"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 5
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# ============================================
|
|
# Valkey - Session Cache (Redis-Fork, BSD-3)
|
|
# Redis-compatible, 100% Open Source
|
|
# ============================================
|
|
valkey:
|
|
image: valkey/valkey:8-alpine
|
|
container_name: breakpilot-pwa-valkey
|
|
ports:
|
|
- "6379:6379"
|
|
volumes:
|
|
- valkey_data:/data
|
|
command: valkey-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
|
|
healthcheck:
|
|
test: ["CMD", "valkey-cli", "ping"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 5
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# Go Consent Service
|
|
consent-service:
|
|
build:
|
|
context: ./consent-service
|
|
dockerfile: Dockerfile
|
|
platform: linux/arm64 # Mac Mini Apple Silicon
|
|
container_name: breakpilot-pwa-consent-service
|
|
ports:
|
|
- "8081:8081"
|
|
environment:
|
|
- DATABASE_URL=postgres://breakpilot:breakpilot123@postgres:5432/breakpilot_db?sslmode=disable
|
|
- JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key-change-in-production}
|
|
- JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET:-your-refresh-secret-key-change-in-production}
|
|
- PORT=8081
|
|
- ENVIRONMENT=${ENVIRONMENT:-development}
|
|
- ALLOWED_ORIGINS=http://localhost:8000,http://backend:8000
|
|
# Valkey Session Cache
|
|
- VALKEY_URL=${VALKEY_URL:-redis://valkey:6379}
|
|
- SESSION_TTL_HOURS=${SESSION_TTL_HOURS:-24}
|
|
# E-Mail Konfiguration (Mailpit für Entwicklung)
|
|
- SMTP_HOST=${SMTP_HOST:-mailpit}
|
|
- SMTP_PORT=${SMTP_PORT:-1025}
|
|
- SMTP_USERNAME=${SMTP_USERNAME:-}
|
|
- SMTP_PASSWORD=${SMTP_PASSWORD:-}
|
|
- SMTP_FROM_NAME=${SMTP_FROM_NAME:-BreakPilot}
|
|
- SMTP_FROM_ADDR=${SMTP_FROM_ADDR:-noreply@breakpilot.app}
|
|
- FRONTEND_URL=${FRONTEND_URL:-http://localhost:8000}
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
valkey:
|
|
condition: service_healthy
|
|
mailpit:
|
|
condition: service_started
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# Python Backend
|
|
backend:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile
|
|
platform: linux/arm64 # Mac Mini Apple Silicon
|
|
container_name: breakpilot-pwa-backend
|
|
expose:
|
|
- "8000"
|
|
environment:
|
|
- CONSENT_SERVICE_URL=http://consent-service:8081
|
|
- KLAUSUR_SERVICE_URL=http://klausur-service:8086
|
|
- TROCR_SERVICE_URL=${TROCR_SERVICE_URL:-http://host.docker.internal:18084}
|
|
- CAMUNDA_URL=http://camunda:8080/engine-rest
|
|
- DATABASE_URL=postgres://breakpilot:breakpilot123@postgres:5432/breakpilot_db?sslmode=disable
|
|
- JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key-change-in-production}
|
|
- ENVIRONMENT=${ENVIRONMENT:-development}
|
|
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
|
|
- DEBUG=${DEBUG:-false}
|
|
# Alerts Agent (Google Alerts Monitoring)
|
|
- ALERTS_AGENT_ENABLED=${ALERTS_AGENT_ENABLED:-true}
|
|
# HashiCorp Vault - Secrets Management
|
|
- VAULT_ADDR=${VAULT_ADDR:-http://vault:8200}
|
|
- VAULT_TOKEN=${VAULT_TOKEN:-breakpilot-dev-token}
|
|
- VAULT_SECRETS_PATH=${VAULT_SECRETS_PATH:-breakpilot}
|
|
- USE_VAULT_SECRETS=${USE_VAULT_SECRETS:-true}
|
|
# Keycloak Authentication (optional - wenn nicht gesetzt wird lokales JWT verwendet)
|
|
- KEYCLOAK_SERVER_URL=${KEYCLOAK_SERVER_URL:-}
|
|
- KEYCLOAK_REALM=${KEYCLOAK_REALM:-}
|
|
- KEYCLOAK_CLIENT_ID=${KEYCLOAK_CLIENT_ID:-}
|
|
- KEYCLOAK_CLIENT_SECRET=${KEYCLOAK_CLIENT_SECRET:-}
|
|
- KEYCLOAK_VERIFY_SSL=${KEYCLOAK_VERIFY_SSL:-true}
|
|
# Valkey Session Cache
|
|
- VALKEY_URL=${VALKEY_URL:-redis://valkey:6379}
|
|
- SESSION_TTL_HOURS=${SESSION_TTL_HOURS:-24}
|
|
# vast.ai GPU Infrastructure
|
|
- VAST_API_KEY=${VAST_API_KEY:-}
|
|
- VAST_INSTANCE_ID=${VAST_INSTANCE_ID:-}
|
|
- CONTROL_API_KEY=${CONTROL_API_KEY:-}
|
|
- VAST_AUTO_SHUTDOWN=${VAST_AUTO_SHUTDOWN:-true}
|
|
- VAST_AUTO_SHUTDOWN_MINUTES=${VAST_AUTO_SHUTDOWN_MINUTES:-30}
|
|
# vLLM Backend
|
|
- VLLM_BASE_URL=${VLLM_BASE_URL:-}
|
|
- VLLM_ENABLED=${VLLM_ENABLED:-false}
|
|
# Ollama Backend (lokal auf Mac Mini - DSGVO-konform)
|
|
- OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-http://host.docker.internal:11434}
|
|
- OLLAMA_ENABLED=${OLLAMA_ENABLED:-true}
|
|
- OLLAMA_DEFAULT_MODEL=${OLLAMA_DEFAULT_MODEL:-qwen2.5:14b}
|
|
- OLLAMA_VISION_MODEL=${OLLAMA_VISION_MODEL:-qwen2.5vl:32b}
|
|
- OLLAMA_CORRECTION_MODEL=${OLLAMA_CORRECTION_MODEL:-qwen2.5:14b}
|
|
- OLLAMA_TIMEOUT=${OLLAMA_TIMEOUT:-180}
|
|
# Breakpilot Drive Game API
|
|
- GAME_USE_DATABASE=${GAME_USE_DATABASE:-true}
|
|
- GAME_REQUIRE_AUTH=${GAME_REQUIRE_AUTH:-false}
|
|
- GAME_REQUIRE_BILLING=${GAME_REQUIRE_BILLING:-false}
|
|
- GAME_LLM_MODEL=${GAME_LLM_MODEL:-}
|
|
# Compliance LLM Provider Configuration
|
|
# Options: "anthropic" (cloud) or "self_hosted" (Ollama/local)
|
|
- COMPLIANCE_LLM_PROVIDER=${COMPLIANCE_LLM_PROVIDER:-self_hosted}
|
|
- SELF_HOSTED_LLM_URL=${SELF_HOSTED_LLM_URL:-http://host.docker.internal:11434}
|
|
- SELF_HOSTED_LLM_MODEL=${SELF_HOSTED_LLM_MODEL:-llama3.1:70b}
|
|
- COMPLIANCE_LLM_MAX_TOKENS=${COMPLIANCE_LLM_MAX_TOKENS:-4096}
|
|
- COMPLIANCE_LLM_TEMPERATURE=${COMPLIANCE_LLM_TEMPERATURE:-0.3}
|
|
- COMPLIANCE_LLM_TIMEOUT=${COMPLIANCE_LLM_TIMEOUT:-120}
|
|
# E-Mail Konfiguration (Mailpit fuer Entwicklung)
|
|
- SMTP_HOST=${SMTP_HOST:-mailpit}
|
|
- SMTP_PORT=${SMTP_PORT:-1025}
|
|
- SMTP_USERNAME=${SMTP_USERNAME:-}
|
|
- SMTP_PASSWORD=${SMTP_PASSWORD:-}
|
|
- SMTP_FROM_NAME=${SMTP_FROM_NAME:-BreakPilot}
|
|
- SMTP_FROM_ADDR=${SMTP_FROM_ADDR:-noreply@breakpilot.app}
|
|
extra_hosts:
|
|
- "host.docker.internal:host-gateway"
|
|
- "mac-mini:192.168.178.163"
|
|
volumes:
|
|
# Mount Docker socket for container monitoring (Mac Mini Control)
|
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
# Mount SBOM files for Security Dashboard
|
|
- ./docs/sbom:/app/docs/sbom:ro
|
|
# Mount Projekt-Verzeichnis fuer Test-Dashboard (echte Test-Discovery)
|
|
- /Users/benjaminadmin/Projekte/breakpilot-pwa:/app/project:ro
|
|
depends_on:
|
|
- consent-service
|
|
- valkey
|
|
- mailpit
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# Automatic Database Backup (runs daily at 2 AM)
|
|
backup:
|
|
image: postgres:16-alpine
|
|
container_name: breakpilot-pwa-backup
|
|
volumes:
|
|
- ./backups:/backups
|
|
- postgres_data:/var/lib/postgresql/data:ro
|
|
environment:
|
|
- PGHOST=postgres
|
|
- PGUSER=breakpilot
|
|
- PGPASSWORD=breakpilot123
|
|
- PGDATABASE=breakpilot_db
|
|
entrypoint: ["/bin/sh", "-c"]
|
|
command:
|
|
- |
|
|
echo "Backup service started. Running backup every day at 2 AM..."
|
|
while true; do
|
|
# Berechne Sekunden bis 2 Uhr
|
|
current_hour=$$(date +%H)
|
|
current_min=$$(date +%M)
|
|
current_sec=$$(date +%S)
|
|
|
|
if [ $$current_hour -lt 2 ]; then
|
|
sleep_hours=$$((2 - current_hour - 1))
|
|
else
|
|
sleep_hours=$$((26 - current_hour - 1))
|
|
fi
|
|
sleep_mins=$$((60 - current_min - 1))
|
|
sleep_secs=$$((60 - current_sec))
|
|
total_sleep=$$((sleep_hours * 3600 + sleep_mins * 60 + sleep_secs))
|
|
|
|
echo "Next backup in $$total_sleep seconds (at 2:00 AM)"
|
|
sleep $$total_sleep
|
|
|
|
# Backup erstellen
|
|
TIMESTAMP=$$(date +"%Y%m%d_%H%M%S")
|
|
BACKUP_FILE="/backups/breakpilot_$${TIMESTAMP}.sql.gz"
|
|
|
|
echo "Creating backup: $$BACKUP_FILE"
|
|
pg_dump | gzip > "$$BACKUP_FILE"
|
|
|
|
if [ $$? -eq 0 ]; then
|
|
echo "✓ Backup completed: $$BACKUP_FILE"
|
|
# Alte Backups löschen (älter als 30 Tage)
|
|
find /backups -name "breakpilot_*.sql.gz" -mtime +30 -delete
|
|
echo "✓ Old backups cleaned up"
|
|
else
|
|
echo "✗ Backup failed!"
|
|
fi
|
|
done
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
profiles:
|
|
- backup
|
|
|
|
# Mailpit - Lokaler E-Mail-Server für Entwicklung
|
|
# Web UI: http://localhost:8025
|
|
# SMTP: localhost:1025
|
|
mailpit:
|
|
image: axllent/mailpit:latest
|
|
container_name: breakpilot-pwa-mailpit
|
|
ports:
|
|
- "8025:8025" # Web UI
|
|
- "1025:1025" # SMTP Server
|
|
environment:
|
|
- MP_SMTP_AUTH_ACCEPT_ANY=true
|
|
- MP_SMTP_AUTH_ALLOW_INSECURE=true
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# Matrix Synapse - Schulkommunikation (E2EE Messenger)
|
|
# Admin: http://localhost:8008/_synapse/admin
|
|
synapse:
|
|
image: matrixdotorg/synapse:latest
|
|
container_name: breakpilot-pwa-synapse
|
|
ports:
|
|
- "8008:8008" # Client-Server API
|
|
- "8448:8448" # Federation (optional für später)
|
|
volumes:
|
|
- synapse_data:/data
|
|
environment:
|
|
- SYNAPSE_SERVER_NAME=${MATRIX_SERVER_NAME:-breakpilot.local}
|
|
- SYNAPSE_REPORT_STATS=no
|
|
- SYNAPSE_NO_TLS=1
|
|
- SYNAPSE_ENABLE_REGISTRATION=no
|
|
- SYNAPSE_LOG_LEVEL=INFO
|
|
- UID=1000
|
|
- GID=1000
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "curl -fSs http://localhost:8008/health || exit 1"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 30s
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# PostgreSQL für Matrix Synapse (separate DB)
|
|
synapse-db:
|
|
image: postgres:16-alpine
|
|
container_name: breakpilot-pwa-synapse-db
|
|
environment:
|
|
POSTGRES_USER: synapse
|
|
POSTGRES_PASSWORD: ${SYNAPSE_DB_PASSWORD:-synapse_secret_123}
|
|
POSTGRES_DB: synapse
|
|
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --lc-collate=C --lc-ctype=C"
|
|
volumes:
|
|
- synapse_db_data:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U synapse -d synapse"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 5
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# Go School Service (Klausuren, Noten, Zeugnisse)
|
|
school-service:
|
|
build:
|
|
context: ./school-service
|
|
dockerfile: Dockerfile
|
|
platform: linux/arm64 # Mac Mini Apple Silicon
|
|
container_name: breakpilot-pwa-school-service
|
|
ports:
|
|
- "8084:8084"
|
|
environment:
|
|
- DATABASE_URL=postgres://breakpilot:breakpilot123@postgres:5432/breakpilot_db?sslmode=disable
|
|
- JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key-change-in-production}
|
|
- PORT=8084
|
|
- ENVIRONMENT=${ENVIRONMENT:-development}
|
|
- ALLOWED_ORIGINS=http://localhost:8000,http://backend:8000
|
|
- LLM_GATEWAY_URL=http://backend:8000/llm
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# Embedding Service (ML-heavy operations)
|
|
# Handles: embeddings, re-ranking, PDF extraction
|
|
# Separated for faster klausur-service builds
|
|
embedding-service:
|
|
build:
|
|
context: ./klausur-service/embedding-service
|
|
dockerfile: Dockerfile
|
|
platform: linux/arm64 # Mac Mini Apple Silicon
|
|
container_name: breakpilot-pwa-embedding-service
|
|
ports:
|
|
- "8087:8087"
|
|
environment:
|
|
- EMBEDDING_BACKEND=${EMBEDDING_BACKEND:-local}
|
|
- LOCAL_EMBEDDING_MODEL=${LOCAL_EMBEDDING_MODEL:-BAAI/bge-m3}
|
|
- LOCAL_RERANKER_MODEL=${LOCAL_RERANKER_MODEL:-BAAI/bge-reranker-v2-m3}
|
|
- PDF_EXTRACTION_BACKEND=${PDF_EXTRACTION_BACKEND:-auto}
|
|
- OPENAI_API_KEY=${OPENAI_API_KEY:-}
|
|
- COHERE_API_KEY=${COHERE_API_KEY:-}
|
|
- LOG_LEVEL=${LOG_LEVEL:-INFO}
|
|
volumes:
|
|
- embedding_models:/root/.cache/huggingface
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 4G
|
|
healthcheck:
|
|
test: ["CMD", "python", "-c", "import httpx; httpx.get('http://localhost:8087/health').raise_for_status()"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
start_period: 120s
|
|
retries: 3
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# Klausur-Service (Abitur/Vorabitur Klausurkorrektur)
|
|
# React + FastAPI Microservice
|
|
# Web UI: http://localhost:8086
|
|
klausur-service:
|
|
build:
|
|
context: ./klausur-service
|
|
dockerfile: Dockerfile
|
|
platform: linux/arm64 # Native ARM64 - PaddlePaddle 3.3.0 unterstützt ARM64
|
|
container_name: breakpilot-pwa-klausur-service
|
|
expose:
|
|
- "8086"
|
|
environment:
|
|
- JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key-change-in-production}
|
|
- BACKEND_URL=http://backend:8000
|
|
- SCHOOL_SERVICE_URL=http://school-service:8084
|
|
- ENVIRONMENT=${ENVIRONMENT:-development}
|
|
# PostgreSQL for OCR Labeling & Metrics
|
|
- DATABASE_URL=postgres://breakpilot:breakpilot123@postgres:5432/breakpilot_db
|
|
# Embedding Service (ML operations)
|
|
- EMBEDDING_SERVICE_URL=http://embedding-service:8087
|
|
# BYOEH Configuration
|
|
- QDRANT_URL=http://qdrant:6333
|
|
- BYOEH_ENCRYPTION_ENABLED=true
|
|
- BYOEH_CHUNK_SIZE=1000
|
|
- BYOEH_CHUNK_OVERLAP=200
|
|
# MinIO Configuration (RAG Document Storage)
|
|
- MINIO_ENDPOINT=minio:9000
|
|
- MINIO_ACCESS_KEY=${MINIO_ROOT_USER:-breakpilot}
|
|
- MINIO_SECRET_KEY=${MINIO_ROOT_PASSWORD:-breakpilot123}
|
|
- MINIO_BUCKET=breakpilot-rag
|
|
- MINIO_SECURE=false
|
|
# Ollama LLM Configuration
|
|
- OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-http://host.docker.internal:11434}
|
|
- OLLAMA_ENABLED=${OLLAMA_ENABLED:-true}
|
|
- OLLAMA_DEFAULT_MODEL=${OLLAMA_DEFAULT_MODEL:-qwen2.5:14b}
|
|
- OLLAMA_VISION_MODEL=${OLLAMA_VISION_MODEL:-qwen2.5vl:32b}
|
|
- OLLAMA_CORRECTION_MODEL=${OLLAMA_CORRECTION_MODEL:-qwen2.5:14b}
|
|
# PaddleOCR Service (x86_64 via Rosetta)
|
|
- PADDLEOCR_SERVICE_URL=http://paddleocr-service:8095
|
|
# HashiCorp Vault - Anthropic API Key for Loesung E
|
|
- VAULT_ADDR=http://vault:8200
|
|
- VAULT_TOKEN=${VAULT_DEV_TOKEN:-breakpilot-dev-token}
|
|
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
|
|
volumes:
|
|
- klausur_uploads:/app/uploads
|
|
- eh_uploads:/app/eh-uploads
|
|
- ocr_labeling:/app/ocr-labeling
|
|
- paddle_models:/root/.paddlex # Persist PaddleOCR models across restarts
|
|
- ./docs:/app/docs # NIBIS Abitur-Dateien
|
|
depends_on:
|
|
- backend
|
|
- school-service
|
|
- embedding-service
|
|
- postgres
|
|
- qdrant
|
|
- minio
|
|
- paddleocr-service
|
|
- vault
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8086/health"]
|
|
interval: 30s
|
|
timeout: 30s
|
|
retries: 3
|
|
start_period: 10s
|
|
restart: unless-stopped
|
|
|
|
# ============================================
|
|
# PaddleOCR Service - x86_64 via Rosetta
|
|
# Runs in emulation to avoid ARM64 crashes
|
|
# ============================================
|
|
paddleocr-service:
|
|
build:
|
|
context: ./paddleocr-service
|
|
dockerfile: Dockerfile
|
|
platform: linux/amd64 # Force x86_64 emulation via Rosetta
|
|
container_name: breakpilot-pwa-paddleocr
|
|
expose:
|
|
- "8095"
|
|
environment:
|
|
- PADDLE_PDX_DISABLE_MODEL_SOURCE_CHECK=True
|
|
volumes:
|
|
- paddleocr_models:/root/.paddlex # Cache PaddleX models
|
|
- paddleocr_models:/root/.paddleocr # Cache PaddleOCR 3.x models
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8095/health"]
|
|
interval: 30s
|
|
timeout: 60s
|
|
retries: 5
|
|
start_period: 180s # Models need time to load in emulation
|
|
restart: unless-stopped
|
|
|
|
# Qdrant Vector Database (BYOEH - Erwartungshorizont RAG)
|
|
# REST API: http://localhost:6333
|
|
# gRPC: localhost:6334
|
|
qdrant:
|
|
image: qdrant/qdrant:v1.12.1
|
|
container_name: breakpilot-pwa-qdrant
|
|
ports:
|
|
- "6333:6333"
|
|
- "6334:6334"
|
|
volumes:
|
|
- qdrant_data:/qdrant/storage
|
|
environment:
|
|
- QDRANT__SERVICE__GRPC_PORT=6334
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "bash -c '</dev/tcp/localhost/6333'"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# MinIO Object Storage (RAG Document Storage)
|
|
# Web Console: http://localhost:9001
|
|
# S3 API: http://localhost:9000
|
|
minio:
|
|
image: minio/minio:latest
|
|
container_name: breakpilot-pwa-minio
|
|
ports:
|
|
- "9000:9000" # S3 API
|
|
- "9001:9001" # Web Console
|
|
environment:
|
|
- MINIO_ROOT_USER=${MINIO_ROOT_USER:-breakpilot}
|
|
- MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD:-breakpilot123}
|
|
volumes:
|
|
- minio_data:/data
|
|
command: server /data --console-address ":9001"
|
|
healthcheck:
|
|
test: ["CMD", "mc", "ready", "local"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# Go Billing Service
|
|
billing-service:
|
|
build:
|
|
context: ./billing-service
|
|
dockerfile: Dockerfile
|
|
platform: linux/arm64 # Mac Mini Apple Silicon
|
|
container_name: breakpilot-pwa-billing-service
|
|
ports:
|
|
- "8083:8083"
|
|
environment:
|
|
- DATABASE_URL=postgres://breakpilot:breakpilot123@postgres:5432/breakpilot_db?sslmode=disable
|
|
- JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key-change-in-production}
|
|
- PORT=8083
|
|
- ENVIRONMENT=${ENVIRONMENT:-development}
|
|
- ALLOWED_ORIGINS=http://localhost:8000,http://backend:8000
|
|
# Stripe Configuration
|
|
- STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY:-}
|
|
- STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET:-}
|
|
- STRIPE_PUBLISHABLE_KEY=${STRIPE_PUBLISHABLE_KEY:-}
|
|
# URLs
|
|
- BILLING_SUCCESS_URL=${BILLING_SUCCESS_URL:-http://localhost:3000/success}
|
|
- BILLING_CANCEL_URL=${BILLING_CANCEL_URL:-http://localhost:3000/cancel}
|
|
- FRONTEND_URL=${FRONTEND_URL:-http://localhost:8000}
|
|
# Trial
|
|
- TRIAL_PERIOD_DAYS=${TRIAL_PERIOD_DAYS:-7}
|
|
# Internal API
|
|
- INTERNAL_API_KEY=${INTERNAL_API_KEY:-internal-service-key-change-in-production}
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# Website - BreakPilot Landing/Pricing Page (Next.js)
|
|
# HTTPS via nginx on port 3000
|
|
website:
|
|
build:
|
|
context: ./website
|
|
dockerfile: Dockerfile
|
|
args:
|
|
- NEXT_PUBLIC_BILLING_API_URL=${NEXT_PUBLIC_BILLING_API_URL:-https://macmini:8083}
|
|
- NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL:-https://macmini:8000}
|
|
- NEXT_PUBLIC_KLAUSUR_SERVICE_URL=${NEXT_PUBLIC_KLAUSUR_SERVICE_URL:-https://macmini:8086}
|
|
- NEXT_PUBLIC_VOICE_SERVICE_URL=${NEXT_PUBLIC_VOICE_SERVICE_URL:-https://macmini:8091}
|
|
- NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=${STRIPE_PUBLISHABLE_KEY:-}
|
|
platform: linux/arm64 # Mac Mini Apple Silicon
|
|
container_name: breakpilot-pwa-website
|
|
expose:
|
|
- "3000"
|
|
environment:
|
|
- NODE_ENV=production
|
|
- VAST_API_KEY=${VAST_API_KEY:-}
|
|
- CONTROL_API_KEY=${CONTROL_API_KEY:-}
|
|
- BACKEND_URL=http://backend:8000
|
|
- CONSENT_SERVICE_URL=http://consent-service:8081
|
|
# Edu-Search Service (for uni-crawler admin)
|
|
- EDU_SEARCH_URL=${EDU_SEARCH_URL:-http://breakpilot-edu-search:8086}
|
|
- EDU_SEARCH_API_KEY=${EDU_SEARCH_API_KEY:-dev-key}
|
|
# Unity AI Bridge (runs on host machine in Unity Editor)
|
|
- UNITY_BRIDGE_URL=http://host.docker.internal:8090
|
|
# Woodpecker CI/CD Status Widget
|
|
- WOODPECKER_URL=${WOODPECKER_URL:-http://woodpecker-server:8000}
|
|
- WOODPECKER_TOKEN=${WOODPECKER_TOKEN:-}
|
|
depends_on:
|
|
- billing-service
|
|
- backend
|
|
- consent-service
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# ============================================
|
|
# Studio v2 - Neue Lehrer-Oberfläche
|
|
# Next.js auf Port 3001
|
|
# ============================================
|
|
studio-v2:
|
|
build:
|
|
context: ./studio-v2
|
|
dockerfile: Dockerfile
|
|
args:
|
|
- NEXT_PUBLIC_VOICE_SERVICE_URL=${NEXT_PUBLIC_VOICE_SERVICE_URL:-https://macmini:8091}
|
|
- NEXT_PUBLIC_KLAUSUR_SERVICE_URL=${NEXT_PUBLIC_KLAUSUR_SERVICE_URL:-https://macmini:8086}
|
|
platform: linux/arm64 # Mac Mini Apple Silicon
|
|
container_name: breakpilot-pwa-studio-v2
|
|
# Port 443 wird von nginx HTTPS bereitgestellt (studio-v2 intern auf 3001)
|
|
# Port 3004 ist HTTP-only für Mobile Uploads (HSTS-Umgehung)
|
|
ports:
|
|
- "3004:3001" # HTTP-only port for mobile QR uploads
|
|
expose:
|
|
- "3001"
|
|
environment:
|
|
- NODE_ENV=production
|
|
- BACKEND_URL=http://backend:8000
|
|
depends_on:
|
|
- backend
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# ============================================
|
|
# Admin v2 - Neues Admin-Frontend
|
|
# Next.js auf Port 3002
|
|
# ============================================
|
|
admin-v2:
|
|
build:
|
|
context: ./admin-v2
|
|
dockerfile: Dockerfile
|
|
args:
|
|
- NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL:-https://macmini:8000}
|
|
- NEXT_PUBLIC_OLD_ADMIN_URL=${NEXT_PUBLIC_OLD_ADMIN_URL:-https://macmini:3000/admin}
|
|
- NEXT_PUBLIC_SDK_URL=${NEXT_PUBLIC_SDK_URL:-https://macmini:8093}
|
|
- NEXT_PUBLIC_KLAUSUR_SERVICE_URL=${NEXT_PUBLIC_KLAUSUR_SERVICE_URL:-/klausur-api}
|
|
platform: linux/arm64 # Mac Mini Apple Silicon
|
|
container_name: breakpilot-pwa-admin-v2
|
|
# Port 3002 wird über nginx proxied (admin-v2:3000 intern)
|
|
# Port 3005 ist HTTP-only für Mobile Uploads (HSTS-Umgehung)
|
|
ports:
|
|
- "3005:3000" # HTTP-only port for mobile QR uploads
|
|
expose:
|
|
- "3000"
|
|
environment:
|
|
- NODE_ENV=production
|
|
- BACKEND_URL=http://backend:8000
|
|
- CONSENT_SERVICE_URL=http://consent-service:8081
|
|
- KLAUSUR_SERVICE_URL=http://klausur-service:8086
|
|
- SDK_URL=http://ai-compliance-sdk:8090
|
|
# Woodpecker CI Status
|
|
- WOODPECKER_URL=${WOODPECKER_URL:-http://woodpecker-server:8000}
|
|
- WOODPECKER_TOKEN=${WOODPECKER_TOKEN:-}
|
|
# Compliance Advisor LLM
|
|
- OLLAMA_URL=${OLLAMA_BASE_URL:-http://host.docker.internal:11434}
|
|
- COMPLIANCE_LLM_MODEL=${COMPLIANCE_LLM_MODEL:-qwen2.5vl:32b}
|
|
volumes:
|
|
# Mount Docker socket for Mac Mini monitoring dashboard
|
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
extra_hosts:
|
|
- "host.docker.internal:host-gateway"
|
|
depends_on:
|
|
- backend
|
|
- consent-service
|
|
- ai-compliance-sdk
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# ============================================
|
|
# Developer Portal - Oeffentliches SDK-Dokumentationsportal
|
|
# Access: https://macmini:3006/
|
|
# ============================================
|
|
developer-portal:
|
|
build:
|
|
context: ./developer-portal
|
|
dockerfile: Dockerfile
|
|
platform: linux/arm64
|
|
container_name: breakpilot-pwa-developer-portal
|
|
expose:
|
|
- "3000"
|
|
environment:
|
|
- NODE_ENV=production
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# ============================================
|
|
# AI Compliance SDK - Multi-Tenant RBAC & LLM Gateway
|
|
# Go auf Port 8090 (intern), 8093 (extern)
|
|
# CFO Use-Case: Namespace-isolierte KI-Nutzung
|
|
# ============================================
|
|
ai-compliance-sdk:
|
|
build:
|
|
context: ./ai-compliance-sdk
|
|
dockerfile: Dockerfile
|
|
platform: linux/arm64 # Mac Mini Apple Silicon
|
|
container_name: breakpilot-pwa-ai-compliance-sdk
|
|
# Port 8093 wird über nginx proxied (ai-compliance-sdk:8090 intern)
|
|
environment:
|
|
- PORT=8090
|
|
- ENVIRONMENT=${ENVIRONMENT:-development}
|
|
# PostgreSQL for RBAC, Policies, Audit
|
|
- DATABASE_URL=postgres://breakpilot:breakpilot123@postgres:5432/breakpilot_db?sslmode=disable
|
|
- JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key-change-in-production}
|
|
# LLM Provider Configuration
|
|
- LLM_PROVIDER=${SDK_LLM_PROVIDER:-ollama}
|
|
- LLM_FALLBACK_PROVIDER=${SDK_LLM_FALLBACK_PROVIDER:-anthropic}
|
|
# Ollama (Mac Mini lokal - DSGVO-konform)
|
|
- OLLAMA_URL=${OLLAMA_BASE_URL:-http://host.docker.internal:11434}
|
|
- OLLAMA_DEFAULT_MODEL=${OLLAMA_DEFAULT_MODEL:-qwen2.5:14b}
|
|
# Anthropic (Cloud-Fallback via Syseleven BSI-Cloud)
|
|
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
|
|
- ANTHROPIC_DEFAULT_MODEL=${ANTHROPIC_DEFAULT_MODEL:-claude-sonnet-4-20250514}
|
|
# PII Detection & Redaction
|
|
- PII_REDACTION_ENABLED=${PII_REDACTION_ENABLED:-true}
|
|
- PII_REDACTION_LEVEL=${PII_REDACTION_LEVEL:-strict}
|
|
# Audit Trail
|
|
- AUDIT_RETENTION_DAYS=${AUDIT_RETENTION_DAYS:-365}
|
|
- AUDIT_LOG_PROMPTS=${AUDIT_LOG_PROMPTS:-false}
|
|
# CORS
|
|
- ALLOWED_ORIGINS=http://localhost:3002,https://macmini:3002,http://admin-v2:3000
|
|
extra_hosts:
|
|
- "host.docker.internal:host-gateway"
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
healthcheck:
|
|
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8090/health"]
|
|
interval: 30s
|
|
timeout: 3s
|
|
start_period: 10s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
|
|
# DSMS Node - Dezentrales Speichersystem (Private IPFS)
|
|
dsms-node:
|
|
build:
|
|
context: ./dsms-node
|
|
dockerfile: Dockerfile
|
|
container_name: breakpilot-pwa-dsms-node
|
|
ports:
|
|
- "4001:4001" # Swarm P2P
|
|
- "5001:5001" # IPFS API
|
|
- "8085:8080" # IPFS Gateway (8085 um Konflikt mit Backend zu vermeiden)
|
|
volumes:
|
|
- dsms_data:/data/ipfs
|
|
environment:
|
|
- IPFS_PROFILE=server
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "ipfs id > /dev/null 2>&1 || exit 1"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
start_period: 30s
|
|
retries: 3
|
|
|
|
# DSMS Gateway - REST API für DSMS
|
|
dsms-gateway:
|
|
build:
|
|
context: ./dsms-gateway
|
|
dockerfile: Dockerfile
|
|
container_name: breakpilot-pwa-dsms-gateway
|
|
ports:
|
|
- "8082:8082"
|
|
environment:
|
|
- IPFS_API_URL=http://dsms-node:5001
|
|
- IPFS_GATEWAY_URL=http://dsms-node:8080
|
|
- JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key-change-in-production}
|
|
depends_on:
|
|
dsms-node:
|
|
condition: service_healthy
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# ============================================
|
|
# Jitsi Meet - Videokonferenzen für Schulungen
|
|
# Web UI: http://localhost:8443
|
|
# ============================================
|
|
|
|
# Jitsi Web Frontend
|
|
jitsi-web:
|
|
image: jitsi/web:stable-9823
|
|
container_name: breakpilot-pwa-jitsi-web
|
|
expose:
|
|
- "80"
|
|
environment:
|
|
- ENABLE_XMPP_WEBSOCKET=1
|
|
- ENABLE_COLIBRI_WEBSOCKET=1
|
|
- XMPP_DOMAIN=meet.jitsi
|
|
- XMPP_BOSH_URL_BASE=http://jitsi-xmpp:5280
|
|
- XMPP_MUC_DOMAIN=muc.meet.jitsi
|
|
- XMPP_GUEST_DOMAIN=guest.meet.jitsi
|
|
- TZ=Europe/Berlin
|
|
- PUBLIC_URL=${JITSI_PUBLIC_URL:-https://macmini}
|
|
- JICOFO_AUTH_USER=focus
|
|
- ENABLE_AUTH=${JITSI_ENABLE_AUTH:-0}
|
|
- ENABLE_GUESTS=${JITSI_ENABLE_GUESTS:-1}
|
|
- ENABLE_RECORDING=${JITSI_ENABLE_RECORDING:-1}
|
|
- ENABLE_LIVESTREAMING=0
|
|
- DISABLE_HTTPS=1
|
|
# Branding
|
|
- APP_NAME=BreakPilot Meet
|
|
- NATIVE_APP_NAME=BreakPilot Meet
|
|
- PROVIDER_NAME=BreakPilot
|
|
volumes:
|
|
- jitsi_web_config:/config
|
|
- jitsi_web_crontabs:/var/spool/cron/crontabs
|
|
- jitsi_transcripts:/usr/share/jitsi-meet/transcripts
|
|
networks:
|
|
breakpilot-pwa-network:
|
|
aliases:
|
|
- meet.jitsi
|
|
restart: unless-stopped
|
|
depends_on:
|
|
- jitsi-xmpp
|
|
|
|
# Prosody XMPP Server
|
|
jitsi-xmpp:
|
|
image: jitsi/prosody:stable-9823
|
|
container_name: breakpilot-pwa-jitsi-xmpp
|
|
environment:
|
|
- XMPP_DOMAIN=meet.jitsi
|
|
- XMPP_AUTH_DOMAIN=auth.meet.jitsi
|
|
- XMPP_MUC_DOMAIN=muc.meet.jitsi
|
|
- XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi
|
|
- XMPP_GUEST_DOMAIN=guest.meet.jitsi
|
|
- XMPP_RECORDER_DOMAIN=recorder.meet.jitsi
|
|
- XMPP_CROSS_DOMAIN=true
|
|
- TZ=Europe/Berlin
|
|
- JICOFO_AUTH_USER=focus
|
|
- JICOFO_AUTH_PASSWORD=${JITSI_JICOFO_AUTH_PASSWORD:-jicofo_secret_123}
|
|
- JVB_AUTH_USER=jvb
|
|
- JVB_AUTH_PASSWORD=${JITSI_JVB_AUTH_PASSWORD:-jvb_secret_123}
|
|
- JIGASI_XMPP_USER=jigasi
|
|
- JIGASI_XMPP_PASSWORD=${JITSI_JIGASI_XMPP_PASSWORD:-jigasi_secret_123}
|
|
- JIBRI_XMPP_USER=jibri
|
|
- JIBRI_XMPP_PASSWORD=${JITSI_JIBRI_XMPP_PASSWORD:-jibri_secret_123}
|
|
- JIBRI_RECORDER_USER=recorder
|
|
- JIBRI_RECORDER_PASSWORD=${JITSI_JIBRI_RECORDER_PASSWORD:-recorder_secret_123}
|
|
- LOG_LEVEL=info
|
|
- PUBLIC_URL=${JITSI_PUBLIC_URL:-https://macmini}
|
|
- ENABLE_AUTH=${JITSI_ENABLE_AUTH:-0}
|
|
- ENABLE_GUESTS=${JITSI_ENABLE_GUESTS:-1}
|
|
volumes:
|
|
- jitsi_prosody_config:/config
|
|
- jitsi_prosody_plugins:/prosody-plugins-custom
|
|
networks:
|
|
breakpilot-pwa-network:
|
|
aliases:
|
|
- xmpp.meet.jitsi
|
|
restart: unless-stopped
|
|
|
|
# Jicofo - Jitsi Conference Focus
|
|
jitsi-jicofo:
|
|
image: jitsi/jicofo:stable-9823
|
|
container_name: breakpilot-pwa-jitsi-jicofo
|
|
environment:
|
|
- XMPP_DOMAIN=meet.jitsi
|
|
- XMPP_AUTH_DOMAIN=auth.meet.jitsi
|
|
- XMPP_MUC_DOMAIN=muc.meet.jitsi
|
|
- XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi
|
|
- XMPP_SERVER=jitsi-xmpp
|
|
- JICOFO_AUTH_USER=focus
|
|
- JICOFO_AUTH_PASSWORD=${JITSI_JICOFO_AUTH_PASSWORD:-jicofo_secret_123}
|
|
- TZ=Europe/Berlin
|
|
- ENABLE_AUTH=${JITSI_ENABLE_AUTH:-0}
|
|
- AUTH_TYPE=internal
|
|
- ENABLE_AUTO_OWNER=${JITSI_ENABLE_AUTO_OWNER:-1}
|
|
volumes:
|
|
- jitsi_jicofo_config:/config
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
depends_on:
|
|
- jitsi-xmpp
|
|
|
|
# JVB - Jitsi Videobridge (WebRTC SFU)
|
|
jitsi-jvb:
|
|
image: jitsi/jvb:stable-9823
|
|
container_name: breakpilot-pwa-jitsi-jvb
|
|
ports:
|
|
- "10000:10000/udp" # Video/Audio RTP
|
|
- "8080:8080" # Colibri REST API (internal)
|
|
environment:
|
|
- XMPP_DOMAIN=meet.jitsi
|
|
- XMPP_AUTH_DOMAIN=auth.meet.jitsi
|
|
- XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi
|
|
- XMPP_SERVER=jitsi-xmpp
|
|
- JVB_AUTH_USER=jvb
|
|
- JVB_AUTH_PASSWORD=${JITSI_JVB_AUTH_PASSWORD:-jvb_secret_123}
|
|
- JVB_PORT=10000
|
|
- JVB_STUN_SERVERS=meet-jit-si-turnrelay.jitsi.net:443
|
|
- TZ=Europe/Berlin
|
|
- PUBLIC_URL=${JITSI_PUBLIC_URL:-https://macmini}
|
|
- COLIBRI_REST_ENABLED=true
|
|
- ENABLE_COLIBRI_WEBSOCKET=1
|
|
volumes:
|
|
- jitsi_jvb_config:/config
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
depends_on:
|
|
- jitsi-xmpp
|
|
|
|
# ============================================
|
|
# Jibri - Jitsi Recording Service
|
|
# Recordings werden zu MinIO hochgeladen
|
|
# ============================================
|
|
jibri:
|
|
build:
|
|
context: ./docker/jibri
|
|
dockerfile: Dockerfile
|
|
container_name: breakpilot-pwa-jibri
|
|
environment:
|
|
- XMPP_DOMAIN=meet.jitsi
|
|
- XMPP_AUTH_DOMAIN=auth.meet.jitsi
|
|
- XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi
|
|
- XMPP_RECORDER_DOMAIN=recorder.meet.jitsi
|
|
- XMPP_SERVER=jitsi-xmpp
|
|
- XMPP_MUC_DOMAIN=muc.meet.jitsi
|
|
- JIBRI_XMPP_USER=jibri
|
|
- JIBRI_XMPP_PASSWORD=${JITSI_JIBRI_XMPP_PASSWORD:-jibri_secret_123}
|
|
- JIBRI_RECORDER_USER=recorder
|
|
- JIBRI_RECORDER_PASSWORD=${JITSI_JIBRI_RECORDER_PASSWORD:-recorder_secret_123}
|
|
- JIBRI_BREWERY_MUC=jibribrewery
|
|
- JIBRI_RECORDING_DIR=/recordings
|
|
- JIBRI_FINALIZE_SCRIPT=/config/finalize.sh
|
|
- TZ=Europe/Berlin
|
|
# X11 Display Konfiguration (Xvfb)
|
|
- DISPLAY=:0
|
|
- RESOLUTION=1920x1080x24
|
|
# Optional: VNC fuer Debugging (Port 5900)
|
|
# - VNC_PASSWORD=debug123
|
|
# MinIO Upload Konfiguration
|
|
- MINIO_ENDPOINT=minio:9000
|
|
- MINIO_ACCESS_KEY=${MINIO_ROOT_USER}
|
|
- MINIO_SECRET_KEY=${MINIO_ROOT_PASSWORD}
|
|
- MINIO_BUCKET=breakpilot-recordings
|
|
# Backend Webhook (wird nach Upload aufgerufen)
|
|
- BACKEND_WEBHOOK_URL=http://backend:8000/api/recordings/webhook
|
|
volumes:
|
|
- jibri_recordings:/recordings
|
|
- /dev/shm:/dev/shm
|
|
shm_size: '2gb'
|
|
cap_add:
|
|
- SYS_ADMIN
|
|
- NET_BIND_SERVICE
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
depends_on:
|
|
- jitsi-xmpp
|
|
- minio
|
|
profiles:
|
|
- recording
|
|
|
|
# ============================================
|
|
# Transcription Worker - Whisper + pyannote
|
|
# Verarbeitet Recordings asynchron
|
|
# ============================================
|
|
transcription-worker:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile.worker
|
|
container_name: breakpilot-pwa-transcription-worker
|
|
environment:
|
|
- DATABASE_URL=postgres://breakpilot:breakpilot123@postgres:5432/breakpilot_db?sslmode=disable
|
|
- REDIS_URL=redis://valkey:6379/1
|
|
- WHISPER_MODEL=${WHISPER_MODEL:-large-v3}
|
|
- WHISPER_DEVICE=${WHISPER_DEVICE:-cpu}
|
|
- WHISPER_COMPUTE_TYPE=${WHISPER_COMPUTE_TYPE:-int8}
|
|
# pyannote.audio Token (HuggingFace)
|
|
- PYANNOTE_AUTH_TOKEN=${PYANNOTE_AUTH_TOKEN:-}
|
|
# MinIO Storage
|
|
- MINIO_ENDPOINT=${MINIO_ENDPOINT:-minio:9000}
|
|
- MINIO_ACCESS_KEY=${MINIO_ROOT_USER:-breakpilot}
|
|
- MINIO_SECRET_KEY=${MINIO_ROOT_PASSWORD:-breakpilot123}
|
|
- MINIO_BUCKET=breakpilot-recordings
|
|
- MINIO_SECURE=false
|
|
- TZ=Europe/Berlin
|
|
volumes:
|
|
- transcription_models:/root/.cache/huggingface
|
|
- transcription_temp:/tmp/transcriptions
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 8G
|
|
reservations:
|
|
memory: 4G
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
valkey:
|
|
condition: service_healthy
|
|
minio:
|
|
condition: service_started
|
|
profiles:
|
|
- recording
|
|
|
|
# ============================================
|
|
# ERPNext - Open Source ERP System
|
|
# Web UI: http://localhost:8090
|
|
# Default: Administrator / admin
|
|
# ============================================
|
|
|
|
# MariaDB for ERPNext
|
|
erpnext-db:
|
|
image: mariadb:10.6
|
|
container_name: breakpilot-pwa-erpnext-db
|
|
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --skip-character-set-client-handshake --skip-innodb-read-only-compressed
|
|
environment:
|
|
- MYSQL_ROOT_PASSWORD=${ERPNEXT_DB_ROOT_PASSWORD:-changeit123}
|
|
- MYSQL_DATABASE=erpnext
|
|
- MYSQL_USER=erpnext
|
|
- MYSQL_PASSWORD=${ERPNEXT_DB_PASSWORD:-erpnext123}
|
|
volumes:
|
|
- erpnext_db_data:/var/lib/mysql
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${ERPNEXT_DB_ROOT_PASSWORD:-changeit123}"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 10
|
|
|
|
# Redis Queue for ERPNext
|
|
erpnext-redis-queue:
|
|
image: redis:alpine
|
|
container_name: breakpilot-pwa-erpnext-redis-queue
|
|
volumes:
|
|
- erpnext_redis_queue_data:/data
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# Redis Cache for ERPNext
|
|
erpnext-redis-cache:
|
|
image: redis:alpine
|
|
container_name: breakpilot-pwa-erpnext-redis-cache
|
|
volumes:
|
|
- erpnext_redis_cache_data:/data
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# ERPNext Site Creator (runs once)
|
|
erpnext-create-site:
|
|
image: frappe/erpnext:latest
|
|
container_name: breakpilot-pwa-erpnext-create-site
|
|
command:
|
|
- bash
|
|
- -c
|
|
- |
|
|
wait-for-it -t 120 erpnext-db:3306;
|
|
wait-for-it -t 120 erpnext-redis-cache:6379;
|
|
wait-for-it -t 120 erpnext-redis-queue:6379;
|
|
if [[ ! -f sites/erpnext.local/site_config.json ]]; then
|
|
echo "Creating ERPNext site...";
|
|
bench new-site erpnext.local --db-host=erpnext-db --db-port=3306 --admin-password=admin --db-root-password=${ERPNEXT_DB_ROOT_PASSWORD:-changeit123} --install-app erpnext --set-default;
|
|
echo "Site created successfully!";
|
|
else
|
|
echo "Site already exists, skipping creation.";
|
|
fi;
|
|
environment:
|
|
- DB_HOST=erpnext-db
|
|
- DB_PORT=3306
|
|
- REDIS_CACHE=redis://erpnext-redis-cache:6379
|
|
- REDIS_QUEUE=redis://erpnext-redis-queue:6379
|
|
- SOCKETIO_PORT=9000
|
|
volumes:
|
|
- erpnext_sites:/home/frappe/frappe-bench/sites
|
|
- erpnext_logs:/home/frappe/frappe-bench/logs
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
depends_on:
|
|
erpnext-db:
|
|
condition: service_healthy
|
|
erpnext-redis-cache:
|
|
condition: service_started
|
|
erpnext-redis-queue:
|
|
condition: service_started
|
|
|
|
# ERPNext Backend
|
|
erpnext-backend:
|
|
image: frappe/erpnext:latest
|
|
container_name: breakpilot-pwa-erpnext-backend
|
|
command:
|
|
- bash
|
|
- -c
|
|
- |
|
|
wait-for-it -t 120 erpnext-db:3306;
|
|
wait-for-it -t 120 erpnext-redis-cache:6379;
|
|
wait-for-it -t 120 erpnext-redis-queue:6379;
|
|
bench serve --port 8000
|
|
environment:
|
|
- DB_HOST=erpnext-db
|
|
- DB_PORT=3306
|
|
- REDIS_CACHE=redis://erpnext-redis-cache:6379
|
|
- REDIS_QUEUE=redis://erpnext-redis-queue:6379
|
|
- SOCKETIO_PORT=9000
|
|
volumes:
|
|
- erpnext_sites:/home/frappe/frappe-bench/sites
|
|
- erpnext_logs:/home/frappe/frappe-bench/logs
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
depends_on:
|
|
erpnext-db:
|
|
condition: service_healthy
|
|
erpnext-create-site:
|
|
condition: service_completed_successfully
|
|
|
|
# ERPNext WebSocket
|
|
erpnext-websocket:
|
|
image: frappe/erpnext:latest
|
|
container_name: breakpilot-pwa-erpnext-websocket
|
|
command:
|
|
- bash
|
|
- -c
|
|
- |
|
|
wait-for-it -t 120 erpnext-db:3306;
|
|
wait-for-it -t 120 erpnext-redis-cache:6379;
|
|
wait-for-it -t 120 erpnext-redis-queue:6379;
|
|
bench watch
|
|
environment:
|
|
- DB_HOST=erpnext-db
|
|
- DB_PORT=3306
|
|
- REDIS_CACHE=redis://erpnext-redis-cache:6379
|
|
- REDIS_QUEUE=redis://erpnext-redis-queue:6379
|
|
- SOCKETIO_PORT=9000
|
|
volumes:
|
|
- erpnext_sites:/home/frappe/frappe-bench/sites
|
|
- erpnext_logs:/home/frappe/frappe-bench/logs
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
depends_on:
|
|
erpnext-db:
|
|
condition: service_healthy
|
|
erpnext-create-site:
|
|
condition: service_completed_successfully
|
|
|
|
# ERPNext Scheduler
|
|
erpnext-scheduler:
|
|
image: frappe/erpnext:latest
|
|
container_name: breakpilot-pwa-erpnext-scheduler
|
|
command:
|
|
- bash
|
|
- -c
|
|
- |
|
|
wait-for-it -t 120 erpnext-db:3306;
|
|
wait-for-it -t 120 erpnext-redis-cache:6379;
|
|
wait-for-it -t 120 erpnext-redis-queue:6379;
|
|
bench schedule
|
|
environment:
|
|
- DB_HOST=erpnext-db
|
|
- DB_PORT=3306
|
|
- REDIS_CACHE=redis://erpnext-redis-cache:6379
|
|
- REDIS_QUEUE=redis://erpnext-redis-queue:6379
|
|
- SOCKETIO_PORT=9000
|
|
volumes:
|
|
- erpnext_sites:/home/frappe/frappe-bench/sites
|
|
- erpnext_logs:/home/frappe/frappe-bench/logs
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
depends_on:
|
|
erpnext-db:
|
|
condition: service_healthy
|
|
erpnext-create-site:
|
|
condition: service_completed_successfully
|
|
|
|
# ERPNext Worker (Long)
|
|
erpnext-worker-long:
|
|
image: frappe/erpnext:latest
|
|
container_name: breakpilot-pwa-erpnext-worker-long
|
|
command:
|
|
- bash
|
|
- -c
|
|
- |
|
|
wait-for-it -t 120 erpnext-db:3306;
|
|
wait-for-it -t 120 erpnext-redis-cache:6379;
|
|
wait-for-it -t 120 erpnext-redis-queue:6379;
|
|
bench worker --queue long,default,short
|
|
environment:
|
|
- DB_HOST=erpnext-db
|
|
- DB_PORT=3306
|
|
- REDIS_CACHE=redis://erpnext-redis-cache:6379
|
|
- REDIS_QUEUE=redis://erpnext-redis-queue:6379
|
|
- SOCKETIO_PORT=9000
|
|
volumes:
|
|
- erpnext_sites:/home/frappe/frappe-bench/sites
|
|
- erpnext_logs:/home/frappe/frappe-bench/logs
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
depends_on:
|
|
erpnext-db:
|
|
condition: service_healthy
|
|
erpnext-create-site:
|
|
condition: service_completed_successfully
|
|
|
|
# ERPNext Worker (Short)
|
|
erpnext-worker-short:
|
|
image: frappe/erpnext:latest
|
|
container_name: breakpilot-pwa-erpnext-worker-short
|
|
command:
|
|
- bash
|
|
- -c
|
|
- |
|
|
wait-for-it -t 120 erpnext-db:3306;
|
|
wait-for-it -t 120 erpnext-redis-cache:6379;
|
|
wait-for-it -t 120 erpnext-redis-queue:6379;
|
|
bench worker --queue short,default
|
|
environment:
|
|
- DB_HOST=erpnext-db
|
|
- DB_PORT=3306
|
|
- REDIS_CACHE=redis://erpnext-redis-cache:6379
|
|
- REDIS_QUEUE=redis://erpnext-redis-queue:6379
|
|
- SOCKETIO_PORT=9000
|
|
volumes:
|
|
- erpnext_sites:/home/frappe/frappe-bench/sites
|
|
- erpnext_logs:/home/frappe/frappe-bench/logs
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
depends_on:
|
|
erpnext-db:
|
|
condition: service_healthy
|
|
erpnext-create-site:
|
|
condition: service_completed_successfully
|
|
|
|
# ERPNext Frontend (Nginx)
|
|
erpnext-frontend:
|
|
image: frappe/erpnext:latest
|
|
container_name: breakpilot-pwa-erpnext-frontend
|
|
command:
|
|
- nginx-entrypoint.sh
|
|
ports:
|
|
- "8090:8080"
|
|
environment:
|
|
- BACKEND=erpnext-backend:8000
|
|
- SOCKETIO=erpnext-websocket:9000
|
|
- UPSTREAM_REAL_IP_ADDRESS=127.0.0.1
|
|
- UPSTREAM_REAL_IP_HEADER=X-Forwarded-For
|
|
- UPSTREAM_REAL_IP_RECURSIVE=off
|
|
- FRAPPE_SITE_NAME_HEADER=erpnext.local
|
|
volumes:
|
|
- erpnext_sites:/home/frappe/frappe-bench/sites
|
|
- erpnext_logs:/home/frappe/frappe-bench/logs
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
depends_on:
|
|
erpnext-backend:
|
|
condition: service_started
|
|
erpnext-websocket:
|
|
condition: service_started
|
|
|
|
# ============================================
|
|
# Breakpilot Drive - Lernspiel (Unity WebGL)
|
|
# Web UI: http://localhost:3001
|
|
# ============================================
|
|
breakpilot-drive:
|
|
build:
|
|
context: ./breakpilot-drive
|
|
dockerfile: Dockerfile
|
|
container_name: breakpilot-pwa-drive
|
|
ports:
|
|
- "3001:80"
|
|
environment:
|
|
# API Configuration (injected into Unity WebGL)
|
|
- API_BASE_URL=${GAME_API_URL:-http://localhost:8000/api/game}
|
|
# Feature Flags
|
|
- GAME_REQUIRE_AUTH=${GAME_REQUIRE_AUTH:-false}
|
|
- GAME_ENABLE_LEADERBOARDS=${GAME_ENABLE_LEADERBOARDS:-true}
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
depends_on:
|
|
- backend
|
|
healthcheck:
|
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost:80/health.json"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
profiles:
|
|
- game
|
|
|
|
# ============================================
|
|
# Camunda 7 - BPMN Workflow Engine
|
|
# Web UI: http://localhost:8089/camunda
|
|
# REST API: http://localhost:8089/engine-rest
|
|
# License: Apache 2.0 (kommerziell nutzbar)
|
|
# ============================================
|
|
camunda:
|
|
image: camunda/camunda-bpm-platform:7.21.0
|
|
container_name: breakpilot-pwa-camunda
|
|
ports:
|
|
- "8089:8080"
|
|
environment:
|
|
- DB_DRIVER=org.postgresql.Driver
|
|
- DB_URL=jdbc:postgresql://postgres:5432/breakpilot_db
|
|
- DB_USERNAME=breakpilot
|
|
- DB_PASSWORD=${POSTGRES_PASSWORD:-breakpilot123}
|
|
- DB_VALIDATE_ON_BORROW=true
|
|
- WAIT_FOR=postgres:5432
|
|
- CAMUNDA_BPM_ADMIN_USER_ID=admin
|
|
- CAMUNDA_BPM_ADMIN_USER_PASSWORD=${CAMUNDA_ADMIN_PASSWORD:-admin123}
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "curl -f http://localhost:8080/camunda/api/engine || exit 1"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 5
|
|
start_period: 60s
|
|
restart: unless-stopped
|
|
profiles:
|
|
- bpmn
|
|
|
|
# ============================================
|
|
# GeoEdu Service - Self-Hosted OSM + Terrain
|
|
# DSGVO-konforme Erdkunde-Lernplattform
|
|
# Web UI: http://localhost:8088
|
|
# ============================================
|
|
geo-service:
|
|
build:
|
|
context: ./geo-service
|
|
dockerfile: Dockerfile
|
|
platform: linux/arm64 # Mac Mini Apple Silicon
|
|
container_name: breakpilot-pwa-geo-service
|
|
ports:
|
|
- "8088:8088"
|
|
environment:
|
|
- PORT=8088
|
|
- ENVIRONMENT=${ENVIRONMENT:-development}
|
|
- JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key}
|
|
# PostgreSQL (PostGIS fuer OSM-Daten)
|
|
- DATABASE_URL=postgresql+asyncpg://breakpilot:breakpilot123@postgres:5432/breakpilot_db
|
|
# MinIO (AOI Bundles, generierte Assets)
|
|
- MINIO_ENDPOINT=minio:9000
|
|
- MINIO_ACCESS_KEY=${MINIO_ROOT_USER:-breakpilot}
|
|
- MINIO_SECRET_KEY=${MINIO_ROOT_PASSWORD:-breakpilot123}
|
|
- MINIO_BUCKET=breakpilot-geo
|
|
- MINIO_SECURE=false
|
|
# Ollama (Lernstationen generieren)
|
|
- OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-http://host.docker.internal:11434}
|
|
- OLLAMA_MODEL=${OLLAMA_DEFAULT_MODEL:-qwen2.5:14b}
|
|
# Tile Server Config
|
|
- TILE_CACHE_DIR=/app/cache/tiles
|
|
- DEM_CACHE_DIR=/app/cache/dem
|
|
- MAX_AOI_SIZE_KM2=4
|
|
volumes:
|
|
- geo_osm_data:/app/data/osm
|
|
- geo_dem_data:/app/data/dem
|
|
- geo_tile_cache:/app/cache/tiles
|
|
- geo_aoi_bundles:/app/bundles
|
|
extra_hosts:
|
|
- "host.docker.internal:host-gateway"
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
minio:
|
|
condition: service_started
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8088/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
start_period: 60s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
|
|
# ============================================
|
|
# Voice Service - PersonaPlex + TaskOrchestrator
|
|
# Voice-First Interface fuer Breakpilot
|
|
# DSGVO-konform: Keine Audio-Persistenz
|
|
# Web UI: http://localhost:8091
|
|
# ============================================
|
|
voice-service:
|
|
build:
|
|
context: ./voice-service
|
|
dockerfile: Dockerfile
|
|
platform: linux/arm64 # Mac Mini Apple Silicon
|
|
container_name: breakpilot-pwa-voice-service
|
|
# Port 8091 wird von nginx HTTPS bereitgestellt (wss://macmini:8091)
|
|
expose:
|
|
- "8091"
|
|
environment:
|
|
- PORT=8091
|
|
- DATABASE_URL=postgresql+asyncpg://breakpilot:breakpilot123@postgres:5432/breakpilot_db
|
|
- VALKEY_URL=redis://valkey:6379/2
|
|
- PERSONAPLEX_ENABLED=${PERSONAPLEX_ENABLED:-false}
|
|
- PERSONAPLEX_WS_URL=${PERSONAPLEX_WS_URL:-ws://host.docker.internal:8998}
|
|
- ORCHESTRATOR_ENABLED=true
|
|
- FALLBACK_LLM_PROVIDER=${FALLBACK_LLM_PROVIDER:-ollama}
|
|
- OLLAMA_BASE_URL=http://host.docker.internal:11434
|
|
- OLLAMA_VOICE_MODEL=qwen2.5:32b
|
|
- BQAS_JUDGE_MODEL=qwen2.5:14b
|
|
- KLAUSUR_SERVICE_URL=http://klausur-service:8086
|
|
- ENCRYPTION_ENABLED=true
|
|
- AUDIO_PERSISTENCE=false
|
|
- AUDIO_SAMPLE_RATE=24000
|
|
- ENVIRONMENT=${ENVIRONMENT:-development}
|
|
- JWT_SECRET=${JWT_SECRET:-your-super-secret-jwt-key-change-in-production}
|
|
volumes:
|
|
- voice_session_data:/app/data/sessions
|
|
extra_hosts:
|
|
- "host.docker.internal:host-gateway"
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
valkey:
|
|
condition: service_healthy
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8091/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
start_period: 60s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
|
|
# ============================================
|
|
# MkDocs Documentation
|
|
# Web UI: http://localhost:8009
|
|
# Material Theme with German language support
|
|
# ============================================
|
|
docs:
|
|
build:
|
|
context: .
|
|
dockerfile: docs-src/Dockerfile
|
|
platform: linux/arm64 # Mac Mini Apple Silicon
|
|
container_name: breakpilot-pwa-docs
|
|
ports:
|
|
- "8009:80"
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:80/"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
|
|
# ============================================
|
|
# Gitea - Self-hosted Git Server
|
|
# Web UI: http://localhost:3003
|
|
# SSH: localhost:2222
|
|
# Gitea Actions enabled for CI/CD
|
|
# ============================================
|
|
gitea:
|
|
image: gitea/gitea:1.22-rootless
|
|
container_name: breakpilot-pwa-gitea
|
|
extra_hosts:
|
|
- "macmini:192.168.178.100"
|
|
environment:
|
|
- USER_UID=1000
|
|
- USER_GID=1000
|
|
- GITEA__database__DB_TYPE=postgres
|
|
- GITEA__database__HOST=postgres:5432
|
|
- GITEA__database__NAME=gitea
|
|
- GITEA__database__USER=breakpilot
|
|
- GITEA__database__PASSWD=breakpilot123
|
|
- GITEA__server__DOMAIN=macmini
|
|
- GITEA__server__SSH_DOMAIN=macmini
|
|
- GITEA__server__ROOT_URL=http://macmini:3003/
|
|
- GITEA__server__HTTP_PORT=3003
|
|
- GITEA__server__SSH_PORT=2222
|
|
- GITEA__server__SSH_LISTEN_PORT=2222
|
|
- GITEA__actions__ENABLED=true
|
|
- GITEA__actions__DEFAULT_ACTIONS_URL=https://gitea.com
|
|
- GITEA__service__DISABLE_REGISTRATION=true
|
|
- GITEA__service__REQUIRE_SIGNIN_VIEW=false
|
|
- GITEA__repository__DEFAULT_BRANCH=main
|
|
- GITEA__log__LEVEL=Info
|
|
- GITEA__webhook__ALLOWED_HOST_LIST=macmini,192.168.178.100,woodpecker-server,localhost,external
|
|
volumes:
|
|
- gitea_data:/var/lib/gitea
|
|
- gitea_config:/etc/gitea
|
|
- /etc/timezone:/etc/timezone:ro
|
|
- /etc/localtime:/etc/localtime:ro
|
|
ports:
|
|
- "3003:3003"
|
|
- "2222:2222"
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:3003/api/healthz"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 30s
|
|
restart: unless-stopped
|
|
|
|
# ============================================
|
|
# Gitea Actions Runner
|
|
# Executes CI/CD workflows defined in .gitea/workflows/
|
|
# Includes Syft, Grype, Trivy for SBOM generation
|
|
# ============================================
|
|
gitea-runner:
|
|
image: gitea/act_runner:latest
|
|
container_name: breakpilot-pwa-gitea-runner
|
|
environment:
|
|
- CONFIG_FILE=/config/config.yaml
|
|
- GITEA_INSTANCE_URL=http://gitea:3003
|
|
- GITEA_RUNNER_REGISTRATION_TOKEN=${GITEA_RUNNER_TOKEN:-}
|
|
- GITEA_RUNNER_NAME=breakpilot-runner
|
|
- GITEA_RUNNER_LABELS=ubuntu-latest:docker://node:20-bookworm,ubuntu-22.04:docker://ubuntu:22.04,self-hosted:host
|
|
volumes:
|
|
- gitea_runner_data:/data
|
|
- ./gitea/runner-config.yaml:/config/config.yaml:ro
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
depends_on:
|
|
gitea:
|
|
condition: service_healthy
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# ============================================
|
|
# Woodpecker CI - Server
|
|
# Modern CI/CD with native container support
|
|
# Web UI: http://localhost:8085
|
|
# ============================================
|
|
woodpecker-server:
|
|
image: woodpeckerci/woodpecker-server:v3
|
|
container_name: breakpilot-pwa-woodpecker-server
|
|
ports:
|
|
- "8090:8000"
|
|
extra_hosts:
|
|
- "macmini:192.168.178.100"
|
|
environment:
|
|
- WOODPECKER_OPEN=true
|
|
- WOODPECKER_HOST=http://macmini:8090
|
|
- WOODPECKER_ADMIN=pilotadmin,breakpilot_admin
|
|
# Gitea OAuth Integration
|
|
- WOODPECKER_GITEA=true
|
|
- WOODPECKER_GITEA_URL=http://macmini:3003
|
|
- WOODPECKER_GITEA_CLIENT=${WOODPECKER_GITEA_CLIENT:-}
|
|
- WOODPECKER_GITEA_SECRET=${WOODPECKER_GITEA_SECRET:-}
|
|
# Agent Secret (fuer Agent-Authentifizierung)
|
|
- WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET:-woodpecker-agent-secret-key}
|
|
# Database (SQLite fuer einfache Einrichtung)
|
|
- WOODPECKER_DATABASE_DRIVER=sqlite3
|
|
- WOODPECKER_DATABASE_DATASOURCE=/var/lib/woodpecker/woodpecker.sqlite
|
|
# Logging
|
|
- WOODPECKER_LOG_LEVEL=info
|
|
# Trust all repos (allows privileged containers)
|
|
- WOODPECKER_PLUGINS_PRIVILEGED=true
|
|
- WOODPECKER_PLUGINS_TRUSTED_CLONE=true
|
|
volumes:
|
|
- woodpecker_data:/var/lib/woodpecker
|
|
depends_on:
|
|
gitea:
|
|
condition: service_healthy
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
# ============================================
|
|
# Night Scheduler - Nachtabschaltung
|
|
# Stoppt Services nachts, startet sie morgens
|
|
# API: http://localhost:8096
|
|
# ============================================
|
|
night-scheduler:
|
|
build: ./night-scheduler
|
|
container_name: breakpilot-pwa-night-scheduler
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
- ./night-scheduler/config:/config
|
|
- ./docker-compose.yml:/app/docker-compose.yml:ro
|
|
environment:
|
|
- COMPOSE_PROJECT_NAME=breakpilot-pwa
|
|
ports:
|
|
- "8096:8096"
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8096/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 10s
|
|
|
|
# ============================================
|
|
# Woodpecker CI - Agent
|
|
# Executes pipeline steps in containers
|
|
# ============================================
|
|
woodpecker-agent:
|
|
image: woodpeckerci/woodpecker-agent:v3
|
|
container_name: breakpilot-pwa-woodpecker-agent
|
|
command: agent
|
|
environment:
|
|
- WOODPECKER_SERVER=woodpecker-server:9000
|
|
- WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET:-woodpecker-agent-secret-key}
|
|
- WOODPECKER_MAX_WORKFLOWS=4
|
|
- WOODPECKER_LOG_LEVEL=info
|
|
# Backend für Container-Ausführung
|
|
- WOODPECKER_BACKEND=docker
|
|
- DOCKER_HOST=unix:///var/run/docker.sock
|
|
# Extra hosts für Pipeline-Container (damit sie macmini erreichen)
|
|
- WOODPECKER_BACKEND_DOCKER_EXTRA_HOSTS=macmini:192.168.178.100,gitea:192.168.178.100
|
|
# Nutze das gleiche Netzwerk für Pipeline-Container
|
|
- WOODPECKER_BACKEND_DOCKER_NETWORK=breakpilot-dev_breakpilot-pwa-network
|
|
# Docker-Socket für Build-Steps (Host-Docker statt DinD)
|
|
- WOODPECKER_BACKEND_DOCKER_VOLUMES=/var/run/docker.sock:/var/run/docker.sock
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
depends_on:
|
|
- woodpecker-server
|
|
networks:
|
|
- breakpilot-pwa-network
|
|
restart: unless-stopped
|
|
|
|
volumes:
|
|
# Woodpecker CI Data
|
|
woodpecker_data:
|
|
driver: local
|
|
# Vault Data
|
|
vault_data:
|
|
driver: local
|
|
# Vault Agent Config (role-id, secret-id, token)
|
|
vault_agent_config:
|
|
driver: local
|
|
# Vault-managed SSL Certificates
|
|
vault_certs:
|
|
driver: local
|
|
breakpilot_pwa_data:
|
|
driver: local
|
|
# Embedding Service Model Cache
|
|
embedding_models:
|
|
driver: local
|
|
# Valkey Session Cache
|
|
valkey_data:
|
|
driver: local
|
|
dsms_data:
|
|
driver: local
|
|
klausur_uploads:
|
|
driver: local
|
|
eh_uploads:
|
|
driver: local
|
|
ocr_labeling:
|
|
driver: local
|
|
# PaddleOCR Model Cache (persist across container restarts)
|
|
paddle_models:
|
|
driver: local
|
|
# PaddleOCR Service Model Cache (x86_64 emulation)
|
|
paddleocr_models:
|
|
driver: local
|
|
qdrant_data:
|
|
driver: local
|
|
minio_data:
|
|
driver: local
|
|
synapse_data:
|
|
driver: local
|
|
synapse_db_data:
|
|
driver: local
|
|
# Jitsi Volumes
|
|
jitsi_web_config:
|
|
driver: local
|
|
jitsi_web_crontabs:
|
|
driver: local
|
|
jitsi_transcripts:
|
|
driver: local
|
|
jitsi_prosody_config:
|
|
driver: local
|
|
jitsi_prosody_plugins:
|
|
driver: local
|
|
jitsi_jicofo_config:
|
|
driver: local
|
|
jitsi_jvb_config:
|
|
driver: local
|
|
# Jibri Recording Volumes
|
|
jibri_recordings:
|
|
driver: local
|
|
# Transcription Worker Volumes
|
|
transcription_models:
|
|
driver: local
|
|
transcription_temp:
|
|
driver: local
|
|
# ERPNext Volumes
|
|
erpnext_db_data:
|
|
driver: local
|
|
erpnext_redis_queue_data:
|
|
driver: local
|
|
erpnext_redis_cache_data:
|
|
driver: local
|
|
erpnext_sites:
|
|
driver: local
|
|
erpnext_logs:
|
|
driver: local
|
|
# GeoEdu Service Volumes
|
|
geo_osm_data:
|
|
driver: local
|
|
geo_dem_data:
|
|
driver: local
|
|
geo_tile_cache:
|
|
driver: local
|
|
geo_aoi_bundles:
|
|
driver: local
|
|
# Voice Service Volumes (transient sessions only)
|
|
voice_session_data:
|
|
driver: local
|
|
# Gitea Volumes
|
|
gitea_data:
|
|
driver: local
|
|
gitea_config:
|
|
driver: local
|
|
gitea_runner_data:
|
|
driver: local
|
|
|
|
networks:
|
|
breakpilot-pwa-network:
|
|
driver: bridge
|