Germany → worldwide
WZ-IT Logo

Connecting Open WebUI to Nextcloud: RAG with real permissions (ACLs)

Timo Wevelsiep
Timo Wevelsiep
#OpenWebUI #Nextcloud #RAG #ACL #Qdrant #LocalAI

Editorial note: The information in this article was compiled to the best of our knowledge at the time of publication. Technical details, prices, versions, licensing terms, and external content may change. Please verify the information provided independently, particularly before making business-critical or security-related decisions. This article does not replace individual professional, legal, or tax advice.

Connecting Open WebUI to Nextcloud: RAG with real permissions (ACLs)

You want a local ChatGPT on your Nextcloud data - with real permissions instead of prompt promises? We build sovereign RAG systems where every request only sees the sources it is allowed to - see Custom RAG solutions and AI servers & local AI, or schedule an intro call directly.

A local language model on your own Nextcloud documents is quick to set up: Open WebUI as the interface, a few files into a knowledge base, done. For a prototype that is fine. For production it creates a silent data leak - because the permissions from Nextcloud do not travel with the files.

The central rule for a robust system: access control is not checked by the language model, but enforced technically before every vector search. Open WebUI is only the interface; the actual security logic lives in a dedicated retrieval service. This article shows the architecture behind it - from a shared identity through adopting the Nextcloud ACLs to the ACL filter in the vector database, and the path from POC to production. As of July 2026.

Table of contents

The core problem: the language model is not a gatekeeper

The obvious but wrong path: load all documents into a shared knowledge base and tell the model via system prompt to show HR files only to the HR department. That is not a security boundary. A language model is not a permission check - it can be talked into things, and a single unlucky retrieval hit is enough for a passage from a confidential document to end up in an answer.

The heart of the problem with the naive connection: Open WebUI does not automatically adopt the Nextcloud ACL when a file is uploaded. The HR file that is visible only to the HR department in Nextcloud becomes findable in the shared knowledge base for anyone with access to that knowledge base. That must not happen.

The solution is an architecture principle from classic enterprise applications: rights are enforced in the backend, not in the presentation layer. Applied to RAG that means - the model only receives text passages that are already authorized for the requesting user. What they may not see is not "forbidden" by prompt, it never reaches the model in the first place.

Between the interface and the language model sits a dedicated retrieval service that carries the security logic:

User
   │ login via OIDC/SSO
   ▼
Open WebUI                     (interface only)
   │ verified user identity
   ▼
ACL RAG service
   ├── resolve identity and groups server-side
   ├── build a mandatory ACL filter
   ├── run the vector search with the filter
   └── optionally re-authorize the final sources
   ▼
Qdrant / pgvector              (only allowed chunks)
   ▼
LLM via vLLM / LiteLLM

The decisive point: the LLM only ever receives already authorized results. It never sees chunks that are subsequently withheld only by prompt.

A shared identity as the foundation

For rights to propagate cleanly at all, every system - Open WebUI, Nextcloud and the RAG service - needs the same identity provider, for example Keycloak, Microsoft Entra ID or an Active Directory.

A user should have a stable, immutable ID across all systems. The email address is unsuitable as a permanent primary key because it can change. The OIDC sub, or a stable AD/LDAP ID, is better. From it, the user's security principals are derived per request - their own ID plus all groups they belong to (such as group:idp:sales, group:idp:all-staff). It is precisely against these principals that the search filter is later built.

Passing the identity securely to the RAG service

This step deserves a close look, because it is where most misconceptions happen. Open WebUI can forward user information to external OpenAPI or MCP tool servers - but not automatically and not cryptographically secured by default.

By default, forwarding is off. Only when ENABLE_FORWARD_USER_INFO_HEADERS=true is set does Open WebUI send four plaintext headers to the tool server: X-OpenWebUI-User-Id, X-OpenWebUI-User-Email, X-OpenWebUI-User-Name and X-OpenWebUI-User-Role. The Open WebUI documentation itself notes that these are unsigned headers that anything on the network path could spoof (Open WebUI Environment Configuration).

A signed token is only available as opt-in: if you additionally set the environment variable FORWARD_USER_INFO_HEADER_JWT_SECRET, Open WebUI replaces the plaintext headers with an HS256-signed JWT in the X-OpenWebUI-User-Jwt header (default lifetime 300 seconds). Important: HS256 uses a shared secret, not a public key - the RAG service verifies with the same secret. Two practical consequences:

  • The RAG endpoint must not be reachable directly from the browser. Only Open WebUI or an internal API gateway calls it; it lives on the internal network.
  • Groups are not contained in the token. Neither the plaintext headers nor the JWT carry group membership. The RAG service must therefore resolve groups itself from the OIDC token or via LDAP and cache them briefly. This is the correct boundary: the user sends no ACLs and no groups - the server determines them solely from the verified identity.

