Skip to main content
Glama

Athena

Ein persönliches Wiki, in das Ihre KI schreibt und das Sie selbst durchsuchen können.

Athena stellt einen MCP-Server vor Wiki.js. Ihr Assistent durchsucht das Wiki, liest Seiten und legt neue Seiten an: Notizen, Dokumentationen, ganze Gespräche. Alles, was es schreibt, ist eine gewöhnliche Markdown-Seite, die Sie öffnen, bearbeiten und behalten können, lange nachdem ein bestimmtes Modell verschwunden ist.

Claude / ChatGPT / Cursor
        │  MCP over HTTPS
        ▼
   athena-mcp ──── search ──▶ Wiki.js (keyword) + Postgres (meaning)
        │          read ────▶ Wiki.js
        └────────  write ───▶ Wiki.js ──▶ athena-indexer ──▶ Postgres

Wiki.js ist die Quelle der Wahrheit. Der Vektorindex hilft nur beim Auffinden von Dingen und kann jederzeit gelöscht und neu aufgebaut werden.


Schnellstart

Lokal, in etwa fünf Minuten. Für alles im Internet lesen Sie zuerst Auf einem Server bereitstellen.

git clone https://github.com/jannismilz/athena.git
cd athena
cp .env.example .env
$EDITOR .env          # fill in every CHANGE_ME, one per secret:
                      #   openssl rand -hex 32
docker compose up -d
  1. Öffnen Sie Wiki.js und schließen Sie den Setup-Assistenten ab.

  2. In Wiki.js: Administration → API, aktivieren Sie es, erstellen Sie einen Token und setzen Sie ihn in .env als WIKI_API_TOKEN.

  3. docker compose up -d erneut ausführen, um es zu übernehmen.

  4. Öffnen Sie das Dashboard und melden Sie sich mit DASHBOARD_TOKEN an.

Daten werden in ein data/-Verzeichnis neben dem Checkout geschrieben, nicht darin, sodass keine Git-Operation es jemals löschen kann. Ändern Sie ATHENA_DATA_DIR, wenn Sie es woanders haben möchten.

Nichts veröffentlicht einen Port, also erreichen Sie die Dienste über Ihren Reverse-Proxy oder fügen Sie ein temporäres ports:-Mapping hinzu, während Sie es ausprobieren.

Beim ersten Start wird ein Embedding-Modell von einigen hundert MB heruntergeladen. Der Indexer wiederholt den Vorgang, bis es bereit ist. Daher ist es normal, dass embeddings beim ersten Start ein oder zwei Minuten lang als nicht gesund erscheint.


Related MCP server: wiki-js-mcp

Ihre KI verbinden

Alles wird von MCP_PUBLIC_URL bereitgestellt, das eine reine https://-Origin ohne Pfad sein muss. Nicht /mcp.

Claude.ai → Einstellungen → Verbindungen → Benutzerdefinierte Verbindung hinzufügen

  • URL: https://athena-mcp.example.com/mcp

  • Lassen Sie Client-ID und Secret leer. Athena registriert den Client selbst.

  • Eine Browser-Seite fragt nach einem Passwort. Es ist Ihr MCP_TOKEN.

Cursor, Claude Desktop und andere Header-Clients

{
  "mcpServers": {
    "athena": {
      "url": "https://athena-mcp.example.com/mcp",
      "headers": { "Authorization": "Bearer YOUR_MCP_TOKEN" }
    }
  }
}

Werkzeuge

Tool

Was es tut

search_knowledge

Stichwort- und semantische Suche, fusioniert. Jeder Treffer enthält einen Pfad.

get_page

Vollständiges Markdown einer Seite

get_page_structure

Gliederung der Überschriften, ohne den Text

append_to_page

Unter einer Überschrift hinzufügen, den Rest unberührt lassen

create_page

Neue Markdown-Seite

update_page

Seiteninhalt ersetzen

move_page

Verschieben oder umbenennen

delete_page

Löschen und aus dem Index entfernen

save_conversation

Ein Gespräch unter conversations/YYYY/MM/ ablegen

capture_note

