Skip to Content
Deploy & Operate⚙️ App Configuration

App Configuration

DocsGPT is highly configurable, allowing you to tailor it to your specific needs and preferences. You can control various aspects of the application, from choosing the Large Language Model (LLM) provider to selecting embedding models and vector stores.

This document will guide you through the basic settings you can configure in DocsGPT. These settings determine how DocsGPT interacts with LLMs and processes your data.

Configuration Methods

There are two primary ways to configure DocsGPT settings:

The easiest and recommended way to configure basic settings is by using a .env file. Where that file lives depends on how you installed DocsGPT:

Install.env locationHow to change a setting
Installer, docsgpt up (Docker or --native)~/.docsgpt/server/.env (/opt/docsgpt/.env when installed as root on Linux)docsgpt env set KEY=VALUE, then docsgpt up to apply (a running --native install restarts by itself). docsgpt env prints the file’s path and docsgpt env get KEY one value.
pip install (docsgpt api / docsgpt worker)~/.docsgpt/server/.env, whatever directory you run the commands fromEdit the file, then restart docsgpt api and docsgpt worker.
Source checkout (setup.sh, checkout Compose files, development).env in the repository root, next to setup.shEdit the file, then restart the services. Compose commands need --env-file .env; see Docker Deployment.
KubernetesNo file: the docsgpt-secrets Secret and the Deployment envEdit deployment/k8s/docsgpt-secrets.yaml and re-apply; see Kubernetes.

DocsGPT resolves the file in this order:

  1. DOCSGPT_ENV_FILE, when set, names the .env file directly.
  2. Otherwise it reads <DOCSGPT_HOME>/.env. The data home DOCSGPT_HOME is also where inputs/, indexes/ and downloaded models live. When DOCSGPT_HOME is unset, the data home is the source checkout the code runs from, else ~/.docsgpt/server (/opt/docsgpt for root on Linux).

DOCSGPT_HOME and DOCSGPT_ENV_FILE must be set in the process environment (your shell, the service unit), not in .env, because they decide which .env is read. The Docker image sets DOCSGPT_HOME=/app; containers get their settings from Compose’s env_file, not from a file inside the image. docsgpt api, docsgpt worker and docsgpt migrate print the data home and env file they use when they start. Process environment variables override .env.

Example .env file structure:

LLM_PROVIDER=openai API_KEY=YOUR_OPENAI_API_KEY LLM_NAME=gpt-5.5

2. Configuration in code (Advanced)

Every setting is defined in the docsgpt/core/settings/ package, one module per domain (auth.py, llm.py, embeddings.py, …). If you prefer to manage defaults directly in code, change them there; the .env file and the process environment still override whatever the code says.

Using the .env file is recommended for day-to-day configuration. Reserve code changes for new settings or for defaults you want every deployment of your fork to share.

The Settings Reference lists every setting with its type, default and description, generated from those definitions.

Basic Settings Explained

