Eigene BookStack-Instanz installieren
ℹ️ Diese Anleitung startet ab dem Punkt, an dem du bereits einen Linux-Server hast und Docker installiert ist. Die „Schritte davor“ folgen später – es ist wirklich nicht schwer (besonders mit KI-Hilfe).
Überblick: Was wird hier eingerichtet?
Du bekommst am Ende:
- BookStack (Wiki/Docs-System)
- MariaDB als Datenbank
- Caddy als Reverse Proxy mit automatischem HTTPS (Let’s Encrypt) 🌐
Hintergrund: Was ist Caddy? 🌐
Caddy ist ein moderner Webserver (ähnlich Nginx/Apache), geschrieben in Go, der „Security-by-default“ lebt und dir vor allem HTTPS extrem bequem macht.
Kernidee: „Webserver, der einfach funktioniert“ ✅
Wichtige Merkmale ✨
- Automatisches HTTPS (TLS)
- Zertifikate werden automatisch bezogen und erneuert (typisch via Let’s Encrypt).
- Einfache Konfiguration
- Über ein gut lesbares Caddyfile.
- Reverse Proxy & Load Balancing
- Ideal, um Anfragen an Services (z. B. Docker-Container) weiterzuleiten.
- Gute Defaults
- Viele sinnvolle Security-Standards sind direkt aktiv.
- Modular erweiterbar
- Bei speziellen Anforderungen lässt sich Caddy ausbauen.
Typische Einsatzfälle 🧩
- Websites hosten (statisch/dynamisch)
- Reverse Proxy vor einer App (z. B.
/api→ Backend) - TLS-Termination
- Lokale Dev-Setups mit HTTPS
Schritt 1: Verzeichnis & Dateien vorbereiten 🧱
Erstelle das Verzeichnis:
/opt/bookstack
Lege darin zwei Dateien an:
docker-compose.ymlCaddyfile
✍️ Wichtig: Du musst gleich ein paar Werte anpassen – du siehst im YAML sehr deutlich, wo.
Schritt 2: Docker Compose konfigurieren (docker-compose.yml) 🐳
Füge folgenden Inhalt ein (und passe ihn an, wo nötig):
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
Schritt 3: Caddy konfigurieren (Caddyfile) 🛡️
Füge Folgendes ein und ersetze die Domain:
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 4: Container starten ▶️
-
Ins Verzeichnis wechseln:
cd /opt/bookstack/
-
Stack starten:
docker compose up -d
Aktualisieren geht später so:
docker compose pulldocker compose up -d
-
Fertig ✅
Jetzt schnell die URL aufrufen und die Standard-Zugangsdaten ändern!- Standard-Login:
admin@admin.com - Standard-Passwort:
password
- Standard-Login:
Schritt 5: Cron-Job für BookStack ⏱️
Einen Cron-Job anlegen:
- Crontab öffnen:
crontab -e
- Folgende Zeile eintragen (Cron jede Minute):
* * * * * docker exec -i bookstack php /app/www/artisan schedule:run >/dev/null 2>&1
Beschränkungen & Module/Hacks 🧩
Es gibt drei Einschränkungen, die bisher aufgefallen sind:
-
E-Mail-Versand
- (z. B. „Passwort vergessen“) funktioniert bei mir nicht bzw. meine Experimente haben noch keine Lösung hervorgebracht.
- Ich brauche es nicht zwingend – aber z. B. für Kommentare (Benachrichtigungen) kommt man daran nicht vorbei.
- Mehr dazu:
https://www.bookstackapp.com/docs/admin/email-webhooks/#email-configuration
-
Erweiterung über „Hacks“
- BookStack kann über sogenannte „Hacks“ erweitert werden.
- Zwei Empfehlungen:
- MathJax/TeX (Mathe-Formeln):
- Mermaid Viewer (Diagramme):
Wichtiger Hinweis zum Export 📄
- Mermaid (und auch Formeln) funktionieren bei mir nicht sauber im Export (z. B. PDF): statt gerendertem Inhalt erscheinen Code-Blöcke.
Wie installiert man Hacks als Module?
- Den ersten Schritt haben wir bereits gemacht: In der YML steht
APP_THEME=custom
Dadurch werden Module aus folgendem Pfad geladen:/opt/bookstack/bookstack/www/themes/custom/modules
- Dann per SSH:
- In den Container wechseln:
docker exec -it bookstack /bin/bash
- Ins Web-Verzeichnis:
cd /app/www/
- Dort das Kommando ausführen, das im jeweiligen Hack steht (Beispiel Mermaid):
- Auf der Hack-Seite im Abschnitt „Install as Module“
https://www.bookstackapp.com/hacks/mermaid-viewer/
- Auf der Hack-Seite im Abschnitt „Install as Module“
- In den Container wechseln:
-
Shift+Enter – Zeilenumbruch (CommonMark)
- Durch die Entscheidung für den CommonMark-Standard wird ein einfacher Zeilenumbruch standardmäßig nicht gerendert.
- Stattdessen braucht man „zwei Spaces am Zeilenende + Enter“ – das hat mich wahnsinnig gemacht, weil viele Markdown-Editoren Shift+Enter gewohnt sind.
- Mein Fix besteht aus zwei Teilen:
-
In den BookStack-Einstellungen unter
https://example.com/settings/customization
bei „Custom HTML Head Content“ folgenden Code eintragen:<script> window.addEventListener('editor-markdown::setup', event => { event.detail.markdownIt.set({breaks: true}); }); </script> -
Eine
functions.phpanlegen unter:/opt/bookstack/bookstack/www/themes/custom/
Mit folgendem 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 (unter „Customization“) 🛠️
Einstellen hier:
Einfach jeweils unter „Custom HTML Head Content“ eintragen:
-
Blockquotes: kein dicker Rand unten / saubere Abstände
- Ursache: CSS (u. a.
<p>mitmargin-bottom) - Fix (gleicher Abstand oben/unten + keine Scrollbalken):
<style> /* 1) Letztes & erstes direktes Kindelement im Blockquote: Margin */ .content-wrap blockquote > :last-child { margin-bottom: .3em; } .content-wrap blockquote > :first-child { margin-top: .3em; } /* 2) Blockquote: keine Scrollbalken */ .content-wrap blockquote { overflow: visible; /* Standard „ohne Scrollen“ */ overflow-x: visible; overflow-y: visible; } </style> - Ursache: CSS (u. a.
-
Codeblöcke: Soft-Wraps (kein horizontales Scrollen nötig)
<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> -
Dark Mode: Text heller (Überschriften 70%, Text 90%)
<style> html.dark-mode .page-content h1, html.dark-mode .page-content h2, html.dark-mode .page-content h3, html.dark-mode .page-content h4, html.dark-mode .page-content h5, html.dark-mode .page-content h6 { color: hsl(0 0% 70%); } html.dark-mode body { color: hsl(0 0% 90%); } </style> -
Textgröße: Hauptinhalt 110%, Überschriften 90%
<style> .page-content { zoom:1.1; } .page-content h1, .page-content h2, .page-content h3, .page-content h4, .page-content h5, .page-content h6 { zoom:.9; } </style>
Wenn du willst, kann ich dir als nächsten Schritt noch eine „Checkliste vor dem Start“ (DNS, Ports 80/443, Firewall, APP_KEY-Generierung etc.) ergänzen – inhaltlich gleich, nur als schnell abhakbare Sektion.