Skip to main content

Overview

The backend is a Node.js REST API that handles authentication, business logic, data-connector queries, and LLM orchestration. It runs on port 3000 and is exposed through Gateway API or Ingress, usually on its own API hostname. Set CONNECT_SERVICE_URL to the in-cluster Connect service URL when connect.enabled: true, for example http://cobi-dashboard-connect:8000.

Required Secrets

Create the backend Kubernetes Secret before running helm install. The backend will crash-loop if the Secret is missing or incomplete.
kubectl create secret generic cobi-backend-secrets \
  --namespace cobi \
  # ── Database ─────────────────────────────────────────────────────────
  --from-literal=DATABASE_URL="postgres://postgres:<password>@<pg-host>:5432/dashboard_auth?schema=public" \
  --from-literal=CORE_DATABASE_URL="postgres://postgres:<password>@<pg-host>:5432/cobi_core?schema=public" \
  --from-literal=ENABLE_MIGRATIONS="true" \
  # ── Auth ─────────────────────────────────────────────────────────────
  --from-literal=BETTER_AUTH_SECRET="<random-64-char-string>" \
  --from-literal=BETTER_AUTH_URL="https://api.example.com" \
  --from-literal=FRONTEND_URL="https://app.example.com" \
  --from-literal=CONNECT_SERVICE_URL="http://cobi-dashboard-connect:8000" \
  # ── LLM inference ────────────────────────────────────────────────────
  --from-literal=AI_PROVIDER="openai" \
  --from-literal=OPENAI_API_KEY="not-used" \
  --from-literal=OPENAI_BASE_URL="http://cobi-dashboard-vllmstack-engine:8000/v1" \
  --from-literal=DEFAULT_MODEL_ID="QuantTrio/Qwen3.5-9B-AWQ" \
  --from-literal=DEFAULT_FAST_MODEL_ID="QuantTrio/Qwen3.5-9B-AWQ" \
  --from-literal=DEFAULT_OCR_MODEL_ID="QuantTrio/Qwen3.5-9B-AWQ" \
  # ── Vector store (Qdrant) ────────────────────────────────────────────
  --from-literal=QDRANT_URL="http://cobi-dashboard-qdrant:6333" \
  --from-literal=QDRANT_LOCAL_ONLY="true" \
  --from-literal=QDRANT_API_KEY="" \
  --from-literal=QDRANT_CLUSTER_KEY="" \
  --from-literal=QDRANT_COLLECTION_PREFIX="prod_" \
  # ── Object storage (MinIO or AWS S3) ─────────────────────────────────
  --from-literal=S3_BUCKET="documents" \
  --from-literal=S3_REGION="us-east-1" \
  --from-literal=S3_ENDPOINT="http://cobi-dashboard-minio:9000" \
  --from-literal=S3_ACCESS_KEY_ID="admin" \
  --from-literal=S3_SECRET_ACCESS_KEY="<minio-root-password>" \
  # ── Security ─────────────────────────────────────────────────────────
  --from-literal=DATASOURCES_ENCRYPTION_KEY="<random-64-hex-chars>"
After the first successful deployment, change ENABLE_MIGRATIONS to "false" and re-apply the Secret. Running migrations on every pod restart is not safe in production.

Environment Variable Reference

Database

VariableRequiredDescription
DATABASE_URLYesPostgreSQL connection string for the dashboard_auth database (auth, sessions)
CORE_DATABASE_URLYesPostgreSQL connection string for the cobi_core database (application data)
ENABLE_MIGRATIONSYesSet "true" on first install to run schema migrations; "false" after
Both connection strings follow the format:
postgres://<user>:<password>@<host>:<port>/<database>?schema=public
For the in-cluster PostgreSQL subchart, the host is <release-name>-postgresql (e.g. cobi-dashboard-postgresql).

Authentication

VariableRequiredDescription
BETTER_AUTH_SECRETYesSecret key for signing session tokens. Generate with openssl rand -hex 32
BETTER_AUTH_URLYesPublic HTTPS URL of the application — used for auth callbacks and CSRF checks
FRONTEND_URLYesPublic HTTPS URL of the frontend — used for redirect allowlists
BETTER_AUTH_URL must match the public API URL. FRONTEND_URL must match the public frontend URL.

LLM Inference

VariableRequiredDescription
AI_PROVIDERYesAlways "openai" — the backend uses the OpenAI-compatible API
OPENAI_BASE_URLYesBase URL of the vLLM inference service (e.g. http://cobi-dashboard-vllmstack-engine:8000/v1)
OPENAI_API_KEYYesAPI key. Set to any non-empty string for self-hosted vLLM (it ignores the key by default)
DEFAULT_MODEL_IDYesModel ID passed in inference requests (must match the model loaded in vLLM)
DEFAULT_FAST_MODEL_IDNoModel for fast/cheap requests. Defaults to DEFAULT_MODEL_ID if not set
DEFAULT_OCR_MODEL_IDNoModel for OCR document extraction. Defaults to DEFAULT_MODEL_ID if not set
When using OpenRouter or another external provider instead of vLLM:
--from-literal=OPENAI_BASE_URL="https://openrouter.ai/api/v1" \
--from-literal=OPENAI_API_KEY="sk-or-..." \
--from-literal=DEFAULT_MODEL_ID="qwen/qwen3.5-9b"

Vector Store (Qdrant)

VariableRequiredDescription
QDRANT_URLYesHTTP URL of the Qdrant service (e.g. http://cobi-dashboard-qdrant:6333)
QDRANT_LOCAL_ONLYYesSet "true" for in-cluster or on-prem Qdrant; "false" for Qdrant Cloud
QDRANT_COLLECTION_PREFIXNoString prefix for all collection names. Useful to namespace multiple environments sharing one Qdrant instance (e.g. "prod_", "staging_")
QDRANT_API_KEYConditionalRequired when using Qdrant Cloud. Leave empty for local
QDRANT_CLUSTER_KEYConditionalRequired when using Qdrant Cloud. Leave empty for local

Object Storage

VariableRequiredDescription
S3_BUCKETYesBucket name for document storage
S3_REGIONYesSigning region. Set to "us-east-1" for MinIO
S3_ENDPOINTYes for S3-compatible storageCustom S3 endpoint. Set to "http://cobi-dashboard-minio:9000" when using in-cluster MinIO
S3_ACCESS_KEY_IDYes for static credentialsS3 access key ID, or MinIO rootUser
S3_SECRET_ACCESS_KEYYes for static credentialsS3 secret access key, or MinIO rootPassword
When backend.s3.existingSecret is set, the Helm chart maps these generic S3_* Secret keys to the backend container’s runtime environment variables.

Security

VariableRequiredDescription
DATASOURCES_ENCRYPTION_KEYYes64-character hex key used to encrypt stored data-source credentials at rest. Generate with openssl rand -hex 32

Observability

VariableRequiredDescription
OTEL_EXPORTER_OTLP_ENDPOINTNoOTLP receiver URL (e.g. http://cobi-dashboard-otel-lgtm:4318). Set when otel-lgtm is enabled
OTEL_SERVICE_NAMENoService name shown in traces (e.g. "cobi-backend")
OTEL_SERVICE_VERSIONNoService version shown in traces
OTEL_METRIC_EXPORT_INTERVALNoMetric export interval in milliseconds (default 5000)
POSTHOG_API_KEYNoPostHog project API key for product analytics
POSTHOG_HOSTNoPostHog ingest host (e.g. https://eu.i.posthog.com)
POSTHOG_PERSONAL_API_KEYNoPostHog personal API key for server-side calls
LANGFUSE_PUBLIC_KEYNoLangfuse project public key for LLM tracing
LANGFUSE_SECRET_KEYNoLangfuse project secret key
LANGFUSE_HOSTNoLangfuse host (e.g. https://cloud.langfuse.com)
LANGFUSE_TRACING_ENVIRONMENTNoEnvironment label in Langfuse traces (e.g. "production")
LANGFUSE_PROMPT_RUNTIME_MODENo"local-only" to load prompts from bundled files; "langfuse" to fetch from Langfuse at runtime
LANGFUSE_PROMPT_LABELNoPrompt version label to load from Langfuse (default "latest")
LANGFUSE_PROMPT_BUNDLE_PATHNoFile path of the bundled prompt file when LANGFUSE_PROMPT_RUNTIME_MODE=local-only

Helm Values

Reference the Secret in your values file:
backend:
  enabled: true
  image:
    repository: docker.io/hellocobi/dashboard-backend
    tag: "0.2.6"
    pullPolicy: IfNotPresent
  replicaCount: 1
  service:
    type: ClusterIP
    port: 3000
  envFrom:
    - secretRef:
        name: cobi-backend-secrets
  s3:
    existingSecret: cobi-backend-secrets
  resources:
    requests:
      cpu: 250m
      memory: 512Mi
    limits:
      cpu: "1"
      memory: 1Gi

Generating Secure Keys

# BETTER_AUTH_SECRET — 32-byte hex string
openssl rand -hex 32

# DATASOURCES_ENCRYPTION_KEY — 32-byte hex string (64 chars)
openssl rand -hex 32