All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 27s
CI / test-python-voice (push) Successful in 25s
CI / test-bqas (push) Successful in 25s
CI / Deploy (push) Successful in 4s
- Migrate chat API from Ollama to LiteLLM (OpenAI-compatible SSE) - Add 15-min presenter storyline with bilingual scripts for all 20 slides - Add FAQ system (30 entries) with keyword matching for instant answers - Add IntroPresenterSlide with avatar placeholder and start button - Add PresenterOverlay (progress bar, subtitle text, play/pause/stop) - Add AvatarPlaceholder with pulse animation during speaking - Add usePresenterMode hook (state machine: idle→presenting→paused→answering→resuming) - Add 'P' keyboard shortcut to toggle presenter mode - Support [GOTO:slide-id] markers in chat responses - Dynamic slide count (was hardcoded 13, now from SLIDE_ORDER) - TTS stub prepared for future Piper integration Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
864 lines
26 KiB
YAML
864 lines
26 KiB
YAML
# =========================================================
|
|
# BreakPilot Core — Shared Infrastructure
|
|
# =========================================================
|
|
# Start: docker compose up -d
|
|
# Health: http://macmini:8099/health
|
|
# =========================================================
|
|
|
|
networks:
|
|
breakpilot-network:
|
|
driver: bridge
|
|
name: breakpilot-network
|
|
|
|
volumes:
|
|
# Infrastructure
|
|
vault_data:
|
|
vault_agent_config:
|
|
vault_certs:
|
|
breakpilot_db_data:
|
|
valkey_data:
|
|
qdrant_data:
|
|
minio_data:
|
|
# CI/CD
|
|
gitea_data:
|
|
gitea_config:
|
|
gitea_runner_data:
|
|
# ERP
|
|
erpnext_db_data:
|
|
erpnext_redis_queue_data:
|
|
erpnext_redis_cache_data:
|
|
erpnext_sites:
|
|
erpnext_logs:
|
|
# Services
|
|
embedding_models:
|
|
|
|
services:
|
|
|
|
# =========================================================
|
|
# REVERSE PROXY
|
|
# =========================================================
|
|
nginx:
|
|
image: nginx:alpine
|
|
container_name: bp-core-nginx
|
|
ports:
|
|
- "443:443"
|
|
- "80:80"
|
|
- "3000:3000" # Website (Lehrer)
|
|
- "3002:3002" # Admin Lehrer
|
|
- "3006:3006" # Developer Portal (Compliance)
|
|
- "3007:3007" # Admin Compliance (NEU)
|
|
- "8000:8000" # Backend Core
|
|
- "8001:8001" # Backend Lehrer (NEU)
|
|
- "8002:8002" # Backend Compliance (NEU)
|
|
- "8086:8086" # Klausur Service
|
|
- "8087:8087" # Embedding Service
|
|
- "8089:8089" # Edu-Search
|
|
- "8091:8091" # Voice Service (WSS)
|
|
- "8093:8093" # AI Compliance SDK
|
|
- "8097:8097" # RAG Service (NEU)
|
|
- "8443:8443" # Jitsi Meet
|
|
- "3008:3008" # Admin Core
|
|
- "3010:3010" # Portal Dashboard
|
|
- "8011:8011" # Compliance Docs (MkDocs)
|
|
volumes:
|
|
- ./nginx/conf.d:/etc/nginx/conf.d:ro
|
|
- vault_certs:/etc/nginx/certs:ro
|
|
- ./nginx/html:/usr/share/nginx/html/portal:ro
|
|
- /Users/benjaminadmin/rag-originals:/data/rag-originals:ro
|
|
depends_on:
|
|
vault-agent:
|
|
condition: service_started
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
# =========================================================
|
|
# SECRETS MANAGEMENT
|
|
# =========================================================
|
|
vault:
|
|
image: hashicorp/vault:1.15
|
|
entrypoint: ["vault"]
|
|
command: server -config=/vault/config/config.hcl
|
|
container_name: bp-core-vault
|
|
ports:
|
|
- "8200:8200"
|
|
volumes:
|
|
- vault_data:/vault/data
|
|
- ./vault/config.hcl:/vault/config/config.hcl:ro
|
|
cap_add:
|
|
- IPC_LOCK
|
|
environment:
|
|
VAULT_ADDR: "http://127.0.0.1:8200"
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "vault status; test $? -le 2"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
vault-init:
|
|
image: hashicorp/vault:1.15
|
|
container_name: bp-core-vault-init
|
|
volumes:
|
|
- ./vault/init-vault.sh:/vault/scripts/init-vault.sh:ro
|
|
- ./vault/init-pki.sh:/vault/scripts/init-pki.sh:ro
|
|
- ./vault/init-secrets.sh:/vault/scripts/init-secrets.sh:ro
|
|
- vault_data:/vault/data
|
|
- vault_agent_config:/vault/agent/data
|
|
- vault_certs:/vault/certs
|
|
environment:
|
|
VAULT_ADDR: "http://vault:8200"
|
|
entrypoint: /bin/sh
|
|
command: /vault/scripts/init-vault.sh
|
|
depends_on:
|
|
vault:
|
|
condition: service_healthy
|
|
restart: "no"
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
vault-agent:
|
|
image: hashicorp/vault:1.15
|
|
container_name: bp-core-vault-agent
|
|
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
|
|
environment:
|
|
VAULT_ADDR: "http://vault:8200"
|
|
entrypoint: /bin/sh
|
|
command: -c "vault agent -config=/vault/agent/config.hcl"
|
|
depends_on:
|
|
vault:
|
|
condition: service_healthy
|
|
vault-init:
|
|
condition: service_completed_successfully
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
# =========================================================
|
|
# DATABASES
|
|
# =========================================================
|
|
postgres:
|
|
image: postgis/postgis:16-3.4-alpine
|
|
container_name: bp-core-postgres
|
|
ports:
|
|
- "5432:5432"
|
|
volumes:
|
|
- breakpilot_db_data:/var/lib/postgresql/data
|
|
- ./scripts/init-schemas.sql:/docker-entrypoint-initdb.d/20-init-schemas.sql:ro
|
|
environment:
|
|
POSTGRES_USER: ${POSTGRES_USER:-breakpilot}
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-breakpilot123}
|
|
POSTGRES_DB: ${POSTGRES_DB:-breakpilot_db}
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U breakpilot -d breakpilot_db"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 5
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
valkey:
|
|
image: valkey/valkey:8-alpine
|
|
container_name: bp-core-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
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
# =========================================================
|
|
# VECTOR DB & OBJECT STORAGE
|
|
# =========================================================
|
|
qdrant:
|
|
image: qdrant/qdrant:v1.12.1
|
|
container_name: bp-core-qdrant
|
|
ports:
|
|
- "6333:6333"
|
|
- "6334:6334"
|
|
volumes:
|
|
- qdrant_data:/qdrant/storage
|
|
environment:
|
|
QDRANT__SERVICE__GRPC_PORT: 6334
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/127.0.0.1/6333'"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
minio:
|
|
image: minio/minio:latest
|
|
container_name: bp-core-minio
|
|
ports:
|
|
- "9000:9000"
|
|
- "9001:9001"
|
|
volumes:
|
|
- minio_data:/data
|
|
environment:
|
|
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-breakpilot}
|
|
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-breakpilot123}
|
|
command: server /data --console-address ":9001"
|
|
healthcheck:
|
|
test: ["CMD", "mc", "ready", "local"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
# =========================================================
|
|
# SHARED SERVICES
|
|
# =========================================================
|
|
backend-core:
|
|
build:
|
|
context: ./backend-core
|
|
dockerfile: Dockerfile
|
|
container_name: bp-core-backend
|
|
platform: linux/arm64
|
|
expose:
|
|
- "8000"
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
environment:
|
|
DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-breakpilot}:${POSTGRES_PASSWORD:-breakpilot123}@postgres:5432/${POSTGRES_DB:-breakpilot_db}?options=-csearch_path%3Dcore,public
|
|
JWT_SECRET: ${JWT_SECRET:-your-super-secret-jwt-key-change-in-production}
|
|
ENVIRONMENT: ${ENVIRONMENT:-development}
|
|
VALKEY_URL: redis://valkey:6379/0
|
|
SESSION_TTL_HOURS: ${SESSION_TTL_HOURS:-24}
|
|
CONSENT_SERVICE_URL: http://consent-service:8081
|
|
VAULT_ADDR: http://vault:8200
|
|
VAULT_TOKEN: ${VAULT_TOKEN:-breakpilot-dev-token}
|
|
USE_VAULT_SECRETS: ${USE_VAULT_SECRETS:-false}
|
|
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"
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
valkey:
|
|
condition: service_healthy
|
|
consent-service:
|
|
condition: service_started
|
|
mailpit:
|
|
condition: service_started
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
consent-service:
|
|
build:
|
|
context: ./consent-service
|
|
dockerfile: Dockerfile
|
|
container_name: bp-core-consent-service
|
|
platform: linux/arm64
|
|
ports:
|
|
- "8081:8081"
|
|
environment:
|
|
DATABASE_URL: postgres://${POSTGRES_USER:-breakpilot}:${POSTGRES_PASSWORD:-breakpilot123}@postgres:5432/${POSTGRES_DB:-breakpilot_db}
|
|
JWT_SECRET: ${JWT_SECRET:-your-super-secret-jwt-key-change-in-production}
|
|
JWT_REFRESH_SECRET: ${JWT_REFRESH_SECRET:-your-refresh-secret}
|
|
PORT: 8081
|
|
ENVIRONMENT: ${ENVIRONMENT:-development}
|
|
ALLOWED_ORIGINS: "*"
|
|
VALKEY_URL: redis://valkey:6379/0
|
|
SESSION_TTL_HOURS: ${SESSION_TTL_HOURS:-24}
|
|
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:-https://macmini}
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
valkey:
|
|
condition: service_healthy
|
|
mailpit:
|
|
condition: service_started
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
billing-service:
|
|
build:
|
|
context: ./billing-service
|
|
dockerfile: Dockerfile
|
|
container_name: bp-core-billing-service
|
|
platform: linux/arm64
|
|
ports:
|
|
- "8083:8083"
|
|
environment:
|
|
DATABASE_URL: postgres://${POSTGRES_USER:-breakpilot}:${POSTGRES_PASSWORD:-breakpilot123}@postgres:5432/${POSTGRES_DB:-breakpilot_db}
|
|
JWT_SECRET: ${JWT_SECRET:-your-super-secret-jwt-key-change-in-production}
|
|
PORT: 8083
|
|
ENVIRONMENT: ${ENVIRONMENT:-development}
|
|
ALLOWED_ORIGINS: "*"
|
|
STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY:-}
|
|
STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET:-}
|
|
STRIPE_PUBLISHABLE_KEY: ${STRIPE_PUBLISHABLE_KEY:-}
|
|
BILLING_SUCCESS_URL: ${BILLING_SUCCESS_URL:-https://macmini/billing/success}
|
|
BILLING_CANCEL_URL: ${BILLING_CANCEL_URL:-https://macmini/billing/cancel}
|
|
FRONTEND_URL: ${FRONTEND_URL:-https://macmini}
|
|
TRIAL_PERIOD_DAYS: ${TRIAL_PERIOD_DAYS:-14}
|
|
INTERNAL_API_KEY: ${INTERNAL_API_KEY:-internal-key}
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
# =========================================================
|
|
# RAG SERVICE (NEU — extrahiert aus klausur-service)
|
|
# =========================================================
|
|
rag-service:
|
|
build:
|
|
context: ./rag-service
|
|
dockerfile: Dockerfile
|
|
container_name: bp-core-rag-service
|
|
platform: linux/arm64
|
|
expose:
|
|
- "8097"
|
|
environment:
|
|
PORT: 8097
|
|
QDRANT_URL: http://qdrant:6333
|
|
MINIO_ENDPOINT: nbg1.your-objectstorage.com
|
|
MINIO_ACCESS_KEY: T18RGFVXXG2ZHQ5404TP
|
|
MINIO_SECRET_KEY: KOUU4WO6wh07cQjNgh0IZHkeKQrVfBz6hnIGpNss
|
|
MINIO_BUCKET: ${MINIO_BUCKET:-breakpilot-rag}
|
|
MINIO_SECURE: "true"
|
|
EMBEDDING_SERVICE_URL: http://embedding-service:8087
|
|
OLLAMA_URL: ${OLLAMA_URL:-http://host.docker.internal:11434}
|
|
OLLAMA_EMBED_MODEL: ${OLLAMA_EMBED_MODEL:-bge-m3}
|
|
JWT_SECRET: ${JWT_SECRET:-your-super-secret-jwt-key-change-in-production}
|
|
ENVIRONMENT: ${ENVIRONMENT:-development}
|
|
extra_hosts:
|
|
- "host.docker.internal:host-gateway"
|
|
depends_on:
|
|
qdrant:
|
|
condition: service_healthy
|
|
minio:
|
|
condition: service_healthy
|
|
embedding-service:
|
|
condition: service_healthy
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://127.0.0.1:8097/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 15s
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
embedding-service:
|
|
build:
|
|
context: ./embedding-service
|
|
dockerfile: Dockerfile
|
|
container_name: bp-core-embedding-service
|
|
platform: linux/arm64
|
|
volumes:
|
|
- embedding_models:/root/.cache/huggingface
|
|
environment:
|
|
EMBEDDING_BACKEND: ${EMBEDDING_BACKEND:-local}
|
|
LOCAL_EMBEDDING_MODEL: ${LOCAL_EMBEDDING_MODEL:-BAAI/bge-m3}
|
|
LOCAL_RERANKER_MODEL: ${LOCAL_RERANKER_MODEL:-cross-encoder/ms-marco-MiniLM-L-6-v2}
|
|
PDF_EXTRACTION_BACKEND: ${PDF_EXTRACTION_BACKEND:-pymupdf}
|
|
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
|
|
COHERE_API_KEY: ${COHERE_API_KEY:-}
|
|
LOG_LEVEL: ${LOG_LEVEL:-INFO}
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 8G
|
|
healthcheck:
|
|
test: ["CMD", "python", "-c", "import httpx; r=httpx.get('http://127.0.0.1:8087/health'); r.raise_for_status()"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
start_period: 120s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
# =========================================================
|
|
# HEALTH AGGREGATOR (NEU)
|
|
# =========================================================
|
|
health-aggregator:
|
|
build:
|
|
context: ./scripts
|
|
dockerfile: Dockerfile.health
|
|
container_name: bp-core-health
|
|
platform: linux/arm64
|
|
ports:
|
|
- "8099:8099"
|
|
environment:
|
|
PORT: 8099
|
|
CHECK_SERVICES: "postgres:5432,valkey:6379,qdrant:6333,minio:9000,backend-core:8000,rag-service:8097,embedding-service:8087"
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://127.0.0.1:8099/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
# =========================================================
|
|
# DEVOPS & CI/CD
|
|
# =========================================================
|
|
gitea:
|
|
image: gitea/gitea:1.22-rootless
|
|
container_name: bp-core-gitea
|
|
ports:
|
|
- "3003:3003"
|
|
- "2222:2222"
|
|
volumes:
|
|
- gitea_data:/var/lib/gitea
|
|
- gitea_config:/etc/gitea
|
|
- /etc/timezone:/etc/timezone:ro
|
|
- /etc/localtime:/etc/localtime:ro
|
|
environment:
|
|
USER_UID: "1000"
|
|
USER_GID: "1000"
|
|
GITEA__database__DB_TYPE: postgres
|
|
GITEA__database__HOST: postgres:5432
|
|
GITEA__database__NAME: ${POSTGRES_DB:-breakpilot_db}
|
|
GITEA__database__USER: ${POSTGRES_USER:-breakpilot}
|
|
GITEA__database__PASSWD: ${POSTGRES_PASSWORD:-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://github.com"
|
|
GITEA__service__DISABLE_REGISTRATION: "true"
|
|
GITEA__service__REQUIRE_SIGNIN_VIEW: "true"
|
|
GITEA__repository__DEFAULT_BRANCH: main
|
|
GITEA__log__LEVEL: Warn
|
|
GITEA__security__INSTALL_LOCK: "true"
|
|
GITEA__webhook__ALLOWED_HOST_LIST: "*"
|
|
extra_hosts:
|
|
- "macmini:192.168.178.100"
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://127.0.0.1:3003/api/healthz"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
start_period: 30s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
gitea-runner:
|
|
image: gitea/act_runner:latest
|
|
container_name: bp-core-gitea-runner
|
|
volumes:
|
|
- gitea_runner_data:/data
|
|
- ./gitea/runner-config.yaml:/config/config.yaml:ro
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
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-bullseye,ubuntu-22.04:docker://node:20-bullseye"
|
|
depends_on:
|
|
gitea:
|
|
condition: service_healthy
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
# =========================================================
|
|
# DOCUMENTATION & UTILITIES
|
|
# =========================================================
|
|
docs:
|
|
build:
|
|
context: .
|
|
dockerfile: docs-src/Dockerfile
|
|
container_name: bp-core-docs
|
|
profiles: [docs]
|
|
platform: linux/arm64
|
|
ports:
|
|
- "8009:80"
|
|
healthcheck:
|
|
test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:80/"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
mailpit:
|
|
image: axllent/mailpit:latest
|
|
container_name: bp-core-mailpit
|
|
ports:
|
|
- "8025:8025"
|
|
- "1025:1025"
|
|
environment:
|
|
MP_SMTP_AUTH_ACCEPT_ANY: "true"
|
|
MP_SMTP_AUTH_ALLOW_INSECURE: "true"
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
# =========================================================
|
|
# NIGHT SCHEDULER
|
|
# =========================================================
|
|
night-scheduler:
|
|
build:
|
|
context: ./night-scheduler
|
|
dockerfile: Dockerfile
|
|
container_name: bp-core-night-scheduler
|
|
ports:
|
|
- "8096:8096"
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
- ./night-scheduler/config:/config
|
|
environment:
|
|
COMPOSE_PROJECT_NAME: breakpilot-core
|
|
CONTAINER_PATTERN: "bp-*"
|
|
EXCLUDED_CONTAINERS: "bp-core-night-scheduler,bp-core-nginx,bp-core-postgres,bp-core-valkey"
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://127.0.0.1:8096/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
start_period: 10s
|
|
retries: 3
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
# =========================================================
|
|
# ADMIN CORE
|
|
# =========================================================
|
|
admin-core:
|
|
build:
|
|
context: ./admin-core
|
|
dockerfile: Dockerfile
|
|
args:
|
|
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-https://macmini:8000}
|
|
container_name: bp-core-admin
|
|
platform: linux/arm64
|
|
expose:
|
|
- "3000"
|
|
environment:
|
|
NODE_ENV: production
|
|
BACKEND_URL: http://backend-core:8000
|
|
OLLAMA_URL: ${OLLAMA_URL:-http://host.docker.internal:11434}
|
|
extra_hosts:
|
|
- "host.docker.internal:host-gateway"
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
|
|
# =========================================================
|
|
# ERP (ERPNext)
|
|
# =========================================================
|
|
erpnext-db:
|
|
image: mariadb:10.6
|
|
container_name: bp-core-erpnext-db
|
|
profiles: [erp]
|
|
environment:
|
|
MYSQL_ROOT_PASSWORD: ${ERPNEXT_DB_ROOT_PASSWORD:-erpnext_root}
|
|
MYSQL_DATABASE: erpnext
|
|
MYSQL_USER: erpnext
|
|
MYSQL_PASSWORD: ${ERPNEXT_DB_PASSWORD:-erpnext_secret}
|
|
volumes:
|
|
- erpnext_db_data:/var/lib/mysql
|
|
healthcheck:
|
|
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 10
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
erpnext-redis-queue:
|
|
image: redis:alpine
|
|
profiles: [erp]
|
|
container_name: bp-core-erpnext-redis-queue
|
|
volumes:
|
|
- erpnext_redis_queue_data:/data
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
erpnext-redis-cache:
|
|
profiles: [erp]
|
|
image: redis:alpine
|
|
container_name: bp-core-erpnext-redis-cache
|
|
volumes:
|
|
- erpnext_redis_cache_data:/data
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
erpnext-create-site:
|
|
image: frappe/erpnext:latest
|
|
container_name: bp-core-erpnext-create-site
|
|
profiles: [erp]
|
|
volumes:
|
|
- erpnext_sites:/home/frappe/frappe-bench/sites
|
|
- erpnext_logs:/home/frappe/frappe-bench/logs
|
|
environment:
|
|
DB_HOST: erpnext-db
|
|
DB_PORT: "3306"
|
|
REDIS_CACHE: redis://erpnext-redis-cache:6379/0
|
|
REDIS_QUEUE: redis://erpnext-redis-queue:6379/0
|
|
SOCKETIO_PORT: "9000"
|
|
entrypoint: bash -c "ls sites/erpnext.local/site_config.json 2>/dev/null && echo 'Site exists' || bench new-site erpnext.local --mariadb-root-password=${ERPNEXT_DB_ROOT_PASSWORD:-erpnext_root} --admin-password=${ERPNEXT_ADMIN_PASSWORD:-admin} --install-app erpnext --set-default"
|
|
depends_on:
|
|
erpnext-db:
|
|
condition: service_healthy
|
|
erpnext-redis-cache:
|
|
condition: service_started
|
|
erpnext-redis-queue:
|
|
condition: service_started
|
|
restart: "no"
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
erpnext-backend:
|
|
image: frappe/erpnext:latest
|
|
container_name: bp-core-erpnext-backend
|
|
profiles: [erp]
|
|
volumes:
|
|
- erpnext_sites:/home/frappe/frappe-bench/sites
|
|
- erpnext_logs:/home/frappe/frappe-bench/logs
|
|
environment:
|
|
DB_HOST: erpnext-db
|
|
DB_PORT: "3306"
|
|
REDIS_CACHE: redis://erpnext-redis-cache:6379/0
|
|
REDIS_QUEUE: redis://erpnext-redis-queue:6379/0
|
|
SOCKETIO_PORT: "9000"
|
|
depends_on:
|
|
erpnext-db:
|
|
condition: service_healthy
|
|
erpnext-create-site:
|
|
condition: service_completed_successfully
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
erpnext-websocket:
|
|
image: frappe/erpnext:latest
|
|
container_name: bp-core-erpnext-websocket
|
|
profiles: [erp]
|
|
command: ["node", "/home/frappe/frappe-bench/apps/frappe/socketio.js"]
|
|
volumes:
|
|
- erpnext_sites:/home/frappe/frappe-bench/sites
|
|
- erpnext_logs:/home/frappe/frappe-bench/logs
|
|
environment:
|
|
DB_HOST: erpnext-db
|
|
DB_PORT: "3306"
|
|
REDIS_CACHE: redis://erpnext-redis-cache:6379/0
|
|
REDIS_QUEUE: redis://erpnext-redis-queue:6379/0
|
|
SOCKETIO_PORT: "9000"
|
|
depends_on:
|
|
erpnext-db:
|
|
condition: service_healthy
|
|
erpnext-create-site:
|
|
condition: service_completed_successfully
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
erpnext-scheduler:
|
|
image: frappe/erpnext:latest
|
|
container_name: bp-core-erpnext-scheduler
|
|
profiles: [erp]
|
|
command: ["bench", "schedule"]
|
|
volumes:
|
|
- erpnext_sites:/home/frappe/frappe-bench/sites
|
|
- erpnext_logs:/home/frappe/frappe-bench/logs
|
|
environment:
|
|
DB_HOST: erpnext-db
|
|
DB_PORT: "3306"
|
|
REDIS_CACHE: redis://erpnext-redis-cache:6379/0
|
|
REDIS_QUEUE: redis://erpnext-redis-queue:6379/0
|
|
SOCKETIO_PORT: "9000"
|
|
depends_on:
|
|
erpnext-db:
|
|
condition: service_healthy
|
|
erpnext-create-site:
|
|
condition: service_completed_successfully
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
erpnext-worker-long:
|
|
image: frappe/erpnext:latest
|
|
container_name: bp-core-erpnext-worker-long
|
|
profiles: [erp]
|
|
command: ["bench", "worker", "--queue", "long"]
|
|
volumes:
|
|
- erpnext_sites:/home/frappe/frappe-bench/sites
|
|
- erpnext_logs:/home/frappe/frappe-bench/logs
|
|
environment:
|
|
DB_HOST: erpnext-db
|
|
DB_PORT: "3306"
|
|
REDIS_CACHE: redis://erpnext-redis-cache:6379/0
|
|
REDIS_QUEUE: redis://erpnext-redis-queue:6379/0
|
|
SOCKETIO_PORT: "9000"
|
|
depends_on:
|
|
erpnext-db:
|
|
condition: service_healthy
|
|
erpnext-create-site:
|
|
condition: service_completed_successfully
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
erpnext-worker-short:
|
|
image: frappe/erpnext:latest
|
|
container_name: bp-core-erpnext-worker-short
|
|
profiles: [erp]
|
|
command: ["bench", "worker", "--queue", "short"]
|
|
volumes:
|
|
- erpnext_sites:/home/frappe/frappe-bench/sites
|
|
- erpnext_logs:/home/frappe/frappe-bench/logs
|
|
environment:
|
|
DB_HOST: erpnext-db
|
|
DB_PORT: "3306"
|
|
REDIS_CACHE: redis://erpnext-redis-cache:6379/0
|
|
REDIS_QUEUE: redis://erpnext-redis-queue:6379/0
|
|
SOCKETIO_PORT: "9000"
|
|
depends_on:
|
|
erpnext-db:
|
|
condition: service_healthy
|
|
erpnext-create-site:
|
|
condition: service_completed_successfully
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
erpnext-frontend:
|
|
image: frappe/erpnext:latest
|
|
container_name: bp-core-erpnext-frontend
|
|
profiles: [erp]
|
|
command: ["nginx-entrypoint.sh"]
|
|
ports:
|
|
- "8092:8080"
|
|
volumes:
|
|
- erpnext_sites:/home/frappe/frappe-bench/sites
|
|
- erpnext_logs:/home/frappe/frappe-bench/logs
|
|
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
|
|
depends_on:
|
|
- erpnext-backend
|
|
- erpnext-websocket
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
# =========================================================
|
|
# BACKUP (Profile)
|
|
# =========================================================
|
|
backup:
|
|
image: postgres:16-alpine
|
|
container_name: bp-core-backup
|
|
volumes:
|
|
- ./backups:/backups
|
|
environment:
|
|
PGHOST: postgres
|
|
PGUSER: ${POSTGRES_USER:-breakpilot}
|
|
PGPASSWORD: ${POSTGRES_PASSWORD:-breakpilot123}
|
|
PGDATABASE: ${POSTGRES_DB:-breakpilot_db}
|
|
entrypoint: /bin/sh
|
|
command: -c "pg_dump -Fc > /backups/breakpilot_db_$(date +%Y%m%d_%H%M%S).backup && echo 'Backup complete'"
|
|
profiles:
|
|
- backup
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
# =========================================================
|
|
# PITCH DECK - Investor Presentation
|
|
# =========================================================
|
|
pitch-deck:
|
|
build:
|
|
context: ./pitch-deck
|
|
dockerfile: Dockerfile
|
|
container_name: bp-core-pitch-deck
|
|
platform: linux/arm64
|
|
ports:
|
|
- "3012:3000"
|
|
environment:
|
|
NODE_ENV: production
|
|
DATABASE_URL: postgres://${POSTGRES_USER:-breakpilot}:${POSTGRES_PASSWORD:-breakpilot123}@postgres:5432/${POSTGRES_DB:-breakpilot_db}
|
|
LITELLM_URL: ${LITELLM_URL:-https://llm-dev.meghsakha.com}
|
|
LITELLM_MODEL: ${LITELLM_MODEL:-gpt-oss-120b}
|
|
LITELLM_API_KEY: ${LITELLM_API_KEY:-sk-0nAyxaMVbIqmz_ntnndzag}
|
|
extra_hosts:
|
|
- "host.docker.internal:host-gateway"
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|
|
|
|
# =========================================================
|
|
# LEVIS HOLZBAU - Kinder-Holzwerk-Website
|
|
# =========================================================
|
|
levis-holzbau:
|
|
build:
|
|
context: ./levis-holzbau
|
|
dockerfile: Dockerfile
|
|
container_name: bp-core-levis-holzbau
|
|
platform: linux/arm64
|
|
ports:
|
|
- "3013:3000"
|
|
environment:
|
|
NODE_ENV: production
|
|
restart: unless-stopped
|
|
networks:
|
|
- breakpilot-network
|