For the connection itself, Open WebUI supports external OpenAPI tool servers registered centrally by an administrator; global tools are called by the Open WebUI backend (Open WebUI Tools).

Adopting Nextcloud permissions into ACLs

During indexing the connector must determine the effective ACL for each document: who owns it, who is it directly shared with, does it sit in a shared parent folder, do additional file-access-control rules apply? Nextcloud exposes these shares via the OCS Share API. For a path you can query the shares; with the reshares parameter you get not only your own but all shares of a file, and with subfiles all shares within a folder (Nextcloud OCS Share API).

For internal RAG you adopt by default only owner, direct user shares, internal group shares and explicitly shared team folders. Public link shares should not automatically mean that every AI user gets access. The computed effective ACL is materialized during indexing and stored as a list of principals in each chunk's payload:

{
  "tenant_id": "customer-a",
  "document_id": "nextcloud:file:597996",
  "chunk_id": "nextcloud:file:597996:chunk:12",
  "allow_principals": ["user:nc:mueller", "group:idp:sales"],
  "visibility": "restricted",
  "deleted": false
}

For ongoing changes, Nextcloud has offered the FullTextSearch Collection API since version 27. It is designed precisely for indexing into an external search engine and delivers new, changed and newly shared documents including content as a feed. An important security note is stated verbatim in the documentation: the account linked to the collection gains access to the content of all documents of all Nextcloud users through this API (Nextcloud FullTextSearch Collection API). The connector is thus a highly privileged component and must be secured accordingly. In addition, Nextcloud serves files over WebDAV for download and change detection.

From the user's principals the retrieval service builds a mandatory filter that is executed together with the vector search. In Qdrant it looks conceptually like this:

from qdrant_client.models import FieldCondition, Filter, MatchAny, MatchValue

user_principals = ["user:idp:8db4...", "group:idp:sales", "group:idp:staff"]

query_filter = Filter(
    must=[
        FieldCondition(key="tenant_id", match=MatchValue(value="customer-a")),
        FieldCondition(key="deleted", match=MatchValue(value=False)),
    ],
    should=[
        FieldCondition(key="visibility", match=MatchValue(value="all_authenticated")),
        FieldCondition(key="allow_principals", match=MatchAny(any=user_principals)),
    ],
    must_not=[
        FieldCondition(key="deny_principals", match=MatchAny(any=user_principals)),
    ],
)

What matters is what does not happen here: no unfiltered search for the top 100 documents followed by removing the forbidden hits. Qdrant integrates the filter condition directly into the graph traversal of the similarity search (filterable HNSW) rather than as a post-filter (Qdrant Filtering). That way the model does not see forbidden chunks - unlike a post-filter, which is error-prone and weakens tenant separation.

For separating multiple customers, Qdrant explicitly recommends one collection with payload partitioning (a tenant_id field) over a separate collection per user; the tenant field should be created as a payload index (Qdrant Multitenancy). Two rules are non-negotiable: the tenant_id filter is always mandatory, and no search endpoint accepts freely supplied user or group IDs.

Revocation and the fail-closed principle

A production system must not only index new files but also enforce revocations quickly - a removed share, a deactivated user, a member removed from a group. Two separate synchronization paths have proven effective: a content sync (text and file version) and an ACL sync (permissions via Share API and identity provider), complemented by a regular full reconciliation at night. Security-critical changes invalidate the cache immediately.

For an unclear or faulty ACL the rule is fail-closed: if the permission cannot be determined, the document is not searchable - never the other way around. For especially sensitive data (HR, legal, executive) a second check pays off: the top hits of the vector search are re-authorized against the current state before being handed to the model. This shrinks the window between a revocation in Nextcloud and the next index synchronization.

From proof of concept to production

Not every project needs the full architecture at once. Two stages make sense:

Proof of concept - a shared knowledge folder. Create a clearly delimited folder in Nextcloud (such as /company-knowledge-ai/) that only holds documents all intended AI users may see. A technical read-only user gets access only to this folder; the folder is synchronized with the built-in Open WebUI knowledge base via WebDAV or the Nextcloud client. The formula: one Nextcloud share = one knowledge base = one defined user group. This is quick to production but explicitly not intended for individual user permissions.