Schnelle Notiz in inbox/ zur späteren Ablage

list_pages

Alles, mit Pfaden und Zeitstempeln

get_wiki_stats

Größe, Form und Veralterung, damit die KI beantworten kann, was fehlt

append_to_page ist die, die man kennen sollte: Das Hinzufügen einer Tatsache kostet einen Absatz, nicht eine Neufassung der ganzen Seite.

Warum es gut abruft. Exakte Begriffe treffen den Volltext-Index von Wiki.js, vage Fragen treffen den Vektor-Index, und die Ergebnisse werden mit dem Reciprocal Rank Fusion fusioniert, sodass keine Quelle die andere überlagern kann. Chunks zeichnen die darüber liegenden Überschriften auf, sodass das Zurückgegebene seinen Kontext behält. Jede Seite, die ein Assistent berührt, wird mit dem Datum und dem Assistenten gestempelt, die aus dem authentifizierten Client stammen, nicht aus dem, was das Modell über sich selbst behauptet.


Dashboard

Ein eigener Dienst, auf Port 8082. Melden Sie sich mit DASHBOARD_TOKEN an; es gibt keinen Token in einer URL. Für Skripte verwenden Sie einen Bearer-Header:

curl -H "Authorization: Bearer $DASHBOARD_TOKEN" \
  https://wiki.example.com/dashboard/api/metrics?days=30

Bereich

Antworten

Inhalt

Seiten, Wörter, pro Bereich, größte, veraltend

KI-Aktivität

Aufrufe pro Tag, welche Werkzeuge, welcher Assistent, lesen vs. schreiben

Suchvorgänge ohne Treffer

was Ihr Wiki nicht beantworten konnte

Index-Zustand

gespeicherte Chunks, indizierte Seiten, wie weit zurück

Sicherung

wann der letzte Lauf endete, wie groß, wohin es ging

Die dritte Zeile ist die, die ihren Platz verdient. Jeder Eintrag ist eine Seite, die es wert ist, geschrieben zu werden.

Es ist doppelt schreibgeschützt: Es schreibt nie und verbindet sich als athena_readonly mit Postgres, einer Rolle, die nur SELECT und nichts anderes besitzt. Zahlen werden in Postgres aggregiert und zwischengespeichert, sodass eine Aktualisierung fast nichts kostet.


Auf einem Server bereitstellen

Ein 4-GB-VPS betreibt alles, einschließlich des Embedding-Modells auf der CPU.

1. Host und Firewall

sudo ufw default deny incoming && sudo ufw default allow outgoing
sudo ufw allow 22/tcp && sudo ufw allow 80/tcp && sudo ufw allow 443/tcp
sudo ufw enable

Installieren Sie Docker, dann erstellen Sie einen Benutzer, der die Bereitstellung besitzt:

sudo useradd --create-home --shell /bin/bash athena
sudo usermod -aG docker athena

Führen Sie Compose als diesen Benutzer aus, niemals mit sudo, sonst werden die Bind-Mounts root gehören. Die Mitgliedschaft in der docker-Gruppe ist gleichbedeutend mit root auf dem Host, also halten Sie sie klein.

2. DNS

Zwei A-Einträge, die auf den Host verweisen:

Name

Wird bereitgestellt

wiki.example.com

Wiki.js und das Dashboard unter /dashboard/

athena-mcp.example.com

den MCP-Endpunkt

3. Anlegen und konfigurieren

Alles, was Athena schreibt, wird durch eine Einstellung, ATHENA_DATA_DIR, gesteuert, sodass die gesamte Installation unter einem einzigen Verzeichnis leben kann. Verwenden Sie zwei Unterverzeichnisse mit unterschiedlichen Lebenszyklen:

/athena
├── app/     the git repository   replaceable, thrown away on every upgrade
└── data/    postgres, state,     irreplaceable, never touched by git
             uploads, backups

Sie sind Geschwister, nicht verschachtelt, und das ist der ganze Sinn. data/ ist in .gitignore, und git clean -xdf löscht ignorierte Dateien, sodass Daten im Checkout nur einen Routinebefehl von der Löschung ohne Bestätigung und ohne Rückgängigmachung entfernt sind. Ein Geschwisterverzeichnis kann von keiner Git-Operation erreicht werden.

