open-notebook/docs/5-CONFIGURATION/advanced.md
Luis Novo 95f76e5a59
docs: complete env reference; troubleshooting keyed on real error messages (#1461)
* docs: complete env reference; troubleshooting keyed on real error messages

Configuration (docs/5-CONFIGURATION):
- environment-reference.md is now the single complete list, checked
  against the code and the content-core, esperanto, surreal-commands and
  langsmith libraries: adds the undocumented variables, a "Read by"
  column, correct defaults (SURREAL_COMMANDS_RETRY_ENABLED=false,
  WAIT_MAX=60, LANGCHAIN_PROJECT=default, SurrealDB defaults), which
  legacy provider vars Migrate to Database copies, and a table of
  variables nothing reads.
- security.md: PBKDF2 derivation, POST /api/credentials/migrate-encryption
  with the back-up-first / no-downgrade warning, password stored in
  localStorage, full list of unauthenticated paths, real upload endpoint.
- reverse-proxy.md: drop v1.0 legacy sections and the non-existent
  multi-container images; real /api/config output; how API_URL
  auto-detection works; the 100 MB Next.js proxy cap.
- ai-providers.md, ollama.md, openai-compatible.md: one shared setup
  procedure with current UI labels, provider/modality table from
  provider_registry.py, no stale model lists or prices; Ollama
  num_ctx and 180 s ESPERANTO_LLM_TIMEOUT; Azure form limits.
- local-tts.md is the shared Speaches page; local-stt.md keeps only
  STT specifics (Whisper models, CCORE_AUDIO_SEGMENT_MINUTES).
- advanced.md, index.md, database.md: link to the reference instead of
  re-listing variables; fix service names, port changes, backups.

Troubleshooting (docs/6-TROUBLESHOOTING):
- Entries start with the exact message from the code or the en-US
  locale. New processing-issues.md covers queued/failed sources (the
  content-core failure reasons), uploads, search, podcasts (profile
  errors and NOTE hints). ai-chat-issues.md covers timeouts, error
  classifier messages, empty responses, Ollama context, encryption
  key and decryption errors.
- Removed invented entries ("too many connections", "Model is not a
  LanguageModel: None", soft delete, retry vars as a connection fix).

SECURITY_REVIEW.md is marked as a historical January 2026 snapshot of
the credentials UI, with the SSRF and security-warning rows corrected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: address review on configuration and troubleshooting pages

- No predictable keys or passwords: placeholders plus the openssl /
  PowerShell generation commands used by the install docs.
- Every 0.0.0.0 bind and firewall rule (Ollama, OpenAI-compatible
  servers, Speaches, LAN access) restricted to the host and Docker
  networks or the LAN, with an explicit exposure warning.
- Diagnostic commands no longer print secrets.
- systemd drop-in includes [Service]; Traefik middleware attached to
  the router.
- Provider pages link to Connect a provider (#1459) instead of
  repeating steps; Vertex and keyless local providers called out;
  "Add Selected" (a select-all toggle) no longer described as the add
  button; "Manage -> Models" instead of "the Models page".
- Startup database failure described correctly (API down, not the
  Database Connection Failed overlay); worker crash causes, Test
  timeout/404 meanings, .env overrides when moving servers, frontend
  restart from source, privacy claims scoped to self-hosted servers.
- Drop claims about bugs fixed in #1457; restore the ollama.md
  GPU acceleration anchor used by quick-start-local.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: address second review round on configuration pages

- Anthropic Compatible always needs an API key and a Base URL
  (enforced in api/models.py), noted in the provider differences.
- Speaches firewall guidance covers a separate Open Notebook host.
- The password check mirrors get_secret_from_env: a readable,
  non-empty _FILE wins, otherwise the variable; never prints values.
- From source, frontend variables go in frontend/.env.local or the
  shell: `make frontend` runs `next dev` in frontend/, which doesn't
  read the root .env.
- The env listing prints every variable name, without values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: correct the default API path for the frontend; deduplicate

Without API_URL the browser calls <host>:5055 directly (the /config
route auto-detects it); INTERNAL_API_URL only serves requests that hit
the Next.js /api forwarding. Full explanation stays in the environment
reference; the configuration index links to it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: upload limit depends on whether API calls go through the frontend proxy

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 23:28:50 -03:00

11 KiB
Raw Permalink Blame History

Advanced Configuration

Performance tuning, ports, logging, backups and container management. Every variable mentioned here is described in the Environment Reference; this page explains when to change them.

With Docker Compose, variables go under the open_notebook service's environment: block and take effect with docker compose up -d (docker compose restart keeps the old environment).


Performance Tuning

Worker concurrency

OPEN_NOTEBOOK_WORKER_MAX_TASKS (default 5) is how many background jobs run at once: source processing, embeddings, insights, transformations and podcasts.

Setup Value
Local model on a single GPU (Ollama, LM Studio) 1
Cloud provider with tight rate limits 2–3
Cloud provider with plenty of quota 5 (default) or more

Higher values process bulk uploads faster but send more parallel requests to your models and cause more SurrealDB transaction conflicts. Conflicts are retried automatically (source processing up to 15 times).

The value is read when the worker starts. In Docker, recreate the container (docker compose up -d). From source, export it in your shell before make worker-start.

Model call timeout

ESPERANTO_LLM_TIMEOUT (default 180 seconds) limits each language-model call and applies to every provider, Ollama included. When a call runs out of time, the user sees an error and the job or chat message fails.

  • Slow local models (large models on CPU, first load of a model): raise it, for example ESPERANTO_LLM_TIMEOUT=420.
  • Keep it below 600. The web UI waits 10 minutes for a response (NEXT_PUBLIC_API_TIMEOUT_MS), and that value is compiled into the published images. Reverse proxies need read timeouts of at least 600 seconds too (see Reverse Proxy → Timeouts).

Speech has its own timeouts: ESPERANTO_TTS_TIMEOUT (300 s, podcast audio) and CCORE_STT_TIMEOUT (3600 s, transcription of audio and video sources).

Podcast audio

TTS_BATCH_SIZE (default 5) is how many text-to-speech requests a podcast sends in parallel. Lower it to 1 or 2 for self-hosted TTS servers and providers with strict concurrency limits; generation gets slower but stops failing on rate limits.

Embeddings

For CPU-only or strict OpenAI-compatible embedding servers, lower OPEN_NOTEBOOK_EMBEDDING_BATCH_SIZE (default 50). Chunking is controlled by OPEN_NOTEBOOK_CHUNK_SIZE (400 tokens) and OPEN_NOTEBOOK_CHUNK_OVERLAP (15%). After changing chunking or the embedding model, rebuild embeddings from the Advanced page.


Ports

Service Port Notes
Web UI 8502 (Docker), 3000 (npm run dev from source)
API 5055
SurrealDB 8000 Published on 127.0.0.1 only in the shipped compose file

Changing the web UI port

Change the host side of the mapping:

services:
  open_notebook:
    ports:
      - "8001:8502"   # UI now at http://localhost:8001
      - "5055:5055"

The API address is still auto-detected as <host>:5055, so nothing else changes.

Changing the API port

services:
  open_notebook:
    ports:
      - "8502:8502"
      - "5056:5055"   # API published on 5056
    environment:
      - API_URL=http://localhost:5056   # the address the browser uses

Auto-detection assumes port 5055, so set API_URL whenever the API is published elsewhere. Inside the container the API always listens on 5055.

Changing the SurrealDB port

Only the host side of the mapping changes. Containers talk to each other on the compose network, where SurrealDB stays on 8000, so SURREAL_URL=ws://surrealdb:8000/rpc stays as it is:

services:
  surrealdb:
    ports:
      - "127.0.0.1:8001:8000"   # host tools (Surrealist, surreal sql) now use 8001

SSL for Self-Signed Providers

If a provider endpoint (Ollama behind a proxy, an internal OpenAI-compatible server) uses a certificate your container doesn't trust, mount the CA bundle and point ESPERANTO_SSL_CA_BUNDLE at it:

services:
  open_notebook:
    environment:
      - ESPERANTO_SSL_CA_BUNDLE=/certs/ca-bundle.pem
    volumes:
      - /path/to/ca-bundle.pem:/certs/ca-bundle.pem:ro

This covers model calls and the credential Test Connection and model discovery. ESPERANTO_SSL_VERIFY=false turns verification off entirely; use it only for short tests on a trusted network.


Logging & Debugging

Application logs

All three processes (API, worker, frontend) log to the container output:

docker compose logs -f open_notebook
docker compose logs --since 10m open_notebook | grep -iE "error|warning"

Set LOGURU_LEVEL=INFO (or WARNING) to hide debug lines from the API and worker. The worker log includes content-core's extraction messages, which is where the full reason for a failed source appears.

SurrealDB logs

The database log level is the --log argument in the surrealdb service's command: (info in the shipped compose file; debug and trace are more verbose).

docker compose logs -f surrealdb

LangSmith tracing

To inspect the LangGraph workflows (chat, Ask, transformations):

environment:
  - LANGSMITH_TRACING=true
  - LANGSMITH_API_KEY=your-key
  - LANGSMITH_PROJECT=open-notebook   # optional; default "default"

Traces include your prompts and source content. The older LANGCHAIN_* names also work.


Content Extraction Engines

Which engine extracts URLs and documents is chosen in Settings → Content Processing (see Content Processing Engines). Engines that need configuration:

  • Firecrawl: FIRECRAWL_API_KEY, optionally FIRECRAWL_API_URL for a self-hosted instance.
  • Jina: JINA_API_KEY (optional).
  • Crawl4AI: OPEN_NOTEBOOK_ENABLE_CRAWL4AI=true installs it in the container on first start; or point CRAWL4AI_API_URL (and CRAWL4AI_API_TOKEN) at a remote Crawl4AI server.
  • Docling: OPEN_NOTEBOOK_ENABLE_DOCLING=true installs it on first start.
  • YouTube blocked: CCORE_YOUTUBE_PROXY or CCORE_YOUTUBE_COOKIES_FILE.

Details and defaults: Environment Reference → Content extraction.


Using Several Providers

Each provider gets its own credential in Manage → Models, and every registered model is tied to the credential it came from. A common split:

  • Chat and transformations from one provider (for example Anthropic, which has no embedding models)
  • Embeddings from another (OpenAI, Google, Voyage AI, Mistral, Ollama…)
  • Text-to-speech from a third (ElevenLabs, or a local Speaches server through OpenAI Compatible)

Then pick a model for each role under Default Model Assignments on the same page.

To use several OpenAI-compatible servers (say, LM Studio for chat and Speaches for speech), add one OpenAI Compatible credential per server, each with its own Base URL. See OpenAI-Compatible Providers.


Backup & Restore

What to back up

With the shipped compose file, everything lives in two directories next to docker-compose.yml:

Host directory Container path Contents
./notebook_data /app/data (open_notebook) Uploaded files, podcast audio, chat checkpoints, caches
./surreal_data /mydata (surrealdb) The SurrealDB database

The single-container image keeps the database in ./surreal_single_data instead (see examples/docker-compose-single.yml). Also keep OPEN_NOTEBOOK_ENCRYPTION_KEY somewhere safe and separate: without it, the stored provider keys in a restored database can't be decrypted.

Backup

# Stop for a consistent copy of the database
docker compose down
tar -czf open-notebook-$(date +%Y%m%d-%H%M%S).tar.gz notebook_data/ surreal_data/
docker compose up -d

Take a backup before every upgrade. Some upgrades change data in ways older versions can't read (for example the v1.15.0 credential encryption, see Security), and restoring a backup is the only way back.

A daily cron job:

#!/bin/bash
# backup.sh
cd /path/to/open-notebook            # the directory with docker-compose.yml
BACKUP_DIR=/path/to/backups
DATE=$(date +%Y%m%d-%H%M%S)

docker compose down
tar -czf "$BACKUP_DIR/open-notebook-$DATE.tar.gz" notebook_data/ surreal_data/
docker compose up -d

# Keep the last 7 days
find "$BACKUP_DIR" -name "open-notebook-*.tar.gz" -mtime +7 -delete
0 2 * * * /path/to/backup.sh >> /var/log/open-notebook-backup.log 2>&1

Restore

docker compose down
mv notebook_data notebook_data.old && mv surreal_data surreal_data.old
tar -xzf open-notebook-20260115-020000.tar.gz
docker compose up -d

Restore with the same image version you backed up from, or a newer one. Database migrations run automatically on startup and only move forward.

Moving to another server

Copy the backup archive, your docker-compose.yml (with the same OPEN_NOTEBOOK_ENCRYPTION_KEY), and the .env file next to it or any other environment overrides (custom SURREAL_USER/SURREAL_PASSWORD live there; without them the stack falls back to root/root and can't sign in to your database). Extract the archive next to them and run docker compose up -d.


Container Management

The shipped compose file has two services: surrealdb and open_notebook. The API, worker and frontend are processes inside open_notebook, so they are started, stopped and logged together.

docker compose up -d                    # start, or apply changes to docker-compose.yml
docker compose ps                       # status
docker compose logs -f open_notebook    # app logs (API, worker, frontend)
docker compose logs -f surrealdb        # database logs
docker compose restart open_notebook    # restart without changing configuration
docker compose down                     # stop (data in ./notebook_data and ./surreal_data stays)
docker compose pull && docker compose up -d   # update to the latest image (back up first)
docker stats                            # CPU and memory per container

docker compose down -v does not delete your data either: the shipped file uses bind mounts, not named volumes. To start from scratch, stop the stack and delete ./notebook_data and ./surreal_data yourself.