Here are some of the most fundamental settings you’ll likely want to configure:

  • LLM_PROVIDER: This setting determines which Large Language Model (LLM) provider DocsGPT will use. It tells DocsGPT which API to interact with.

    • Common values:
      • docsgpt: Use the DocsGPT Public API Endpoint (simple and free, as offered in setup.sh option 1).
      • openai: Use OpenAI’s API (requires an API key).
      • google: Use Google Gemini models with an AI Studio API key (Vertex AI is not supported).
      • anthropic: Use Anthropic’s Claude models.
      • groq: Use Groq’s models.
      • openrouter, novita: Use OpenRouter or Novita.
      • openai (when using local inference engines like Ollama, Llama.cpp, TGI, etc.): This signals DocsGPT to use an OpenAI-compatible API format, even if the actual LLM is running locally.
  • LLM_NAME: The default model. For a cloud provider it must be a model id from the model catalog  or from a custom model YAML; any other name is ignored, with a warning in the log, and the provider’s first model is used. With OPENAI_BASE_URL it is required and names the model(s) your server serves, comma-separated. See Default Model Selection.

    • Examples:
      • For LLM_PROVIDER=openai: gpt-5.5
      • For LLM_PROVIDER=google: gemini-3.5-flash
      • For local models (e.g., Ollama): llama3.2:1b (or any model name available in your setup).
  • EMBEDDINGS_NAME: This setting defines which embedding model DocsGPT will use to generate vector embeddings for your documents. Embeddings are numerical representations of text that allow DocsGPT to understand the semantic meaning of your documents for efficient search and retrieval.

    • Default value: leave it unset and DocsGPT picks for you at first boot, recording the choice so it never changes underneath you: a fresh install is pinned to ibm-granite/granite-embedding-311m-multilingual-r2 (multilingual, 32k context, same 768 dimensions), and an install that already has sources is pinned to huggingface_sentence-transformers/all-mpnet-base-v2 so its index stays readable. Setting it here overrides that pin.
    • Other options: Any FastEmbed built-in model, or any Hugging Face repository shipping an ONNX export. See Embeddings.
    • Changing it on an existing index requires re-embedding — same-width models swap without any error and silently degrade retrieval. Run python -m docsgpt.scripts.reembed.
  • API_KEY: Required for most cloud-based LLM providers. This is your authentication key for the provider named in LLM_PROVIDER. Each provider also has its own variable (OPENAI_API_KEY, ANTHROPIC_API_KEY, …); see Provider API keys.

  • OPENAI_BASE_URL: Specifically used when LLM_PROVIDER is set to openai but you are connecting to a local inference engine (like Ollama, Llama.cpp, etc.) that exposes an OpenAI-compatible API. This setting tells DocsGPT where to find your local LLM server.

  • STT_PROVIDER: Selects the speech-to-text provider used for microphone transcription in chat and for audio file ingestion through the parser pipeline. Set it to none to switch speech-to-text off: the microphone button is hidden, and audio files fail to ingest with a message naming the setting.

  • TTS_PROVIDER: Selects the text-to-speech provider behind the Speak button on answers: google_tts (default) or elevenlabs. Both are hosted services. Set it to none to switch text-to-speech off and hide the button. With elevenlabs, set ELEVENLABS_API_KEY; ELEVENLABS_VOICE_ID picks the voice (an ID from your ElevenLabs voice library). When an auth mode is on, only signed-in users (or requests with an agent API key) can use it. TTS_MAX_CHARS (default 10000) caps how much text one request may speak, counted after markdown is stripped.

  • SERVE_UI: Whether the API process serves the web UI shipped in the Python package (pip install docsgpt). Defaults to true; the backend Docker image ships the same build, so it serves the UI on port 7091 too. Set false when a separate frontend, such as the arc53/docsgpt-fe image in docker-compose-hub.yaml or the frontend that docker-compose.yaml builds, serves the UI.

  • API_URL: The address of the API, default http://localhost:7091. The worker calls the API at it to hand over finished indexes, and the API builds the agent image, agent webhook, device pairing and MCP OAuth callback links it gives to browsers and other clients from it. With Docker Compose the two need different values: the Compose files set the worker’s to http://backend:7091, which takes precedence over .env, so .env sets the backend’s. When other machines open DocsGPT, set it to the address they use (http://<server-address>:7091, or the public https:// address behind a proxy). docsgpt up and the setup scripts write it when DocsGPT is exposed; see Docker and Kubernetes.

  • WORKER_API_URL: The address the worker uses for its own calls into the API; unset, it falls back to API_URL. Set it when the API and the worker read one .env (a pip install, docsgpt up --native) and API_URL is a public address, so the worker’s calls stay on the machine: WORKER_API_URL=http://127.0.0.1:7091. docsgpt up --native sets it. The Kubernetes manifests set WORKER_API_URL=http://docsgpt-api-service for internal index handoff while both app containers inherit the public API_URL from the shared Secret for browser-facing links and OAuth callbacks. Docker Compose gives the worker its own API_URL instead, so leave WORKER_API_URL unset there.

Configuration Examples

Let’s look at some concrete examples of how to configure these settings in your .env file.

Example for Cloud API Provider (OpenAI)

To use OpenAI’s gpt-5.5 model, you would configure your .env file like this:

LLM_PROVIDER=openai API_KEY=YOUR_OPENAI_API_KEY # Replace with your actual OpenAI API key LLM_NAME=gpt-5.5

Make sure to replace YOUR_OPENAI_API_KEY with your actual OpenAI API key.

Example for Local Deployment

To use a local Ollama server with the llama3.2:1b model, you would configure your .env file like this:

LLM_PROVIDER=openai # Using OpenAI compatible API format for local models API_KEY=None # API Key is not needed for local Ollama LLM_NAME=llama3.2:1b OPENAI_BASE_URL=http://host.docker.internal:11434/v1 # Default Ollama API URL within Docker EMBEDDINGS_NAME=ibm-granite/granite-embedding-311m-multilingual-r2 # runs locally; see Models/embeddings for alternatives

In this case, even though you are using Ollama locally, LLM_PROVIDER is set to openai because Ollama (and many other local inference engines) are designed to be API-compatible with OpenAI. OPENAI_BASE_URL points DocsGPT to the local Ollama server.

Adding Custom Models (MODELS_CONFIG_DIR)

DocsGPT ships with a built-in catalog of models for the providers it supports out of the box (OpenAI, Anthropic, Google, Groq, OpenRouter, Novita, DeepSeek, Alibaba Qwen, Z.ai, DocsGPT). To add your own models without forking the repo — for example, a Mistral or Together account, a self-hosted vLLM endpoint, or any other OpenAI-compatible API — point MODELS_CONFIG_DIR at a directory of YAML files.

MODELS_CONFIG_DIR=/etc/docsgpt/models MISTRAL_API_KEY=sk-...

A minimal YAML for one provider:

# /etc/docsgpt/models/mistral.yaml provider: openai_compatible display_provider: mistral api_key_env: MISTRAL_API_KEY base_url: https://api.mistral.ai/v1 defaults: supports_tools: true context_window: 128000 models: - id: mistral-large-latest display_name: Mistral Large - id: mistral-small-latest display_name: Mistral Small

After restart, those models appear in /api/models and are selectable in the UI. A working template lives at docsgpt/core/models/examples/mistral.yaml.example.

What you can do:

  • Add new openai_compatible providers (Mistral, Together, Fireworks, Ollama, vLLM, …) — one YAML per provider, each with its own api_key_env and base_url.
  • Extend an existing provider’s catalog by dropping a YAML with the same provider: value as the built-in (e.g. provider: anthropic with extra models).
  • Override a built-in model’s capabilities by re-declaring the same id — later wins, override is logged at WARNING.

What you cannot do via MODELS_CONFIG_DIR: add a brand-new non-OpenAI provider. That requires a Python plugin under docsgpt/llm/providers/. See docsgpt/core/models/README.md for the full schema reference.

Docker

Mount the directory and set the env var:

# docker-compose.yml services: app: image: arc53/docsgpt environment: MODELS_CONFIG_DIR: /etc/docsgpt/models MISTRAL_API_KEY: ${MISTRAL_API_KEY} volumes: - ./my-models:/etc/docsgpt/models:ro

Misconfiguration

If MODELS_CONFIG_DIR is set but the path doesn’t exist (or isn’t a directory), the app logs a WARNING at boot and continues with just the built-in catalog — it does not fail to start. If a YAML declares an unknown provider name or has a schema error, the app does fail to start, with the offending file path in the message.

Document Upload Limits

DocsGPT bounds public document and attachment uploads before storage or parsing. ZIP limits are cumulative across nested archives. Unsafe archive paths, duplicate file entries, encrypted members, symlinks, and other special files are rejected. Repeated directory records are ignored, and case-colliding names are disambiguated without overwriting either file. Nested archives expand into a directory named after the archive; files that merely end in .zip remain ordinary files.

SettingDefaultDescription
UPLOAD_MAX_REQUEST_BYTES268435456Maximum request body for a public file-upload route, including multipart overhead.
UPLOAD_MAX_FILE_BYTES104857600Maximum encoded size of one uploaded file or one extracted ZIP member.
PARSE_SPEC_MAX_BYTES10485760Maximum UTF-8 size of an uploaded or JSON API specification.
UPLOAD_MAX_ARCHIVE_BYTES262144000Maximum total uncompressed bytes across all ZIP layers in one extraction.
UPLOAD_MAX_ARCHIVE_FILES10000Maximum total extracted files across all nested layers; directory records do not count.
UPLOAD_MAX_ARCHIVE_RATIO1000Maximum uncompressed-to-compressed expansion ratio for each archive layer.
UPLOAD_MAX_ARCHIVE_DEPTH3Maximum number of nested ZIP layers expanded after the outer archive.

These byte/count limits and the non-negative nesting depth can be overridden in .env. The request limit intentionally applies only to public upload routes; internal worker index transfers use their own trusted service boundary.

Document Parsing

Uploaded sources and chat attachments are converted to Markdown before chunking or prompting. See the Document Parsing and OCR guide for the engines and flows.

SettingDefaultDescription
DOC_PARSER_ENGINEanydocParser engine: anydoc (fast Rust converter, no ML models) or docling (layout/table models, structured output). Files anydoc cannot read fall back to Docling when installed. Docling is an optional extra: pip install -r docsgpt/requirements-docling.txt, or Docker builds with --build-arg INSTALL_DOCLING=true.
OCR_ENABLEDfalseOCR for source ingestion. Alias: DOCLING_OCR_ENABLED.
OCR_ATTACHMENTS_ENABLEDfalseOCR for chat attachments. Alias: DOCLING_OCR_ATTACHMENTS_ENABLED.
OCR_BACKENDautoWho performs OCR: auto (Docling when installed, else native), native (pypdfium2 + Pillow rendering into tesseract or DeepSeek-OCR; no docling needed), or docling (layout-model hybrid OCR). See the OCR guide.
ATTACHMENT_PDF_TEXT_FAST_PATHtrueUnder the docling engine, read PDF attachments through their text layer (pypdfium2) and only hand scans to Docling. Not needed under anydoc.
DOCLING_TABULAR_MAX_BYTES2000000Docling engine: CSV/XLSX larger than this (by content) use the lightweight tabular parsers.
DOCLING_MARKUP_MAX_BYTES8000000Docling engine: HTML/VTT larger than this are head-truncated before parsing.
MARKUP_MAX_BYTES8000000anydoc engine: HTML/XHTML larger than this are head-truncated before the markdownify parser runs (its tree costs ~50x the input). 0 disables the gate.
PDF_TRUST_CHECKtrueTrust-check anydoc’s PDF output for the two silent-loss classes (Type0 fonts without ToUnicode, CJK-declaring PDFs with CJK-less text). Flagged files re-parse on Docling when installed, else carry parse_warnings metadata.
ANYDOC_TABLEIZEfalseRewrite dot-leader / whitespace-aligned table runs in anydoc’s PDF markdown into GFM tables.
OCR_ENGINEtesseractOCR engine when OCR is on: tesseract (recommended, both backends; optional system package — build with INSTALL_TESSERACT=true or apt/brew install it), deepseek (DeepSeek-OCR on a local or hosted endpoint; always the native backend), or the Docling-only auto, ocrmac, rapidocr. Unavailable engines degrade with a warning. See the OCR guide.
OCR_LANGSengTesseract language packs, +-separated (e.g. eng+chi_sim+deu).
OCR_DEEPSEEK_PROVIDERollamaWhere DeepSeek-OCR runs: ollama, vllm, novita, deepinfra or custom. Each preset supplies the URL, model and concurrency. See DeepSeek-OCR.
OCR_DEEPSEEK_URLpresetChat-completions URL; overrides the preset’s.
OCR_DEEPSEEK_MODELpresetModel name at that endpoint; overrides the preset’s.
OCR_DEEPSEEK_API_KEYunsetBearer token. Required by novita (falls back to NOVITA_API_KEY) and deepinfra.
OCR_DEEPSEEK_CONCURRENCYpresetPage requests in flight per file: 4 for vllm, novita, deepinfra; 1 for ollama, custom.
OCR_DEEPSEEK_MAX_RETRIES3Retries per page after a 429, 5xx or refused connection, with backoff honouring Retry-After.
OCR_DEEPSEEK_TIMEOUT300Seconds allowed per page request.
OCR_DEEPSEEK_PROMPTFree OCR.Instruction sent with each page.
OCR_RENDER_DPI200Native backend: resolution at which pages without a text layer are rendered before OCR (clamped to 72-600).
OCR_MIN_CHARS_PER_PAGE20Chars-per-page floor for the OCR dropout guard: a multi-page parse whose OCR returns nothing fails loudly instead of indexing an empty document (docling retries once on full-page OCR first); output below the floor but non-empty is indexed with a warning. 0 disables. Alias: DOCLING_OCR_MIN_CHARS_PER_PAGE.