Der Standardwert ATHENA_DATA_DIR=../data gibt Ihnen dieses Layout automatisch, sodass Sie sich nichts merken müssen.

sudo mkdir -p /athena && sudo chown athena:athena /athena
cd /athena
git clone https://github.com/jannismilz/athena.git app
cd app
cp .env.example .env
chmod 600 .env        # it holds every secret

ATHENA_DATA_DIR ist standardmäßig ../data, das relativ zum Verzeichnis mit der Compose-Datei aufgelöst wird. Klonen Sie wie oben in /athena/app und die Daten landen in /athena/data, ohne dass etwas konfiguriert werden muss. Setzen Sie die Geheimnisse:

POSTGRES_PASSWORD=...
MCP_TOKEN=...
DASHBOARD_TOKEN=...
DASHBOARD_DB_PASSWORD=...
MCP_PUBLIC_URL=https://athena-mcp.example.com
WIKI_PUBLIC_URL=https://wiki.example.com

Compose erstellt /athena/data und seine Unterverzeichnisse beim ersten Start. Führen Sie jeden docker compose-Befehl von /athena/app aus.

/athena/data
├── postgres/     the wiki, users, settings, uploads, activity log, vectors
├── wikijs/       Wiki.js config, cache, upload cache
├── mcp/          oauth-state.json, the tokens issued to AI clients
├── indexer/      index bookkeeping, rebuilt automatically if lost
├── embeddings/   the downloaded model
└── backups/      local dumps plus status.json

Nur postgres/ ist unersetzlich, und der Backup-Container sichert es stündlich. Alles andere wird entweder automatisch neu generiert oder kostet eine erneute Verbindung.

Wenn Sie stattdessen der Dateisystem-Hierarchie-Konvention folgen möchten, legen Sie die Daten in /srv/athena und den Checkout in /opt/athena. Das obige Single-Root-Layout ist auf einer Maschine, die eine Aufgabe erledigt, einfacher, und beides funktioniert: Nur ATHENA_DATA_DIR entscheidet.

4. Reverse-Proxy

Kein Container veröffentlicht einen Port. Dienste befinden sich in zwei Netzwerken:

  • athena, intern. Postgres, das Embedding-Modell und der Indexer leben nur hier, sodass ein kompromittierter Proxy nicht auf die Datenbank zugreifen kann.

  • athena-edge, dem Ihr Reverse-Proxy beitritt. Nur die drei unten genannten Dienste sind darauf.

Leiten Sie diese weiter:

Host

Zu

Hinweise

wiki.example.com

wikijs:3000

WebSocket-Upgrade, 100M Body-Limit

wiki.example.com/dashboard/

dashboard:8082

athena-mcp.example.com

mcp:8080

darf nicht puffern, MCP-Streams

Leiten Sie X-Forwarded-For weiter: Die Anmeldungen drosseln pro Adresse, und ohne sie sieht jeder Versuch so aus, als käme er vom Proxy.

Führen Sie nginx als Container aus, der dem athena-edge-Netzwerk beitritt, wie unten, oder auf dem Host mit einem ports:-Mapping, das an 127.0.0.1 gebunden ist. Der Beitritt zum Edge-Netzwerk bedeutet, dass der Proxy Wiki.js, den MCP-Server und das Dashboard erreichen kann, und sonst nichts.

