services: litellm-db: image: postgres:16-alpine container_name: litellm-db environment: - POSTGRES_DB=litellm - POSTGRES_USER=litellm - POSTGRES_PASSWORD=litellm volumes: - /mnt/ssd/dbs/litellm/postgres:/var/lib/postgresql/data restart: always litellm: image: ghcr.io/berriai/litellm:main-latest container_name: litellm ports: - "4000:4000" volumes: - ./litellm-config.yaml:/app/config.yaml environment: - DATABASE_URL=postgresql://litellm:litellm@litellm-db:5432/litellm - LITELLM_MASTER_KEY=sk-fjQC1BxAiGFSMs - LANGFUSE_PUBLIC_KEY=${LANGFUSE_PUBLIC_KEY:-changeme} - LANGFUSE_SECRET_KEY=${LANGFUSE_SECRET_KEY:-changeme} - LANGFUSE_HOST=http://langfuse:3000 - OPENROUTER_API_KEY=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 command: ["--config", "/app/config.yaml", "--port", "4000"] extra_hosts: - "host.docker.internal:host-gateway" depends_on: - litellm-db - langfuse restart: always kimi-agent: build: ./kimi-agent container_name: kimi-agent volumes: - /home/alvis/kimi-workspace:/workspace - kimi-agent-home:/root/.kimi-code restart: unless-stopped langfuse-db: image: postgres:16-alpine container_name: langfuse-db environment: - POSTGRES_DB=langfuse - POSTGRES_USER=langfuse - POSTGRES_PASSWORD=langfuse volumes: - /mnt/ssd/dbs/langfuse/postgres:/var/lib/postgresql/data restart: always langfuse: image: ghcr.io/langfuse/langfuse:2 container_name: langfuse ports: - "3200:3000" environment: - DATABASE_URL=postgresql://langfuse:langfuse@langfuse-db:5432/langfuse - NEXTAUTH_URL=https://lf.alogins.net - NEXTAUTH_SECRET=532a746b24ac40afa39f9d317031cab94d4d6881107ea3b1209b28020f1a9761 - SALT=7927b3b0092afe4542274940b557becea6418a5fed79f7acd25c3a789349fdc9 - AUTH_DISABLE_SIGNUP=true depends_on: - langfuse-db restart: always qdrant: image: qdrant/qdrant container_name: qdrant ports: - "6333:6333" - "6334:6334" restart: always volumes: - /mnt/ssd/dbs/qdrant:/qdrant/storage:z faster-whisper: image: fedirz/faster-whisper-server:latest-cuda container_name: faster-whisper runtime: nvidia ports: - "8880:8000" environment: - WHISPER__MODEL=deepdml/faster-whisper-large-v3-turbo-ct2 - WHISPER__INFERENCE_DEVICE=cuda - WHISPER__COMPUTE_TYPE=int8 - WHISPER__LANGUAGE=ru - NVIDIA_VISIBLE_DEVICES=all - NVIDIA_DRIVER_CAPABILITIES=compute,utility volumes: - /mnt/ssd/ai/faster-whisper:/root/.cache/huggingface restart: always silero-tts: build: ./silero-tts container_name: silero-tts ports: - "8881:8881" volumes: - /mnt/ssd/ai/silero-tts:/cache/torch restart: always pipecat: build: ./pipecat container_name: pipecat ports: - "8882:8882" environment: - LIVEKIT_URL=ws://host.docker.internal:7880 - LIVEKIT_PUBLIC_URL=wss://lk.alogins.net - LIVEKIT_API_KEY=devkey - LIVEKIT_SECRET=ef3ef4b903ca8469b09b2dd7ab6af529c4d2f3c95668f53832fc351cf67777a9 - ADOLF_URL=http://host.docker.internal:8000/v1 - STT_URL=http://host.docker.internal:8880/v1 - TTS_URL=http://host.docker.internal:8881/v1 - STT_MODEL=deepdml/faster-whisper-large-v3-turbo-ct2 - TTS_VOICE=onyx extra_hosts: - "host.docker.internal:host-gateway" restart: unless-stopped # Adolf — OpenClaw fork (Matrix-first personal assistant). The OpenClaw # gateway config (Matrix channel + allow-list, model provider -> # adolf-llm:8010, MCP registry, gateway.tools.allow for cron/nodes) is # version-controlled at agap_git/adolf/openclaw.json (repo root, alongside # this openai/ project, not nested inside it) and bind-mounted read-only # over the adolf-state volume (see volumes below), so git is the single # source of truth — not a hand-edited volume file. The volume still # holds runtime state only (Matrix crypto/devices, credentials, sessions, # workspace/SOUL.md, logs). Matrix creds and ADOLF_KEY come from # openai/.env (gitignored, never committed). Source tree: /home/alvis/adolf. # To change config: edit ../adolf/openclaw.json + restart adolf. adolf: build: context: ../../adolf # Matrix is opt-in at build time (see adolf/Dockerfile); without this, # the gateway logs "no-channel-owner" and channels.matrix is inert. args: OPENCLAW_EXTENSIONS: matrix image: adolf:local container_name: adolf environment: - HOME=/home/node - OPENCLAW_HOME=/home/node - OPENCLAW_STATE_DIR=/home/node/.openclaw - OPENCLAW_CONFIG_PATH=/home/node/.openclaw/openclaw.json - OPENCLAW_CONFIG_DIR=/home/node/.openclaw - OPENCLAW_WORKSPACE_DIR=/home/node/.openclaw/workspace - OPENCLAW_GATEWAY_TOKEN=${ADOLF_GATEWAY_TOKEN:-} - ADOLF_KEY=${ADOLF_KEY:-} - MATRIX_HOMESERVER=${MATRIX_HOMESERVER:-} - MATRIX_USER_ID=${MATRIX_USER_ID:-} - MATRIX_PASSWORD=${MATRIX_PASSWORD:-} - MATRIX_DEVICE_NAME=${MATRIX_DEVICE_NAME:-Adolf OpenClaw Gateway} # marketplace-mcp bearer token (kb task #61) -- referenced by # openclaw.json's mcp.servers.marketplace.headers.Authorization via # ${MARKETPLACE_MCP_TOKEN} substitution; never inlined into that file. - MARKETPLACE_MCP_TOKEN=${MARKETPLACE_MCP_TOKEN:-} - TZ=Europe/Riga volumes: # Runtime state only (Matrix crypto/devices, credentials, sessions, # workspace, logs). The gateway config file itself is overlaid below. - adolf-state:/home/node/.openclaw # Version-controlled OpenClaw gateway config, mounted read-only on top # of the state volume so it is the single source of truth. The gateway # reads this JSONC file and snapshots its own .last-good/.rejected # copies into the volume dir (writable) — it never rewrites this file, # so read-only is safe. Edit the tracked file + restart to change config; # runtime/UI edits are intentionally disabled by the ro mount. - ../adolf/openclaw.json:/home/node/.openclaw/openclaw.json:ro # quota-command plugin (kb #62) — same read-only-bind-over-volume # pattern as openclaw.json above, applied to a single external plugin # dir instead of the whole state tree. Previously the only precedent # (cognee-memory) was docker cp'd straight into the adolf-state volume # at runtime with no git backing; this plugin is small enough (no # node_modules — only Node built-ins/global fetch) to just bind-mount # its tracked source directly at its extensions/ path, so git stays # the single source of truth the same way it already is for # openclaw.json. Activated via plugins.entries.quota-command in that file. - ./quota-command-openclaw-plugin:/home/node/.openclaw/extensions/quota-command:ro # hindsight-memory plugin (kb #75, H3) — same read-only-bind-over-volume # pattern as quota-command above. Structural successor to cognee-memory # (still docker cp'd into the adolf-state volume, no git backing; that # plugin's activation/container is decommissioned in H4, not here). # Forced hooks (before_prompt_build recall / agent_end retain) against # the hindsight service (see that service's block below), replacing # Cognee as Adolf's memory backend. Activated via # plugins.entries.hindsight-memory in openclaw.json. - ./hindsight-openclaw-plugin:/home/node/.openclaw/extensions/hindsight-memory:ro extra_hosts: - "host.docker.internal:host-gateway" # mtx.alogins.net's public A record can't hairpin-NAT back through the # router from inside a container; route it to the host gateway instead, # matching matrix/docker-compose.yml's lk-jwt-service (same problem, # same fix). Caddy on the host terminates TLS on :443 and proxies to # synapse:8008. - "mtx.alogins.net:host-gateway" cap_drop: - NET_RAW - NET_ADMIN security_opt: - no-new-privileges:true init: true ports: - "18789:18789" - "18790:18790" command: ["node", "dist/index.js", "gateway", "--bind", "lan", "--port", "18789"] restart: unless-stopped # cognee-llm — stateless one-shot Kimi-CLI wrapper for Cognee's batch cognify # (P3). Opposite policy to kimi-agent: no resume, non-streaming, text-only. # Note (SPIKE-FINDINGS gate 5): Cognee should DEFAULT its LLM to LiteLLM; this # is the optional low-volume path. Needs `kimi login` in its own volume. cognee-llm: build: ./cognee-llm container_name: cognee-llm ports: - "8011:8011" volumes: - cognee-llm-home:/root/.kimi-code restart: unless-stopped # adolf-llm — conversational Kimi-CLI wrapper (:8010), the model backend for # the Adolf OpenClaw gateway (P2). Real streaming (SSE), chat_id session-keying # + 1:1 kimi resume, media, per-session .mcp.json sourced from the shared # shared-mcp.json contract (cognee-mcp P4, openclaw-tools P5). Needs # `kimi login` in adolf-llm-home. adolf-llm: build: ./adolf-llm container_name: adolf-llm ports: - "8010:8010" volumes: - adolf-llm-workspace:/workspace - adolf-llm-home:/root/.kimi-code - ./shared-mcp.json:/shared-mcp.json:ro extra_hosts: # Needed to reach kanboard-mcp-adolf (:3104, network_mode: host, outside # this compose project's network) via shared-mcp.json's "kanboard" # entry — same host-gateway trick used by adolf/cognee/pipecat above. - "host.docker.internal:host-gateway" restart: unless-stopped # cognee — Adolf's memory backend (P4). FastAPI + embedded Kuzu graph + # Qdrant vectors. LLM via cognee-llm:8011 (Kimi CLI wrapper), embeddings via # ollama directly (host.docker.internal:11436, separate compose project — # hence extra_hosts below). Sole owner of the on-disk Kuzu/SQLite files # under /mnt/ssd/dbs/cognee/ (Kuzu is not safe for concurrent multi-process # access) — never run a second process against those files. cognee: build: ./cognee container_name: cognee restart: unless-stopped environment: # Real OS env var, not just the mounted .env file: the qdrant vector # adapter's registration hook (cognee/Dockerfile's sitecustomize.py) # gates on os.environ.get("VECTOR_DB_PROVIDER") at Python interpreter # start, which only sees actual container env vars — pydantic-settings' # env_file=".env" parsing (used for the rest of cognee.env) never # populates os.environ itself. Without this, cognee raises # "Unsupported vector database provider: qdrant" at startup even though # cognee.env sets VECTOR_DB_PROVIDER=qdrant. Verified 2026-07-05. - VECTOR_DB_PROVIDER=qdrant volumes: - ./cognee/cognee.env:/app/.env - /mnt/ssd/dbs/cognee/data:/data - /mnt/ssd/dbs/cognee/system:/system extra_hosts: - "host.docker.internal:host-gateway" # Not published to the host — only cognee-mcp (same compose network) # needs to reach it. Uncomment for local debugging: # ports: # - "8000:8000" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s # cognee-mcp — thin MCP-to-HTTP proxy in API mode (API_URL=cognee:8000). # Never opens the graph/vector files itself, so it's safe to run alongside # `cognee` without a second writer on the same Kuzu database. Exposes 3 # tools: remember / recall / forget. # # Built from a local Dockerfile (kb#70 fix) instead of the bare upstream # image: forget was missing a data_id parameter end-to-end, so agents # could delete a whole dataset but never a single entry. See # ./cognee-mcp/Dockerfile and ./cognee-mcp/src/ for the patched files. cognee-mcp: build: ./cognee-mcp container_name: cognee-mcp restart: unless-stopped environment: - ENV=local - LOG_LEVEL=INFO - PYTHONUNBUFFERED=1 - TRANSPORT_MODE=http - API_URL=http://cognee:8000 - MCP_ALLOWED_HOSTS=cognee-mcp:* ports: - "8001:8000" depends_on: - cognee # hindsight — Adolf memory backend, replacing cognee/cognee-mcp/cognee-llm # (kb#73, migration doc agap_git/adolf/HINDSIGHT-MIGRATION.md, H1). One # container: REST API :8888 (also serves the built-in MCP at /mcp/{bank}/), # UI :9999, built-in Postgres (pg0) bind-mounted to # /mnt/ssd/dbs/hindsight/ (host dir created + chowned 1000:1000 to match # the image's non-root `hindsight` user, confirmed via # `docker run --entrypoint id`). # # LLM + embeddings reconfigured 2026-07-15 (kb#84) to fix two wrong H1 # choices for a Russian/multilingual use case: # # LLM -> cognee-llm:8011 (the existing Kimi-CLI wrapper, same shim cognee # uses — see cognee/cognee.env's LLM section for the full precedent, # including why LLM_INSTRUCTOR_MODE=json_mode isn't needed here since # Hindsight's own client doesn't go through `instructor`). Replaces the # H1 choice of LiteLLM + ollama/gemma3:4b (a tiny local model): validated # 2026-07-15 that cognee-llm returns clean, JSON-parseable structured # extraction for Russian input (see kb#84 probe B) — gemma3:4b's fluency # on Russian was never actually verified, it was picked only to dodge # qwen3:8b's -token empty-content bug. Kimi is also the flat-rate # subscription already paid for, so this isn't a new cost. # # Embeddings -> ollama's bge-m3 on the GPU (host.docker.internal:11436, # separate compose project, same extra_hosts trick as cognee/adolf-llm # below), via ollama's OpenAI-compatible /v1/embeddings endpoint # (confirmed 200 + 1024-dim vector 2026-07-15, kb#84 probe A). Replaces # the H1 choice of Hindsight's built-in `local` provider # (BAAI/bge-small-en-v1.5, English-only, 384-d, CPU-bound in-process # SentenceTransformers). The hindsight image itself is CPU-only (torch # +cpu build, no onnxruntime GPU provider — confirmed 2026-07-15), so its # in-process local/onnx embedders can never reach the GPU; routing # through ollama's `openai` embeddings provider (HTTP, not the bespoke # cognee-style `ollama` provider Hindsight doesn't have) is how GPU # serving happens here. Dimensions var matches cognee.env's own bge-m3 # swap (kb#60): 1024. # # Runs ALONGSIDE cognee/cognee-mcp/cognee-llm during the migration; those # are untouched here and only decommissioned in H4, after H2/H3/H5 prove # this service out. Not yet wired into openclaw.json/shared-mcp.json # (that's H2, kb#74) — this block only stands the service up and proves # retain/recall against a throwaway bank. hindsight: image: ghcr.io/vectorize-io/hindsight:latest container_name: hindsight restart: unless-stopped environment: - HINDSIGHT_API_LLM_PROVIDER=openai - HINDSIGHT_API_LLM_BASE_URL=http://cognee-llm:8011/v1 - HINDSIGHT_API_LLM_MODEL=openai/cognee-llm # cognee-llm ignores the key entirely (Kimi CLI wrapper, no real # OpenAI auth) — same dummy value cognee.env uses for LLM_API_KEY. - HINDSIGHT_API_LLM_API_KEY=sk-cognee-llm-local - HINDSIGHT_API_EMBEDDINGS_PROVIDER=openai - HINDSIGHT_API_EMBEDDINGS_OPENAI_BASE_URL=http://host.docker.internal:11436/v1 - HINDSIGHT_API_EMBEDDINGS_OPENAI_MODEL=bge-m3 - HINDSIGHT_API_EMBEDDINGS_OPENAI_DIMENSIONS=1024 # ollama doesn't check this value at all (no auth), but the openai # embeddings client requires a non-empty key to construct. - HINDSIGHT_API_EMBEDDINGS_OPENAI_API_KEY=ollama # Stable worker id (compose service name), not the container hostname # default -- without this, recreating the container orphans any # in-flight async retain/consolidation tasks under the old hostname # (startup log warns about exactly this). - HINDSIGHT_API_WORKER_ID=hindsight # Reranker -> multilingual (kb#84 follow-up). The TEMPR rerank stage # defaulted to English cross-encoder/ms-marco-MiniLM, which ranks # Russian/multilingual candidates poorly. jina v2 multilingual fixes # that. Runs on CPU in this image (no CUDA torch) but only over the # small recall candidate set. trust_remote_code: jina ships custom code. - HINDSIGHT_API_RERANKER_PROVIDER=local - HINDSIGHT_API_RERANKER_LOCAL_MODEL=jinaai/jina-reranker-v2-base-multilingual - HINDSIGHT_API_RERANKER_LOCAL_TRUST_REMOTE_CODE=true volumes: - /mnt/ssd/dbs/hindsight:/home/hindsight/.pg0 # Persist HuggingFace/sentence-transformers model cache so the jina # reranker (~1GB) doesn't re-download on every container recreate. - /mnt/ssd/dbs/hindsight-cache:/home/hindsight/.cache ports: - "8888:8888" - "9999:9999" extra_hosts: # Needed to resolve host.docker.internal from inside the container # for the ollama embeddings call above — ollama lives in a separate # compose project, same trick as cognee/adolf-llm elsewhere in this # file. - "host.docker.internal:host-gateway" depends_on: - cognee-llm # openclaw-tools — MCP bridge (P5) exposing a minimal slice of the Adolf # OpenClaw gateway's agent tools (message/cron/nodes/browser) over MCP # Streamable HTTP, so Kimi CLI sessions (adolf-llm) can call them instead of # bypassing OpenClaw entirely. Proxies each MCP tool call to the gateway's # `POST /tools/invoke` HTTP surface (http://adolf:18789). NOTE: `cron` and # `nodes` are hard-denied on that surface by default until P6 adds them to # `gateway.tools.allow` in the adolf openclaw.json — see openclaw-tools/ # server.js for the full gate writeup. Not useful until `adolf` (P6) is # configured and running; safe to build/run standalone before that. openclaw-tools: build: ./openclaw-tools container_name: openclaw-tools environment: - OPENCLAW_GATEWAY_URL=http://adolf:18789 - OPENCLAW_GATEWAY_TOKEN=${ADOLF_GATEWAY_TOKEN:-} ports: - "8020:8020" restart: unless-stopped volumes: kimi-agent-home: adolf-state: cognee-llm-home: adolf-llm-workspace: adolf-llm-home: