Install your own BookStack instance
'>
ℹ️
DieseThisAnleitungguidestartetstartsabfromdemthePunktpoint,anwheredemyoudualreadybereitshaveeinenaLinux-ServerLinux serverhast undand Dockerinstalliertisist.installed.DieThe„Schritte“stepsdavor“beforefolgenthat”späterwill–followeslaterist—wirklichit’snichtreallyschwernot hard (besondersespeciallymitwithKI-Hilfe)AI help).
Überblick:Overview: WasWhat’s wirdbeing hierset eingerichtet?up here?
DuIn bekommstthe amend Ende:you’ll have:
- BookStack (
Wiki/Docs-System)wiki/docs system) - MariaDB
alsasDatenbankthe database - Caddy
alsasReverseaProxyreversemitproxy withautomatischemautomatic HTTPS (Let’s Encrypt) 🌐
Hintergrund:Background: WasWhat istis Caddy? 🌐
Caddy
istiseinamodernermodernWebserverweb server (ähnlichsimilar to Nginx/Apache),geschriebenwritten in Go,derthat„embraces “Security-security-by-default“”lebtand,undabovedirall,vor allemmakes HTTPSextremextremelybequem macht.convenient.
Kernidee:Core idea: „Webserver,“A derweb einfachserver funktioniert“that just works” ✅
WichtigeKey Merkmalefeatures ✨
AutomatischesAutomatic HTTPS (TLS)ZertifikateCertificateswerdenareautomatischobtainedbezogenandundrenewederneuertautomatically (typischtypically via Let’s Encrypt).
EinfacheSimpleKonfigurationconfigurationÜberViaeinangut lesbareseasy-to-read Caddyfile.
- Reverse
Proxyproxy &LoadloadBalancingbalancingIdeal,IdealumforAnfragenforwardinganrequestsServicesto services (z.e.g.,B.DockerDocker-Container) weiterzuleiten.containers).
GuteGoodDefaultsdefaultsVieleManysinnvollesensibleSecurity-Standardssecuritysindstandardsdirektareaktiv.enabled by default.
- Modular
erweiterbarextensibilityBeiIfspeziellenyouAnforderungenhavelässtspecialsichrequirements, Caddyausbauen.can be extended.
TypischeTypical Einsatzfälleuse cases 🧩
WebsitesHostinghostenwebsites (statisch/dynamisch)static/dynamic)- Reverse
ProxyproxyvorineinerfrontAppof an app (z. B.e.g.,/api→Backend)backend) TLS-TerminationTLS terminationLokaleLocalDev-Setupsdevmitsetups with HTTPS
SchrittStep 1: VerzeichnisPrepare directory & Dateien vorbereitenfiles 🧱
ErstelleCreate dasthe Verzeichnis:directory:
/opt/bookstack
Lege darinCreate zweitwo Dateienfiles an:inside it:
docker-compose.ymlCaddyfile
✍️
Wichtig:Important:DuYou’llmusstneedgleichtoeinadjustpaaraWertefewanpassenvalues–induasiehstmomentim—YAMLyousehrcandeutlich,clearly seewowhere.in the YAML.
SchrittStep 2: Configure Docker Compose konfigurieren (docker-compose.yml) 🐳
FügePaste folgendenthe Inhaltfollowing eincontent (undand passeadjust ihnit an,where wo nötig)necessary):
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
# WoWhere wirdwill BookStack aufrufbarbe sein?accessible? (DeineYour URL)
- APP_KEY=base64:...
# ZumTo Generierengenerate dasit, ausführen:run: docker run -it --rm --entrypoint /bin/bash lscr.io/linuxserver/bookstack:latest appkey
- APP_THEME=custom
#'custom' ermöglichmakes esit Hackspossible zuto nutzen;use mehrhacks; dazumore hier:on that here: https://www.bookstackapp.com/hacks/applying/
- DB_HOST=mariadb
- DB_PORT=3306
- DB_DATABASE=bookstack
- DB_USERNAME=bookstack
- DB_PASSWORD=PW_OF_MYSQL_DB
# (WieAs oben!above!)
- APP_DEFAULT_DARK_MODE=true
# (Geschmackssache)Personal preference)
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 -dAktualisieren geht später so:
docker compose pulldocker compose up -dFertig ✅
Jetzt schnell die URL aufrufen und die Standard-Zugangsdaten ändern!
admin@admin.compasswordSchritt 5: Cron-Job für BookStack ⏱️
Einen Cron-Job anlegen:
crontab -e* * * * * docker exec -i bookstack php /app/www/artisan schedule:run >/dev/null 2>&1Beschränkungen & Module/Hacks 🧩
Es gibt drei Einschränkungen, die bisher aufgefallen sind:
E-Mail-Versand
Erweiterung über „Hacks“
Wichtiger Hinweis zum Export 📄
Wie installiert man Hacks als Module?
APP_THEME=custom/opt/bookstack/bookstack/www/themes/custom/modulesdocker exec -it bookstack /bin/bashcd /app/www/Shift+Enter – Zeilenumbruch (CommonMark)
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.php anlegen 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:
https://deineurl.com/settings/customizationEinfach jeweils unter „Custom HTML Head Content“ eintragen:
Blockquotes: kein dicker Rand unten / saubere Abstände
<p>margin-bottom <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>
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>