Configuration

Ragz configuration is split across two layers that get set in different places, by different people, at different times:

  1. Bootstrap environment variables (RAGZ_*) — read once at process start, from .env / your Compose file / your orchestrator's secret store. These are the things a deployment needs before the app can even connect to its own database: connection strings, the encryption root key, the first superadmin's credentials, upload limits.
  2. Superadmin app-settings — configured live, after the app is running, from the Admin → Settings page in the web UI. These are the things an operator tunes and re-tunes over the life of the install: which document parser to use, which reranker, which web-search provider, whether generative UI is on. They're stored in Postgres (the app_settings table) and take effect immediately — no restart, no redeploy.

Secrets never live in .env

Beyond the database connection string and the KEK source, no secret ever belongs in .env. LLM provider keys, the Cohere/Tavily/LlamaParse API keys, SMTP credentials — all of it is entered once through the admin API, envelope-encrypted with AES-256-GCM, and stored in Postgres. Fields that hold secrets are write-only: the API will tell you a key is configured (*_key_set: true) but will never hand the value back, in a response, a log line, or a trace.

Where each concern is configured

ConcernLayerWhere
Database / Redis / Qdrant / MinIO connectionBootstrap env var.env, RAGZ_DATABASE_URL etc.
Encryption root key (KEK)Bootstrap env varRAGZ_KEK_FILE
First superadmin accountBootstrap env var (one-time)RAGZ_BOOTSTRAP_EMAIL / RAGZ_BOOTSTRAP_PASSWORD, python -m ragz.bootstrap
LiteLLM proxy admin credentialBootstrap env varRAGZ_LITELLM_MASTER_KEY + LITELLM_MASTER_KEY/LITELLM_SALT_KEY
Upload size limitsBootstrap env varRAGZ_MAX_UPLOAD_MB, RAGZ_INTERACTIVE_UPLOAD_MB
OCR kill-switchBootstrap env varRAGZ_OCR_ENABLED
Trusted reverse-proxy CIDRsBootstrap env varRAGZ_TRUSTED_PROXIES
LLM provider connections (OpenAI, Anthropic, Ollama, ...)App-setting + secretAdmin → Models
Document parser (liteparse / anydoc / docling / llamaparse)App-settingAdmin → Settings
Reranker (local TEI / Cohere)App-setting + secretAdmin → Settings
Web search provider (DuckDuckGo / Tavily)App-setting + secretAdmin → Settings
Generative UI on/off, web-result imagesApp-settingAdmin → Settings
Default chunking methodApp-settingAdmin → Settings
Email delivery (SMTP / SES)App-setting + secretAdmin → Settings

The rest of this section works through each row in detail: the full environment variable reference, then models and providers, parsers and OCR, web search, and generative UI.

Why the split

Bootstrap env vars answer "how does this process find its own database and unlock its own secrets" — questions that have to be answered before a single line of application code runs, so they can't live in the database they describe. Everything else — which model to call, which parser to run, which search provider to hit — is a decision an operator revisits after the platform is live, often per environment or as new providers become available. Putting those behind a live admin UI means changing them is an audited API call, not a redeploy.

Per-workspace vs. global

Most Admin → Settings values (parser, reranker, web search, generative UI) are install-wide — one choice for the whole Ragz instance. Model selection (which model a workspace uses to generate and embed) is set per workspace under Admin → Models, layered on top of the provider connections configured globally.