This is not a line-by-line explanation of the sample files. It is a deployment configuration guide focused on where each setting belongs, how priority works, and which decisions must be stable before production release.

Configuration Model#

DEEIX Chat separates configuration into three categories: startup configuration, runtime business settings, and frontend build configuration. Startup configuration determines whether the service can connect to database, cache, storage, and complete boot. Runtime business settings define models, routing, billing, RAG, MCP, and file-processing policy. Frontend build configuration determines which API origin the browser calls. Keeping these categories separate gives deployment, migration, secret rotation, and debugging a clear operational boundary.

LayerScopeStored inChange path
Startup configurationPorts, public URLs, database, cache, storage, secrets, GeoIP, tracingconfig.yaml and environment variablesEdit and restart the service
Business configurationLogin policy, models, upstreams, routing, file processing, RAG, MCP, billing, announcementsDatabase system_settingsChange from the admin console
Frontend build configurationPublic API URL used by the browserBuild-time environment variableRebuild the frontend

The effective priority is always environment variables > config.yaml > built-in defaults. If the container receives POSTGRES_DSN, REDIS_ADDR, or secrets through environment variables, those values override matching fields in config.yaml.

Deployment Shapes#

Choose the deployment shape before copying a template. The three templates map to different dependency models and should not be mixed casually. Lightweight deployment is for quick validation. Standard deployment connects to existing infrastructure. Full deployment runs the app, PostgreSQL, and Redis in one Compose stack.

Deployment shapeBest forTemplateCompose fileData and cache
Lightweight deploymentLocal evaluation, demos, small single-node installsconfig.sqlite.example.yamldocker-compose.sqlite.ymlSQLite + memory cache
Standard deploymentExisting PostgreSQL, Redis, or platform infrastructureconfig.example.yamldocker-compose.ymlExternal PostgreSQL + Redis
Full deploymentOne machine running app, database, and cacheconfig.full.example.yamldocker-compose.full.ymlPostgreSQL + Redis inside Compose
  1. Choose a deployment shape.
  2. Copy the matching template to config.yaml.
  3. Configure public URLs, security secrets, database, cache, and storage.
  4. After startup, configure models, routing, files, billing, and login policy from the admin console.

terminal

The backend reads config.yaml by default. Running from the repository root or Docker /app reads ./config.yaml; running from backend/ reads ../config.yaml. Use CONFIG_FILE for custom paths, and use the container path in Docker.

config.yaml#

config.yaml should contain only infrastructure settings that must be known before the service starts. It should answer where the service listens, what public URLs it uses, which database and cache it connects to, where files are written, and which security secrets protect the system. Models, upstreams, routes, pricing, subscriptions, RAG, MCP, and file-processing policy belong to the admin console, not static YAML.

Service URLs#

For public deployments, API URL, web URL, CORS, and reverse proxy settings must be reviewed together.

  • Database DSNs target the container network.
  • public_api_base_url is used by browsers, callbacks, and generated API links.
  • public_web_base_url is used by shares, redirects, and notification links.
  • Separated frontend/backend deployments must also align NEXT_PUBLIC_API_BASE_URL at frontend build time.

config.yaml

FieldPurposeProduction requirement
app.envEnables production validationUse prod or production
server.http_portGo service listen portUpdate Compose port mapping if changed
server.cors_allow_originFrontend origins allowed to call the APIUse exact origins, not wildcard
server.trusted_proxiesTrusted reverse proxy CIDRsInclude only real proxy sources
server.public_api_base_urlPublic API URLMust be HTTPS in production
server.public_web_base_urlPublic web URLMust be HTTPS in production

Security Secrets#

Sample secrets are for local development only and must be replaced before public deployment. In production mode, the backend rejects empty values, built-in development defaults, and secrets that are too short. Environment variables override matching values in config.yaml.

SecretMinimum requirementNotes
security.jwt_secret
JWT_SECRET
16 charactersSigns login sessions and access tokens; rotate through a controlled secret-rotation process.
security.data_encryption_key
DATA_ENCRYPTION_KEY
32 charactersDerives the AES-GCM key for upstream API keys, SSO secrets, MCP tokens, sensitive settings, and TOTP secrets; keep it stable after release.

Security secret generator

security.jwt_secret

JWT_SECRET

security.data_encryption_key

DATA_ENCRYPTION_KEY