Production - a dedicated ACL-aware retrieval service. As soon as individual user and group permissions must be mapped, the path leads through a dedicated retrieval service (such as FastAPI): JWT verification, principal resolution, ACL filter and source check, fed by a Nextcloud connector over FullTextSearch Collection API, WebDAV and OCS Share API. PostgreSQL holds document status, ACL mapping and audit; Qdrant holds the embeddings with the ACL payload. Open WebUI integrates this service via an OpenAPI tool. This is also the point where Langfuse for LLM observability and a clean audit trail pay off.

How we work at WZ-IT

We build such systems as a Custom RAG solution on sovereign infrastructure - fully local or in a European cloud, without data leaking to US AI services:

  1. Data classification first. Before any hardware arrives, we clarify which data may go into the AI at all, what share structure exists in Nextcloud and which identity provider delivers the principals.
  2. Security in the backend, not in the prompt. The ACL filter runs in the retrieval service, mandatory on every search, fail-closed. The model only sees authorized results.
  3. Operate and maintain. ACL sync, revocation, reindexing and model updates run under contract - including an audit log of which source with which ACL version went to which request.

That turns "a chatbot on our files" into a system whose access protection is as robust as that of a classic line-of-business application - regardless of how cooperative the model happens to be.

Further guides

Before the first HR file lands in the wrong chat window: we design and operate RAG systems where permissions are enforced technically - not left to the language model. Schedule an intro call.

Sources

Frequently Asked Questions

Answers to important questions about this topic

No - and it should not. Open WebUI is the interface. Leaving access control to the language model means trusting the model to obey a prompt instruction. That is not a security boundary. In a production system the ACLs are enforced technically before every vector search, in a dedicated retrieval service. The model only ever sees results that are already authorized.

Only if you actively enable it. By default Open WebUI does not forward signed tokens; when forwarding is enabled at all, it sends unsigned plaintext headers (X-OpenWebUI-User-Id, -Email, -Name, -Role) that anything on the network path could spoof. A signed JWT is only produced when you additionally set a secret via the environment variable FORWARD_USER_INFO_HEADER_JWT_SECRET; then an HS256-signed token is sent in the X-OpenWebUI-User-Jwt header. HS256 uses a shared secret, not a public key. The RAG endpoint must only be reachable internally.

Not from Open WebUI. The forwarded header or JWT contains no groups - there is no X-OpenWebUI-User-Groups header and no groups claim. The RAG service must therefore resolve groups server-side itself, from the central identity provider (OIDC) or via LDAP. This is not a drawback but the correct architecture: access rights must never be derived from client-supplied data.

During indexing a connector computes the effective ACL per document: owner, direct shares, inherited folder shares and internal group shares. This ACL is stored as a list of security principals in each chunk's payload. Nextcloud exposes the shares via the OCS Share API; changes to files and shares can be pulled as a feed via the FullTextSearch Collection API.

Because post-filtering is error-prone and weakens tenant separation. Qdrant applies the filter directly during the similarity search (filterable HNSW) instead of first finding top results and then removing forbidden ones. That way the model never sees forbidden chunks. For tenant separation, Qdrant explicitly recommends payload filters over a collection per user.

For a single shared knowledge folder released to all AI users, yes - that is a good POC. For mapping individual user and group permissions, no: the built-in knowledge base does not automatically adopt the Nextcloud ACL on upload. That requires a dedicated retrieval service that Open WebUI calls via an OpenAPI tool or pipeline.

There is no officially documented one-click switch. But all interfaces to build the connection cleanly are documented: Nextcloud WebDAV and OCS Share API, the FullTextSearch Collection API as a change feed, plus Open WebUI's file and knowledge API and its forwarding of the user identity to external tool servers.

Timo Wevelsiep

Written by

Timo Wevelsiep

Co-Founder & CEO

Co-Founder of WZ-IT. Specialized in cloud infrastructure, open-source platforms and managed services for SMEs and enterprise clients worldwide.

LinkedIn

Let's Talk About Your Idea

Whether a specific IT challenge or just an idea - we look forward to the exchange. In a brief conversation, we'll evaluate together if and how your project fits with WZ-IT.

E-Mail
[email protected]

Leading companies trust WZ-IT

  • ml&s
  • Rekorder
  • Keymate
  • Führerscheinmacher
  • SolidProof
  • ARGE
  • Boese VA
  • nextGYM
  • Maho Management
  • Golem.de
  • Millenium
  • Paritel
  • Yonju
  • EVADXB
  • Mr. Clipart
  • Aphy AG
  • Negosh
  • ABCO Water Systems
Timo Wevelsiep & Robin Zins - CEOs of WZ-IT

Timo Wevelsiep & Robin Zins

Managing Directors of WZ-IT

1/3 - Topic Selection33%

What is your inquiry about?

Select one or more areas where we can support you.