Eigene BookStack-Instanz installieren
Schritt 1: Komposition vorbereiten
Wir wollen, dass eine Domain eingerichtet wird, die mit https://... aufgerufen werden kann, weshalb ich mich für Caddy entschieden habe.
Erstelle einen Ordner hier: /opt/bookstack Und darin zwei Dateien: Caddyfile und docker-compose.yml
Füge dort den folgenden Inhalt ein und passe ihn an:
BookStack-YML (docker-compose.yml)
services:
mariadb:
image: lscr.io/linuxserver/mariadb:latest
container_name: bookstack-mariadb
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Berlin
- MYSQL_ROOT_PASSWORD=PW_OF_MYSQL_ROOT
- MYSQL_DATABASE=bookstack
- MYSQL_USER=bookstack
- MYSQL_PASSWORD=PW_OF_MYSQL_DB
volumes:
- ./mariadb:/config
restart: unless-stopped
bookstack:
image: lscr.io/linuxserver/bookstack:latest
container_name: bookstack
depends_on:
- mariadb
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Berlin
- APP_URL=https://wiki.fabula.vision
# Wo wird BookStack aufrufbar sein? (Deine URL)
- APP_KEY=base64:...
# Zum Generieren das ausführen: docker run -it --rm --entrypoint /bin/bash lscr.io/linuxserver/bookstack:latest appkey
- APP_THEME=custom
#'custom' ermöglich es Hacks zu nutzen; mehr dazu hier: https://www.bookstackapp.com/hacks/applying/
- DB_HOST=mariadb
- DB_PORT=3306
- DB_DATABASE=bookstack
- DB_USERNAME=bookstack
- DB_PASSWORD=PW_OF_MYSQL_DB
# (Wie oben!)
- APP_DEFAULT_DARK_MODE=true
# (Geschmackssache)
volumes:
- ./bookstack:/config
restart: unless-stopped
caddy:
image: caddy:latest
container_name: caddy
depends_on:
- bookstack
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy/data:/data
- ./caddy/config:/config
restart: unless-stopped
Caddyfile
wiki.fabula.vision {
# Deine URL natürlich...
encode zstd gzip
# Reverse Proxy zu BookStack (Container heißt "bookstack", interner Port 80)
reverse_proxy bookstack:80
# sinnvolle Header (optional)
header {
# HSTS (nur setzen, wenn du sicher bist, dass HTTPS dauerhaft aktiv sein soll)
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
Referrer-Policy "strict-origin-when-cross-origin"
}
}
Schritt 2: Starten
- Ins Verzeichnis wechseln:
cd /opt/bookstack/ - Unser Zeugs installieren:
docker compose up -d
Aktualisieren geht dann so:
docker compose pull;docker compose up -d - Fertig, aber nun schnell die URL aufrufen und die Standard-Zugangsdaten ändern!
Standard-Login (User + Passwort):admin@admin.com+password
Beschränkungen & Module/Hacks
Es gibt drei Einschränkungen, die ich bisher festgestellt habe:
-
E-Mail-Versand (z.B. „Passwort vergessen“) funktioniert nicht, bzw. meine Experimente haben noch keine Lösung hervorgebracht und ich brauche das auch nicht zwingend. Aber wenn man z.B. Kommentare aktivieren will (User bekommen eine Benachrichtigung, wenn ihre Seiten kommentiert werden), dann kommt man da nicht drumherum. Mehr dazu hier.
-
Man kann die Funktionalität mit sogenannten „Hacks" erweitern und ich kann zwei Hacks schon mal empfehlen:
- https://www.bookstackapp.com/hacks/mathjax-tex/
Mathe-Formeln darstellen; - https://www.bookstackapp.com/hacks/mermaid-viewer/
(Mermaid-)Diagramme darstellen;
Allerdings funktioniert das nicht mit der Export-Funktion, d.h. wenn ein Besucher Buch X als PDF beispielsweise exportiert, dann sieht er statt Formeln und Diagrammen nur Code-Blöcke.
Und das mit dem Exportieren funktioniert eh leider nicht bei mir, habe keine Ahnung warum und deshalb die Funktion einfach deaktiviert.
Ok, aber wie installiert man nun die Hacks? – Also den ersten Schritt haben wir getan, indem wir oben (in der YML-Datei)
APP_THEME=customdefiniert haben, was dafür sorgt, dass fortan Module geladen werden können, die sich hier befinden/opt/bookstack/bookstack/www/themes/custom/modulesNun muss man per SSH das eingeben:
docker exec -it bookstack /bin/bashDamit kann man dann Befehle „von innen“ heraus ausführen;- Dann:
cd /app/www/; - Und dort dann das Kommando ausführen, das hier angezeigt wird (am Beispiel Mermaid):
https://www.bookstackapp.com/hacks/mermaid-viewer/ (Dort dann im Abschnitt: „Install as Module“)
- https://www.bookstackapp.com/hacks/mathjax-tex/
-
Shift+Enter – Zeilenumbruch: Da sich die Entwickler auf den CommonMark-Standard festgelegt haben, bedeutet es, dass u.a. standardmäßig ein einfacher Zeilenumbruch nicht gerendert wird: Man muss zwei Spaces am Zeilenende schreiben und dann Enter, damit ein einfacher Linebreak stattfindet – das hat mich wahnsinnig gemacht, weil alle Markdown-Editoren, die ich kenne funktionieren da anders (einfach Shift+Enter). Das wollte ich unbedingt ändern und habe dafür ein paar Stunden Zeit investiert. Jedenfalls sieht der Fix folgendermaßen aus:
-
Hier (https://example.com/settings/customization) bei „Custom HTML Head Content“ diesen Code eintragen:
<script> window.addEventListener('editor-markdown::setup', event => { event.detail.markdownIt.set({breaks: true}); }); </script> -
Dann hier eine
functions.phpanlegen:/opt/bookstack/bookstack/www/themes/
Mit dem folgenden Inhalt:<?php use BookStack\Theming\ThemeEvents; use BookStack\Facades\Theme; Theme::listen(ThemeEvents::COMMONMARK_ENVIRONMENT_CONFIGURE, function ($environment) { $environment->mergeConfig([ 'renderer' => [ 'soft_break' => "<br>", ] ]); return $environment; });
-
Weitere QoL-Fixes (einzustellen hier: https://example.com/settings/customization)
Einfach unter „Custom HTML Head Content“ eintragen:
Blockquotes haben keinen dicken Rand unten (liegt am CSS, weil u.a. alle <p>-Elemente margin-bottom haben):
<style>
/* 1) Letztes direktes Kindelement im Blockquote: kein Bottom-Margin */
.content-wrap blockquote > :last-child {
margin-bottom: 0;
}
/* 2) Blockquote: keine Scrollbalken */
.content-wrap blockquote {
overflow: visible; /* Standard „ohne Scrollen“ */
overflow-x: visible;
overflow-y: visible;
}
</style>
Codeblöcke haben Soft-Wraps (also man muss nicht horizontal scrollen, um die ganze Zeile zu sehen):
<script>
window.addEventListener('library-cm6::pre-init', event => {
const detail = event.detail;
const config = detail.editorViewConfig;
const EditorView = detail.libEditorView;
if (detail.usage === 'content-code-block') {
config.extensions.push(EditorView.lineWrapping);
}
});
</script>