Appearance
Docker
The Lota SDK provides a docker-compose.yml file that runs all required infrastructure services locally.
Quick Start
Get the SDK infrastructure running in three steps:
1. Install Docker
Install Docker Desktop for your platform. Ensure the Docker daemon is running.
2. Start services
bash
docker compose -f infrastructure/docker-compose.yml up -d3. Verify
bash
# Check all containers are running
docker compose -f infrastructure/docker-compose.yml ps
# Test SurrealDB
curl -s http://localhost:8003/health
# Test Redis
redis-cli -p 6382 ping
# Expected: PONG
# Test Bifrost
curl -s http://localhost:8081/healthSurrealDB, Redis, and Bifrost should report healthy status. Qdrant runs as an internal service with no host port exposure. You can now configure the SDK runtime to connect to the stack (see Corresponding SDK Configuration below).
Services
The compose file at infrastructure/docker-compose.yml defines four services:
SurrealDB
The primary database for workstreams, messages, memory, execution plans, and all persistent state.
| Setting | Value |
|---|---|
| Image | surrealdb/surrealdb:v3.0.3 |
| Port | 8003:8000 |
| Storage | RocksDB at /data/database.db |
| Volume | surrealdb_data |
Default credentials:
- Username:
root - Password:
root
Override with environment variables SURREALDB_USER and SURREALDB_PASSWORD.
Redis
Used for BullMQ job queues and distributed memory locks.
| Setting | Value |
|---|---|
| Image | redis:8.6-alpine |
| Port | 6382:6379 |
| Persistence | AOF (append-only file) |
| Volume | redis_data |
Bifrost (AI Gateway)
The AI gateway that all LLM requests route through.
| Setting | Value |
|---|---|
| Image | maximhq/bifrost:latest |
| Port | 8081:8080 |
| Health check | http://localhost:8080/health |
| Config | infrastructure/bifrost.config.json mounted read-only at /app/data/config.json |
| State volume | named gateway_data volume for SQLite config/log state |
Environment variables:
APP_PORT=8080APP_HOST=0.0.0.0LOG_LEVEL=infoLOG_STYLE=json../.envis loaded forAI_GATEWAY_KEY,AI_GATEWAY_ADMIN,AI_GATEWAY_PASS,AI_GATEWAY_QDRANT_KEY, and upstream provider keys
Qdrant
Internal vector store service kept alongside the gateway for future use.
| Setting | Value |
|---|---|
| Image | qdrant/qdrant:v1.17.0 |
| Host port | none |
| Internal gRPC port | 6334 |
| Volume | qdrant_data |
| Auth | AI_GATEWAY_QDRANT_KEY passed to both Qdrant and Bifrost |
Starting Services
bash
cd infrastructure
docker compose up -dOr from the project root:
bash
docker compose -f infrastructure/docker-compose.yml up -dStopping Services
bash
docker compose -f infrastructure/docker-compose.yml downTo also remove volumes (deletes all data):
bash
docker compose -f infrastructure/docker-compose.yml down -vPort Configuration
Default port mappings:
| Service | Container Port | Host Port |
|---|---|---|
| SurrealDB | 8000 | 8003 |
| Redis | 6379 | 6382 |
| Bifrost | 8080 | 8081 |
Corresponding SDK Configuration
Map Docker ports to LotaRuntimeConfig:
ts
const runtime = await createLotaRuntime({
database: {
url: 'ws://localhost:8003/rpc',
namespace: 'lota',
username: 'root',
password: 'root',
},
redis: {
url: 'redis://localhost:6382',
},
aiGateway: {
url: 'http://localhost:8081',
key: 'sk-bf-your-virtual-key',
},
// ...
})Verifying Services
After starting the stack, verify each service is running and healthy.
Check all containers
bash
docker compose -f infrastructure/docker-compose.yml psSurrealDB, Redis, and Bifrost should show Up status. Bifrost should also show (healthy) once its health check passes.
SurrealDB
bash
curl -s http://localhost:8003/healthA 200 OK response confirms SurrealDB is accepting connections. You can also test a query:
bash
curl -s -X POST http://localhost:8003/sql \
-H "Accept: application/json" \
-H "NS: lota" \
-H "DB: lotasdk" \
-u "root:root" \
--data "INFO FOR DB"Redis
bash
redis-cli -p 6382 pingExpected response: PONG. To check memory usage:
bash
redis-cli -p 6382 info memory | head -5Bifrost
bash
curl -s http://localhost:8081/healthA 200 OK response confirms the gateway is running. Bifrost also has a built-in Docker health check that runs every 30 seconds.
Health Checks
SurrealDB
SurrealDB does not expose a dedicated health endpoint in the compose file. The SDK uses connectWithStartupRetry() to poll for readiness:
ts
await connectWithStartupRetry({
connect: () => runtime.connect(),
label: 'SurrealDB',
maxWaitMs: 180_000,
})Redis
Redis readiness is checked through ioredis connection events. The RedisConnectionManager runs periodic health checks (default: every 30 seconds) using PING.
Bifrost
Bifrost includes a health check configuration:
- Endpoint:
http://localhost:8080/health - Interval: 30 seconds
- Timeout: 10 seconds
- Retries: 3
Volumes
| Volume | Service | Purpose |
|---|---|---|
qdrant_data | Qdrant | Semantic cache vector storage |
surrealdb_data | SurrealDB | Database files (RocksDB) |
redis_data | Redis | AOF persistence |
infrastructure/bifrost.config.json | Bifrost | Tracked gateway bootstrap config |
gateway_data | Bifrost | SQLite config/log state after bootstrap |
Troubleshooting
Port conflicts
If a service fails to start with a "port already in use" error, another process is occupying the host port.
bash
# Find what is using port 8003 (SurrealDB)
lsof -i :8003
# Find what is using port 6382 (Redis)
lsof -i :6382
# Find what is using port 8081 (Bifrost)
lsof -i :8081Stop the conflicting process, or change the host port mapping in docker-compose.yml. For example, to move SurrealDB to port 8004:
yaml
ports:
- "8004:8000"Then update your SDK config to use ws://localhost:8004/rpc.
Volume permission issues
If SurrealDB or Redis fail with permission errors on their data volumes:
bash
# Remove volumes and recreate
docker compose -f infrastructure/docker-compose.yml down -v
docker compose -f infrastructure/docker-compose.yml up -dOn Linux, you may need to ensure the Docker user has write access to the volume mount paths. Named volumes (used by SurrealDB and Redis) are managed by Docker and rarely have permission issues. The .gateway-data bind mount for Bifrost is created automatically.
Bifrost not starting
Bifrost requires environment variables for API keys. If Bifrost exits immediately or shows unhealthy status:
- Check that
../.envexists relative to theinfrastructure/directory (i.e.,.envat the project root). - Ensure the following variables are set in
.env:AI_GATEWAY_KEY-- The virtual key for SDK requestsAI_GATEWAY_ADMIN-- Admin username for BifrostAI_GATEWAY_PASS-- Admin password for Bifrost- At least one upstream provider key (e.g.,
ANTHROPIC_API_KEY,OPENAI_API_KEY)
- Check Bifrost logs:
bash
docker compose -f infrastructure/docker-compose.yml logs bifrost- Verify
infrastructure/bifrost.config.jsonexists and is valid JSON.
SurrealDB connection refused
If the SDK cannot connect to SurrealDB after docker compose up:
- Container not running: Check
docker compose psto see if the container exited. - Still starting up: SurrealDB may take a few seconds to initialize. The SDK's
connectWithStartupRetry()handles this with retries up to 180 seconds. - Wrong URL: Ensure you are using
ws://localhost:8003/rpc(not port 8000, which is the container-internal port). - Authentication failure: Verify credentials match between
docker-compose.ymland your SDK config. Default isroot/root.
bash
# Check SurrealDB container logs
docker compose -f infrastructure/docker-compose.yml logs surrealdbRedis connection issues
If workers fail to start or queues are not processing:
bash
# Check Redis container status
docker compose -f infrastructure/docker-compose.yml logs redis
# Test connectivity
redis-cli -p 6382 pingEnsure your SDK config uses redis://localhost:6382 (not port 6379).
Production Considerations
The provided Docker Compose setup is intended for local development. For production deployments, address the following.
Credentials
Do not use the default root/root credentials for SurrealDB in production. Set strong passwords:
bash
export SURREALDB_USER=your_secure_username
export SURREALDB_PASSWORD=your_secure_passwordSimilarly, set strong values for AI_GATEWAY_ADMIN, AI_GATEWAY_PASS, and AI_GATEWAY_KEY in your production environment.
Redis persistence and memory
The development setup uses AOF (append-only file) persistence. For production:
- Enable both AOF and RDB snapshots for durability.
- Set a
maxmemorylimit and an appropriate eviction policy. BullMQ requiresnoevictionto prevent job data loss:maxmemory 2gb maxmemory-policy noeviction - Consider Redis Sentinel or Redis Cluster for high availability.
- Enable Redis AUTH with a strong password.
SurrealDB storage
The development setup uses RocksDB with a Docker volume. For production:
- Back up the
surrealdb_datavolume regularly. - Monitor disk usage -- RocksDB storage grows with data and compaction.
- Consider running SurrealDB on dedicated infrastructure with SSD storage for better I/O performance.
Bifrost configuration
For production AI gateway deployments:
- Use dedicated API keys per environment.
- Configure rate limiting and cost controls in
bifrost.config.json. - Set
LOG_LEVEL=warnorLOG_LEVEL=errorto reduce log volume. - Monitor the
.gateway-dataSQLite state for request logs and analytics.
Volume backup strategies
For Docker volume backups:
bash
# Backup SurrealDB data
docker run --rm -v surrealdb_data:/data -v $(pwd)/backups:/backup \
alpine tar czf /backup/surrealdb-$(date +%Y%m%d).tar.gz -C /data .
# Backup Redis data
docker run --rm -v redis_data:/data -v $(pwd)/backups:/backup \
alpine tar czf /backup/redis-$(date +%Y%m%d).tar.gz -C /data .Schedule these as cron jobs or use your infrastructure provider's snapshot capabilities. For Redis, trigger a BGSAVE before backing up to ensure a consistent snapshot.
Network security
In production, do not expose database and Redis ports to the public internet. Use:
- Internal Docker networks or private subnets.
- Bind host ports to
127.0.0.1only if services run on the same host as the application:yamlports: - "127.0.0.1:8003:8000" - "127.0.0.1:6382:6379" - TLS for SurrealDB WebSocket connections and Redis connections where supported.