server {
    listen 80;
    server_name wiki.example.com;

    location / {
        proxy_pass http://wikijs:3000;
        proxy_http_version 1.1;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade           $http_upgrade;
        proxy_set_header Connection        "upgrade";
        client_max_body_size 100M;
        proxy_read_timeout 120s;
    }

    location /dashboard/ {
        proxy_pass http://dashboard:8082/;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

server {
    listen 80;
    server_name athena-mcp.example.com;

    location / {
        proxy_pass http://mcp:8080;
        proxy_http_version 1.1;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # MCP streams responses. Without these, long tool calls appear to hang.
        proxy_set_header Connection "";
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 300s;
    }
}

Dann stellen Sie Zertifikate mit certbot aus oder terminieren Sie TLS, wo immer Sie es bereits tun.

Hier ist nichts plattformspezifisch. Eine PaaS, die Compose ausführt und einen eigenen Proxy bereitstellt, benötigt drei Einstellungen, alle in .env:

ATHENA_DATA_DIR=../files          # Dokploy's persistent directory
ATHENA_EDGE_NETWORK=dokploy-network
ATHENA_EDGE_EXTERNAL=true

ATHENA_DATA_DIR ist am wichtigsten: Dokploy bereinigt absolute Bind-Mount-Pfade bei der erneuten Bereitstellung, sodass ein absoluter Pfad dort die Datenbank zerstören würde. Ein Pfad relativ zum App-Verzeichnis überlebt.

Dann fügen Sie Domains in der Plattform-UI hinzu, die auf den Dienst und seinen Port verweisen:

Domain

Service

Port

wiki.example.com

wikijs

3000

athena-mcp.example.com

mcp

8080

wiki.example.com/dashboard

dashboard

8082

Die Plattform generiert ihre eigenen Routing-Labels und kümmert sich um TLS, also überspringen Sie den nginx-Abschnitt vollständig. Alles andere, einschließlich der Compose-Datei, bleibt unverändert.

Sie müssen keine Images in eine Registry veröffentlichen: Dokploy baut aus dem Repository. Das Erstellen von vier Images konkurriert mit Postgres und dem Embedding-Modell um Speicher, daher sollten Sie auf einem kleinen Host möglicherweise lieber in CI bauen und stattdessen pullen.

5. Starten, dann das Wiki absichern

docker compose up -d && docker compose ps

Schließen Sie den Wiki.js-Assistenten sofort ab. Solange Sie das nicht tun, kann jeder, der den Host findet, das Admin-Konto übernehmen. Dann in Wiki.js:

  • Gruppen → Gäste: Leseberechtigung entfernen, es sei denn, Sie möchten das Wiki öffentlich machen.

  • Authentifizierung: Selbstregistrierung deaktivieren.

  • API: aktivieren und den Token für WIKI_API_TOKEN erstellen.

6. Überprüfen

curl -s https://athena-mcp.example.com/health

# Must reject unauthenticated calls:
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://athena-mcp.example.com/mcp
# expected: 401

Sicherungen

Ein pg_dump ist ein vollständiges Backup. Wiki.js speichert Seiten, Verlauf, Benutzer, Berechtigungen, Einstellungen und die Bytes jeder hochgeladenen Datei in Postgres. Uploads leben in der assetData-Tabelle; die Dateien unter data/wikijs/uploads sind nur ein Cache. Das Aktivitätsprotokoll und die Suchvektoren von Athena befinden sich in einer zweiten Datenbank auf demselben Server.

Daten

Im Backup

Seiten, Verlauf, Benutzer, Einstellungen

ja

Hochgeladene Bilder und Dateien

ja

Aktivitätsprotokoll und Suchvektoren

ja

Index-Buchhaltung, OAuth-Registrierungen

nein, wird neu aufgebaut oder neu verbunden

.env

nein, Kopie in einem Passwort-Manager aufbewahren

Der backup-Container läuft stündlich. Jeder Lauf sichert beide Datenbanken, prüft, ob jeder Dump lesbar ist, behält eine lokale Kopie, überträgt an Ihr rclone-Ziel, überprüft, ob der Upload übereinstimmt, und löscht erst dann. Ein fehlgeschlagener Lauf kann niemals Ihr letztes gutes Backup löschen.

docker compose run --rm backup now            # take one now
docker compose run --rm backup restore list   # see what exists
docker compose logs -f backup                 # watch the schedule

Konfiguriere alles in .env. Jedes rclone-Ziel funktioniert: S3, Backblaze, Wasabi, MinIO, Hetzner. Lasse BACKUP_REMOTE leer, um Backups nur auf dem Host zu behalten.

Füge ein Crypt-Remote hinzu und setze BACKUP_REMOTE darauf. Das Ziel erhält dann nur noch Chiffrat, einschließlich Dateinamen.

BACKUP_REMOTE=crypt:
RCLONE_CONFIG_CRYPT_TYPE=crypt
RCLONE_CONFIG_CRYPT_REMOTE=s3:my-bucket/athena
RCLONE_CONFIG_CRYPT_PASSWORD=<rclone obscure ...>
RCLONE_CONFIG_CRYPT_PASSWORD2=<rclone obscure ...>

Bewahre beide Passwörter in deinem Passwort-Manager auf. Ohne sie sind die Backups unlesbar, auch für dich.

Wiederherstellung

Übe das, bevor du es brauchst. Eine Wiederherstellung, die niemand durchgeführt hat, ist eine Vermutung.

docker compose run --rm backup restore list
docker compose stop wikijs mcp indexer dashboard
docker compose run --rm backup restore run 2026-08-18T115529Z
docker compose start wikijs mcp indexer dashboard

Es fordert dich auf, den Datenbanknamen zur Bestätigung einzugeben. restore fetch <stamp> lädt ein Backup herunter, ohne es wiederherzustellen, und meldet, ob jeder Dump lesbar ist.

Der Suchindex repariert sich danach selbst: Der Indexer liest jede Seite erneut und bettet alles, dessen Inhalt sich geändert hat, neu ein.


Konfiguration

Alles kommt aus der Umgebung. Jeder Dienst validiert seine eigene Konfiguration beim Start und beendet sich mit einer Liste dessen, was falsch ist, sodass ein Tippfehler sofort und nicht um drei Uhr morgens auffällt.

Die fünf Geheimnisse, alle von dir generiert. Keine Anmeldedaten von Claude, OpenAI oder irgendjemand anderem werden jemals in .env gespeichert.

Geheimnis

Gehalten von

Schützt

POSTGRES_PASSWORD

postgres, mcp, indexer

vollständiger Datenbankzugriff

WIKI_API_TOKEN

mcp, indexer

die Wiki.js API

MCP_TOKEN

mcp

den MCP-Endpunkt

DASHBOARD_TOKEN

dashboard

die Dashboard-Anmeldung

DASHBOARD_DB_PASSWORD

dashboard, mcp, indexer

eine SELECT-only Datenbankrolle

Was läuft

Dienst

Port

Was es ist

postgres

intern

Wiki.js-Daten, Aktivitätsprotokoll und Vektoren via pgvector

wikijs

3000

Das Wiki, das du liest und bearbeitest

embeddings

intern

Das Embedding-Modell, auf CPU

mcp

8080

Womit sich deine KI verbindet

indexer

8081

Hält den Vektorindex synchron mit dem Wiki

dashboard

8082

Metriken

backup

keiner

Stündlicher Dump, Überprüfung, Push

Es gibt keine separate Vektordatenbank. Vektoren leben in Postgres, also sichert ein Backup alles ab.

Auf ARM-Hosts wird das Embeddings-Image nur für linux/amd64 veröffentlicht und läuft nicht nativ. Setze stattdessen EMBEDDINGS_PROVIDER=openai auf einen OpenAI-kompatiblen Endpunkt wie Ollama.

Variable

Standard

Hinweise

ATHENA_DATA_DIR

../data

Wurzel jedes Bind-Mounts, ein Geschwister des Checkouts

ATHENA_INSTANCE_NAME

Athena

Wird auf der Anmeldeseite und im Dashboard angezeigt

ATHENA_EDGE_NETWORK

athena-edge

Netzwerk, dem dein Reverse-Proxy beitritt

ATHENA_EDGE_EXTERNAL

false

true, wenn die Plattform dieses Netzwerk bereitstellt

ATHENA_LOG_LEVEL

info

debug, info, warn, error

TZ

UTC

Herkunftsstempel und datierte Pfade

POSTGRES_DB

wiki

Die Wiki.js-Datenbank

ATHENA_DB

athena

Aktivitätsprotokoll und Vektoren, wird automatisch erstellt

WIKI_LOCALE

en

Inhaltssprache

WIKI_PUBLIC_URL

http://localhost:3000

Wird für Dashboard-Links verwendet

MCP_PUBLIC_URL

erforderlich

Bloße https-Origin, kein Pfad

METRICS_CACHE_SECONDS

60

Wie lange Dashboard-Zahlen wiederverwendet werden

EMBEDDINGS_MODEL

intfloat/multilingual-e5-small

Eine Änderung indiziert alles neu

EMBEDDINGS_PROVIDER

tei

tei oder openai für einen kompatiblen Endpunkt

INDEX_INTERVAL_SECONDS

300

Vollständiges Abgleichsintervall

CHUNK_MAX_CHARS

1200

Obergrenze der Chunk-Größe

BACKUP_*

siehe .env.example

Zeitplan, Aufbewahrung, rclone-Ziel

Eine Änderung von EMBEDDINGS_MODEL ändert die Vektorbreite, und Vektoren von zwei Modellen können nicht verglichen werden, also baut der Indexer die Tabelle neu auf und bettet jede Seite neu ein. Der Wiki.js-Inhalt bleibt unberührt.


Sicherheit

Jeder Container erhält nur die Anmeldedaten, die er verwendet. Das Dashboard bekommt weder POSTGRES_PASSWORD noch WIKI_API_TOKEN, sodass eine Kompromittierung Lesezugriff und nichts weiter ergibt. Jederzeit überprüfbar:

docker compose exec dashboard env | grep -iE 'PASSWORD|TOKEN'
  • Nicht authentifizierte MCP-Anfragen erhalten 401 und keine Erklärung.

  • Beide Anmeldepfade drosseln nach 5 Fehlversuchen pro Adresse; ein Anmeldelink verfällt nach 3 Versuchen.

  • Dashboard-Sitzungen sind signierte Cookies, die ein Ablaufdatum und eine Nonce tragen, niemals das Token. HttpOnly, SameSite=Strict, und standortübergreifende Posts werden abgelehnt.

  • Geheimnisvergleiche sind zeitkonstant.

  • Proxy-Header werden nur von Loopback vertraut, sodass ein entfernter Client seine Adresse nicht fälschen kann, um einer Drosselung zu entgehen.

  • Container laufen als ein Nicht-Root-Benutzer.

Bewusst nicht vorhanden: Berechtigungen pro Tool. Jeder authentifizierte Client kann jedes Tool aufrufen, einschließlich delete_page. Wiki.js führt eine Seitenhistorie, sodass ein Löschen wiederherstellbar ist, aber behandle MCP_TOKEN als vollständigen Schreibzugriff auf dein Wiki. Athena geht außerdem von einem einzigen Besitzer aus; Wiki.js hat seine eigenen Benutzer zum Lesen des Wikis.

MCP_TOKEN funktioniert auf zwei Arten, weil KI-Clients sich auf zwei Arten authentifizieren.

Header-Clients wie Cursor und Claude Desktop senden Authorization: Bearer <MCP_TOKEN>. Das ist der gesamte Mechanismus.

Claude.ai im Browser kann das nicht. Seine benutzerdefinierten Konnektoren unterstützen nur OAuth, und die MCP-Spezifikation erfordert eine dynamische Client-Registrierung, also muss ein Server, der Browser-Claude akzeptiert, selbst ein Autorisierungsserver sein. Athena implementiert einen:

  1. Claude registriert sich selbst und erhält eine generierte Client-ID. Kein Geheimnis von dir ist beteiligt.

  2. Claude sendet dich zu einer Anmeldeseite auf deinem eigenen Server.

  3. Du gibst MCP_TOKEN als Passwort ein. Das ist der menschliche Genehmigungsschritt.

  4. Athena stellt Claude-Tokens aus, die Athena selbst geprägt hat.

Diese Tokens werden in data/mcp/oauth-state.json geschrieben, niemals in .env. Widerrufe sie mit:

rm data/mcp/oauth-state.json && docker compose restart mcp

Wenn du Browser-Claude nie verwendest, ignoriere das alles. Der Bearer-Pfad berührt es nicht.


Betrieb

docker compose logs -f mcp
curl -s localhost:8081/stats | python3 -m json.tool

# Force a full reconciliation
docker compose exec -T indexer bun -e 'await fetch("http://127.0.0.1:8081/sync",{method:"POST"})'

Aktualisierung. Erstelle immer zuerst ein Backup: Wiki.js führt beim Start seine eigenen Migrationen durch, und diese sind nicht durch Stoppen des Containers umkehrbar.

docker compose run --rm backup now
git pull && docker compose build && docker compose up -d

Symptom

Ursache

Ein Dienst beendet sich beim Start und listet Konfiguration auf

Eine erforderliche Variable fehlt oder ist noch CHANGE_ME

Claude kann keine Verbindung herstellen, keine Anmeldeseite

MCP_PUBLIC_URL hat einen Pfad oder ist nicht https

Anmeldung lehnt das richtige Passwort ab

Nach 5 Fehlversuchen gedrosselt, eine Minute warten

Keine semantischen Suchergebnisse

embeddings lädt noch herunter, überprüfe seine Logs

Dashboard zeigt Seiten im Rückstand

Indexer holt auf, überprüfe seine Logs

Tool-Aufrufe schlagen mit 401 fehl

Statusdatei gelöscht oder Token geändert, Client neu verbinden

Postgres beendet sich, "database files are incompatible"

Die Hauptversionsnummer des Images hat sich unter vorhandenen Daten geändert

Postgres kann kein Datenverzeichnis lesen, das von einer anderen Hauptversion geschrieben wurde. Dump, leeren, wiederherstellen:

docker compose run --rm backup now             # on the OLD version
docker compose down
mv data/postgres data/postgres.old             # keep until you are happy
# edit the image tag in docker-compose.yml and the FROM line in
# docker/backup/Dockerfile to the same new major version
docker compose build backup
docker compose up -d postgres
docker compose run --rm backup restore run <stamp>   # once per database
docker compose up -d

Der Vektorindex wird mit allem anderen wiederhergestellt, also wird nichts neu eingebettet.


Entwicklung

bun install
bun test          # 145 tests
bun run check     # typecheck, lint, test

Paket

Was es ist

packages/core

Wiki.js-Client, Chunking, Suchzusammenführung, Vektoren, Auth, Konfiguration

packages/mcp

MCP-Server, OAuth-Autorisierungsserver, die Tools

packages/indexer

Sync-Schleife, Embeddings, Vektorschreibvorgänge, interne Such-API

packages/dashboard

Metrik-Schnittstelle

docker/backup

Backup- und Wiederherstellungscontainer

website/

Die Einseiten-Website

themes/wikijs/

Optionales Wiki.js-CSS und -JS

Bun führt TypeScript direkt aus, es gibt also keinen Build-Schritt und die Container führen den Quellcode aus. bun run --cwd packages/dashboard preview schreibt eine preview.html mit Beispieldaten.

Wie es zusammenhängt:

  • Der Indexer ist inkrementell. Er erstellt einen Fingerabdruck jeder Seite und überspringt alles Unveränderte, sodass ein Durchlauf über ein unberührtes Wiki nichts kostet.

  • Jeder Dienst mit Admin-Anmeldedaten bereitet die Datenbank beim Start unter einer Advisory Lock vor, sodass die Startreihenfolge keine Rolle spielt.

  • Das Dashboard ist serverseitig gerendertes HTML mit Inline-SVG-Diagrammen. Kein Client-JavaScript, keine Diagrammbibliothek, kein Build-Schritt.

Veröffentlichen der Website. website/index.html wird bei jedem Push, der sie betrifft, auf GitHub Pages bereitgestellt. Aktiviere Pages einmalig manuell: Einstellungen → Seiten → Build und Bereitstellung → Quelle: GitHub Actions. Dies kann nicht automatisiert werden, da das Erstellen einer Pages-Site ein Token mit Administratorrechten erfordert und GITHUB_TOKEN diese nicht hat.


Lizenz

Apache-2.0. Siehe LICENSE.

Related MCP Connectors

Related MCP Servers