# 02-bookstack.md

kstack:
  book: Centerpoint Home Lab
  chapter: Documents & Organization
  page: BookStack
  tags: [bookstack, wiki, documentation, mariadb, oidc]
---

## Overview

BookStack is the self-hosted personal knowledge base and documentation wiki —
the platform this very documentation is written in. It organises content into
Shelves → Books → Chapters → Pages and provides a full Markdown editor. Access
is protected by Authentik OIDC on the external route. On the internal route,
authentication still passes through BookStack's own OIDC flow (no Traefik
ForwardAuth bypass), so the Authentik session is always required.

## Access

| Type     | URL                                     | Auth                             |
|----------|-----------------------------------------|----------------------------------|
| External | `https://wiki.jeeves5454.ddns.net`      | Authentik OIDC + GeoBlock + CrowdSec |
| Internal | `https://wiki.home.local`               | Authentik OIDC (Step-CA TLS)    |

BookStack uses its own OIDC integration rather than Traefik ForwardAuth. The
external Traefik route applies GeoBlock and CrowdSec but **not**
`authentik-auth@docker` — BookStack manages the OIDC redirect itself.

## Containers

| Container      | Image             | Role             |
|----------------|-------------------|------------------|
| `bookstack`    | `lscr.io/linuxserver/bookstack:latest` | Web application |
| `bookstack-db` | `mariadb:10.11`   | MariaDB database |

### bookstack (application)

**Key environment variables:**

| Variable                  | Value / Notes                                                  |
|---------------------------|----------------------------------------------------------------|
| `APP_URL`                 | `https://wiki.jeeves5454.ddns.net`                             |
| `AUTH_METHOD`             | `oidc`                                                         |
| `AUTH_AUTO_INITIATE`      | `true` — skips BookStack login page, redirects to Authentik    |
| `OIDC_NAME`               | `Authentik`                                                    |
| `OIDC_ISSUER`             | `https://auth.jeevesconsults.ca/application/o/book-stack-website-s/` |
| `OIDC_ISSUER_DISCOVER`    | `true`                                                         |
| `OIDC_CLIENT_ID`          | `QjpMMmpDqNCQIM75np6gGyMkN9Y569AtyNVhfJvx`                     |
| `OIDC_CLIENT_SECRET`      | **REDACTED**                                                   |
| `OIDC_EXTERNAL_ID_CLAIM`  | `email`                                                        |
| `OIDC_DISPLAY_NAME_CLAIMS`| `name`                                                         |
| `OIDC_FETCH_AVATAR`       | `false`                                                        |
| `OIDC_END_SESSION_ENDPOINT` | `false`                                                      |
| `DB_HOST`                 | `bookstack-db`                                                 |
| `DB_DATABASE`             | `bookstack`                                                    |
| `DB_USERNAME`             | `bookstack`                                                    |
| `DB_PASSWORD`             | **REDACTED**                                                   |
| `MAIL_HOST`               | `smtp.gmail.com`                                               |
| `MAIL_PORT`               | `587`                                                          |
| `MAIL_USERNAME`           | `jeeves5454@gmail.com`                                         |
| `MAIL_ENCRYPTION`         | `TLS`                                                          |
| `MAIL_FROM`               | `noreply@jeevesconsults.ca`                                    |
| `PUID` / `PGID`           | `1000`                                                         |
| `TZ`                      | `America/Toronto`                                              |

**Bind mounts:**

| Host Path                              | Container Path | Purpose                    |
|----------------------------------------|----------------|----------------------------|
| `/home/jeeves/docker/bookstack/config` | `/config`      | App config, attachments, uploads |
| `/home/jeeves/docker/bookstack/public` | `/public`      | Public web assets          |

### bookstack-db (MariaDB 10.11)

**Bind mounts:**

| Host Path                           | Container Path     |
|-------------------------------------|--------------------|
| `/home/jeeves/docker/bookstack/db`  | `/var/lib/mysql`   |

## Traefik Labels

```yaml
traefik.http.routers.bookstack-ext.rule: Host(`wiki.jeeves5454.ddns.net`)
traefik.http.routers.bookstack-ext.entrypoints: websecure
traefik.http.routers.bookstack-ext.tls.certresolver: letsencrypt
traefik.http.routers.bookstack-ext.middlewares: plex-geoblock@file,crowdsec-bouncer@file
traefik.http.routers.bookstack-ext.service: bookstack-svc

traefik.http.routers.bookstack-int.rule: Host(`wiki.home.local`)
traefik.http.routers.bookstack-int.entrypoints: websecure
traefik.http.routers.bookstack-int.tls.certresolver: step-ca
traefik.http.routers.bookstack-int.service: bookstack-svc

traefik.http.services.bookstack-svc.loadbalancer.server.port: 80
```

## Notes / Gotchas

- `APP_URL` is set to the external URL even though both internal and external
  routes exist. This is intentional — it is used for OIDC redirect URIs and
  email links, which must be reachable externally.
- `AUTH_AUTO_INITIATE: true` means anyone who hits the URL is immediately
  redirected to Authentik. There is no BookStack login form shown unless OIDC
  fails. To bypass OIDC in an emergency, use `?prevent_auto_init=true` appended
  to the URL.
- For an existing user to link their Authentik account, go to Admin → Users →
  select user → set **External Authentication ID** to their email address.
- The LSIO image uses `DB_USERNAME`, not `DB_USER`. Using `DB_USER` silently
  falls back to no authentication and causes confusing login failures.
- `APP_KEY` (Laravel application key) is stored in the `/config` directory and
  persists across container restarts. Do not delete the config bind mount or the
  key must be regenerated and all sessions will be invalidated.

---
*Last Updated: 2026-06-17*