Skip to content
BotServBotServ
Nextcloud TalkBotAI BotOllamaSelf-HostingNextcloudOpen Source

Nextcloud Talk Bot with Local AI

Build a Nextcloud Talk bot with Ollama: webhook integration, chat commands, and fully self-hosted AI.

S

schutzgeist

6 min read
Nextcloud Talk Bot with Local AI

Building a Nextcloud Talk Bot with Local AI

What This Article Covers

  • Building a bot for Nextcloud Talk using Ollama.
  • Two approaches: webhook-based bots (official) and the webhook listener flow.
  • Creating a bot, receiving messages, sending replies, completely on-premise.
  • Extensions: file analysis, RAG on Nextcloud documents, notifications.
  • When Nextcloud Talk is the right platform and when it isn’t.

Introduction

If you’re already running Nextcloud, you get Nextcloud Talk practically for free: a chat platform with video calls, channels, and file sharing, all on your own server. Bots have been officially supported since Talk 18+: as “bots” with webhook registration or as classic chat commands.

Combining Nextcloud Talk with Ollama gives you perhaps the most sovereign bot solution available: chat, files, and AI all on a single private server. For families, clubs, and small businesses with existing Nextcloud infrastructure, this adds minimal overhead.

Common Use Cases

  • File assistant: “Summarize this PDF for me.” The bot accesses Nextcloud files directly, no upload needed.
  • Family AI: Kids and parents chat with the assistant on the family server.
  • Club chat: Questions about the club wiki answered via RAG.
  • Proactive notifications: Nextcloud events (new file, calendar reminders) delivered as AI comments.
  • Internal team bot: For organizations already using Nextcloud as their file hub.

Requirements

  • Nextcloud 28+ with Nextcloud Talk installed
  • Admin access (bot registration via occ command or admin UI)
  • Ollama with a model
  • Python 3.10+, Flask or FastAPI for the webhook endpoint

Step 1: Register the Bot in Talk

Nextcloud Talk supports two bot types:

  • Webhook bot: Talk calls your HTTP endpoint whenever a new message arrives (signature verified).
  • Command: A /command in Talk triggers a script, simplest entry point.

Register a webhook bot with occ:

sudo -u www-data php occ talk:bot:install \
    "AI Assistant" \
    "secret-shared-secret" \
    "https://your-domain.de/talk-bot/webhook"

This returns a bot ID and secret. The secret verifies that requests actually come from your Nextcloud instance.

.env:

NC_URL=https://cloud.your-domain.de
BOT_SECRET=secret-shared-secret
BOT_ID=123
OLLAMA_URL=http://localhost:11434
OLLAMA_MODEL=llama3.1:8b

Step 2: Webhook Endpoint (Python/Flask)

Talk sends a signed JSON POST to your endpoint each time a message arrives in a bot conversation:

import hashlib
import hmac
import os
import requests
import ollama
from flask import Flask, request, abort
from dotenv import load_dotenv

load_dotenv()
app = Flask(__name__)

NC_URL = os.environ["NC_URL"]
SECRET = os.environ["BOT_SECRET"].encode()
MODEL = os.environ.get("OLLAMA_MODEL", "llama3.1:8b")
ollama_client = ollama.Client(host=os.environ["OLLAMA_URL"])

SYSTEM = "You are a Nextcloud AI assistant. Keep answers concise and in English."


def verify_signature(req):
    """Talk signs requests with the shared secret."""
    signature = req.headers.get("X-Nextcloud-Talk-Bot-Signature", "")
    random_val = req.headers.get("X-Nextcloud-Talk-Random", "")
    backend = req.headers.get("X-Nextcloud-Talk-Backend", "")
    digest = hmac.new(SECRET, (random_val + req.get_data(as_text=True)).encode(),
                      hashlib.sha256).hexdigest()
    return hmac.compare_digest(signature, digest)


def reply(token, text, reference_id=None):
    """Post a reply to the Talk conversation."""
    requests.post(
        f"{NC_URL}/ocs/v2.php/apps/spreed/api/v1/bot/{token}/message",
        headers={"OCS-APIRequest": "true"},
        json={"message": text[:32000], "referenceId": reference_id or ""},
        auth=("bot", SECRET.decode()),
    )


def ask_ollama(text):
    resp = ollama_client.chat(model=MODEL, messages=[
        {"role": "system", "content": SYSTEM},
        {"role": "user", "content": text},
    ])
    return resp["message"]["content"]


@app.route("/talk-bot/webhook", methods=["POST"])
def webhook():
    if not verify_signature(request):
        abort(401)
    data = request.json or {}
    message = (data.get("object", {}).get("content") or "")
    actor = data.get("actor", {})
    convo = data.get("target", {})
    token = convo.get("id")

    if not message or not token:
        return {"ok": True}

    # Only reply to mentions or in direct chats
    if data.get("object", {}).get("type") == "chat_message":
        if "@" in message or convo.get("type") == 1:
            text = message.replace("@ai-assistant", "").strip()
            answer = ask_ollama(text)
            reply(token, answer, data["object"].get("id"))

    return {"ok": True}


