Deployment
-
Docker-First
Compose stack for Postgres, Neo4j, exporter, and API.
-
Configurable
All behavior via Pydantic config and environment variables.
-
Portable
Works on local dev, CI, or container platforms.
Persistent Volumes
Data lives in named Docker volumes (postgres_data, qdrant_data, neo4j_data, ...) owned by the ragweld Compose project. Back up the volumes rather than bind mounts.
Environment Template
Copy the provided environment configuration to .env and fill in DB credentials. Upstream provider keys (OPENAI_API_KEY, OPENROUTER_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY) are gateway-owned: they belong only in the gateway's private infra/litellm.env, initialized from infra/litellm.env.example on a new install (disabled is not a working key). The app talks to the gateway with LITELLM_BASE_URL and LITELLM_API_KEY from its own environment — never with an upstream provider key. ./start.sh unsets inherited provider keys, the Compose API service blanks them, and importing the app drops any that survive, so a leaked shell export can never impersonate the gateway's upstream credential.
Precedence: shell environment beats .env
./start.sh sources .env with set -a, but it first snapshots every exported variable in your shell and restores that exact snapshot after sourcing. The practical effect: caller-provided environment always wins over .env — .env fills in only the keys you did not already set. This matters for ports (BACKEND_PORT, FRONTEND_PORT), provider keys you inject from a secret manager, and any CI runner that exports configuration before invoking ./start.sh.
The snapshot/restore uses export -p + eval rather than bash-4 associative arrays, so the behavior is identical under macOS's stock bash 3.2. A regression here (a .env value silently clobbering an exported override) is caught by tests/unit/test_runtime_lifecycle.py.
Production Secrets
Use a secret manager for API keys and DB credentials in production. Do not rely on .env files in containerized environments.
Services and Ports
| Service | Port | Purpose |
|---|---|---|
| API (uvicorn, host) | 58012 | REST endpoints under /api |
| PostgreSQL | 5432 | Chunk rows, summaries, caches |
| Qdrant | 56333 | Dense + sparse chunk vectors |
| Neo4j Bolt | 7687 | Graph driver |
| Neo4j Browser | 7474 | Admin UI |
| LiteLLM | 54000 | Generation + native OpenAI embedding gateway |
| MLflow | 55500 | Training run tracking |
| Prometheus | 59090 | Metrics (remote-writes to Mimir) |
| Grafana | 3301 | Dashboards |
| Loki | 53100 | Log aggregation |
flowchart LR
Dev["Developer"] --> Compose["Docker Compose"]
Compose --> API["API"]
Compose --> Postgres["Postgres"]
Compose --> Neo4j["Neo4j"]
Postgres --> Exporter["Postgres Exporter"] Bring-Up Tasks
- Create
.envwith DB creds (upstream provider keys belong ininfra/litellm.env, not here) - Initialize
infra/litellm.envfrominfra/litellm.env.exampleand fill in the upstream keys you need -
docker compose up -d -
uv run scripts/generate_types.py - Start API service
import subprocess, os
# Generate types from Pydantic (1)!
subprocess.check_call(["uv", "run", "scripts/generate_types.py"]) # (1) Pydantic → TS types
# Start FastAPI via uvicorn (2)!
os.system("uvicorn server.main:app --reload --port 8000") # (2) Dev server
// Frontend dev typically proxies to :8000
console.log("Ensure generated.ts exists and API ready at /ready");
flowchart TB
Env[".env"] --> Compose
P["Pydantic"] --> Types["generated.ts"]
Types --> UI["Frontend"]
Compose --> API["API"]
API --> READY["/api/ready"] Container Logs
Use /docker/{container}/logs to fetch current log lines via API for basic troubleshooting when UI access is limited.