Files
local-deep-research/docs/docker-compose-guide.md
LearningCircuit 1b558bc1ba feat(lmstudio): add optional API key support for authenticated instances (#3573) (#3740)
* feat(lmstudio): add optional API key support for authenticated instances

Recent LM Studio versions can require an API key on the local server.
LDR previously hardcoded "not-required", making authenticated instances
fail silently. This adds an optional `llm.lmstudio.api_key` setting
(UI field on the home page + auto-rendered Settings → LLM field +
`LDR_LLM_LMSTUDIO_API_KEY` env var), mirroring the Ollama optional-key
pattern. Backward compatible: an empty/whitespace key falls back to
the existing placeholder so unauthenticated installs require no change.

`is_available()` now sends the key as an `Authorization: Bearer` header
so authenticated LM Studio instances are correctly detected as available.
The parallel `get_llm()` direct-construction path in `llm_config.py` is
also updated so the user's key flows through both code paths. The path
allowlist in `.gitleaks.toml` is extended to cover `llm_config.py` —
this file already legitimately holds `api_key=` kwargs for all providers,
matching the existing allowlist for `llm/providers/`.

Closes #3573

* test(lmstudio): cover llm_config.py direct get_llm path for api key

The provider-class path (LMStudioProvider.create_llm) is already covered
in test_lmstudio_provider.py, but the parallel get_llm("lmstudio", ...)
branch in llm_config.py had no test asserting the user's key flows
through to ChatOpenAI. Adds two tests mirroring the existing
test_openai_endpoint_without_api_key_uses_placeholder pattern: one for
configured-key passthrough, one for the empty-key fallback to
"not-required". Closes a coverage gap surfaced during PR review.

* feat(lmstudio): override list_models_for_api + FAQ entry for save UX

Folds two of the three deferred follow-ups into the PR:

1. Override `LMStudioProvider.list_models_for_api` so the optional API key
   is read from settings on the high-level `list_models()` path, matching
   what the settings route already does. Caller-provided keys (route path)
   short-circuit the settings read via an `if not api_key:` guard, so the
   route remains untouched. Eliminates the drift hazard between the two
   key-resolution paths.

2. Add a FAQ entry documenting the save-then-poll UX: the password field
   saves on blur, so pasting + immediately clicking refresh can produce an
   empty model list. Recovery is to tab out then refresh.

Adds 3 new tests for the override (dummy-key fallback, user-key passthrough
from settings, route-provided key not overwritten by settings read).

The third deferred item (`llm.ollama.api_key` JSON entry) stays as a
separate cleanup PR — different provider, different feature.
2026-05-10 00:02:52 +02:00

7.0 KiB

Docker Compose Guide

This guide covers Docker Compose setup for Local Deep Research. For the quickest start, see the Quick Start section below.

Quick Start

CPU-Only (All Platforms)

Works on macOS (M1/M2/M3/M4 and Intel), Windows, and Linux:

curl -O https://raw.githubusercontent.com/LearningCircuit/local-deep-research/main/docker-compose.yml && docker compose up -d

With NVIDIA GPU (Linux Only)

For hardware-accelerated inference:

curl -O https://raw.githubusercontent.com/LearningCircuit/local-deep-research/main/docker-compose.yml && \
curl -O https://raw.githubusercontent.com/LearningCircuit/local-deep-research/main/docker-compose.gpu.override.yml && \
docker compose -f docker-compose.yml -f docker-compose.gpu.override.yml up -d

Prerequisites for GPU: Install the NVIDIA Container Toolkit first. For step-by-step Ubuntu/Debian install commands, see the Installation Guide.

Open http://localhost:5000 after ~30 seconds.

Using a Different Model

Specify a model with the LDR_LLM_MODEL environment variable:

LDR_LLM_MODEL=gemma3:4b docker compose up -d

The model will be automatically pulled if not already available.

Configuration Options

docker-compose.yml

The base configuration includes:

Service Description
local-deep-research The main web application (port 5000)
ollama Local LLM inference engine
searxng Privacy-focused meta search engine

Key Environment Variables

Most settings can be configured through the web UI at http://localhost:5000/settings. Environment variables override UI settings and lock them. For the complete list of all environment variables and their defaults, see CONFIGURATION.md.

⚠️ Warning: Setting environment variables causes a hard override—the setting becomes read-only in the UI and cannot be changed until the environment variable is removed. For settings you may want to adjust later, use the web UI instead. Environment variables are best suited for deployment-specific values like LDR_DATA_DIR or API keys.

Note: Empty environment variables (e.g., LDR_LLM_PROVIDER= or LDR_LLM_PROVIDER="") are treated as not set — they will not override anything and the setting remains editable in the UI. This prevents Docker Compose templates with blank fields from accidentally locking settings. Only non-empty values act as overrides. Setting an API key to an empty string does not block or clear it — if a key exists in the database, it will still be used. To explicitly block a key, set it to any non-empty invalid value (e.g., DISABLED).

Variable Description
LDR_WEB_HOST Bind address (default: 0.0.0.0 for Docker)
LDR_WEB_PORT Internal port (default: 5000)
LDR_DATA_DIR Data directory (default: /data)
LDR_APP_ALLOW_REGISTRATIONS Allow new user registration (default: true). Set to false for public deployments after creating your initial account.
LDR_LLM_PROVIDER LLM provider (ollama, openai, anthropic, etc.)
LDR_LLM_MODEL Model name (e.g., gemma3:12b)

Changing the External Port

Use Docker's port mapping instead of environment variables:

ports:
  - "8080:5000"  # Expose on port 8080 instead of 5000

Volume Mounts

Volume Purpose
ldr_data Application data
ldr_scripts Startup scripts
ldr_rag_cache RAG index cache
ollama_data Downloaded models
searxng_data Search engine config

Resource Limits

Warning: Resource limits in the base docker-compose.yml are intentionally minimal:

  • nofile (file descriptors): Not set. Docker's daemon default (typically 1M+) is appropriate. Setting a lower value can cause unable to open database file errors under load.
  • memlock: Set to unlimited so SQLCipher's mlock() (a system call that prevents memory from being swapped to disk) can lock encryption keys in RAM when cipher_memory_security is enabled (opt-in, off by default).
  • To customize, use a docker-compose.override.yml for your deployment.

Local Document Collections

Use the Collections system in the Web UI to manage your local documents. Upload files directly through the Collections page — no volume mounts required.

For more customization, use Cookie Cutter to generate a tailored docker-compose file:

# Install cookiecutter
pip install --user cookiecutter

# Clone the repository
git clone https://github.com/LearningCircuit/local-deep-research.git
cd local-deep-research

# Generate custom configuration
cookiecutter cookiecutter-docker/

Cookie Cutter will prompt you for:

Option Description
config_name Name for your configuration
host_port Port to expose (default: 5000)
host_ip IP to bind (default: 0.0.0.0)
host_network Use host networking
enable_gpu Enable NVIDIA GPU support
enable_searxng Include SearXNG service

Then start with:

docker compose -f docker-compose.default.yml up -d

Using External LLM Providers

OpenRouter (100+ Models)

environment:
  - LDR_LLM_PROVIDER=openai_endpoint
  - LDR_LLM_OPENAI_ENDPOINT_URL=https://openrouter.ai/api/v1
  - LDR_LLM_OPENAI_ENDPOINT_API_KEY=<your-api-key>
  - LDR_LLM_MODEL=anthropic/claude-3.5-sonnet

LM Studio (Running on Host)

environment:
  - LDR_LLM_PROVIDER=lmstudio
  - LDR_LLM_LMSTUDIO_URL=http://host.docker.internal:1234/v1
  # - LDR_LLM_LMSTUDIO_API_KEY=<api-key-if-required>   # optional; leave out for unauth instances
  - LDR_LLM_MODEL=<your-loaded-model>

Common Commands

# Start services
docker compose up -d

# Start with GPU support
docker compose -f docker-compose.yml -f docker-compose.gpu.override.yml up -d

# View logs
docker compose logs -f

# Stop services
docker compose down

# Update to latest version
docker compose pull && docker compose up -d

# Remove all data (fresh start)
docker compose down -v

Troubleshooting

Container won't start

  • Check logs: docker compose logs local-deep-research
  • Ensure port 5000 is available

Ollama model not loading

  • Check Ollama logs: docker compose logs ollama
  • Verify model name in LDR_LLM_MODEL environment variable
  • Ensure sufficient disk space for model download

GPU not detected

  • Verify NVIDIA drivers: nvidia-smi
  • Check container toolkit: docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi