Skip to content

Bitcoin accepted at checkout  |  Ships from Laval, QC, Canada  |  Expert support since 2016

Local-AI Telemetry Audit: Which Self-Hosted Tools Phone Home

You moved your AI stack on-premise for privacy — but “runs locally” and “opens no sockets to the internet” are different claims, and most guides never check the second one. This registry audits fourteen self-hosted AI tools at the code level: what each one contacts by default on install, launch and idle (update checks, analytics SDKs, registry pulls), the exact domains involved, whether it’s opt-in or opt-out, the exact environment variable or setting that kills it, and a copy-paste air-gap recipe per tool. Evidence is graded — source code first, official docs second — and anything that couldn’t be verified exactly says unverified instead of pretending.

Quick answer

"Local" is not the same as "offline". Of the fourteen self-hosted AI tools audited here, only four are truly zero-outbound by default (llamafile, whisper.cpp, KoboldCpp, llama.cpp with a local model file). Three ship usage telemetry switched ON — vLLM (stats.vllm.ai, every 10 minutes), AnythingLLM (PostHog) and Open WebUI (PostHog via its bundled ChromaDB, though the official Docker image pre-disables it) — all honestly documented and all killable with one env var. Ollama has no analytics at all, but its desktop tray app checks ollama.com for updates hourly (the headless server is silent). LM Studio is closed source: its docs promise your chats stay local, but that promise cannot be code-verified, and it does phone home for updates and opt-out usage stats. GPT4All's analytics are opt-in, yet its launcher unconditionally fetches its catalog over plain HTTP with certificate verification disabled.

The pleb rule: assume every GUI phones home until the source code says otherwise. Set DO_NOT_TRACK=1 globally (vLLM, Open WebUI and others honor it), use the per-tool env vars below, and for a real air-gap: pre-download models, then firewall the listed domains — a docs promise is not an observed-silent socket.

none zero outbound by default   model-downloads-only user-initiated fetches only   update-check pings home for versions   telemetry / multiple analytics or several defaults ON   A/B/C evidence grade (source-code / docs / community)

ToolDefault outboundEndpoints & kill switchesTelemetryAir-gap recipeLicenseGrade
llamafile~v0.10.x, July 2026 none — no unsolicited endpoints non/a Run ./model.llamafile — weights are embedded in the executable, the HTTP server binds localhost only, zero outbound out of the box. Nothing to download, nothing to block. Apache-2.0 A
The strictest air-gap answer on this list: a single Cosmopolitan-libc binary with the model inside. Evidence: official docs + source (Mozilla llamafile repo).
Whisper.cppmaster, July 2026 none

huggingface.co — GGML model download via the OPTIONAL download-ggml-model.sh helper (only when the user runs the script)
Kill: supply a local model path

non/a whisper-cli -m /path/ggml-*.bin -f audio.wav makes zero network calls. The only outbound path is the user-run download helper script. MIT A
Plain C/C++ with no update check and no analytics. Evidence: source code (no HTTP client in core).
KoboldCpp~v1.9x, July 2026 none

*.trycloudflare.com — optional public tunnel to your local server (also downloads the cloudflared binary on first use) (ONLY with --remotetunnel)
Kill: do not pass --remotetunnel (default off)

noopt-in (all remote features) koboldcpp --model model.gguf binds localhost:5001 with zero outbound. Skip --remotetunnel, AI-Horde worker mode and URL model fetch and it never opens a socket outward. AGPL-3.0 A
Single-file binary; every outbound path is an explicit opt-in flag. Evidence: source code + maintainer README.
llama.cpp (llama-server)master, July 2026 none

huggingface.co — model download/revalidation for -hf / --hf-repo models (only when an -hf model is used (may revalidate cache at startup))
Kill: use a local -m path.gguf, or pass --offline

non/a llama-server -m /path/model.gguf is fully offline — no update check, no analytics code in the binary. If you used -hf, add --offline to pin the cache. MIT A
The one caveat: an -hf-sourced model may GET huggingface.co at startup unless --offline is set. Evidence: source code (network only in the HF download path).
text-generation-webui (oobabooga)main, July 2026 model-downloads-only

huggingface.co — model/tokenizer downloads via HF Hub (user-initiated or uncached HF repo id)
Kill: HF_HUB_OFFLINE=1 + TRANSFORMERS_OFFLINE=1, load local folders

noopt-out (project already disabled it for you) Gradio's api.gradio.app analytics is double-disabled in-tree (GRADIO_ANALYTICS_ENABLED=False + analytics_enabled=False). Export HF_HUB_OFFLINE=1 and TRANSFORMERS_OFFLINE=1 after caching models and it is fully offline. AGPL-3.0 A
The historically risky path — Gradio's default telemetry — is explicitly neutralized in source. Evidence: source code (server.py, issue #801).
LocalAIv4.7.x, July 2026 model-downloads-only

raw.githubusercontent.com — default model + backend gallery indexes (when the gallery is used/auto-loaded)
Kill: --galleries='[]' --autoload-galleries=false --disable-gallery-endpoint

huggingface.co — model weight downloads (user-initiated install)
Kill: preload local models

quay.io — OCI backend images (v3+ runtime backend pulls) (backend install)
Kill: pre-provision backend images

non/a Preload models ($LOCALAI_PRELOAD_MODELS) and backends, then --autoload-galleries=false --galleries='[]' --disable-gallery-endpoint. The local /metrics endpoint is Prometheus-style with no egress (disable: $LOCALAI_DISABLE_METRICS_ENDPOINT=true). MIT A
The one telemetry scare was a misread of the bundled OpenTelemetry /metrics endpoint — local-only; the maintainer rebutted it and shipped a disable flag. Evidence: maintainer statement (issue #3942) + source + CLI docs.
OllamaJuly 2026 (updater unchanged for years) update-check

ollama.com — desktop tray-app update check (GET /api/update) (macOS/Windows GUI only, ~hourly)
Kill: run headless ollama serve (Linux/CLI has no updater), or firewall the domain

registry.ollama.ai — model layer/manifest pulls (only on ollama pull/run of a non-local model)
Kill: n/a — user-initiated; fully local once cached

non/a ollama serve has no updater and no analytics SDK — pre-pull your models and it runs fully offline. The only unsolicited ping is the GUI tray updater: use the server binary or block ollama.com. MIT A
"Zero telemetry" is true of analytics but imprecise for the desktop app — the tray updater phones ollama.com hourly. Server use: genuinely silent. Evidence: source code (app/lifecycle updater.go; no analytics SDK in repo).
ComfyUI (core)master, July 2026; Manager + Desktop are separate products none

api.comfy.org — ComfyUI-MANAGER node-registry fetch (not core) (Manager startup unless offline mode)
Kill: network_mode = private or offline in Manager config.ini

raw.githubusercontent.com — Manager node-DB channel lists (Manager catalog refresh)
Kill: Manager offline mode

github.com — core frontend package resolution; Manager node clones (frontend version resolution / user installs)
Kill: pin --front-end-version; install offline

no (core even sets DO_NOT_TRACK=1 and HF_HUB_DISABLE_TELEMETRY=1 itself)n/a (Desktop app's analytics are opt-in — a separate product using PostHog/Datadog per its privacy policy) Core Python install is fully offline once models and frontend are present. If Manager is installed set network_mode=offline (and verify — reports exist it is not always fully honored). Avoid the Desktop build for true air-gap. Audit custom nodes separately — they run arbitrary Python. GPL-3.0-only A
Network activity blamed on ComfyUI is almost always the Manager extension or the Desktop app, not core. Evidence: source code (main.py) + Manager source + comfy.org privacy docs.
Jan~v0.8.x (Tauri), July 2026 update-check

apps.jan.ai — Tauri auto-updater (on launch / update check)
Kill: disable auto-update or firewall

github.com — fallback updater manifest + update binaries (update check)
Kill: disable auto-update

eu-assets.i.posthog.com — PostHog EU analytics (in app CSP) (ONLY if analytics toggled on)
Kill: leave Settings > Privacy > Analytics OFF (default off)

yes — PostHog EU, but OPT-IN and off by defaultopt-in Analytics needs no action (default off). Disable the auto-updater or firewall apps.jan.ai + github.com; import local GGUF files and inference is fully offline. Apache-2.0 A
Default install phones home only for update checks; exact PostHog ingest hostname unverified (CSP lists the EU asset host). Evidence: source code (tauri.conf.json updater + CSP hosts) + privacy docs.
GPT4Allv3.10.0 (Feb 2025 — app dormant since) multiple

gpt4all.io — model catalog, release check, news banner — plain HTTP with certificate verification DISABLED (on launch, UNCONDITIONALLY (no toggle))
Kill: none in-app — firewall the domain

api.mixpanel.com — Mixpanel analytics (ONLY if opted in at first launch)
Kill: decline the opt-in prompt (default off)

api.gpt4all.io — opt-in Datalake chat contribution (ONLY if Datalake enabled)
Kill: leave Datalake off (default)

api.ipify.org — public-IP lookup within the opted-in analytics flow (only with analytics on)
Kill: off with telemetry

yes — Mixpanel, but OPT-IN and off by defaultopt-in (analytics + Datalake); the catalog/update/news fetch has NO toggle Decline both first-launch prompts, then firewall gpt4all.io, api.gpt4all.io, api.mixpanel.com, api.ipify.org. Inference is fully local after model download; the unconditional catalog/news fetches fail harmlessly offline. MIT A
Genuinely opt-in analytics, but NOT zero-outbound: the launch-time catalog/update/news fetch runs plain HTTP with cert verification off and cannot be disabled in-app. Desktop app appears dormant since Feb 2025. Evidence: source code (network.cpp, mysettings.cpp, download.cpp).
LM Studio0.3.x line, July 2026 (closed source) multiple

unverified (update/CDN host not published) — update check — sends app/OS version + IP per privacy policy (launch / periodic)
Kill: no dedicated toggle; block at network level

unverified (model catalog/hub) — model search/downloads + anonymized search/download stats (when searching/downloading)
Kill: Settings: disable anonymous usage reporting

yes — anonymized usage/search stats per privacy policy (vendor undisclosed; closed source)opt-out Disable anonymous usage data in Settings, pre-download models, then network-block the app. Docs state chats/RAG never leave the device — but closed source means none of it is code-verifiable. Proprietary B
Never describe LM Studio as zero-telemetry: it phones home for updates and ships opt-out usage stats, and exact domains are unpublished. Evidence: official docs only (lmstudio.ai/app-privacy) — no source to audit.
Open WebUIv0.6.x, July 2026 telemetry

*.posthog.com (via bundled ChromaDB) — ChromaDB's anonymized product telemetry — a dependency, not an Open WebUI pixel (on vector-DB init/use)
Kill: ANONYMIZED_TELEMETRY=false (official Docker image ships this) or DO_NOT_TRACK=true

unverified Scarf gateway — install/pull download analytics (image/package pull)
Kill: SCARF_NO_ANALYTICS=true

api.github.com — version/update check (admin version check)
Kill: unverified toggle; block the domain

yes — PostHog via the ChromaDB dependency + Scarf install analyticsopt-out (official Docker image pre-disables the ChromaDB telemetry) Set ANONYMIZED_TELEMETRY=false, DO_NOT_TRACK=true, SCARF_NO_ANALYTICS=true (the first is already false in the official image). Chat inference itself stays local once models are on your runtime. BSD-3-Clause + branding clause (since v0.5.4 — not pure OSI) A
The telemetry originates in the bundled ChromaDB vector store; a ChromaDB pin fix landed in v0.6.18. Scarf destination domain unverified. Evidence: maintainer statement (discussion #15624) + .env.example + docs.
AnythingLLM~v1.15, July 2026 telemetry

app.posthog.com — PostHog Cloud anonymous product analytics (events like sent_chat, document_uploaded — metadata only, no content per docs) (ON BY DEFAULT: app start + tracked events)
Kill: DISABLE_TELEMETRY="true" env var (exact string match in source) or the in-app Privacy toggle

huggingface.co — one-time built-in model/embedder downloads (user-initiated)
Kill: skip once local

yes — PostHog Cloud, ON by defaultopt-out Set DISABLE_TELEMETRY="true" exactly (source checks === "true") or use the Privacy toggle; pick local providers only (Ollama/LocalAI + built-in embedder + LanceDB). Belt-and-suspenders: firewall app.posthog.com — issues #5496/#4534 suggest the flag alone may not kill every connection. MIT A
Docs say anonymous event metadata only, never chats/documents — but it ships enabled, which most self-hosters do not expect. Evidence: source code (server/models/telemetry.js, docker/.env.example).
vLLMv0.7–v0.11 line, July 2026 telemetry

stats.vllm.ai — first-party anonymous usage stats (GPU count/type/memory, cloud provider, OS/arch, vLLM version, model architecture) (on first engine start, then every 10 minutes)
Kill: VLLM_NO_USAGE_STATS=1, or DO_NOT_TRACK=1, or touch ~/.config/vllm/do_not_track

yes — first-party (no third-party SDK; collected data is publicly released)opt-out Export VLLM_NO_USAGE_STATS=1 (or DO_NOT_TRACK=1) before launch; add HF_HUB_OFFLINE=1 with pre-downloaded weights for full air-gap. A local copy of what would be sent sits in ~/.config/vllm/usage_stats.json — read it yourself. Apache-2.0 A
The most-cited surprise in local-AI serving: production inference engine, telemetry ON by default — though transparently documented and honoring DO_NOT_TRACK. Evidence: source code (vllm/usage/usage_lib.py) + official usage-stats docs.

Open data (CC BY 4.0): CSV · JSON · API: /wp-json/dc/v1/ai-telemetry?tool=vllm

Why “local” is not “offline”

Even tools that never transmit a single prompt routinely make unsolicited outbound connections for other reasons: desktop update checks (Ollama’s tray app, Jan’s Tauri updater, LM Studio), usage telemetry — first-party (vLLM’s stats endpoint) or smuggled in by a dependency (Open WebUI inherits PostHog from its bundled ChromaDB vector store) — crash reporters, model-registry and node-catalog pulls, and install-analytics beacons like Scarf. Model downloads are user-initiated and expected; this audit cares about what fires without asking. The cleanest cross-tool kill switch is the DO_NOT_TRACK convention — vLLM and Open WebUI both honor it — but per-tool env vars remain the reliable path, and a firewall rule remains the only proof.

Reading the verdicts fairly

A “telemetry” badge here is not an accusation of spying. vLLM’s usage stats are transparently documented, anonymous, and publicly released; AnythingLLM’s events are metadata only, never your chats or documents — the issue is that they ship enabled, which is not what most self-hosters assume. Conversely, an “opt-in” label doesn’t mean zero outbound: GPT4All’s analytics are genuinely off by default, yet its launcher still fetches its model catalog unconditionally over plain HTTP with certificate verification disabled. And closed source cuts both ways: LM Studio’s privacy policy is reasonable, but nobody can verify it in code, which is why it caps at evidence grade B. If your threat model is real — client data under Law 25, clearance environments, air-gapped coding — the recipe column plus a default-deny egress rule is the answer, not any vendor’s promise.

This registry completes the sovereignty story of our local-AI stack references: pick your runtime with the inference server comparison, size it with the VRAM & throughput calculator, ground it with local embedding models and a self-hosted vector database, then verify it’s actually private with the table above. For hardware that never needed a cloud in the first place, start at the Local LLM Canada hub.