if __name__ == "__main__":
    app.run(host="127.0.0.1", port=5050)

Configure your reverse proxy (Nginx or Caddy) to route https://your-domain.de/talk-bot/ to 127.0.0.1:5050.

Extensions

Analyzing Nextcloud Files

The bot can access files via the Nextcloud WebDAV API using an app password or bot user account. When someone says “Summarize file X”, the bot retrieves it, extracts text, and sends it to Ollama:

def fetch_file(path):
    r = requests.get(
        f"{NC_URL}/remote.php/dav/files/bot/{path}",
        auth=("bot", APP_PASSWORD))
    return r.content

Convert PDFs to text using Stirling-PDF or pypdf, then send to the model.

RAG on Nextcloud Documents

Regularly index a Nextcloud folder (text extraction + embeddings + Qdrant): the bot answers questions from all team documents. See Local RAG.

Proactive Notifications

The bot can post without being asked. For example, when a cron job forwards Nextcloud events (new file, calendar reminder) to the bot.

Command Variant (Simpler Entry Point)

Instead of webhooks, register a Talk command /ai: Talk executes your script with parameters:

sudo -u www-data php occ talk:command:add ai "Ask the AI" \
    --script "/opt/bot/ai.sh {ARGUMENTS}" --response 2

Good for simple commands and requires no web server, but lacks conversation context.

Deployment

services:
  talk-bot:
    build: ./bot
    restart: always
    env_file: .env
    ports: ["127.0.0.1:5050:5050"]
    depends_on: [ollama]

  ollama:
    image: ollama/ollama:latest
    volumes: [ollama_data:/root/.ollama]
    restart: always

volumes:
  ollama_data:

Security

  • Signature verification: Always verify, otherwise anyone with the URL can impersonate the bot.
  • Shared secret: Treat it like a password, never commit it.
  • HTTPS: Talk requires HTTPS endpoints. Use a reverse proxy with TLS.
  • Bot permissions: The bot only reads conversations it’s added to.

Common Pitfalls

  • Signature verification fails: Hash X-Nextcloud-Talk-Random + body in the correct order, using raw bytes, not re-parsed JSON.
  • Bot doesn’t see channel: The bot must be added to the conversation via the UI or occ talk:bot:add-to-room.
  • Webhook unreachable: Talk calls from the Nextcloud server, so localhost endpoints only work if Nextcloud runs locally.
  • Talk not installed: Bot features require the Talk app. Install it in Nextcloud’s app store.

Further Reading

Key Takeaways:

  • Nextcloud Talk + Ollama gives you the most sovereign bot solution possible: chat, file storage, and on-premise AI all in one.
  • Register the bot via occ command and implement webhook signature verification.
  • Standout feature: the bot accesses Nextcloud files directly, no manual uploads needed.
  • Least effort for existing Nextcloud users; if you’re building a standalone chat platform, Mattermost or Matrix are stronger choices.
  • Use commands for simple /slash commands, webhooks for full conversational bot logic.

FAQ

What are the minimum requirements?

Nextcloud 28+ with the Talk app, a registered bot (via occ talk:bot:install), an HTTPS endpoint for the webhook, and Ollama. No cloud account or external registration needed.

Webhook bot or command?

Use commands (/ki question) for simple one-step calls without server overhead. Webhook bots handle conversations with context, mentions, and proactive messages. A webhook is the right choice for an AI assistant.

Are Talk chats encrypted?

Talk provides transport and server-side encryption by default, but no end-to-end encryption. For E2EE, Matrix and Signal are better choices. The tradeoff is that with Talk you have complete data control on your own server.

How does Talk perform with many users?

For small to medium installations (up to roughly 50 users), Talk performs well. With many concurrent chat users, the High-Performance Backend (HPB) helps, though it requires additional setup. For large communities, Matrix or Mattermost scale better.

Can the bot read Nextcloud files?

Yes, via the WebDAV API using a dedicated bot user or app password. Download files, extract text (from PDFs using Stirling-PDF or pypdf), and send to Ollama. No manual uploads required.

What does it cost?

Nothing. Nextcloud Talk is open source. Costs come only from your server and GPU for Ollama. Ideal for families or associations that already run Nextcloud.

Talk or Matrix?

Choose Talk if you already use Nextcloud, since you avoid a second server and get file integration. Choose Matrix if you want a standalone chat platform with federation and E2EE. Both are self-hosted and open source.

Sources and Further Reading

Back to Blog
Share:

Related Posts