Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 12:07:03 +08:00

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: