mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2026-03-21 22:56:47 +00:00
* feat: migrate file and live post-processing pipelines from Celery to Hatchet workflow engine * fix: always force reprocessing * fix: ci tests with live pipelines * fix: ci tests with live pipelines
406 lines
12 KiB
YAML
406 lines
12 KiB
YAML
# Self-hosted production Docker Compose — single file for everything.
|
|
#
|
|
# Usage: ./scripts/setup-selfhosted.sh <--gpu|--cpu|--hosted> [--ollama-gpu|--ollama-cpu] [--garage] [--caddy]
|
|
# or: docker compose -f docker-compose.selfhosted.yml [--profile gpu] [--profile ollama-gpu] [--profile garage] [--profile caddy] up -d
|
|
#
|
|
# ML processing modes (pick ONE — required):
|
|
# --gpu NVIDIA GPU container for transcription/diarization/translation (profile: gpu)
|
|
# --cpu In-process CPU processing on server/worker (no ML container needed)
|
|
# --hosted Remote GPU service URL (no ML container needed)
|
|
#
|
|
# Local LLM (optional — for summarization/topics):
|
|
# --profile ollama-gpu Local Ollama with NVIDIA GPU
|
|
# --profile ollama-cpu Local Ollama on CPU only
|
|
#
|
|
# Daily.co multitrack processing (auto-detected from server/.env):
|
|
# --profile dailyco Hatchet workflow engine + CPU/LLM workers
|
|
#
|
|
# Other optional services:
|
|
# --profile garage Local S3-compatible storage (Garage)
|
|
# --profile caddy Reverse proxy with auto-SSL
|
|
#
|
|
# Prerequisites:
|
|
# 1. Run ./scripts/setup-selfhosted.sh to generate env files and secrets
|
|
# 2. Or manually create server/.env and www/.env from the .selfhosted.example templates
|
|
|
|
services:
|
|
# ===========================================================
|
|
# Always-on core services (no profile required)
|
|
# ===========================================================
|
|
|
|
server:
|
|
build:
|
|
context: ./server
|
|
dockerfile: Dockerfile
|
|
image: monadicalsas/reflector-backend:latest
|
|
restart: unless-stopped
|
|
ports:
|
|
- "127.0.0.1:1250:1250"
|
|
- "51000-51100:51000-51100/udp"
|
|
env_file:
|
|
- ./server/.env
|
|
environment:
|
|
ENTRYPOINT: server
|
|
# Docker-internal overrides (always correct inside compose network)
|
|
DATABASE_URL: postgresql+asyncpg://reflector:reflector@postgres:5432/reflector
|
|
REDIS_HOST: redis
|
|
CELERY_BROKER_URL: redis://redis:6379/1
|
|
CELERY_RESULT_BACKEND: redis://redis:6379/1
|
|
# ML backend config comes from env_file (server/.env), set per-mode by setup script
|
|
# HF_TOKEN needed for in-process pyannote diarization (--cpu mode)
|
|
HF_TOKEN: ${HF_TOKEN:-}
|
|
# WebRTC: fixed UDP port range for ICE candidates (mapped above)
|
|
WEBRTC_PORT_RANGE: "51000-51100"
|
|
# Hatchet workflow engine (always-on for processing pipelines)
|
|
HATCHET_CLIENT_SERVER_URL: ${HATCHET_CLIENT_SERVER_URL:-http://hatchet:8888}
|
|
HATCHET_CLIENT_HOST_PORT: ${HATCHET_CLIENT_HOST_PORT:-hatchet:7077}
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_started
|
|
volumes:
|
|
- server_data:/app/data
|
|
|
|
worker:
|
|
build:
|
|
context: ./server
|
|
dockerfile: Dockerfile
|
|
image: monadicalsas/reflector-backend:latest
|
|
restart: unless-stopped
|
|
env_file:
|
|
- ./server/.env
|
|
environment:
|
|
ENTRYPOINT: worker
|
|
DATABASE_URL: postgresql+asyncpg://reflector:reflector@postgres:5432/reflector
|
|
REDIS_HOST: redis
|
|
CELERY_BROKER_URL: redis://redis:6379/1
|
|
CELERY_RESULT_BACKEND: redis://redis:6379/1
|
|
# ML backend config comes from env_file (server/.env), set per-mode by setup script
|
|
HF_TOKEN: ${HF_TOKEN:-}
|
|
# Hatchet workflow engine (always-on for processing pipelines)
|
|
HATCHET_CLIENT_SERVER_URL: ${HATCHET_CLIENT_SERVER_URL:-http://hatchet:8888}
|
|
HATCHET_CLIENT_HOST_PORT: ${HATCHET_CLIENT_HOST_PORT:-hatchet:7077}
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_started
|
|
volumes:
|
|
- server_data:/app/data
|
|
|
|
beat:
|
|
build:
|
|
context: ./server
|
|
dockerfile: Dockerfile
|
|
image: monadicalsas/reflector-backend:latest
|
|
restart: unless-stopped
|
|
env_file:
|
|
- ./server/.env
|
|
environment:
|
|
ENTRYPOINT: beat
|
|
DATABASE_URL: postgresql+asyncpg://reflector:reflector@postgres:5432/reflector
|
|
REDIS_HOST: redis
|
|
CELERY_BROKER_URL: redis://redis:6379/1
|
|
CELERY_RESULT_BACKEND: redis://redis:6379/1
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_started
|
|
|
|
web:
|
|
build:
|
|
context: ./www
|
|
dockerfile: Dockerfile
|
|
image: monadicalsas/reflector-frontend:latest
|
|
restart: unless-stopped
|
|
ports:
|
|
- "127.0.0.1:3000:3000"
|
|
env_file:
|
|
- ./www/.env
|
|
environment:
|
|
NODE_ENV: production
|
|
NODE_TLS_REJECT_UNAUTHORIZED: "0"
|
|
SERVER_API_URL: http://server:1250
|
|
KV_URL: redis://redis:6379
|
|
KV_USE_TLS: "false"
|
|
NEXTAUTH_URL_INTERNAL: http://localhost:3000
|
|
depends_on:
|
|
- redis
|
|
|
|
redis:
|
|
image: redis:7.2-alpine
|
|
restart: unless-stopped
|
|
ports:
|
|
- "6379:6379"
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "ping"]
|
|
interval: 30s
|
|
timeout: 3s
|
|
retries: 3
|
|
volumes:
|
|
- redis_data:/data
|
|
|
|
postgres:
|
|
image: postgres:17-alpine
|
|
restart: unless-stopped
|
|
command: ["postgres", "-c", "max_connections=200"]
|
|
environment:
|
|
POSTGRES_USER: reflector
|
|
POSTGRES_PASSWORD: reflector
|
|
POSTGRES_DB: reflector
|
|
volumes:
|
|
- postgres_data:/var/lib/postgresql/data
|
|
- ./server/docker/init-hatchet-db.sql:/docker-entrypoint-initdb.d/init-hatchet-db.sql:ro
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U reflector"]
|
|
interval: 30s
|
|
timeout: 3s
|
|
retries: 3
|
|
|
|
# ===========================================================
|
|
# Specialized model containers (transcription, diarization, translation)
|
|
# Only the gpu profile is activated by the setup script (--gpu mode).
|
|
# The cpu service definition is kept for manual/standalone use but is
|
|
# NOT activated by --cpu mode (which uses in-process local backends).
|
|
# Both services get alias "transcription" so server config never changes.
|
|
# ===========================================================
|
|
|
|
gpu:
|
|
build:
|
|
context: ./gpu/self_hosted
|
|
dockerfile: Dockerfile
|
|
profiles: [gpu]
|
|
restart: unless-stopped
|
|
ports:
|
|
- "127.0.0.1:8000:8000"
|
|
environment:
|
|
HF_TOKEN: ${HF_TOKEN:-}
|
|
volumes:
|
|
- gpu_cache:/root/.cache
|
|
deploy:
|
|
resources:
|
|
reservations:
|
|
devices:
|
|
- driver: nvidia
|
|
count: all
|
|
capabilities: [gpu]
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8000/docs"]
|
|
interval: 15s
|
|
timeout: 5s
|
|
retries: 10
|
|
start_period: 120s
|
|
networks:
|
|
default:
|
|
aliases:
|
|
- transcription
|
|
|
|
cpu:
|
|
build:
|
|
context: ./gpu/self_hosted
|
|
dockerfile: Dockerfile.cpu
|
|
profiles: [cpu]
|
|
restart: unless-stopped
|
|
ports:
|
|
- "127.0.0.1:8000:8000"
|
|
environment:
|
|
HF_TOKEN: ${HF_TOKEN:-}
|
|
volumes:
|
|
- gpu_cache:/root/.cache
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8000/docs"]
|
|
interval: 15s
|
|
timeout: 5s
|
|
retries: 10
|
|
start_period: 120s
|
|
networks:
|
|
default:
|
|
aliases:
|
|
- transcription
|
|
|
|
# ===========================================================
|
|
# Ollama — local LLM for summarization & topic detection
|
|
# Only started with --ollama-gpu or --ollama-cpu modes.
|
|
# ===========================================================
|
|
|
|
ollama:
|
|
image: ollama/ollama:latest
|
|
profiles: [ollama-gpu]
|
|
restart: unless-stopped
|
|
ports:
|
|
- "127.0.0.1:11435:11435"
|
|
volumes:
|
|
- ollama_data:/root/.ollama
|
|
environment:
|
|
OLLAMA_HOST: "0.0.0.0:11435"
|
|
OLLAMA_KEEP_ALIVE: "24h"
|
|
deploy:
|
|
resources:
|
|
reservations:
|
|
devices:
|
|
- driver: nvidia
|
|
count: all
|
|
capabilities: [gpu]
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:11435/api/tags"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
|
|
ollama-cpu:
|
|
image: ollama/ollama:latest
|
|
profiles: [ollama-cpu]
|
|
restart: unless-stopped
|
|
ports:
|
|
- "127.0.0.1:11435:11435"
|
|
volumes:
|
|
- ollama_data:/root/.ollama
|
|
environment:
|
|
OLLAMA_HOST: "0.0.0.0:11435"
|
|
OLLAMA_KEEP_ALIVE: "24h" # keep model loaded to avoid reload delays
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:11435/api/tags"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
|
|
# ===========================================================
|
|
# Garage — local S3-compatible object storage (optional)
|
|
# ===========================================================
|
|
|
|
garage:
|
|
image: dxflrs/garage:v1.1.0
|
|
profiles: [garage]
|
|
restart: unless-stopped
|
|
ports:
|
|
- "3900:3900" # S3 API
|
|
- "3903:3903" # Admin API
|
|
volumes:
|
|
- garage_data:/var/lib/garage/data
|
|
- garage_meta:/var/lib/garage/meta
|
|
- ./data/garage.toml:/etc/garage.toml:ro
|
|
healthcheck:
|
|
test: ["CMD", "/garage", "stats"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
start_period: 5s
|
|
|
|
# ===========================================================
|
|
# Caddy — reverse proxy with automatic SSL (optional)
|
|
# Maps 80:80 and 443:443 — only exposed ports in the stack.
|
|
# ===========================================================
|
|
|
|
caddy:
|
|
image: caddy:2-alpine
|
|
profiles: [caddy]
|
|
restart: unless-stopped
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
volumes:
|
|
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
|
- caddy_data:/data
|
|
- caddy_config:/config
|
|
depends_on:
|
|
- web
|
|
- server
|
|
|
|
# ===========================================================
|
|
# Hatchet workflow engine + workers
|
|
# Required for all processing pipelines (file, live, Daily.co multitrack).
|
|
# Always-on — every selfhosted deployment needs Hatchet.
|
|
# ===========================================================
|
|
|
|
hatchet:
|
|
image: ghcr.io/hatchet-dev/hatchet/hatchet-lite:latest
|
|
restart: on-failure
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
ports:
|
|
- "127.0.0.1:8888:8888"
|
|
- "127.0.0.1:7078:7077"
|
|
env_file:
|
|
- ./.env.hatchet
|
|
environment:
|
|
DATABASE_URL: "postgresql://reflector:reflector@postgres:5432/hatchet?sslmode=disable&connect_timeout=30"
|
|
SERVER_AUTH_COOKIE_INSECURE: "t"
|
|
SERVER_GRPC_BIND_ADDRESS: "0.0.0.0"
|
|
SERVER_GRPC_INSECURE: "t"
|
|
SERVER_GRPC_BROADCAST_ADDRESS: hatchet:7077
|
|
SERVER_GRPC_PORT: "7077"
|
|
SERVER_AUTH_SET_EMAIL_VERIFIED: "t"
|
|
SERVER_INTERNAL_CLIENT_INTERNAL_GRPC_BROADCAST_ADDRESS: hatchet:7077
|
|
volumes:
|
|
- hatchet_config:/config
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8888/api/live"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 5
|
|
start_period: 30s
|
|
|
|
hatchet-worker-cpu:
|
|
build:
|
|
context: ./server
|
|
dockerfile: Dockerfile
|
|
image: monadicalsas/reflector-backend:latest
|
|
profiles: [dailyco]
|
|
restart: unless-stopped
|
|
env_file:
|
|
- ./server/.env
|
|
environment:
|
|
ENTRYPOINT: hatchet-worker-cpu
|
|
DATABASE_URL: postgresql+asyncpg://reflector:reflector@postgres:5432/reflector
|
|
REDIS_HOST: redis
|
|
CELERY_BROKER_URL: redis://redis:6379/1
|
|
CELERY_RESULT_BACKEND: redis://redis:6379/1
|
|
HATCHET_CLIENT_SERVER_URL: http://hatchet:8888
|
|
HATCHET_CLIENT_HOST_PORT: hatchet:7077
|
|
depends_on:
|
|
hatchet:
|
|
condition: service_healthy
|
|
volumes:
|
|
- server_data:/app/data
|
|
|
|
hatchet-worker-llm:
|
|
build:
|
|
context: ./server
|
|
dockerfile: Dockerfile
|
|
image: monadicalsas/reflector-backend:latest
|
|
restart: unless-stopped
|
|
env_file:
|
|
- ./server/.env
|
|
environment:
|
|
ENTRYPOINT: hatchet-worker-llm
|
|
DATABASE_URL: postgresql+asyncpg://reflector:reflector@postgres:5432/reflector
|
|
REDIS_HOST: redis
|
|
CELERY_BROKER_URL: redis://redis:6379/1
|
|
CELERY_RESULT_BACKEND: redis://redis:6379/1
|
|
HATCHET_CLIENT_SERVER_URL: http://hatchet:8888
|
|
HATCHET_CLIENT_HOST_PORT: hatchet:7077
|
|
depends_on:
|
|
hatchet:
|
|
condition: service_healthy
|
|
volumes:
|
|
- server_data:/app/data
|
|
|
|
volumes:
|
|
postgres_data:
|
|
redis_data:
|
|
server_data:
|
|
gpu_cache:
|
|
garage_data:
|
|
garage_meta:
|
|
ollama_data:
|
|
caddy_data:
|
|
caddy_config:
|
|
hatchet_config:
|
|
|
|
networks:
|
|
default:
|
|
attachable: true
|