Generated locally in your browser. Keys are not collected, stored, or sent anywhere.

  • ssrf_protection_enabled defaults to false; enable it for public deployments only after reviewing upstream, MCP, file-processing, and internal-network access requirements.
  • If secrets are injected through Kubernetes, Cloudflare, Docker Secret, or platform environment variables, the same length requirements still apply.
  • Plan data migration or re-encryption before changing data_encryption_key; existing ciphertext cannot be decrypted with a different value.

config.yaml

Data, Cache, and Storage#

Long-running multi-user deployments should use PostgreSQL + Redis. SQLite + memory cache is suitable for lightweight single-node installs and demos, but not for multi-instance, high-concurrency, or operationally strict production environments.

config.yaml

ModuleRecommended production settingNotes
DatabasePostgreSQLUsers, sessions, models, billing, audit logs, file indexes, and system settings
CacheRedisRequired for multi-instance deployments; memory cache is only for one process
StorageS3-compatibleRecommended for multi-instance or long-running production
SQLite/app/data/deeix.dbLightweight deployment only, with a persistent volume
Local storage/app/storageStores uploaded and generated files; must be backed up

GeoIP and Tracing#

GeoIP and OpenTelemetry do not block basic startup, but they affect audit context, tracing, and incident investigation.

  • Prefer MMDB for stable audit enrichment instead of relying on external HTTP lookup.
  • Enable tracing only after an OTLP Collector, sampling rate, and log-correlation plan exist.
  • Avoid full tracing without a sampling strategy.

config.yaml

Docker Compose#

Compose defines runtime topology: image, ports, volumes, network, config mount, and deployment-level environment variables. It describes how containers run, not how product policy is managed. Models, routes, pricing, and file policy should remain in the admin console.

app Container Contract#

All Compose files are built around the app service.

  • It binds to localhost by default; public traffic should normally go through a reverse proxy.
  • config.yaml is mounted read-only to avoid container-side drift.
  • app_storage and app_data must be persistent.
  • Optional file-processing services join the same deeix-chat-network.

docker-compose.yml

Full Deployment Overrides#

docker-compose.full.yml starts PostgreSQL and Redis, then injects environment variables that override connection settings. This is intentional: it ensures the app container connects to the internal Compose services.

docker-compose.full.yml

For production full deployments, replace at least the PostgreSQL password, Redis password, jwt_secret, and data_encryption_key.

Environment Overrides and Release Checks#

Environment variables are useful for container platforms, CI/CD, and secret managers. A practical rule: inject secrets through environment variables, keep stable structural settings in config.yaml, and keep runtime business settings in the admin console. Avoid maintaining the same value in multiple places; if an override is necessary, record where it comes from.

Common Override Variables#

AreaCommon variablesConfig fields
Config fileCONFIG_FILEConfig file path
ServiceAPP_ENV, HTTP_PORT, PUBLIC_API_BASE_URL, PUBLIC_WEB_BASE_URL, CORS_ALLOW_ORIGINapp.*, server.*
SecurityJWT_SECRET, DATA_ENCRYPTION_KEY, SSRF_PROTECTION_ENABLEDsecurity.*
DatabaseDATABASE_DRIVER, POSTGRES_DSN, SQLITE_PATHdatabase.*
CacheCACHE_DRIVER, REDIS_ADDR, REDIS_PASSWORD, REDIS_DBcache.*, database.redis.*
StorageSTORAGE_BACKEND, STORAGE_ROOT_DIR, STORAGE_S3_BUCKET, STORAGE_S3_SECRET_ACCESS_KEYstorage.*
ObservabilityOTEL_ENABLED, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_TRACES_SAMPLER_ARGobservability.tracing.*

Production Checklist#

  • app.env is prod or production.
  • jwt_secret and data_encryption_key are strong random values and stored in secret management.
  • public_api_base_url and public_web_base_url are HTTPS public URLs.
  • cors_allow_origin uses exact frontend origins and no wildcard.
  • trusted_proxies contains only real reverse proxy CIDRs.
  • Production database uses PostgreSQL, and production cache uses Redis.
  • /app/data and /app/storage are mounted to reliable persistent volumes with backups.
  • Multi-instance deployment uses S3-compatible storage instead of per-instance local storage.
  • Default PostgreSQL and Redis passwords in Compose have been replaced.
  • OpenTelemetry is enabled only after the collector, sampling rate, and log-correlation plan are clear.