Deployment¶
Last verified: v2.0
This guide covers running MEHO in Docker for development and testing. MEHO ships as a Docker Compose stack with a unified backend service, React frontend, and supporting infrastructure (PostgreSQL, Redis, MinIO, Keycloak, Seq).
Prerequisites¶
- Docker 24+ with Docker Compose v2
- Git for cloning the repository
- An Anthropic API key (Claude Opus 4.6 / Sonnet 4.6)
- A Voyage AI API key (for embeddings and reranking)
Quick Start¶
# Clone the repository
git clone <repository-url>
cd MEHO.X
# Copy environment file and set required secrets
cp env.example .env
# Edit .env -- set these three required values:
# ANTHROPIC_API_KEY=sk-ant-your-key-here
# VOYAGE_API_KEY=your-voyage-key-here
# CREDENTIAL_ENCRYPTION_KEY=your-encryption-key-here
# Start everything (builds images, starts services, runs migrations)
./scripts/dev-env.sh up
After startup completes, you will see:
| Service | URL | Credentials |
|---|---|---|
| Frontend | http://localhost:5173 | Keycloak login |
| Backend API | http://localhost:8000 | JWT required |
| API Docs (Swagger) | http://localhost:8000/docs | -- |
| Keycloak Admin | http://localhost:8080 | admin / admin |
| MinIO Console | http://localhost:9001 | minioadmin / minioadmin |
| Seq (Logs/Traces) | http://localhost:5341 | -- |
| PostgreSQL | localhost:5432 | meho / password |
| Redis | localhost:6379 | -- |
Use the helper script
Always use ./scripts/dev-env.sh instead of running docker compose directly. The helper script handles migrations, Keycloak configuration, health checks, and service ordering that raw Docker Compose skips.
Development Modes¶
Full Docker (CI/Testing)¶
./scripts/dev-env.sh up # Build and start everything
./scripts/dev-env.sh down # Stop everything
./scripts/dev-env.sh restart # Restart everything
./scripts/dev-env.sh logs # Tail all logs
./scripts/dev-env.sh logs meho # Tail backend logs only
./scripts/dev-env.sh status # Show service status
./scripts/dev-env.sh test # Run smoke + contract tests
./scripts/dev-env.sh test-all # Run all tests
Local Hot-Reload (Development)¶
For active development with instant feedback on code changes:
This mode runs:
- Infrastructure (PostgreSQL, Redis, MinIO, Keycloak, Seq) in Docker
- Backend locally with
uvicorn --reloadfor hot-reload on Python changes - Frontend locally with
vite devfor hot-reload on TypeScript/React changes
Requires a Python virtual environment (.venv) and Node.js installed locally.
Environment Variables¶
Required Secrets¶
These must be set in .env -- Docker Compose will refuse to start without them.
| Variable | Description |
|---|---|
ANTHROPIC_API_KEY |
Anthropic API key for Claude models (Opus 4.6, Sonnet 4.6) |
VOYAGE_API_KEY |
Voyage AI API key for embeddings (voyage-4-large) and reranking (rerank-2.5) |
CREDENTIAL_ENCRYPTION_KEY |
Fernet symmetric key for encrypting connector credentials at rest |
LLM Models (Anthropic)¶
Two-tier model configuration: Opus 4.6 for heavy reasoning, Sonnet 4.6 for utility tasks.
| Variable | Default | Purpose |
|---|---|---|
LLM_MODEL |
anthropic:claude-opus-4-6 |
General reasoning model |
STREAMING_AGENT_MODEL |
anthropic:claude-opus-4-6 |
Streaming investigation agent |
PLANNER_MODEL |
anthropic:claude-opus-4-6 |
Investigation planner |
EXECUTOR_MODEL |
anthropic:claude-opus-4-6 |
Operation executor |
INTERPRETER_MODEL |
anthropic:claude-opus-4-6 |
Result interpreter |
CLASSIFIER_MODEL |
anthropic:claude-sonnet-4-6 |
Query classifier |
DATA_EXTRACTOR_MODEL |
anthropic:claude-sonnet-4-6 |
Data extraction |
WORKFLOW_BUILDER_MODEL |
anthropic:claude-sonnet-4-6 |
Workflow generation |
TRANSFORM_GENERATION_MODEL |
anthropic:claude-sonnet-4-6 |
Transform generation |
WORKFLOW_LLM_REPORT_MODEL |
anthropic:claude-sonnet-4-6 |
Workflow reports |
EMBEDDING_MODEL |
voyage-4-large |
Voyage AI embedding model (1024D) |
Database (PostgreSQL)¶
Defaults work with the Docker Compose stack. Override only for external databases.
| Variable | Default | Purpose |
|---|---|---|
POSTGRES_USER |
meho |
PostgreSQL user |
POSTGRES_PASSWORD |
password |
PostgreSQL password |
POSTGRES_DB |
meho |
Database name |
DATABASE_URL |
postgresql+asyncpg://meho:password@postgres:5432/meho |
Full connection string |
Redis¶
| Variable | Default | Purpose |
|---|---|---|
REDIS_URL |
redis://redis:6379/0 |
Redis connection URL |
Keycloak (Identity Provider)¶
| Variable | Default | Purpose |
|---|---|---|
KEYCLOAK_ADMIN_PASSWORD |
admin |
Keycloak admin console password |
KEYCLOAK_CLIENT_ID |
meho-api |
Backend client ID in Keycloak |
KEYCLOAK_URL |
http://localhost:8080 |
Keycloak base URL (frontend) |
KEYCLOAK_REALM |
example-tenant |
Keycloak realm name |
VITE_KEYCLOAK_URL |
http://localhost:8080 |
Keycloak URL for Vite build |
VITE_KEYCLOAK_REALM |
example-tenant |
Realm for Vite build |
VITE_KEYCLOAK_CLIENT_ID |
meho-frontend |
Frontend client ID |
Object Storage (MinIO / S3)¶
| Variable | Default | Purpose |
|---|---|---|
OBJECT_STORAGE_BUCKET |
meho-dev-data |
S3 bucket name |
OBJECT_STORAGE_ENDPOINT |
http://minio:9000 |
S3-compatible endpoint |
OBJECT_STORAGE_ACCESS_KEY |
minioadmin |
S3 access key |
OBJECT_STORAGE_SECRET_KEY |
minioadmin |
S3 secret key |
OBJECT_STORAGE_USE_SSL |
false |
Enable HTTPS for S3 |
Observability (OpenTelemetry)¶
| Variable | Default | Purpose |
|---|---|---|
OTEL_SERVICE_NAME |
meho |
Service name in traces |
OTEL_EXPORTER_OTLP_ENDPOINT |
http://seq:80/ingest/otlp |
OTLP collector endpoint |
OTEL_CONSOLE |
true |
Also log to console |
MEHO_LOG_LEVEL |
INFO |
Application log level |
OTEL_TRACE_LEVEL |
full |
Trace detail: full, truncated, summary |
Application Settings¶
| Variable | Default | Purpose |
|---|---|---|
APP_ENVIRONMENT |
dev |
Environment name (dev, staging, production) |
CORS_ORIGINS |
["http://localhost:5173"] |
Allowed CORS origins (JSON array) |
Feature Flags¶
| Variable | Default | Purpose |
|---|---|---|
ENABLE_RATE_LIMITING |
true |
API rate limiting |
ENABLE_MEMORY_EXTRACTION |
true |
Auto-extract memories from conversations |
ENABLE_TRANSCRIPT_PERSISTENCE |
true |
Persist agent transcripts |
ENABLE_DETAILED_EVENTS |
true |
Send detailed SSE events to frontend |
ENABLE_OBSERVABILITY_API |
true |
Enable observability endpoints |
Orchestrator Tuning¶
| Variable | Default | Purpose |
|---|---|---|
ORCHESTRATOR_MAX_ITERATIONS |
3 |
Max orchestrator retry iterations |
ORCHESTRATOR_AGENT_TIMEOUT |
30.0 |
Per-agent timeout (seconds) |
ORCHESTRATOR_TOTAL_TIMEOUT |
120.0 |
Total orchestrator timeout (seconds) |
Service Architecture¶
The Docker Compose stack runs these services:
| Service | Image | Purpose |
|---|---|---|
| meho | Custom (Dockerfile.meho) | Unified FastAPI backend -- API, agents, connectors, knowledge, topology |
| meho-frontend | Custom (Dockerfile.meho-frontend) | React/TypeScript frontend with Vite |
| postgres | pgvector/pgvector:pg15 | PostgreSQL with pgvector extension for hybrid search |
| redis | redis/redis-stack-server | Redis with RediSearch and RedisJSON modules |
| keycloak | quay.io/keycloak/keycloak:24.0 | Identity provider (OIDC, RBAC, multi-tenant) |
| minio | minio/minio | S3-compatible object storage for Parquet cache and documents |
| seq | datalust/seq | Log aggregation and OTLP trace ingestion |
| pgadmin | dpage/pgadmin4 | Database admin UI (optional, --profile tools) |
Port Map¶
| Port | Service | Protocol |
|---|---|---|
| 5173 | Frontend (Vite) | HTTP |
| 8000 | Backend API (FastAPI) | HTTP |
| 8080 | Keycloak | HTTP |
| 5432 | PostgreSQL | TCP |
| 6379 | Redis | TCP |
| 9000 | MinIO S3 API | HTTP |
| 9001 | MinIO Console | HTTP |
| 5341 | Seq (Logs UI + OTLP) | HTTP |
| 5050 | pgAdmin (tools profile) | HTTP |
Database Migrations¶
MEHO uses Alembic for database migrations with per-module migration chains. Each domain module maintains its own Alembic configuration and migration history:
| Module | Alembic Directory |
|---|---|
| agents | meho_app/modules/agents/alembic/ |
| connectors | meho_app/modules/connectors/alembic/ |
| knowledge | meho_app/modules/knowledge/alembic/ |
| topology | meho_app/modules/topology/alembic/ |
| memory | meho_app/modules/memory/alembic/ |
| ingestion | meho_app/modules/ingestion/alembic/ |
| scheduled_tasks | meho_app/modules/scheduled_tasks/alembic/ |
| orchestrator_skills | meho_app/modules/orchestrator_skills/alembic/ |
| audit | meho_app/modules/audit/alembic/ |
Automatic Migrations¶
When using ./scripts/dev-env.sh up, migrations run automatically after services are healthy. The script calls scripts/run-migrations-monolith.sh inside the running container.
Manual Migrations¶
To run migrations manually (for local development or troubleshooting):
# Inside the Docker container
docker compose exec meho bash
cd /app
bash scripts/run-migrations-monolith.sh
# Or for a specific module
cd meho_app/modules/agents
alembic upgrade head
For local hot-reload mode, ./scripts/dev-env.sh local runs migrations against localhost:5432 automatically.
Migration Ordering
Module migrations run in a specific order because of foreign key dependencies. The topology module must migrate before connectors. The helper scripts handle this ordering automatically.
Production Considerations¶
The Docker Compose development setup is not production-ready as-is. For production deployment, address these areas:
Secrets Management¶
- Move
ANTHROPIC_API_KEY,VOYAGE_API_KEY, andCREDENTIAL_ENCRYPTION_KEYto a secrets manager (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault). - Replace the default PostgreSQL password (
password) and Keycloak admin password (admin). - Do not use the default MinIO credentials in production.
HTTPS Termination¶
- Place a reverse proxy (nginx, Traefik, Caddy, or a cloud load balancer) in front of MEHO to terminate TLS.
- Update
CORS_ORIGINSto match your production frontend domain. - Configure HSTS headers at the proxy level for strict transport security.
Persistent Storage¶
- Use external managed PostgreSQL (RDS, Cloud SQL, Azure Database) instead of the Docker volume.
- Use external managed Redis (ElastiCache, Memorystore) for production reliability.
- Use external S3-compatible storage instead of local MinIO for Parquet cache durability.
Keycloak Configuration¶
- Configure a production Keycloak realm with proper client settings, redirect URIs, and user federation.
- The development setup auto-imports a realm configuration from
config/keycloak/. Production deployments should manage Keycloak configuration through its admin API or admin console. - Enable HTTPS for Keycloak and set
KC_HOSTNAME_STRICT: "true".
Scaling¶
- The MEHO backend is a single-process FastAPI application. For higher throughput, run multiple replicas behind a load balancer.
- The in-process approval flow (asyncio.Event) requires sticky sessions when scaling to multiple workers. For multi-worker deployments, migrate to Redis pub/sub for approval signaling.
Observability¶
- Replace Seq with your preferred observability stack. Point
OTEL_EXPORTER_OTLP_ENDPOINTto your OTLP collector (Jaeger, Grafana Tempo, Datadog, New Relic). - Set
OTEL_TRACE_LEVEL=summaryin production to reduce trace payload size. - Set
MEHO_LOG_LEVEL=WARNINGfor reduced log volume.