f9447f8e5f
CI / typecheck · build · test · bundle-size (push) Failing after 1s
CI / clean-room dependency closure smoke (push) Failing after 1s
CI / server-runtime e2e (docker · pg + valkey) (push) Failing after 2s
Deploy Install Scripts / deploy (push) Failing after 2s
Windows / build (push) Has been cancelled
183 lines
7.5 KiB
YAML
183 lines
7.5 KiB
YAML
# Phase 10 — server-beta deployable runtime.
|
|
#
|
|
# Stack: Postgres (canonical storage) + Valkey (BullMQ queue) +
|
|
# claude-mem-server (HTTP, no generation) +
|
|
# claude-mem-worker (BullMQ generation consumer).
|
|
#
|
|
# SECURITY: This file MUST NOT be deployed unmodified to any environment
|
|
# that is reachable from the public internet, including staging behind a
|
|
# VPN where lateral movement is possible. The Postgres credentials are
|
|
# required env vars (no defaults) — start the stack with a `.env` file or
|
|
# inline `POSTGRES_USER=... POSTGRES_PASSWORD=... docker compose up`. The
|
|
# stack will refuse to start if any required secret is missing.
|
|
#
|
|
# The legacy `worker-service.cjs` runtime is NEVER spawned in this stack.
|
|
# `claude-mem-server` runs `server-beta-service.cjs --daemon`; the
|
|
# `claude-mem-worker` service runs `server-beta-service.cjs worker start`
|
|
# from the same image. Scale generation via:
|
|
# docker compose up -d --scale claude-mem-worker=N
|
|
#
|
|
# Required env vars (validated at startup by validateServerBetaEnv()):
|
|
# CLAUDE_MEM_RUNTIME=server-beta
|
|
# CLAUDE_MEM_QUEUE_ENGINE=bullmq
|
|
# CLAUDE_MEM_SERVER_DATABASE_URL=postgres://...
|
|
# CLAUDE_MEM_REDIS_URL=redis://valkey:6379
|
|
# CLAUDE_MEM_AUTH_MODE=api-key (local-dev is REJECTED inside Docker)
|
|
#
|
|
# Required secrets (no defaults — must be supplied in env or .env):
|
|
# POSTGRES_USER
|
|
# POSTGRES_PASSWORD
|
|
# POSTGRES_DB
|
|
#
|
|
# #2558 — every long-running service declares `restart: unless-stopped` so a
|
|
# crashed container (OOM, panic, transient dependency failure) is brought back
|
|
# automatically; a killed container recovers without operator intervention.
|
|
#
|
|
# #2558 — Redis/Valkey URL has a fallback so the stack is not brittle: the
|
|
# worker/server read CLAUDE_MEM_REDIS_URL with a default of
|
|
# redis://valkey:6379 instead of hard-failing when the var is unset.
|
|
#
|
|
# #2558 — secrets can be supplied via a credentials file mounted into the
|
|
# server/worker containers (see the commented `secrets:` blocks below) instead
|
|
# of being passed inline through the environment.
|
|
#
|
|
# Auth modes (#2554):
|
|
# - API-KEY auth (default here, CLAUDE_MEM_AUTH_MODE=api-key): every request
|
|
# carries a bearer key created with `server api-key create`. Generation
|
|
# uses a configured provider API key (ANTHROPIC_API_KEY/...). This path
|
|
# bills per token and can be EXPENSIVE at high observation volume.
|
|
# - SUBSCRIPTION auth: point the generation provider at a Claude subscription
|
|
# / Pro session instead of a metered API key to avoid per-token API cost.
|
|
# Set the provider credentials accordingly on the worker service; the HTTP
|
|
# auth contract (bearer API keys) is unchanged.
|
|
|
|
services:
|
|
postgres:
|
|
image: postgres:17-alpine
|
|
restart: unless-stopped
|
|
environment:
|
|
POSTGRES_USER: ${POSTGRES_USER:?POSTGRES_USER is required}
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
|
|
POSTGRES_DB: ${POSTGRES_DB:?POSTGRES_DB is required}
|
|
volumes:
|
|
- postgres-data:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U \"$$POSTGRES_USER\" -d \"$$POSTGRES_DB\""]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 12
|
|
start_period: 5s
|
|
|
|
valkey:
|
|
image: valkey/valkey:8-alpine
|
|
restart: unless-stopped
|
|
# BullMQ requires noeviction; AOF gives durability across restarts.
|
|
command:
|
|
- valkey-server
|
|
- --appendonly
|
|
- "yes"
|
|
- --appendfsync
|
|
- everysec
|
|
- --maxmemory-policy
|
|
- noeviction
|
|
volumes:
|
|
- valkey-data:/data
|
|
healthcheck:
|
|
test: ["CMD", "valkey-cli", "ping"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 12
|
|
|
|
claude-mem-server:
|
|
build:
|
|
context: .
|
|
dockerfile: docker/claude-mem/Dockerfile
|
|
restart: unless-stopped
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
valkey:
|
|
condition: service_healthy
|
|
environment:
|
|
CLAUDE_MEM_CONTAINER_MODE: server
|
|
CLAUDE_MEM_DOCKER: "1"
|
|
CLAUDE_MEM_RUNTIME: server-beta
|
|
CLAUDE_MEM_HOST: 0.0.0.0
|
|
CLAUDE_MEM_SERVER_HOST: 0.0.0.0
|
|
CLAUDE_MEM_SERVER_PORT: "37877"
|
|
# Legacy var some libraries still read; keep aligned with server port
|
|
# so the existing E2E driver and viewer continue to work.
|
|
CLAUDE_MEM_WORKER_HOST: 0.0.0.0
|
|
CLAUDE_MEM_WORKER_PORT: "37877"
|
|
CLAUDE_MEM_DATA_DIR: /data/claude-mem
|
|
CLAUDE_MEM_QUEUE_ENGINE: bullmq
|
|
# #2558 — REDIS_URL fallback: default to the in-stack valkey service so the
|
|
# var is not a brittle hard requirement; override CLAUDE_MEM_REDIS_URL to
|
|
# point at an external Redis.
|
|
CLAUDE_MEM_REDIS_URL: ${CLAUDE_MEM_REDIS_URL:-redis://valkey:6379}
|
|
CLAUDE_MEM_REDIS_MODE: docker
|
|
CLAUDE_MEM_SERVER_DATABASE_URL: postgres://${POSTGRES_USER:?POSTGRES_USER is required}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@postgres:5432/${POSTGRES_DB:?POSTGRES_DB is required}
|
|
CLAUDE_MEM_AUTH_MODE: api-key
|
|
CLAUDE_MEM_CHROMA_ENABLED: "false"
|
|
# The HTTP service does not consume BullMQ jobs; the worker container
|
|
# does. This split keeps HTTP latency unaffected by provider calls.
|
|
CLAUDE_MEM_GENERATION_DISABLED: "true"
|
|
ports:
|
|
- "37877:37877"
|
|
volumes:
|
|
- claude-mem-data:/data/claude-mem
|
|
# #2558 — credentials-file mount. Place provider/API secrets in a file
|
|
# (git-ignored) and mount it read-only instead of inlining secrets in the
|
|
# environment. The entrypoint / operator can `source` it. Uncomment and
|
|
# point CREDENTIALS_FILE at the host path:
|
|
# - ${CREDENTIALS_FILE:-./.docker-credentials}:/run/secrets/claude-mem-credentials:ro
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:37877/healthz"]
|
|
interval: 10s
|
|
timeout: 3s
|
|
retries: 12
|
|
start_period: 20s
|
|
|
|
claude-mem-worker:
|
|
build:
|
|
context: .
|
|
dockerfile: docker/claude-mem/Dockerfile
|
|
restart: unless-stopped
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
valkey:
|
|
condition: service_healthy
|
|
claude-mem-server:
|
|
condition: service_healthy
|
|
environment:
|
|
CLAUDE_MEM_CONTAINER_MODE: worker
|
|
CLAUDE_MEM_DOCKER: "1"
|
|
CLAUDE_MEM_RUNTIME: server-beta
|
|
CLAUDE_MEM_DATA_DIR: /data/claude-mem
|
|
CLAUDE_MEM_QUEUE_ENGINE: bullmq
|
|
# #2558 — REDIS_URL fallback (see server service above).
|
|
CLAUDE_MEM_REDIS_URL: ${CLAUDE_MEM_REDIS_URL:-redis://valkey:6379}
|
|
CLAUDE_MEM_REDIS_MODE: docker
|
|
CLAUDE_MEM_SERVER_DATABASE_URL: postgres://${POSTGRES_USER:?POSTGRES_USER is required}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@postgres:5432/${POSTGRES_DB:?POSTGRES_DB is required}
|
|
CLAUDE_MEM_AUTH_MODE: api-key
|
|
CLAUDE_MEM_CHROMA_ENABLED: "false"
|
|
# Provider configuration. ANTHROPIC_API_KEY (or
|
|
# CLAUDE_MEM_ANTHROPIC_API_KEY) is required for real generation; the
|
|
# worker stays running but never produces observations without one.
|
|
CLAUDE_MEM_SERVER_PROVIDER: ${CLAUDE_MEM_SERVER_PROVIDER:-claude}
|
|
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
|
|
CLAUDE_MEM_ANTHROPIC_API_KEY: ${CLAUDE_MEM_ANTHROPIC_API_KEY:-}
|
|
GEMINI_API_KEY: ${GEMINI_API_KEY:-}
|
|
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY:-}
|
|
volumes:
|
|
- claude-mem-data:/data/claude-mem
|
|
# #2558 — credentials-file mount (see server service above). Keeps
|
|
# provider/API secrets out of the inline environment.
|
|
# - ${CREDENTIALS_FILE:-./.docker-credentials}:/run/secrets/claude-mem-credentials:ro
|
|
|
|
volumes:
|
|
claude-mem-data:
|
|
postgres-data:
|
|
valkey-data:
|