The browser tab still showed Wiki.js because only favicon.ico + 16/32 were
replaced — the larger icons the tab picks (android-chrome-192, apple-touch-180,
mstile-150) were still the defaults. Add ThreadNet versions and subPath-mount
them. Adding these pushed the single branding ConfigMap to ~1.04 MB (the 1 MiB
etcd limit), so split the 604 KB background into its own platform-branding-bg
ConfigMap mounted at /_assets/img/bg; authLoginBgUrl follows.
Add wikijs-backup, a nightly Borg CronJob (03:30) that dumps the Wiki.js postgres
DB to the Storage Box — the content lives in git-storage, but comments, local
accounts and the search index do not, so the runtime state gets its own backup.
Mirrors authentik-backup (DB-only), reusing synapse-backup-credentials and
-known-hosts with a separate repo path; NetworkPolicy lets the backup pod reach
wikijs-postgres. Also flip tocPosition to right so the page TOC sits beside the
content instead of in the left rail.
The Betrieb/Anwender content structure is created (lives in git-storage, not the
job). Add a page rule so wiki-anwender can read the home page besides /anwender —
otherwise "/" would be denied for them. betrieb/* still matches no rule, so
Wiki.js' default-deny keeps it invisible to users (verified in checkAccess:
returns match && !deny). rule() gains a match param for the EXACT home rule.
Set the blue Docusaurus-style accent (#2b6cb0 light / #63b3ed dark) via injectCSS
on the app UI — the login page is excluded because Wiki.js renders it without
custom CSS, so a dark login card is not themeable and is left as-is. Mount the
ThreadNet favicon (favicon.ico + favicon-16/32 PNGs the browser tab uses) from the
platform-branding ConfigMap via subPath, overlaying only those files.
The site title (top-left + browser tab) was the hardcoded "Wiki.js". Drive it
from a deployment variable instead; the config job sets site.title from
WIKI_SITE_TITLE (default "Wiki"), set here to wiki.axion1337.chat.
Wiki.js cannot reach git.lab from the cluster, so its content syncs to Gitea
(sorb/ThreadNetWiki) over HTTPS with a dedicated deploy PAT; a CI job canonizes
Gitea->git.lab (TURN-rotation pattern). The config job's ensure_git_storage
configures the git storage target (mode sync, config values {v:...}-encoded like
the auth strategy). Repo/user/branch/author are plain env; only the PAT lives in
the SOPS secret wikijs-git-secret, wired optional so the job still runs without it.
Serve the ThreadNet logo and the shared platform login background (alpenglow.jpg,
same file Authentik and Element use) as public static files under
/_assets/img/branding, mounted from a single platform-branding ConfigMap. This
avoids two bad patterns: linking the background via an external URL (runtime
dependency on axion1337.chat) and uploading the logo as a gated Wiki.js asset
(which 404/403s on the unauthenticated login page unless guests get read:assets).
Wiki.js serves /wiki/assets publicly at /_assets, so mounted files need no
read:assets — guests stay locked out of pages. The config job sets logoUrl and
authLoginBgUrl to the local paths and enables dark mode as default. The ConfigMap
uses a name hash so a branding change rolls the pod. It can later be mounted into
Authentik/Element too, keeping one source of truth for the shared assets.
Disabling local (previous approach) left the login page empty: Wiki.js needs a
form strategy to render the provider list, so with only OIDC the card was blank
and login hung. Keep local ENABLED and instead set the built-in authHideLocal
site config, which removes local from the provider list on the login page —
only "Login with Authentik" shows.
local stays usable because the config job logs in through it, and it is the
break-glass path, reachable via /login?all (Wiki.js honors ?all to bypass
hideLocal). Verified live end-to-end: job runs idempotently, both strategies
enabled, authHideLocal=true.
Nobody should log in manually. The job disables the local strategy as its final
step (with a still-valid JWT), so the login page offers only Authentik OIDC.
Re-runs without a DB reset find local disabled -> login returns None -> the job
exits cleanly (already configured). Break-glass = DB reset (finalize re-enables
local). Verified live: local login is BLOCKED after the run.
The OIDC strategy failed at startup ('requires an issuer option') because the
config values never persisted: Wiki.js reads each via _.get(JSON.parse(value),
'v', null) (source-verified in server/graph/resolvers/authentication.js), so the
value MUST be {"v": <value>}. None of the earlier encodings had the 'v' key.
Fixed and verified live: strategy now loads [ OK ].
Idempotent GraphQL bootstrap job (verified live): /finalize with the random SOPS
admin, then the OIDC strategy and the groups 'authentik Admins' (full) and
'wiki-anwender' (read /anwender), Guests locked. Replaces the manual setup wizard
entirely. OIDC client_id/secret in a SOPS secret; NetworkPolicy lets the job reach
wikijs. Script as a fixed-name ConfigMap; re-run = delete the Job.