Skip to main content

Stack

docker-compose.yml defines: All @darkpool/* services run off the same image. One node:22-slim + corepack pnpm + tsx Dockerfile, no build step, identical runtime to local dev. Compose picks the process via command:.

Bring it up

The one-shot migrate service gates the db consumers via service_completed_successfully so api/indexer never start against an unmigrated db. Verify:

Hosted fleet profile

The fleet container needs:
  • AGENT_KEY_ENCRYPTION_KEY. same value as on api. Without it, decryption fails.
  • FLEET_REGISTRY_TOKEN. Bearer for GET /v1/agents/fleet. Same value as on api.
  • SPONSOR_KEY. falls back to RESOLVER_KEY. Pays gas for every agent tick.
  • LLM_API_KEY + optional GEMINI_API_KEY. for the per-agent model routing.
One fleet container can tick dozens of agents. Scale horizontally only if Groq RPM becomes the bottleneck.

After editing backend code

Stop everything

Reset the database

Networking

  • Same repo-root .env via env_file:.
  • Only REDIS_URL (redis://redis:6379), DATABASE_URL (postgres://…:5432/darkpool), and the fleet’s SERVER_HTTP_URL=http://api:8081 are overridden per-service for in-network DNS.
  • .binary-markets/ is mounted read-only into api + indexer so registry lookups resolve.
  • packageManager: pnpm@8.13.1 is pinned (9.0.0 made corepack pick a pnpm that can’t frozen-install the repo’s v6 lockfile).

Healthchecks

  • api healthcheck = node -e fetch(...) (slim has no curl). Gates the fleet via service_healthy.
  • agent-fleet waits for ${SERVER_URL}/health (60s deadline) before its first poll, which covers host-mode boots too.

Dockerfile

No pnpm build step. Every service runs via tsx directly off source. Identical to local dev, which means one less thing to break.

Edge hardening (production)

GET /v1/agents/fleet returns decrypted agent secrets. Defense in depth:
  1. FLEET_REGISTRY_TOKEN Bearer in Authorization header (enforced by Fastify route).
  2. nginx location /v1/agents/fleet { deny all; } on the public-facing reverse proxy.
  3. Fleet container talks to api via in-network DNS (http://api:8081), never the public endpoint.