Speech-to-Text Settings

DocsGPT can transcribe audio in two places:

  • Voice input in the chat.
  • Audio file ingestion. Uploaded .wav, .mp3, .m4a, .ogg, and .webm files are transcribed first and then passed through the normal parser, chunking, embedding, and indexing pipeline.

The settings below control speech-to-text behaviour for both voice input and audio file ingestion.

SettingPurposeTypical values
STT_PROVIDERSpeech-to-text backend provider, or none to switch speech-to-text off.openai, faster_whisper, none
OPENAI_STT_MODELOpenAI transcription model used when STT_PROVIDER=openai.gpt-4o-mini-transcribe
STT_LANGUAGEOptional language hint passed to the provider. Leave unset for auto-detection when supported.en, es, unset
STT_MAX_FILE_SIZE_MBMaximum file size accepted by the synchronous /api/stt endpoint.50
STT_ENABLE_TIMESTAMPSInclude timestamp segments in the normalized transcript response and stored parser metadata.true, false
STT_ENABLE_DIARIZATIONReserved provider option for speaker diarization. Some providers may ignore it.true, false

Example: OpenAI Speech-to-Text

STT_PROVIDER=openai OPENAI_API_KEY=YOUR_OPENAI_API_KEY OPENAI_STT_MODEL=gpt-4o-mini-transcribe STT_LANGUAGE= STT_MAX_FILE_SIZE_MB=50 STT_ENABLE_TIMESTAMPS=false STT_ENABLE_DIARIZATION=false

If you already use API_KEY for OpenAI, DocsGPT can reuse that key for transcription. Set OPENAI_API_KEY only when you want a dedicated key.

Example: Local faster_whisper

STT_PROVIDER=faster_whisper STT_LANGUAGE=en STT_ENABLE_TIMESTAMPS=true STT_ENABLE_DIARIZATION=false

faster_whisper is an optional backend dependency. Install it in the Python environment used by the DocsGPT API and worker before selecting this provider.

Agent Image Settings

Agent avatars uploaded to DocsGPT must be valid PNG, JPEG, GIF, or WebP files. The decoded image and its file extension must agree; SVG and other formats are rejected. These limits apply before the image is written to local or S3 storage.

SettingDefaultDescription
AGENT_IMAGE_MAX_BYTES5000000Maximum encoded avatar file size in bytes.
AGENT_IMAGE_MAX_PIXELS16777216Maximum decoded width × height, limiting decompression-bomb images.

Secrets to set before going live

Three secrets protect a DocsGPT install. setup.sh, setup.ps1 and docsgpt up generate them on a fresh install and keep them when run again; set them yourself when you write .env by hand, and keep them out of version control. Generate each with openssl rand -hex 32.

The database password is separate: docsgpt up generates POSTGRES_PASSWORD, and the standalone Compose file reads it from .env, but the checkout Compose files (and so the setup scripts) use the fixed password docsgpt, which is why they publish Postgres on 127.0.0.1 only.

SettingWhat it protectsIf it is missing
INTERNAL_KEYThe worker hands finished indexes and files to the API with it. Required, with the same value on the API and the worker.The API rejects the worker’s uploads, so every ingest fails after parsing.
JWT_SECRET_KEYSigns login tokens in every AUTH_TYPE, and agent-avatar URLs in every mode. Same value on every API and worker process.With DEPLOYMENT_TYPE=production (or cloud), startup fails. Otherwise the API generates .jwt_secret_key in the data home, which suits one local process only: separate containers each generate their own key, and a recreated container gets a new one, which signs everyone out and, under session_jwt, loses sight of their data.
ENCRYPTION_SECRET_KEYSeals stored credentials: connector tokens, MCP credentials, tool secrets and custom-model API keys.It falls back to a public default, and DocsGPT logs a warning at startup. With any AUTH_TYPE set, it refuses to create connections on the Connectors page (OAuth sign-ins and connector keys); tool secrets, MCP server credentials and custom-model keys are still stored, sealed with the public key.
INTERNAL_KEY=<openssl rand -hex 32> JWT_SECRET_KEY=<openssl rand -hex 32> ENCRYPTION_SECRET_KEY=<openssl rand -hex 32> # Optional: fail at startup instead of generating a local JWT key DEPLOYMENT_TYPE=production
⚠️

Set ENCRYPTION_SECRET_KEY before anyone connects a service, and never just replace it: stored credentials are sealed with the key they were saved under. The installers never overwrite an existing value. docsgpt up on Docker adds one only to a fresh install. The setup scripts add one when there is no .env yet, and docsgpt up --native adds one on its first run; both also set ENCRYPTION_SECRET_KEY_PREVIOUS to the public default, since a kept Docker volume or the database it points at may already hold credentials sealed with it. Reseal them with docsgpt connectors reencrypt, then remove ENCRYPTION_SECRET_KEY_PREVIOUS.

To change ENCRYPTION_SECRET_KEY on an install that already stores credentials (including one that ran on the public default, default-docsgpt-encryption-key):

  1. Move the current value to ENCRYPTION_SECRET_KEY_PREVIOUS and put the new one in ENCRYPTION_SECRET_KEY, on the API and the worker.
  2. Restart them, then run docsgpt connectors reencrypt with the same settings. It rewrites every connection, every secret saved on a tool (API Tool secrets, MCP credentials kept on the tool) and every custom-model API key with the new key. Connections neither key opens are marked Reconnect needed; tool and custom-model secrets neither key opens are left unchanged and counted. Running it again changes nothing. In Docker, run it in the backend container of your Compose file:
    • docsgpt up: docker compose -f ~/.docsgpt/server/docker-compose.yaml exec backend python -m docsgpt connectors reencrypt (or the stack directory you chose)
    • standalone file: docker compose -f docker-compose-standalone.yaml exec backend python -m docsgpt connectors reencrypt
    • checkout: docker compose --env-file .env -f deployment/docker-compose-hub.yaml exec backend python -m docsgpt connectors reencrypt (or deployment/docker-compose.yaml)
    • Kubernetes: kubectl exec deploy/docsgpt-worker -- python -m docsgpt connectors reencrypt
  3. Remove ENCRYPTION_SECRET_KEY_PREVIOUS once the command reports nothing unreadable (it says so on its last line).

While the previous key is set, DocsGPT reads every stored credential with either key, so the install keeps working between steps 1 and 2. See Connectors: Encryption key.

Authentication Settings

AUTH_TYPE decides who can use a DocsGPT instance and whether users are told apart. Only oidc gives each person their own account behind a real sign-in; choose it for any install that more than one person uses or that is reachable from the internet. See the security checklist before exposing an install.

AUTH_TYPE Overview

ValueWho gets inUsers told apartAdmin, quotas and personal access tokens
unset (default)Anyone who can reach the instance.No: every visitor is the one user local and shares its conversations, sources, agents and connected services.Personal access tokens, for the one user. Admin and quotas only with LOCAL_MODE_ADMIN=true, for a single-user local install.
simple_jwtAnyone holding the one shared access token.No: the token always means the user local. It is a shared password, not user accounts.None.
session_jwtAnyone who can reach the instance: the page asks /api/generate_token for a token, and the endpoint gives one to every caller.Per browser: each token gets its own random user id, so browsers do not see each other’s data. This separates sessions; it does not control access.None.
oidcPeople your identity provider (Authentik, Keycloak, Okta, …) signs in, optionally limited to groups.Yes, one account per person.All of them. See SSO with OIDC.

simple_jwt and session_jwt tokens never expire and cannot be revoked one by one; changing JWT_SECRET_KEY invalidates all of them (and, under session_jwt, orphans every browser’s data). Teams work in every mode, but only mean something when users are told apart.

How to Configure

Add the following to your .env file:

# Signing key: set it whenever more than one process or container runs JWT_SECRET_KEY=<long-random-value> # No authentication (default): leave AUTH_TYPE unset # OR: one shared access token for everyone AUTH_TYPE=simple_jwt # OR: a separate anonymous identity per browser (no access control) AUTH_TYPE=session_jwt # OR: SSO via an OpenID Connect provider (Authentik, Keycloak, Okta, ...) AUTH_TYPE=oidc OIDC_ISSUER=https://auth.example.com/application/o/docsgpt/ OIDC_CLIENT_ID=your_client_id OIDC_FRONTEND_URL=https://docsgpt.example.com
  • JWT_SECRET_KEY signs authentication tokens where applicable and opaque agent-avatar capabilities in every authentication mode, including no-auth mode.
  • Deployments with more than one API or worker process, container or replica must set a strong JWT_SECRET_KEY, the same on each. With DEPLOYMENT_TYPE=production (or cloud), startup fails rather than creating a key of its own when it is missing.
  • A single local process may omit it. DocsGPT then atomically generates an owner-readable .jwt_secret_key in the data home (DOCSGPT_HOME, the checkout, or ~/.docsgpt/server) and reuses it on later starts. A key an older version wrote to the working directory is copied there (an empty one is ignored), so tokens it signed stay valid. The API and the worker each resolve the key when they start; start the process that holds the old file first, or one started elsewhere generates a new key before the old one is copied.

How Each Method Works

  • None: No authentication. All API and UI access is open, and everyone is the same user.
  • simple_jwt:
    • The token is {"sub": "local"} signed with JWT_SECRET_KEY, so it stays the same until you change the key. The API prints it at startup (Generated Simple JWT Token: ... in the backend log), and docsgpt token prints it for a docsgpt up install.
    • Use this token in the Authorization header for all API requests:
      Authorization: Bearer <SIMPLE_JWT_TOKEN>
    • The frontend will prompt for this token if not already set.
  • session_jwt:
    • The frontend requests a token from /api/generate_token on its first visit. The endpoint needs no credentials, so anyone who can reach it gets a token.
    • Use the received token in the Authorization header for subsequent requests.
    • Each token carries a new random user id; clearing the browser’s storage starts a new, empty identity.
  • oidc:
    • The frontend redirects users to your identity provider to sign in (OAuth2 Authorization Code + PKCE).
    • After a successful sign-in, DocsGPT issues its own session JWT; API requests carry it in the Authorization header like the other modes.
    • Stable per-user identities come from the provider — see the full setup guide: SSO with OIDC.
    • The same guide covers the optional access controls: group allowlists, silent session renewal, back-channel logout, SCIM provisioning, and login auditing.

Security Notes

  • Always keep your JWT_SECRET_KEY secure and private.
  • If you set it manually, use a strong, random string.
  • Keep the value stable. Rotating it invalidates active JWTs and previously generated agent-avatar URLs.
  • simple_jwt and session_jwt travel as bearer tokens; outside a trusted network, serve DocsGPT over HTTPS.

Checking Current Auth Type

  • Use the /api/config endpoint to check the current auth_type and whether authentication is required.

Frontend Token Input for simple_jwt

If you have configured AUTH_TYPE=simple_jwt, the DocsGPT frontend will prompt you to enter the JWT token if it’s not already set or is invalid. Paste the SIMPLE_JWT_TOKEN (printed to the backend log when it starts, or by docsgpt token) into this field to access the application.

Frontend prompt for JWT Token

S3 Storage Backend

By default DocsGPT stores files locally. Set STORAGE_TYPE=s3 to use Amazon S3 — or any S3-compatible service (MinIO, Cloudflare R2, Backblaze B2, DigitalOcean Spaces, …) — instead.

SettingDescriptionDefault
STORAGE_TYPElocal or s3local
S3_BUCKET_NAMEBucket namedocsgpt-test-bucket
S3_ACCESS_KEY_IDAccess key ID—
S3_SECRET_ACCESS_KEYSecret access key—
S3_REGIONRegion (use auto for Cloudflare R2)—
S3_ENDPOINT_URLCustom endpoint for S3-compatible services; leave unset for AWS S3—
S3_PATH_STYLEUse path-style addressing (required by most non-AWS services)false
URL_STRATEGYArtifact-download delivery: backend proxies bytes through the API; s3 returns short-lived presigned object URLs. Agent avatars always use capability URLs and, with S3 storage, redirect to a size-checked presigned URL.backend

AWS S3

STORAGE_TYPE=s3 S3_BUCKET_NAME=your-bucket-name S3_ACCESS_KEY_ID=your-access-key-id S3_SECRET_ACCESS_KEY=your-secret-access-key S3_REGION=us-east-1

S3-compatible services (MinIO, Cloudflare R2, …)

Set S3_ENDPOINT_URL and usually S3_PATH_STYLE=true:

STORAGE_TYPE=s3 S3_BUCKET_NAME=your-bucket-name S3_ACCESS_KEY_ID=your-access-key-id S3_SECRET_ACCESS_KEY=your-secret-access-key S3_REGION=auto S3_ENDPOINT_URL=https://<account>.r2.cloudflarestorage.com S3_PATH_STYLE=true

Your credentials need these permissions on the bucket: s3:PutObject, s3:GetObject, s3:DeleteObject, s3:ListBucket, s3:HeadObject.

Deprecated: earlier versions reused the SAGEMAKER_ACCESS_KEY, SAGEMAKER_SECRET_KEY, and SAGEMAKER_REGION variables for S3 credentials. These are still honored as a fallback (with a deprecation warning) but you should migrate to the S3_* variables above.

User-Data Storage (Postgres)

DocsGPT stores user data — conversations, agents, prompts, sources, attachments, workflows, logs, and token usage — in PostgreSQL. The backend connects via a single setting:

SettingDescriptionDefault
POSTGRES_URISQLAlchemy-compatible Postgres URI. Any standard postgresql:// form works — DocsGPT normalizes it internally to the psycopg v3 dialect.—
AUTO_CREATE_DBOn startup, connect to the server’s postgres maintenance DB and issue CREATE DATABASE if the target is missing. Requires CREATEDB or superuser. No-op when the database already exists. Disable in production.true
AUTO_MIGRATEOn startup, run alembic upgrade head against the target database. Idempotent and serialized across workers via alembic_version. Disable in production in favor of an explicit migration step.true
AUTO_VECTOR_SCHEMAOn startup, with VECTOR_STORE=pgvector, create the vector documents table (and the GraphRAG tables) and check its embedding width. No Alembic migration covers the vector database. Disable it too when the runtime role must not run DDL.true

Example:

POSTGRES_URI=postgresql://docsgpt:docsgpt@localhost:5432/docsgpt # Append ?sslmode=require for managed providers that enforce SSL.

With the defaults, the app applies the schema automatically on first boot. To run it explicitly instead (e.g., in CI/CD or a k8s Job):

python -m docsgpt migrate --no-create

--no-create fails instead of creating a missing database. Images up to 0.21.0 have no python -m docsgpt; run python -m docsgpt.cli migrate --no-create there.

The default Docker Compose file bundles a postgres service, and the app auto-bootstraps the database on boot, so containerized deployments need no manual migration step. See PostgreSQL for User Data for the recommended production flow (AUTO_CREATE_DB, AUTO_MIGRATE and AUTO_VECTOR_SCHEMA set to false, migrations gated by CI/CD).

ℹ️

MONGO_URI is opt-in. It is only consulted when you select the MongoDB Atlas vector-store backend (VECTOR_STORE=mongodb) or when running the one-shot scripts/db/backfill.py migration from a legacy Mongo-based install. Installing the optional Mongo client libraries requires pip install 'pymongo>=4.6'. See PostgreSQL for User Data for the migration path.

Retrieval & RAG Settings

These control how sources are retrieved and whether the advanced RAG features are available. See Per-Source Configuration and GraphRAG for details.

SettingDefaultDescription
PER_SOURCE_RETRIEVAL_ENABLEDtrueMaster switch for per-source retrieval config. When false, all sources fall back to the classic retriever regardless of their stored config.
GRAPHRAG_ENABLEDfalseEnable GraphRAG. Requires VECTOR_STORE=pgvector.
GRAPHRAG_EXTRACTION_MODELunsetModel used for ingest-time graph extraction. Unset falls back to LLM_NAME (on its registry provider, else LLM_PROVIDER).
GRAPHRAG_MAX_CHUNKS_FOR_EXTRACTION2000Hard cap on chunks extracted per source (cost control). 0 extracts nothing.
GRAPHRAG_EXTRACTION_WORKERS8Concurrent extraction calls during ingest (1–32). Model calls run in parallel while graph writes stay serial; 1 is fully serial.

Embeddings Settings

See Embeddings for full guidance.

SettingDefaultDescription
EMBEDDINGS_NAMEhuggingface_sentence-transformers/all-mpnet-base-v2The embedding model. New installs use ibm-granite/granite-embedding-311m-multilingual-r2. Changing it on a populated index requires docsgpt.scripts.reembed.
EMBEDDINGS_BASE_URLunsetBase URL of a remote OpenAI-compatible embeddings server. Setting it routes all embedding calls there.
EMBEDDINGS_THREADSunset (Docker image: 4)Threads one local FastEmbed/onnxruntime session may use. onnxruntime otherwise sizes its pool to the host’s core count, which a CPU-limited container still reports, so the image pins it like OMP_NUM_THREADS. Raise it on a large dedicated worker.
EMBEDDINGS_KEYunsetOptional bearer token for the remote embeddings server.
EMBEDDINGS_MAX_INPUT_TOKENSunsetTruncate each remote embedding input to N tokens (guards servers that reject oversized inputs).
EMBEDDINGS_LOCAL_MAX_TOKENSunsetHard ceiling, in tokens, on every input a local FastEmbed model embeds, documents included; the overflow is dropped. Unset keeps the model’s own maximum (32,768 for granite).
EMBEDDINGS_MAX_QUERY_TOKENS512Clip each search query to N tokens before it is embedded, for every embedder; 0 turns it off. Documents are not clipped.
EMBEDDINGS_DELEGATE_TO_WORKERtrueEmbed queries on the Celery worker instead of loading a model in the API. Requires a worker consuming EMBEDDINGS_QUEUE; set false to run the API standalone. Ignored when EMBEDDINGS_BASE_URL is set.
EMBEDDINGS_QUEUEembeddingsQueue the query-embedding task is routed to. A worker started with an explicit -Q must list it.
EMBEDDINGS_DELEGATE_TIMEOUT60Seconds the API waits for the worker’s vector before failing the search.

Tools Settings

SettingDefaultDescription
DEFAULT_CHAT_TOOLS["memory", "read_webpage", "scheduler"]Tools enabled automatically in regular (agentless) chats. See Tools Basics.

Admin & Access Settings

See Access Control, Roles & Teams for the full model.

SettingDefaultDescription
OIDC_ADMIN_GROUPSunsetComma-separated IdP groups granted the global admin role (OIDC only).
LOCAL_MODE_ADMINfalseGrants admin in no-auth mode (AUTH_TYPE=None) only. Never enable on a networked deployment.

LLM Provider Settings

SettingDefaultDescription
OPENAI_RESPONSES_STOREfalseWhen true, allows OpenAI to persist Responses API state server-side.
OPENAI_RESPONSES_CHAIN_ACROSS_TURNStrueIn store mode, chain a new user turn onto the previous turn’s response with previous_response_id. Set to false for stateless turns that always rebuild from the saved history.
OPENAI_RESPONSES_CHAIN_BUDGET_TOKENSunsetStop chaining across turns once the previous turn’s reported prompt reached this many tokens; the turn then starts from the saved (compressible) history. Unset means the model’s context_window.
OPENAI_RESPONSES_TRUNCATION_AUTOfalseSend truncation: "auto" on Responses API calls so the provider drops the oldest conversation items instead of rejecting a request that exceeds the model’s window.
OPENAI_PROMPT_CACHE_KEYtrueSend an opaque per-user prompt_cache_key (a hash, never the user id itself) on Responses API calls so a user’s requests route to the same prompt-cache shard.
OPENAI_PROMPT_CACHE_RETENTIONunsetValue for prompt_cache_retention on Responses API calls, for example 24h, where the provider offers extended prompt-cache retention.
V1_SESSION_TTL_SECONDS86400Redis correlation lifetime, in seconds, for OpenAI-compatible client sessions. Raw external session IDs are hashed and never stored.
TITLE_MODEL_IDunsetOptional model ID used for asynchronous first-party conversation titles. When unset, the answer model is used. Hidden API conversations never invoke title generation.

LLM Response Cache

DocsGPT keeps LLM answers in Redis (CACHE_REDIS_URL) and replays a cached answer when an identical request comes in: same model, same messages, same generation parameters. This holds at any temperature, so an identical request gets the identical answer while the entry lives.

  • What is cached: the text of calls made without tools. Ordinary chat passes the default chat tools, so it mostly bypasses the cache; tool-less agents, models without tool support, and helper calls such as query rephrasing, compression and guardrail checks are cached.
  • Never cached: calls that pass tools, calls chained to provider-side state (previous_response_id), and streams that produced no text.
  • How long: LLM_CACHE_TTL seconds (default 1800, 30 minutes), then Redis drops the entry.
  • Privacy: cached entries hold answer text in Redis for that long, so protect Redis like the database.
SettingDefaultDescription
LLM_CACHE_ENABLEDtrueSet false to send every call to the provider and store nothing.
LLM_CACHE_TTL1800Seconds a cached answer is kept.

To flush the cache, delete its keys from the Redis database in CACHE_REDIS_URL (database 2 in the Compose files). Other state shares that database, so delete only the cache’s gen: and stream: keys:

redis-cli -n 2 --scan --pattern 'gen:*' | xargs -r redis-cli -n 2 del redis-cli -n 2 --scan --pattern 'stream:*' | xargs -r redis-cli -n 2 del

In Docker, run the same commands through docker compose exec redis sh -c '...'.

Realtime Events Settings

The realtime notifications channel has its own settings — see Realtime Events & Notifications (ENABLE_SSE_PUSH, EVENTS_STREAM_MAXLEN, SSE_MAX_CONCURRENT_PER_USER, and related).

Vector indexes on pgvector

DocsGPT does not create a vector index on the documents table, and for most deployments it should not have one. Exact search is correct and fast well past the size most corpora reach, and searches are filtered to a single source (WHERE source_id = ...) — a filter an approximate index applies only after picking its candidates.

That combination is what makes a badly-sized index dangerous rather than merely slow: the index picks candidates from the whole table, the source filter discards them, and the query returns too few rows or none at all, silently. The model then answers as if the source were empty.

If you have an existing documents_embedding_idx from an older version and your corpus is small (roughly under 50k vectors), drop it:

DROP INDEX IF EXISTS documents_embedding_idx;

DocsGPT still works with one in place — it raises ivfflat.probes to sqrt(lists) automatically and falls back to an exact search whenever an indexed search returns fewer rows than the source actually holds. You can pin probes explicitly with PGVECTOR_IVFFLAT_PROBES.

Only add an index once a corpus is genuinely large, size it to the data you actually have (IVFFlat’s lists guidance is roughly rows / 1000), and build it after the data is loaded — IVFFlat computes its cluster centroids at build time, so an index built on an empty table gets random centroids and never recovers.

Exploring More Settings

These are just the basic settings to get you started. DocsGPT has many more advanced options, such as:

  • Vector store configuration (VECTOR_STORE, Qdrant, Milvus settings) If you’re looking for an easy way to set up a vector store with pgvector, try Neon .
  • Redis connection settings (CACHE_REDIS_URL); for the LLM answer cache see LLM Response Cache
  • Sandbox, scheduler, guardrails and event-stream tuning

The Settings Reference lists every setting with its type, default and description. Remember to restart your Docker containers after making changes to your .env file for the changes to take effect.

Last updated on