This guide covers every way to install and run SourceBridge.ai: Docker Compose for quick evaluation, Helm for Kubernetes deployments, and from-source for contributors.
| Requirement | Docker Compose | Kubernetes / Helm | From Source |
|---|---|---|---|
| Docker + Docker Compose v2 | Required | -- | -- |
| kubectl | -- | Required | -- |
| Helm 3.x | -- | Required | -- |
| Go 1.25+ | -- | -- | Required |
| Python 3.12+ | -- | -- | Required (worker) |
| uv | -- | -- | Required (worker) |
| Node.js 22+ | -- | -- | Required (web UI) |
| LLM provider (Anthropic, OpenAI, or Ollama) | Recommended | Recommended | Recommended |
An LLM provider is not strictly required to start the server, but all AI-powered features (code review, discussion, explanation, field guide generation) depend on one.
Docker Compose is the fastest path from zero to a running SourceBridge instance. It starts four containers: the Go API server, the Python worker, SurrealDB, and the Next.js web UI.
git clone https://github.com/sourcebridge/sourcebridge.git
cd sourcebridge
./setup.sh # guided setup -- generates .env, starts containersOr, if you prefer to skip the interactive script:
git clone https://github.com/sourcebridge/sourcebridge.git
cd sourcebridge
# Create a minimal .env
cat > .env <<'EOF'
SOURCEBRIDGE_GRPC_SECRET=$(openssl rand -hex 16)
SOURCEBRIDGE_JWT_SECRET=$(openssl rand -hex 32)
SOURCEBRIDGE_LLM_PROVIDER=anthropic
SOURCEBRIDGE_LLM_MODEL=claude-sonnet-4-20250514
SOURCEBRIDGE_LLM_API_KEY=sk-ant-...
EOF
docker compose up -dOpen http://localhost:3300 once the containers are healthy.
# Container status
docker compose ps
# API health check
curl http://localhost:8080/healthz
# Follow logs
docker compose logs -fThe Docker Compose file reads its configuration from a .env file in the project
root. All variables are optional and have sensible defaults.
| Variable | Description | Default |
|---|---|---|
SOURCEBRIDGE_GRPC_SECRET |
Shared secret for API-to-worker gRPC auth | dev-shared-secret |
SOURCEBRIDGE_JWT_SECRET |
JWT signing key (≥32 bytes; CA-311 hard rejects shorter at startup) | publicly-known 64-hex placeholder (override with openssl rand -hex 32) |
SOURCEBRIDGE_SECURITY_JWT_SECRET_FILE |
(preferred) File path for the JWT signing key — wins over literal env var | (unset) |
SOURCEBRIDGE_LLM_PROVIDER |
LLM backend: anthropic, openai, ollama, vllm |
ollama |
SOURCEBRIDGE_LLM_MODEL |
Model name | qwen3:32b |
SOURCEBRIDGE_LLM_BASE_URL |
Base URL for the LLM API | (provider default) |
SOURCEBRIDGE_LLM_API_KEY |
API key for cloud LLM providers | -- |
SOURCEBRIDGE_EMBEDDING_PROVIDER |
Embedding backend: voyage, openai, ollama |
-- |
VOYAGE_API_KEY |
API key for Voyage AI embeddings | -- |
SOURCEBRIDGE_INDEXING_ALLOW_PRIVATE_GIT_HOSTS |
DANGEROUS opt-in: allows git clone to private/internal IPs (RFC1918, loopback, link-local, CGNAT, ULA). Only enable on single-operator self-hosted instances where all indexed repos are on your private network. See CA-312. | false |
SOURCEBRIDGE_WORKER_DEBUG |
Enable verbose worker logging. Note: to also enable gRPC reflection for grpcurl debugging, ALSO set SOURCEBRIDGE_WORKER_GRPC_REFLECTION_ENABLED=true. |
false |
SOURCEBRIDGE_WORKER_GRPC_REFLECTION_ENABLED |
Enable gRPC reflection on the worker for grpcurl debugging. Requires SOURCEBRIDGE_WORKER_DEBUG=true as well — both must be true. See CA-202. |
false |
Edit .env to switch providers. Examples:
Anthropic (cloud):
SOURCEBRIDGE_LLM_PROVIDER=anthropic
SOURCEBRIDGE_LLM_MODEL=claude-sonnet-4-20250514
SOURCEBRIDGE_LLM_API_KEY=sk-ant-your-key-here
OpenAI (cloud):
SOURCEBRIDGE_LLM_PROVIDER=openai
SOURCEBRIDGE_LLM_MODEL=gpt-4o
SOURCEBRIDGE_LLM_API_KEY=sk-your-key-here
Ollama (local, free):
SOURCEBRIDGE_LLM_PROVIDER=ollama
SOURCEBRIDGE_LLM_MODEL=qwen3:32b
SOURCEBRIDGE_LLM_BASE_URL=http://host.docker.internal:11434/v1
SOURCEBRIDGE_LLM_API_KEY=not-needed
On Linux, replace host.docker.internal with 172.17.0.1 (the default Docker
bridge gateway) or use --add-host=host.docker.internal:host-gateway in your
Compose override.
vLLM (local, GPU-accelerated):
SOURCEBRIDGE_LLM_PROVIDER=vllm
SOURCEBRIDGE_LLM_MODEL=Qwen/Qwen2.5-32B-Instruct
SOURCEBRIDGE_LLM_BASE_URL=http://host.docker.internal:8000/v1
SOURCEBRIDGE_LLM_API_KEY=not-needed
After editing, restart the worker:
docker compose restart workerSurrealDB data is stored in a named Docker volume (surrealdb-data). Data survives
docker compose down but is removed by docker compose down -v.
When using docker-compose.hub.yml, the encryption-key-init service runs on
first up and generates 32 bytes of entropy via od -An -tx1 | tr -d ' \n'
(Alpine-portable; openssl is not in alpine:3.20 by default). The key is written
to the sourcebridge-secrets named volume and read by the API container via
SOURCEBRIDGE_SECURITY_ENCRYPTION_KEY_FILE. Subsequent up calls reuse the
existing file — the init container is idempotent.
Back up the sourcebridge-secrets volume before any docker compose down -v. That
flag removes all named volumes, including the encryption key and the SurrealDB data.
If the key is lost, every API key stored through /admin/llm is unrecoverable.
See docs/admin-runbooks/encryption-key-setup.md
and docs/admin/llm-config.md for the
full wipe-and-re-enter procedure.
Operator escape hatch: setting SOURCEBRIDGE_SECURITY_ENCRYPTION_KEY as a literal
env var still works, but when a file is present via _FILE, the file wins
(Vault/Postgres convention). See the resolution order in
docs/admin-runbooks/encryption-key-setup.md.
The bundled docker compose stack starts a Redis container by default.
SourceBridge uses it for its shared cache, which backs the MCP session
store: sessions created on one replica stay valid when subsequent requests
hit another replica.
If you're not running MCP or only running a single API replica, you can
remove the redis service from docker-compose.yml and set
SOURCEBRIDGE_STORAGE_REDIS_MODE=memory. SourceBridge will keep the cache
in-process.
To customize the Redis URL, set SOURCEBRIDGE_STORAGE_REDIS_URL (e.g.
redis://host:6379/0). With redis_mode=external and no reachable Redis,
the server logs a warning at startup and falls back to in-memory — it
never refuses to boot.
See docs/user/mcp-clients.md for full MCP client setup and the multi-replica reliability notes.
To back up the volume:
docker run --rm -v sourcebridge_surrealdb-data:/data -v $(pwd):/backup \
alpine tar czf /backup/surrealdb-backup.tar.gz -C /data .git pull
docker compose up -d --buildTo pull new pre-built images instead of building locally:
docker compose pull
docker compose up -ddocker compose down # stop containers, keep data
docker compose down -v # stop containers AND remove data volumesSourceBridge ships a Helm chart for production Kubernetes deployments.
- Kubernetes 1.24+
- Helm 3.x
kubectlconfigured for your cluster- A default StorageClass (or specify one explicitly)
# From a local clone
helm install sourcebridge deploy/helm/sourcebridge/ \
--namespace sourcebridge --create-namespace
# Or from the Helm repository (when published)
helm repo add sourcebridge https://charts.sourcebridge.dev
helm repo update
helm install sourcebridge sourcebridge/sourcebridge \
--namespace sourcebridge --create-namespaceVerify:
kubectl -n sourcebridge get pods
kubectl -n sourcebridge get svcCreate a my-values.yaml and pass it with --values:
helm install sourcebridge deploy/helm/sourcebridge/ \
--namespace sourcebridge --create-namespace \
--values my-values.yamlThe full values reference is in deploy/helm/sourcebridge/values.yaml. The most
important sections are documented below.
global:
domain: sourcebridge.example.com
ingress:
enabled: true
className: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-productionglobal:
domain: sourcebridge.example.com
ingress:
enabled: true
className: nginx
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
cert-manager.io/cluster-issuer: letsencrypt-productionglobal:
domain: sourcebridge.example.com
tls:
enabled: true
secretName: sourcebridge-tls # pre-existing TLS secret
ingress:
enabled: true
className: traefikOr let cert-manager provision the certificate:
global:
domain: sourcebridge.example.com
tls:
enabled: true
ingress:
enabled: true
className: traefik
annotations:
cert-manager.io/cluster-issuer: letsencrypt-production
tls:
- hosts:
- sourcebridge.example.com
secretName: sourcebridge-tlsDisable the built-in SurrealDB and point to your own instance:
surrealdb:
enabled: false
api:
env:
SOURCEBRIDGE_STORAGE_SURREAL_MODE: "external"
SOURCEBRIDGE_STORAGE_SURREAL_URL: "ws://my-surrealdb:8000/rpc"
SOURCEBRIDGE_STORAGE_SURREAL_NAMESPACE: "sourcebridge"
SOURCEBRIDGE_STORAGE_SURREAL_DATABASE: "sourcebridge"
SOURCEBRIDGE_STORAGE_SURREAL_USER: "root"
SOURCEBRIDGE_STORAGE_SURREAL_PASS: "your-password"secrets:
create: true
llmApiKey: "sk-ant-your-key-here"
worker:
env:
SOURCEBRIDGE_WORKER_LLM_PROVIDER: "anthropic"
SOURCEBRIDGE_WORKER_LLM_MODEL: "claude-sonnet-4-20250514"
SOURCEBRIDGE_WORKER_LLM_BASE_URL: ""secrets:
create: true
llmApiKey: "sk-your-key-here"
worker:
env:
SOURCEBRIDGE_WORKER_LLM_PROVIDER: "openai"
SOURCEBRIDGE_WORKER_LLM_MODEL: "gpt-4o"
SOURCEBRIDGE_WORKER_LLM_BASE_URL: ""If Ollama runs on the cluster nodes or as a separate service:
worker:
env:
SOURCEBRIDGE_WORKER_LLM_PROVIDER: "ollama"
SOURCEBRIDGE_WORKER_LLM_MODEL: "qwen3:32b"
SOURCEBRIDGE_WORKER_LLM_BASE_URL: "http://ollama.ollama.svc.cluster.local:11434/v1"
SOURCEBRIDGE_WORKER_LLM_API_KEY: "not-needed"If Ollama runs on the host (outside the cluster), use the node IP or a NodePort service to make it reachable from worker pods.
helm upgrade sourcebridge deploy/helm/sourcebridge/ \
--namespace sourcebridge --values my-values.yamlhelm uninstall sourcebridge --namespace sourcebridge
# Remove persistent volume claims if you want to delete data
kubectl -n sourcebridge delete pvc --all| Key | Description | Default |
|---|---|---|
global.domain |
Public domain for ingress | sourcebridge.example.com |
global.tls.enabled |
Enable TLS on ingress | false |
global.tls.secretName |
Pre-existing TLS secret name | "" |
api.image.repository |
API server image | sourcebridge/api |
api.image.tag |
API server image tag; blank = .Chart.AppVersion (CA-472) |
"" |
api.replicas |
API server replicas | 1 |
api.port |
API server port | 8080 |
api.resources |
API server resource requests/limits | 250m-1 CPU, 512Mi-1Gi |
web.image.repository |
Web UI image | sourcebridge/web |
web.image.tag |
Web UI image tag; blank = .Chart.AppVersion (CA-472) |
"" |
web.replicas |
Web UI replicas | 1 |
web.port |
Web UI port | 3000 |
worker.image.repository |
Worker image | sourcebridge/worker |
worker.image.tag |
Worker image tag; blank = .Chart.AppVersion (CA-472) |
"" |
worker.replicas |
Worker replicas | 1 |
worker.env |
Worker environment variables (LLM config) | (see values.yaml) |
surrealdb.enabled |
Deploy SurrealDB as part of the release | true |
surrealdb.image.tag |
SurrealDB image tag | latest |
surrealdb.persistence.enabled |
Enable persistent storage for SurrealDB | true |
surrealdb.persistence.size |
PVC size for SurrealDB | 1Gi |
surrealdb.persistence.storageClass |
StorageClass (empty = default) | "" |
redis.enabled |
Deploy Redis as part of the release | true |
redis.persistence.enabled |
Enable persistent storage for Redis | true |
redis.persistence.size |
PVC size for Redis | 1Gi |
ingress.enabled |
Create an Ingress resource | false |
ingress.className |
Ingress class name | traefik |
ingress.annotations |
Extra Ingress annotations | {} |
ingress.tls |
Custom TLS configuration for Ingress | [] |
secrets.create |
Create a Kubernetes Secret from values | false |
secrets.llmApiKey |
LLM provider API key | "" |
secrets.surrealdbUser |
SurrealDB admin username | root |
secrets.surrealdbPassword |
SurrealDB admin password (auto-generated if empty) | "" |
Building from source is the best option for contributors and for running the latest unreleased code.
git clone https://github.com/sourcebridge/sourcebridge.git
cd sourcebridge
# Build the Go API server
make build-go
# Install Python worker dependencies
cd workers && uv sync && cd ..
# Install web UI dependencies
cd web && npm ci && cd ..Or use the guided setup:
./setup.sh # choose "Local development" modeStart each component in a separate terminal:
Terminal 1 -- API server:
make devThe API server starts at http://localhost:8080 with embedded SurrealDB. It watches
for file changes if you have air installed.
Terminal 2 -- Web UI:
make dev-webThe Next.js dev server starts at http://localhost:3300 with hot module replacement.
Terminal 3 -- Worker:
cd workers
uv run python -m workersThe gRPC worker listens on port 50051.
For a non-containerized production deployment:
# Build optimized binaries and assets
make build-go
cd web && npm ci && npm run build && cd ..
# Create a production config
cp config.toml.example config.toml
# Edit config.toml with your settings (see Configuration Reference below)
# Run the API server
./bin/sourcebridge serve
# Run the worker (in a separate process or via systemd)
cd workers && uv run python -m workersThe web UI is a standalone Next.js application. After npm run build, serve it with:
cd web
node .next/standalone/server.jsSourceBridge reads configuration from two sources, in order of precedence:
- Environment variables (highest precedence)
- config.toml file (in the working directory or
~/.sourcebridge/config.toml)
Environment variables use the SOURCEBRIDGE_ prefix with nested keys joined by
underscores. For example, [llm] provider maps to SOURCEBRIDGE_LLM_PROVIDER.
Controls the large language model used for reasoning operations (review, discussion, field guide generation, requirement tracing).
[llm]
provider = "anthropic" # anthropic | openai | ollama | vllm
base_url = "" # leave empty for SDK default
summary_model = "claude-sonnet-4-20250514" # model for field guide / summary
review_model = "claude-sonnet-4-20250514" # model for code review
ask_model = "claude-sonnet-4-20250514" # model for discussion / Q&A[server]
http_port = 8080
grpc_port = 50051[storage]
surreal_mode = "embedded" # embedded | external
surreal_url = "" # ws://host:port/rpc (external mode only)
surreal_namespace = "sourcebridge"
surreal_database = "sourcebridge"
surreal_user = "root"
surreal_pass = "root"
redis_mode = "memory" # memory | external — see "When to use Redis" below
redis_url = "" # redis://host:port (external mode only)Redis is optional. Leave redis_mode = "memory" for single-node, single-replica
installs — SourceBridge keeps its cache in-process and everything works.
Switch to redis_mode = "external" when:
- You run the API with more than one replica and want the MCP server
to stay reliable. MCP sessions are stored in this cache; with a shared
Redis, any replica can handle any MCP request. Without it, clients see
intermittent
"Invalid or expired session"errors as requests round-robin across pods. - You want cache state to survive pod restarts.
If redis_mode = "external" is set but SourceBridge can't reach the URL
at startup, it logs a warning and falls back to in-memory — startup does
not fail. Fix the Redis connection to re-enable HA-safe MCP.
Any Redis-compatible server works (Redis 6+, KeyDB, Dragonfly, Upstash over
TLS). The bundled Helm chart enables Redis by default; see redis.enabled
below.
[qa]
server_side_enabled = false # flip to true to enable POST /api/v1/ask + MCP ask_question
local_fast_mode_subprocess = true # local-desktop installs keep the subprocess fast path
question_max_bytes = 4096
session_tokens_per_hour = 100000
repo_tokens_per_day = 1000000
deployment_tokens_per_day = 10000000
synthesis_lane = 4 # concurrent QA synthesis calls against the reasoning workerWhen server_side_enabled = true:
/healthzadvertisesX-SourceBridge-QA: v1sosourcebridge askauto-selects the server path (no pre-flight GraphQL round trip).POST /api/v1/askreturns structuredAskResultwith diagnostics, references, usage, and optional debug payload.- The MCP
ask_questiontool becomes an active orchestrator call rather than returning a "server-side QA disabled" hint.
The subprocess cli_ask.py path remains the only route that reads
uncommitted working-tree changes, so it stays available for local
development via sourcebridge ask --legacy.
Default mode change (CA-319): As of this release, omitting mode on
POST /api/v1/ask and GraphQL ask defaults to deep retrieval (file
and snippet context attached before synthesis). Explicit mode: "fast"
remains available for callers that want the pure-LLM, no-retrieval path.
The sourcebridge ask --server CLI inherits the server-side default when
--mode is unset; scripts that need a specific mode should pass --mode
explicitly. Operators tuning concurrency: deep-mode calls engage the
synthesis lane — SOURCEBRIDGE_QA_SYNTHESIS_LANE is the throttle to
revisit if deep-default load saturates the existing lane size.
[security]
mode = "oss" # oss | enterprise
jwt_secret = "" # required for token auth
grpc_auth_secret = "" # shared secret for API <-> worker| Environment Variable | config.toml Key | Description |
|---|---|---|
SOURCEBRIDGE_LLM_PROVIDER |
[llm] provider |
LLM provider name |
SOURCEBRIDGE_LLM_BASE_URL |
[llm] base_url |
LLM API endpoint |
SOURCEBRIDGE_LLM_SUMMARY_MODEL |
[llm] summary_model |
Model for summaries |
SOURCEBRIDGE_LLM_REVIEW_MODEL |
[llm] review_model |
Model for reviews |
SOURCEBRIDGE_LLM_ASK_MODEL |
[llm] ask_model |
Model for Q&A |
SOURCEBRIDGE_SERVER_HTTP_PORT |
[server] http_port |
API server port |
SOURCEBRIDGE_SERVER_GRPC_PORT |
[server] grpc_port |
gRPC port |
SOURCEBRIDGE_STORAGE_SURREAL_MODE |
[storage] surreal_mode |
Database mode |
SOURCEBRIDGE_STORAGE_SURREAL_URL |
[storage] surreal_url |
SurrealDB URL |
SOURCEBRIDGE_STORAGE_SURREAL_NAMESPACE |
[storage] surreal_namespace |
SurrealDB namespace |
SOURCEBRIDGE_STORAGE_SURREAL_DATABASE |
[storage] surreal_database |
SurrealDB database |
SOURCEBRIDGE_STORAGE_SURREAL_USER |
[storage] surreal_user |
SurrealDB username |
SOURCEBRIDGE_STORAGE_SURREAL_PASS |
[storage] surreal_pass |
SurrealDB password |
SOURCEBRIDGE_STORAGE_REDIS_MODE |
[storage] redis_mode |
Redis mode |
SOURCEBRIDGE_STORAGE_REDIS_URL |
[storage] redis_url |
Redis URL |
SOURCEBRIDGE_SECURITY_MODE |
[security] mode |
Auth mode |
SOURCEBRIDGE_SECURITY_JWT_SECRET |
[security] jwt_secret |
JWT signing key |
SOURCEBRIDGE_SECURITY_GRPC_AUTH_SECRET |
[security] grpc_auth_secret |
gRPC shared secret |
SOURCEBRIDGE_QA_SERVER_SIDE_ENABLED |
[qa] server_side_enabled |
Turn on /api/v1/ask + MCP ask_question |
SOURCEBRIDGE_QA_LOCAL_FAST_MODE_SUBPROCESS |
[qa] local_fast_mode_subprocess |
Keep subprocess fast path for local-desktop installs |
SOURCEBRIDGE_QA_QUESTION_MAX_BYTES |
[qa] question_max_bytes |
Cap question payload size |
SOURCEBRIDGE_QA_SESSION_TOKENS_PER_HOUR |
[qa] session_tokens_per_hour |
Per-session token budget |
SOURCEBRIDGE_QA_REPO_TOKENS_PER_DAY |
[qa] repo_tokens_per_day |
Per-repo daily token budget |
SOURCEBRIDGE_QA_DEPLOYMENT_TOKENS_PER_DAY |
[qa] deployment_tokens_per_day |
Deployment circuit breaker |
SOURCEBRIDGE_QA_SYNTHESIS_LANE |
[qa] synthesis_lane |
Concurrent QA synthesis calls |
| Provider | provider value |
base_url |
api_key |
Notes |
|---|---|---|---|---|
| Anthropic | anthropic |
(leave empty) | SOURCEBRIDGE_WORKER_LLM_API_KEY (Makefile dev targets also accept ANTHROPIC_API_KEY) |
Claude models via cloud API |
| OpenAI | openai |
(leave empty) | SOURCEBRIDGE_WORKER_LLM_API_KEY |
GPT models via cloud API |
| Ollama | ollama |
http://localhost:11434/v1 |
not-needed |
Local inference, no API key |
| vLLM | vllm |
http://localhost:8000/v1 |
not-needed |
Local GPU-accelerated inference |
| Any OpenAI-compatible | openai |
Custom endpoint URL | As required | Works with LiteLLM, LocalAI, etc. |
Embeddings are used for semantic search and knowledge retrieval in large repositories.
| Provider | Worker env vars | Notes |
|---|---|---|
| Voyage AI | SOURCEBRIDGE_WORKER_EMBEDDING_PROVIDER=voyage, VOYAGE_API_KEY=... |
Recommended for production |
| OpenAI | SOURCEBRIDGE_WORKER_EMBEDDING_PROVIDER=openai, OPENAI_API_KEY=... |
Uses text-embedding-3-small |
| Ollama | SOURCEBRIDGE_WORKER_EMBEDDING_PROVIDER=ollama, SOURCEBRIDGE_WORKER_EMBEDDING_BASE_URL=http://localhost:11434 |
Local, uses nomic-embed-text |
| Endpoint | Component | Expected response |
|---|---|---|
GET /healthz |
API server | 200 OK |
GET /readyz |
API server | 200 OK when fully initialized |
GET /metrics |
API server | Prometheus metrics |
GET /health (port 8000) |
SurrealDB | 200 OK |
Symptom: docker compose ps shows a container in restarting or exited state.
Solutions:
-
Check logs for the failing container:
docker compose logs sourcebridge docker compose logs worker docker compose logs surrealdb
-
If SurrealDB fails, the data volume may be corrupt. Remove it and restart:
docker compose down -v docker compose up -d
-
If the worker fails with an import error, rebuild the image:
docker compose build worker docker compose up -d worker
-
If
/auth/inforeturns HTTP 500 and you are runningdocker-compose.hub.ymlwith asourcebridge-web:latestimage pulled before 2026-05-05, pull the updated image. The build-time rewrites pointed tohttp://localhost:8080, which is unreachable inside the container; the fix is in commits1fee78b,9ba671b,873bc53onmain.docker compose -f docker-compose.hub.yml pull web docker compose -f docker-compose.hub.yml up -d web
Symptom: curl http://localhost:8080/healthz fails.
Solutions:
- Verify the container is running:
docker compose ps sourcebridge - Check if port 8080 is already in use:
lsof -i :8080 - Try a different host port by editing
docker-compose.yml:ports: - "9090:8080"
Symptom: AI features (review, discussion) return errors or time out.
Solutions:
- Check the worker logs:
docker compose logs worker - Verify the gRPC shared secret matches in both the API server and worker environment
- Ensure SurrealDB is healthy:
curl http://localhost:8000/health
Symptom: The CLI command sourcebridge review or sourcebridge ask shows
"Python worker required".
Solutions:
- Install Python 3.12+ and uv:
curl -LsSf https://astral.sh/uv/install.sh | sh - Install worker dependencies:
cd workers && uv sync
- Start the worker:
cd workers && uv run python -m workers
Symptom: Review, discussion, or field guide requests return empty results or generic errors.
Solutions:
- Verify your LLM provider is configured correctly (check
.envorconfig.toml) - For cloud providers, verify the API key is valid:
# Anthropic curl https://api.anthropic.com/v1/messages \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{"model":"claude-sonnet-4-20250514","max_tokens":10,"messages":[{"role":"user","content":"Hi"}]}'
- For Ollama, verify the model is pulled and Ollama is running:
ollama list curl http://localhost:11434/v1/models
- Check worker logs for LLM errors:
docker compose logs worker
Symptom: Indexing completes but queries return no symbols.
Solutions:
- Verify the repository path exists and contains source files
- Confirm the language is supported: Go, Python, TypeScript, JavaScript, Java, Rust, C, C++, C#
- Re-index with verbose logging:
sourcebridge index /path/to/repo --verbose
Symptom: Container fails to start because the port is already allocated.
Default ports used:
| Port | Service |
|---|---|
| 3000 | Web UI |
| 8080 | API server |
| 8000 | SurrealDB |
| 50051 | Worker (gRPC) |
To resolve, either stop the conflicting process or change the port mapping in
docker-compose.yml.
Symptom: Page hangs at "loading"; browser DevTools console shows
blocked by CORS policy.
If you override SOURCEBRIDGE_WEB_PORT (e.g. to 3300 because port 3000 is
taken), also set SOURCEBRIDGE_SERVER_CORS_ORIGINS on the API container to
include the new origin. The Go API rejects requests whose Origin header is not
in the allowlist (default: ["http://localhost:3300"]).
SOURCEBRIDGE_SERVER_CORS_ORIGINS='["http://localhost:3300"]'
Symptom: /admin/monitor (and other admin SSE streams) disconnect after a
short idle period.
Node's default keepAliveTimeout in standalone mode is 5 seconds. If the Go
API's SSE heartbeat interval exceeds this, the underlying TCP connection closes
between heartbeats. Set NEXT_HTTP_KEEP_ALIVE_TIMEOUT=60000 (milliseconds) on
the web container, or shorten the upstream heartbeat interval. The middleware
proxy preserves stream chunks but cannot extend the TCP keepalive independently.
# All containers
docker compose logs -f
# Specific container
docker compose logs -f sourcebridge
docker compose logs -f worker
docker compose logs -f web
docker compose logs -f surrealdb
# Kubernetes
kubectl -n sourcebridge logs -f deployment/sourcebridge-api
kubectl -n sourcebridge logs -f deployment/sourcebridge-worker
kubectl -n sourcebridge logs -f deployment/sourcebridge-web
# From-source (API server)
make dev # logs go to stdout
# From-source (worker)
cd workers && uv run python -m workers # logs go to stdoutIf something is deeply broken, a full reset is the fastest path:
# Docker Compose
docker compose down -v
docker compose up -d --build
# Helm
helm uninstall sourcebridge -n sourcebridge
kubectl -n sourcebridge delete pvc --all
helm install sourcebridge deploy/helm/sourcebridge/ -n sourcebridge
# From source (embedded SurrealDB stores data in the working directory)
rm -rf .surreal/
make dev