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:
1. Configuration via .env file (Recommended)
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 location | How 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 from | Edit 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.sh | Edit the file, then restart the services. Compose commands need --env-file .env; see Docker Deployment. |
| Kubernetes | No file: the docsgpt-secrets Secret and the Deployment env | Edit deployment/k8s/docsgpt-secrets.yaml and re-apply; see Kubernetes. |
DocsGPT resolves the file in this order:
DOCSGPT_ENV_FILE, when set, names the.envfile directly.- Otherwise it reads
<DOCSGPT_HOME>/.env. The data homeDOCSGPT_HOMEis also whereinputs/,indexes/and downloaded models live. WhenDOCSGPT_HOMEis unset, the data home is the source checkout the code runs from, else~/.docsgpt/server(/opt/docsgptfor 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.52. 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 insetup.shoption 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.
- Common values:
-
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. WithOPENAI_BASE_URLit 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).
- For
- Examples:
-
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 tohuggingface_sentence-transformers/all-mpnet-base-v2so 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.
- 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
-
API_KEY: Required for most cloud-based LLM providers. This is your authentication key for the provider named inLLM_PROVIDER. Each provider also has its own variable (OPENAI_API_KEY,ANTHROPIC_API_KEY, …); see Provider API keys. -
OPENAI_BASE_URL: Specifically used whenLLM_PROVIDERis set toopenaibut 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 tononeto 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) orelevenlabs. Both are hosted services. Set it tononeto switch text-to-speech off and hide the button. Withelevenlabs, setELEVENLABS_API_KEY;ELEVENLABS_VOICE_IDpicks 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(default10000) 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 totrue; the backend Docker image ships the same build, so it serves the UI on port 7091 too. Setfalsewhen a separate frontend, such as thearc53/docsgpt-feimage indocker-compose-hub.yamlor the frontend thatdocker-compose.yamlbuilds, serves the UI. -
API_URL: The address of the API, defaulthttp://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 tohttp://backend:7091, which takes precedence over.env, so.envsets the backend’s. When other machines open DocsGPT, set it to the address they use (http://<server-address>:7091, or the publichttps://address behind a proxy).docsgpt upand 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 toAPI_URL. Set it when the API and the worker read one.env(a pip install,docsgpt up --native) andAPI_URLis a public address, so the worker’s calls stay on the machine:WORKER_API_URL=http://127.0.0.1:7091.docsgpt up --nativesets it. The Kubernetes manifests setWORKER_API_URL=http://docsgpt-api-servicefor internal index handoff while both app containers inherit the publicAPI_URLfrom the shared Secret for browser-facing links and OAuth callbacks. Docker Compose gives the worker its ownAPI_URLinstead, so leaveWORKER_API_URLunset 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.5Make 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 alternativesIn 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 SmallAfter 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_compatibleproviders (Mistral, Together, Fireworks, Ollama, vLLM, …) — one YAML per provider, each with its ownapi_key_envandbase_url. - Extend an existing provider’s catalog by dropping a YAML with the
same
provider:value as the built-in (e.g.provider: anthropicwith extra models). - Override a built-in model’s capabilities by re-declaring the same
id— later wins, override is logged atWARNING.
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:roMisconfiguration
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.
| Setting | Default | Description |
|---|---|---|
UPLOAD_MAX_REQUEST_BYTES | 268435456 | Maximum request body for a public file-upload route, including multipart overhead. |
UPLOAD_MAX_FILE_BYTES | 104857600 | Maximum encoded size of one uploaded file or one extracted ZIP member. |
PARSE_SPEC_MAX_BYTES | 10485760 | Maximum UTF-8 size of an uploaded or JSON API specification. |
UPLOAD_MAX_ARCHIVE_BYTES | 262144000 | Maximum total uncompressed bytes across all ZIP layers in one extraction. |
UPLOAD_MAX_ARCHIVE_FILES | 10000 | Maximum total extracted files across all nested layers; directory records do not count. |
UPLOAD_MAX_ARCHIVE_RATIO | 1000 | Maximum uncompressed-to-compressed expansion ratio for each archive layer. |
UPLOAD_MAX_ARCHIVE_DEPTH | 3 | Maximum 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.
| Setting | Default | Description |
|---|---|---|
DOC_PARSER_ENGINE | anydoc | Parser 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_ENABLED | false | OCR for source ingestion. Alias: DOCLING_OCR_ENABLED. |
OCR_ATTACHMENTS_ENABLED | false | OCR for chat attachments. Alias: DOCLING_OCR_ATTACHMENTS_ENABLED. |
OCR_BACKEND | auto | Who 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_PATH | true | Under the docling engine, read PDF attachments through their text layer (pypdfium2) and only hand scans to Docling. Not needed under anydoc. |
DOCLING_TABULAR_MAX_BYTES | 2000000 | Docling engine: CSV/XLSX larger than this (by content) use the lightweight tabular parsers. |
DOCLING_MARKUP_MAX_BYTES | 8000000 | Docling engine: HTML/VTT larger than this are head-truncated before parsing. |
MARKUP_MAX_BYTES | 8000000 | anydoc 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_CHECK | true | Trust-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_TABLEIZE | false | Rewrite dot-leader / whitespace-aligned table runs in anydoc’s PDF markdown into GFM tables. |
OCR_ENGINE | tesseract | OCR 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_LANGS | eng | Tesseract language packs, +-separated (e.g. eng+chi_sim+deu). |
OCR_DEEPSEEK_PROVIDER | ollama | Where DeepSeek-OCR runs: ollama, vllm, novita, deepinfra or custom. Each preset supplies the URL, model and concurrency. See DeepSeek-OCR. |
OCR_DEEPSEEK_URL | preset | Chat-completions URL; overrides the preset’s. |
OCR_DEEPSEEK_MODEL | preset | Model name at that endpoint; overrides the preset’s. |
OCR_DEEPSEEK_API_KEY | unset | Bearer token. Required by novita (falls back to NOVITA_API_KEY) and deepinfra. |
OCR_DEEPSEEK_CONCURRENCY | preset | Page requests in flight per file: 4 for vllm, novita, deepinfra; 1 for ollama, custom. |
OCR_DEEPSEEK_MAX_RETRIES | 3 | Retries per page after a 429, 5xx or refused connection, with backoff honouring Retry-After. |
OCR_DEEPSEEK_TIMEOUT | 300 | Seconds allowed per page request. |
OCR_DEEPSEEK_PROMPT | Free OCR. | Instruction sent with each page. |
OCR_RENDER_DPI | 200 | Native backend: resolution at which pages without a text layer are rendered before OCR (clamped to 72-600). |
OCR_MIN_CHARS_PER_PAGE | 20 | Chars-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.webmfiles 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.
| Setting | Purpose | Typical values |
|---|---|---|
STT_PROVIDER | Speech-to-text backend provider, or none to switch speech-to-text off. | openai, faster_whisper, none |
OPENAI_STT_MODEL | OpenAI transcription model used when STT_PROVIDER=openai. | gpt-4o-mini-transcribe |
STT_LANGUAGE | Optional language hint passed to the provider. Leave unset for auto-detection when supported. | en, es, unset |
STT_MAX_FILE_SIZE_MB | Maximum file size accepted by the synchronous /api/stt endpoint. | 50 |
STT_ENABLE_TIMESTAMPS | Include timestamp segments in the normalized transcript response and stored parser metadata. | true, false |
STT_ENABLE_DIARIZATION | Reserved 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=falseIf 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=falsefaster_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.
| Setting | Default | Description |
|---|---|---|
AGENT_IMAGE_MAX_BYTES | 5000000 | Maximum encoded avatar file size in bytes. |
AGENT_IMAGE_MAX_PIXELS | 16777216 | Maximum 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.
| Setting | What it protects | If it is missing |
|---|---|---|
INTERNAL_KEY | The 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_KEY | Signs 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_KEY | Seals 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=productionSet 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):
- Move the current value to
ENCRYPTION_SECRET_KEY_PREVIOUSand put the new one inENCRYPTION_SECRET_KEY, on the API and the worker. - Restart them, then run
docsgpt connectors reencryptwith 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(ordeployment/docker-compose.yaml) - Kubernetes:
kubectl exec deploy/docsgpt-worker -- python -m docsgpt connectors reencrypt
- Remove
ENCRYPTION_SECRET_KEY_PREVIOUSonce 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
| Value | Who gets in | Users told apart | Admin, 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_jwt | Anyone holding the one shared access token. | No: the token always means the user local. It is a shared password, not user accounts. | None. |
session_jwt | Anyone 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. |
oidc | People 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.comJWT_SECRET_KEYsigns 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. WithDEPLOYMENT_TYPE=production(orcloud), 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_keyin 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 withJWT_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), anddocsgpt tokenprints it for adocsgpt upinstall. - Use this token in the
Authorizationheader for all API requests:Authorization: Bearer <SIMPLE_JWT_TOKEN> - The frontend will prompt for this token if not already set.
- The token is
- session_jwt:
- The frontend requests a token from
/api/generate_tokenon its first visit. The endpoint needs no credentials, so anyone who can reach it gets a token. - Use the received token in the
Authorizationheader for subsequent requests. - Each token carries a new random user id; clearing the browser’s storage starts a new, empty identity.
- The frontend requests a token from
- 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
Authorizationheader 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_KEYsecure 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_jwtandsession_jwttravel as bearer tokens; outside a trusted network, serve DocsGPT over HTTPS.
Checking Current Auth Type
- Use the
/api/configendpoint to check the currentauth_typeand 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.
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.
| Setting | Description | Default |
|---|---|---|
STORAGE_TYPE | local or s3 | local |
S3_BUCKET_NAME | Bucket name | docsgpt-test-bucket |
S3_ACCESS_KEY_ID | Access key ID | — |
S3_SECRET_ACCESS_KEY | Secret access key | — |
S3_REGION | Region (use auto for Cloudflare R2) | — |
S3_ENDPOINT_URL | Custom endpoint for S3-compatible services; leave unset for AWS S3 | — |
S3_PATH_STYLE | Use path-style addressing (required by most non-AWS services) | false |
URL_STRATEGY | Artifact-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-1S3-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=trueYour 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, andSAGEMAKER_REGIONvariables for S3 credentials. These are still honored as a fallback (with a deprecation warning) but you should migrate to theS3_*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:
| Setting | Description | Default |
|---|---|---|
POSTGRES_URI | SQLAlchemy-compatible Postgres URI. Any standard postgresql:// form works — DocsGPT normalizes it internally to the psycopg v3 dialect. | — |
AUTO_CREATE_DB | On 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_MIGRATE | On 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_SCHEMA | On 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.
| Setting | Default | Description |
|---|---|---|
PER_SOURCE_RETRIEVAL_ENABLED | true | Master switch for per-source retrieval config. When false, all sources fall back to the classic retriever regardless of their stored config. |
GRAPHRAG_ENABLED | false | Enable GraphRAG. Requires VECTOR_STORE=pgvector. |
GRAPHRAG_EXTRACTION_MODEL | unset | Model used for ingest-time graph extraction. Unset falls back to LLM_NAME (on its registry provider, else LLM_PROVIDER). |
GRAPHRAG_MAX_CHUNKS_FOR_EXTRACTION | 2000 | Hard cap on chunks extracted per source (cost control). 0 extracts nothing. |
GRAPHRAG_EXTRACTION_WORKERS | 8 | Concurrent 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.
| Setting | Default | Description |
|---|---|---|
EMBEDDINGS_NAME | huggingface_sentence-transformers/all-mpnet-base-v2 | The embedding model. New installs use ibm-granite/granite-embedding-311m-multilingual-r2. Changing it on a populated index requires docsgpt.scripts.reembed. |
EMBEDDINGS_BASE_URL | unset | Base URL of a remote OpenAI-compatible embeddings server. Setting it routes all embedding calls there. |
EMBEDDINGS_THREADS | unset (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_KEY | unset | Optional bearer token for the remote embeddings server. |
EMBEDDINGS_MAX_INPUT_TOKENS | unset | Truncate each remote embedding input to N tokens (guards servers that reject oversized inputs). |
EMBEDDINGS_LOCAL_MAX_TOKENS | unset | Hard 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_TOKENS | 512 | Clip each search query to N tokens before it is embedded, for every embedder; 0 turns it off. Documents are not clipped. |
EMBEDDINGS_DELEGATE_TO_WORKER | true | Embed 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_QUEUE | embeddings | Queue the query-embedding task is routed to. A worker started with an explicit -Q must list it. |
EMBEDDINGS_DELEGATE_TIMEOUT | 60 | Seconds the API waits for the worker’s vector before failing the search. |
Tools Settings
| Setting | Default | Description |
|---|---|---|
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.
| Setting | Default | Description |
|---|---|---|
OIDC_ADMIN_GROUPS | unset | Comma-separated IdP groups granted the global admin role (OIDC only). |
LOCAL_MODE_ADMIN | false | Grants admin in no-auth mode (AUTH_TYPE=None) only. Never enable on a networked deployment. |
LLM Provider Settings
| Setting | Default | Description |
|---|---|---|
OPENAI_RESPONSES_STORE | false | When true, allows OpenAI to persist Responses API state server-side. |
OPENAI_RESPONSES_CHAIN_ACROSS_TURNS | true | In 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_TOKENS | unset | Stop 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_AUTO | false | Send 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_KEY | true | Send 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_RETENTION | unset | Value for prompt_cache_retention on Responses API calls, for example 24h, where the provider offers extended prompt-cache retention. |
V1_SESSION_TTL_SECONDS | 86400 | Redis correlation lifetime, in seconds, for OpenAI-compatible client sessions. Raw external session IDs are hashed and never stored. |
TITLE_MODEL_ID | unset | Optional 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_TTLseconds (default1800, 30 minutes), then Redis drops the entry. - Privacy: cached entries hold answer text in Redis for that long, so protect Redis like the database.
| Setting | Default | Description |
|---|---|---|
LLM_CACHE_ENABLED | true | Set false to send every call to the provider and store nothing. |
LLM_CACHE_TTL | 1800 | Seconds 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 delIn 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.