services: postgres: image: pgvector/pgvector:pg16 environment: POSTGRES_USER: ${POSTGRES_USER:-synsc} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-synsc} POSTGRES_DB: ${POSTGRES_DB:-synsc} ports: - "${POSTGRES_PORT:-5432}:5432" volumes: - pgdata:/var/lib/postgresql/data - ./database/supabase/setup_local.sql:/docker-entrypoint-initdb.d/01-setup.sql healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-synsc} -d ${POSTGRES_DB:-synsc}"] interval: 5s timeout: 3s retries: 10 api: build: context: ./backend target: api env_file: - .env depends_on: postgres: condition: service_healthy environment: DATABASE_URL: postgresql://${POSTGRES_USER:-synsc}:${POSTGRES_PASSWORD:-synsc}@postgres:5432/${POSTGRES_DB:-synsc} SYNSC_API_HOST: "0.0.0.0" SYNSC_API_PORT: "8742" SYNSC_LOG_FORMAT: json FRONTEND_URL: http://localhost:3000 ports: - "${SYNSC_API_HOST_PORT:-8742}:8742" volumes: # Shared HuggingFace Hub cache. Without it, api and worker each # download Qwen3-Embedding-0.6B (~1.2 GB) on first boot, and # `delphi config` force-recreates re-download the lot. The named # volume survives `compose restart` and `compose down`; only # `compose down -v` (`delphi uninstall`) clears it. - hf-cache:/home/synsc/.cache/huggingface worker: build: context: ./backend target: worker env_file: - .env depends_on: postgres: condition: service_healthy api: condition: service_healthy environment: DATABASE_URL: postgresql://${POSTGRES_USER:-synsc}:${POSTGRES_PASSWORD:-synsc}@postgres:5432/${POSTGRES_DB:-synsc} SYNSC_LOG_FORMAT: json SYNSC_WORKER_THREADS: "4" volumes: - hf-cache:/home/synsc/.cache/huggingface # Dashboard UI. Only needed for the "run my own index" flow; agent-path # users (Claude Code/Cursor/etc.) just talk to the API via the MCP proxy. # Activate with `docker compose --profile dashboard up`. frontend: profiles: ["dashboard"] build: context: ./frontend args: # Baked into routes-manifest.json by `next build` — see Dockerfile. # INTERNAL_API_URL stays at the docker-network hostname (api:8742) # since the api container always listens on 8742 internally; only # the *host-side* port can shift if 8742 was taken at install. INTERNAL_API_URL: http://api:8742 # NEXT_PUBLIC_API_URL is also baked at build time but must point # at whatever host port the user actually maps. The CLI writes # SYNSC_API_HOST_PORT to .env after pre-flight port discovery; # we interpolate that here so a fresh frontend bundle ships with # the correct localhost:port for browser-side direct fetches. NEXT_PUBLIC_API_URL: http://localhost:${SYNSC_API_HOST_PORT:-8742} depends_on: - api ports: - "${FRONTEND_PORT:-3000}:3000" volumes: pgdata: hf-cache: