Open-WebUI#
Open-WebUI runs on ereshkigal as a Podman OCI container managed by the
tsunaminoai.openWebui NixOS module
(modules/nixos/containers/open-webui/default.nix). It is the LLM chat front-end
for the local stack and doubles as a RAG knowledge base over the
Paperless-NGX document library. All inference is
delegated to Ollama on mokou over Tailscale — see
the AI overview for the full topology.
- Web UI (HTTP): http://ereshkigal:3000
- Web UI (HTTPS):
https://ereshkigal.<tailscaleDomain>:3001(when ACME is active) - Module option:
tsunaminoai.openWebui.enable = true;
Architecture#
The container is ghcr.io/open-webui/open-webui:main, run on the
openwebui_default Podman network with the alias open-webui. The host port
(default 3000) maps to container port 8080. Persistent state — including the
embedded ChromaDB vector store — lives in the named Podman volume
openwebui_data (/app/backend/data).
Chat and RAG embeddings both go to Ollama on mokou via the ollamaHost option,
which sets OLLAMA_BASE_URL to http://<ollamaHost>:11434. RAG uses the
ollama embedding engine backed by nomic-embed-text; web search is disabled
(ENABLE_RAG_WEB_SEARCH = "false") so retrieval stays local. The container is
started with --add-host=host.containers.internal:host-gateway so it can reach
mokou through the host’s Tailscale routing.
WEBUI_AUTH = "true", so login is required and the first user to register
becomes the admin.
Note
When tsunaminoai.pki.acme.enable is true, the module also stands up an
nginx vhost on port + 1 (3001) that reverse-proxies the web UI over TLS
using the host’s step-ca ACME cert
(useACMEHost = ereshkigal.<tailscaleDomain>). WEBUI_URL is set to that
HTTPS origin so absolute links and CSRF/CORS checks behave behind the proxy.
The firewall opens port, plus port + 1 only when ACME is active.
Enabling the module#
# hosts/x86_64-nixos/ereshkigal/default.nix
tsunaminoai.openWebui = {
enable = true;
ollamaHost = "mokou.${config.tsunaminoai.nix.tailscaleDomain}";
port = 3000;
paperlessPort = 8011;
};
Module options#
| Option | Default | Description |
|---|---|---|
enable |
false |
Enable Open-WebUI |
ollamaHost |
"localhost" |
Hostname/IP of the Ollama server (chat + embeddings); use mokou’s Tailscale FQDN |
port |
3000 |
Host port for Open-WebUI (HTTP); HTTPS is port + 1 |
paperlessPort |
8011 |
Port Paperless-NGX listens on (used by the sync timer) |
Environment variables#
| Variable | Value | Purpose |
|---|---|---|
OLLAMA_BASE_URL |
http://<ollamaHost>:11434 |
Chat inference endpoint |
WEBUI_AUTH |
"true" |
Require login; first user becomes admin |
WEBUI_URL |
https://<host>:3001 |
Public URL for link generation / CSRF |
RAG_EMBEDDING_ENGINE |
"ollama" |
RAG embedding backend |
RAG_EMBEDDING_MODEL |
"nomic-embed-text" |
Embedding model on mokou |
OLLAMA_BASE_URL_FOR_EMBEDDINGS |
http://<ollamaHost>:11434 |
Embedding endpoint |
ENABLE_RAG_WEB_SEARCH |
"false" |
Keep RAG local — no outbound web search |
VECTOR_DB |
"chroma" |
Embedded ChromaDB in openwebui_data |
Paperless → Open-WebUI RAG sync#
A nightly systemd timer, paperless-openwebui-sync (OnCalendar = 02:00,
Persistent so it catches up after downtime), pulls already-OCR’d Paperless-NGX
documents and upserts them into an Open-WebUI Knowledge collection via the
Knowledge API. The one-shot service reads two sops secrets at start
(ExecStartPre writes them to a runtime EnvironmentFile):
paperless/api-token— Paperless admin → Profile → API Tokenopenwebui/api-key— Open-WebUI → Settings → API Keys
Both must be created after first boot. The sync talks to Paperless at
http://127.0.0.1:<paperlessPort> and Open-WebUI at http://127.0.0.1:<port>.
Dashboard#
When tsunaminoai.homer.enable is set, the module registers a Homer tile
(“Open-WebUI”, under the Media group, ai tag) pointing at the HTTPS origin
when ACME is active, otherwise the plain HTTP URL.
Related#
- Ollama on mokou — the inference server this connects to
- Paperless-NGX — the document source for RAG sync
- ereshkigal — the host this runs on
- Container modules — overview of the Podman container modules