7.1 KiB
Egress modes — what each one does
⚠️ Experimental. The egress boundary is new and ships as defense-in-depth, not an absolute guarantee. It blocks the known data-egress paths under the scope you pick, but this is an early version — don't rely on it as your only protection for highly sensitive data yet. See the threat model and limitations linked just below.
LDR's egress scope (Settings → Egress Scope, or the Privacy & Egress panel on the research form) controls where your research traffic is allowed to go — which search engines run, whether your LLM/embeddings may be cloud services, and which URLs may be fetched. It's the single switch for "how much of this run is allowed to leave my machine?"
Pick a mode below. The default is Adaptive, which just follows your primary search engine, so most people never need to think about it.
This page explains the modes for everyday use. For the threat model, guarantees, and limitations, see
SECURITY.mdand the technical egress package README.
At a glance
| Mode | Search engines | LLM / embeddings | Best for |
|---|---|---|---|
| Adaptive (default) | follows your primary engine | forced local only when the run is private | "just do the sensible thing" |
| Unprotected | any engine (no restriction) | any provider (cloud allowed) | escape hatch — not recommended; disables egress protection (hard SSRF / cloud-metadata blocking still applies) |
| Public only | public web/academic engines only | your configured providers | public research; your local collections aren't touched |
| Private only | local engines only (collections, local SearXNG/Ollama) | forced local — cloud blocked | sensitive work that must stay on the machine |
| Strict | only your one primary engine | your configured providers | a single, exact source with zero expansion |
🔀 Adaptive (default)
Adaptive follows your primary search engine and resolves to a concrete mode for each run:
- Primary is a public engine (e.g. SearXNG pointed at a public instance, arXiv, PubMed) → behaves like Public only.
- Primary is a private source (a local collection, your library) → behaves like Private only (and therefore forces local LLM + embeddings).
Why it's the default: you choose a search engine anyway, and the privacy posture "just matches" it. If you make a private collection your primary, the whole run automatically stays local — nothing leaves the box.
Note: to use a cloud LLM on a private collection, mark the collection public (see below) or add the provider to trusted inference providers; to drop all restrictions for one run, use Unprotected. Adaptive deliberately narrows to match the primary.
🔓 Unprotected
Not recommended — an escape hatch. Egress-scope restrictions are disabled
for the run: any engine, URL, and LLM/embeddings provider is permitted. The
hard SSRF and cloud-metadata blocks still apply. A loud, non-dismissible banner
shows while it is active. Prefer marking a collection public, or adding a
trusted destination (policy.trusted_inference_providers /
policy.trusted_search_engines) for the specific case, over disabling
protection wholesale.
The older Both scope (blanket-permit any classified engine) has been retired: existing saved
bothconfigurations are migrated to Adaptive (which follows your primary engine and forces local inference for a private primary). If you relied onbothto use a private collection with a cloud model, mark that collection public, or choose Unprotected to opt out of protection explicitly.
☁️ Public only
Only public web/academic engines run; your local collections are excluded. URL fetches are allowed to public hosts and blocked for private ones. Inference is whatever you configured (cloud allowed). Use it when you want public research and don't want your private documents queried at all.
🔒 Private only
The privacy mode. Only local engines run (collections, library, a local SearXNG/Ollama). Crucially, it forces local LLM and embeddings — cloud providers (OpenAI, Anthropic, Google, OpenRouter, …) are blocked, so your query and your retrieved documents never reach a cloud model. Public URL fetches are blocked, and a process-wide socket guard blocks stray outbound connections. Nothing leaves the machine.
If you have no local LLM configured, a Private-only run will refuse rather than silently fall back to the cloud — that's intentional (fail-closed).
🎯 Strict
The tightest mode: only your single primary engine runs — no expansion to any other engine at all. At the URL layer it behaves like Private-only (private hosts allowed, public blocked), but it does not force local inference — set the Require local toggles if you also want local LLM/embeddings.
Per-collection public/private
Each RAG collection has a public/private flag (default private):
- A private collection is excluded under Public only / Adaptive-public, and when used it forces local inference — its chunks never reach a cloud model.
- Mark a collection public (the Public collection checkbox when creating it) only if its contents are non-sensitive and you're happy to process them with cloud inference / use them under public scope.
The two local-inference toggles
Independent of the scope, you can force local inference any time:
- Require local LLM endpoint — refuse cloud LLM providers / non-local URLs.
- Require local embeddings — refuse cloud embedders, and refuse a HuggingFace download for an uncached local model.
Both are implied automatically under Private only (and Adaptive-private), which is why those toggles auto-check and lock when you select Private only.
Per-research overrides
The three primary controls — Egress Scope, Require local LLM endpoint, and Require local embeddings — also appear on the research-form page as per-run dropdown / checkbox overrides. Values set there apply only to that research run and do not persist to the settings database, so you can do a one-off private run without changing your defaults.
Audit log
Changes to any policy.* key, llm.require_local_endpoint,
llm.allowed_local_hostnames, or embeddings.require_local emit a
policy_audit=True log line so administrators can trace configuration changes.
Those audit lines are deliberately filtered out of the WebSocket progress
stream (they never reach browser subscribers).
See also
- Configuration reference — the exact setting
keys (
policy.egress_scope,llm.require_local_endpoint,embeddings.require_local,llm.allowed_local_hostnames) and their auto-generatedLDR_*environment variables. SECURITY.md— threat model, guarantees, and caveats (including what this does not defend against).