BookStack is a self-hosted documentation platform with an intuitive structure borrowed from the physical world: Shelves → Books → Chapters → Pages. Non-technical colleagues understand it instantly, and it comes with a WYSIWYG editor (or Markdown), page revisions, search, permissions, diagrams via draw.io, and exports to PDF and HTML.

It’s a Laravel (PHP) application with MySQL/MariaDB — light enough for a small VPS.

1. Run BookStack with Docker Compose

The widely used LinuxServer.io image packages BookStack with Nginx and PHP:

mkdir -p ~/bookstack && cd ~/bookstack

compose.yaml:

services:
  bookstack:
    image: lscr.io/linuxserver/bookstack:latest
    restart: unless-stopped
    environment:
      PUID: "1000"
      PGID: "1000"
      TZ: Etc/UTC
      APP_URL: https://docs.example.com
      APP_KEY: ${APP_KEY}
      DB_HOST: db
      DB_PORT: "3306"
      DB_USERNAME: bookstack
      DB_PASSWORD: ${DB_PASSWORD}
      DB_DATABASE: bookstack
    volumes:
      - ./config:/config
    ports:
      - "127.0.0.1:6875:80"
    depends_on:
      - db

  db:
    image: lscr.io/linuxserver/mariadb:latest
    restart: unless-stopped
    environment:
      PUID: "1000"
      PGID: "1000"
      TZ: Etc/UTC
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: bookstack
      MYSQL_USER: bookstack
      MYSQL_PASSWORD: ${DB_PASSWORD}
    volumes:
      - ./db:/config

Generate secrets. APP_KEY must be a Laravel key in base64: format:

cat > .env <<EOF
APP_KEY=base64:$(openssl rand -base64 32)
DB_PASSWORD=$(openssl rand -hex 16)
DB_ROOT_PASSWORD=$(openssl rand -hex 16)
EOF
chmod 600 .env
docker compose up -d

Check the image documentation for current variable names; some versions differ.

APP_URL must exactly match the URL users visit — BookStack uses it to build links and assets. Getting it wrong is the most common cause of broken styling or redirect loops.

2. HTTPS reverse proxy

server {
    listen 80;
    server_name docs.example.com;

    client_max_body_size 100M;

    location / {
        proxy_pass http://127.0.0.1:6875;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d docs.example.com

3. Change the default login

Log in at https://docs.example.com with the default account: [email protected] / password. Immediately change the email and password (My Account), and enable multi-factor authentication.

4. Organise content

  • Shelves — top-level groups (e.g. “Engineering”, “HR”, “Customer Support”).
  • Books — a topic (e.g. “Server Runbooks”).
  • Chapters — sections within a book (optional).
  • Pages — the actual content.

Tags, templates (Settings → Customization → Page templates) and cross-links help as the library grows.

5. Permissions and roles

Settings → Roles define what users can do system-wide; each shelf, book, chapter or page can override permissions for specific roles. Typical setup: Admin, Editor, Viewer roles; sensitive books visible only to certain roles.

Disable public registration (Settings → Registration) unless you want it. Optionally allow public (guest) viewing for specific books — useful for public product docs.

6. Single sign-on

BookStack supports OIDC, SAML 2.0 and LDAP via environment variables, for example OIDC:

      AUTH_METHOD: oidc
      OIDC_NAME: "Company SSO"
      OIDC_DISPLAY_NAME_CLAIMS: name
      OIDC_CLIENT_ID: bookstack
      OIDC_CLIENT_SECRET: ${OIDC_SECRET}
      OIDC_ISSUER: https://auth.example.com/application/o/bookstack/
      OIDC_ISSUER_DISCOVER: "true"

Pair it with Authentik or Keycloak.

7. Email

Notifications, invitations and password resets need SMTP:

      MAIL_DRIVER: smtp
      MAIL_HOST: smtp.example.com
      MAIL_PORT: "587"
      MAIL_ENCRYPTION: tls
      MAIL_USERNAME: [email protected]
      MAIL_PASSWORD: ${MAIL_PASSWORD}
      MAIL_FROM: [email protected]

8. Backups

Back up the database and uploaded files:

docker compose exec db mariadb-dump -u bookstack -p"$(grep DB_PASSWORD .env | cut -d= -f2)" bookstack | gzip > bookstack-$(date +%F).sql.gz
tar czf bookstack-files-$(date +%F).tar.gz config/www/uploads config/www/files config/www/images 2>/dev/null

Paths inside ./config depend on the image version — verify where uploads live. Keep .env (the APP_KEY) with your backups; it’s needed to decrypt some stored data.

9. Updates

docker compose pull && docker compose up -d

Database migrations run automatically on startup.

BookStack vs Wiki.js

BookStack is opinionated and easy for everyone; Wiki.js is more flexible and developer-oriented (Git sync, Markdown files). Both run happily on a small Docker VPS.

  • BookStack
  • Documentation
  • Self-Hosting