Files
management/docs/wiki/stolpersteine/wikijs.md
T
Thore CimbalandClaude Opus 4.8 8fd23274d8 docs(wiki): harvest Wiki.js stumbles; mark AAR harvested
Consolidate the 13 findings + learnings from the Wiki.js AAR into
docs/wiki/stolpersteine/wikijs.md (config/deploy, theming, navigation,
locale/timezone incl. the standing fork patch, access control, git-storage),
link it from the wiki index, and set the AAR status to harvested.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-14 12:00:00 +00:00

5.5 KiB

type, area, sources, related
type area sources related
wiki-page stolpersteine
docs/aar/2026-08-13-wikijs-umzug.md
docs/adr/0014-wikijs-loest-docusaurus-ab.md
docs/adr/0015-wiki-git-storage-ueber-gitea-kanonisieren.md

Stolpersteine: Wiki.js (Betrieb & Config)

Geerntet aus dem AAR zum Wiki.js-Umzug (2026-08-13/14); Belege, Diagnosen und Commits dort. Grundregel: Wiki.js ist config-seitig mächtig, aber eigenwillig — vieles ist nur durch Quellcode-Lesen im Pod (/wiki/server/...) herauszufinden. Der Konfig-Job (gitops:apps/production/wikijs-config.py) kapselt das reproduzierbar und ist die eigentliche Doku.

Config & Deploy

  • Config-Werte brauchen {"v": value}-Kodierung. Auth-Strategy, Storage-Target UND Renderer-Config lesen jeden Wert via _.get(JSON.parse(value),'v',null). Ohne die Kodierung sind alle Werte null (z.B. „requires an issuer option").
  • hideLocal statt local deaktivieren. Wiki.js braucht eine Formular-Strategie, sonst rendert die Login-Seite leer. „Nur OIDC" ⇒ local aktiv lassen + authHideLocal=true; Break-Glass über /login?all.
  • Geänderte immutable Job-Spec blockiert den GANZEN Flux-Apply — auch unabhängige ConfigMaps/Mounts kommen dann still nicht durch, obwohl die Source-Revision aktuell ist. Fix: Job löschen (kubectl delete job …), Flux legt ihn neu an.
  • ConfigMap ohne Hash-Suffix (disableNameSuffixHash) aktualisiert in-place, die Job-Spec ändert sich nicht → kein Immutable-Block, aber der fertige Job läuft nicht von selbst neu: ebenfalls Job löschen für den Rerun. (Propagation kann kurz nachhängen — vor dem Rerun den CM-Inhalt gegenprüfen.)
  • 1-MiB-ConfigMap-Limit. Hochskalierte Favicons + großer Hintergrund sprengen es. Fix: Hintergrund runterskalieren (1920 px), Icons NICHT hochskalieren, alles in EINER ConfigMap.
  • Flux streift Bilder aus dem Build-Artefakt (*.png/*.jpg in der Default-Ignore) → configMapGenerator scheitert mit „no such file or directory". Fix: .sourceignore mit Negationen.

Theming & Branding

  • Die Login-Seite ist nicht per Custom-CSS themebarmaster.pug rendert kein injectCSS, der Login-Bundle wendet es nicht an. Eine dunkle Login-Karte ist config-seitig unmöglich.
  • Branding als statische Datei, nicht als gated Asset. Ein hochgeladenes Logo hängt an read:assets → 403 auf der unauth. Login-Seite. Lösung: unter /_assets/img/... mounten (öffentlich).
  • Browser cachen Favicons hartnäckig — ein „falsches" Tab-Icon ist meist Cache, kein Deploy-Fehler. Erst server-seitig 16/32/favicon.ico prüfen, dann hart neu laden.

Navigation

  • Die Nav-Sidebar rendert target wortwörtlich als href (Default-Theme: href: item.target, keine targetType- oder Slash-Behandlung). Page-Targets ohne führenden Slash lösen relativ auf → von /betrieb/x aus wird betrieb/y zu /betrieb/betrieb/y → 404 (von / aus geht es zufällig, daher lange unbemerkt); home mit leerem Target ist ebenfalls tot. Fix: Targets absolut speichern (/<pfad>; home/).

Locale & Zeitzone

  • Locale-Wechsel migriert nur pages. Default umstellen via localization.updateLocale (lädt live, KEIN Neustart) + pages.migrateToLocale — letzteres patcht NUR die pages-Tabelle. pageTree/pageLinks/pageHistory/Suchindex bleiben auf der alten Locale → danach pages.rebuildTree + search.rebuildIndex, pageLinks/pageHistory-Restzeilen einmalig nachziehen. Der Nav-Baum muss unter der NEUEN Locale liegen (getTree nutzt die Seiten-Locale), sonst leere Sidebar. namespacing:false → saubere /<pfad>-URLs. Inhalte gleich unter der Ziel-Locale anlegen, spart die Migration.
  • Die New-User-Zeitzone kommt aus dem DB-Spalten-Default (users.timezone = America/New_York), NICHT aus Config: SSO-processProfile legt Nutzer ohne timezone an (localeCode dagegen aus WIKI.config.lang.code). Bestehende Konten per users.update korrigieren (patcht nur übergebene Felder). Neue Nutzer brauchen einen Fork-Patch — es gibt kein Custom-Image, daher als Startup-Overlay (Container-command sed-patcht server/models/users.js), idempotent + fail-open. ⚠️ Stehende Upstream-Abweichung: hängt am Anker localeCode: WIKI.config.lang.code,, bei jedem Wiki.js-Upgrade gegenprüfen (dokumentiert im Manifest und auf /betrieb/upgrades).

Zugriff & Abschottung

  • checkAccess ist Default-Deny (match && !deny): eine Gruppe mit globalem read:pages + Pfad-Regel auf anwender sieht betrieb/* von allein nicht — Abschottung ohne explizite Deny-Regeln. Aber immer mit einem echten Anwender-Konto gegentesten (Testnutzer in wiki-anwender, HTTP-Status je Seite prüfen).

Git-Storage & Editieren

  • Git-Storage braucht den Remote-Branch vorab. „Invalid branch! Make sure it exists on the remote first." — Ziel-Repo mit leerem Initial-Commit auf main bootstrappen. Nach fehlgeschlagenem Init sitzt der lokale Klon fest → purge-Action + re-init.
  • Der Cluster erreicht git.lab nicht (Absicht). Wiki.js pusht nach Gitea, ein CI-Job kanonisiert Gitea→git.lab (Muster canonize_rotation, umgekehrte Richtung).
  • Wiki-Inhalt nur über die Wiki.js-API editieren — git-storage ist bidirektional, nie direkt nach Gitea schreiben (würde beim nächsten Sync kollidieren/überschrieben). Reproduzierbar via kurzlebigem In-Cluster-Job mit gemountetem Admin-Secret (Creds bleiben im Cluster; Pod-Label app.kubernetes.io/name: wikijs-config matcht die NetworkPolicy zu Wiki.js).