Skip to main content

BookStack - Personal wiki

Bookstack is a "simple, self-hosted, easy-to-use platform for organising and storing information." In other words, it's a personal wiki. The documentation for kasad.com (what you're reading now) is hosted using BookStack.

Deployment

BookStack requires two containers, the BookStack server and a database. The lscr.io/linuxserver/bookstack and mysql images are used for those.

Access

The BookStack web app is reverse-proxied behind the Secure Web Application Gateway (SWAG) container. It is not protected by Cloudflare Access policies in order to allow public read-only access to the content. A login is required to edit content.

Docker Compose stack

We deploy the BookStack instance using the following Docker Compose file:

version: "2"

services:

  bookstack:
    image: lscr.io/linuxserver/bookstack:22.09.20220908
    container_name: bookstack
    environment:
      - PUID=1003 # bookstack
      - PGID=941 # servlets
      - UMASK=007
	env_file: stack.env
	volumes:
      - /srv/bookstack/config:/config
    networks:
      - default
      - swag
    restart: unless-stopped
    depends_on:
      - bookstack_db
      
  bookstack_db:
    image: mysql
    container_name: bookstack_db
    environment:
      - PUID=1003 # bookstack
      - PGID=941 # servlets
      - UMASK=007
      - TZ=America/Los_Angeles
      - MYSQL_ROOT_PASSWORD=[redacted]
      - MYSQL_DATABASE=bookstackapp
      - MYSQL_USER=bookstack
      - MYSQL_PASSWORD=[redacted]
    volumes:
      - /srv/bookstack/db_data:/var/lib/mysql
    restart: unless-stopped
  
networks:
  swag:
    external: true
    name: swag_default

SWAG network

Since our BookStack instance is reverse-proxied by the Secure Web Application Gateway, the SWAG container needs network access to the Bookstack container. This has been done in the Compose stack above. See this explanation for details.

Persistent file volumes

BookStack stores most of its data in the MySQL database. However, some of BookStack's configuration data is stored in files in the /config directory and file uploads are stored in the /config/www/uploads directory. So we mount a storage volume on /config within the bookstack container in order to persist this data between service restarts:

    volumes:
      - /srv/bookstack/config:/config

Configuration

The configuration for BookStack's server is done using environment variables. There is a settings interface within the BookStack web frontend which controls settings that pertain to using BookStack.

For example, configuring the SMTP server is done using environment variables whereas configuring user roles is done from the settings interface.

Environment configuration

All of BookStack's configuration can be done using environment variables. By default, BookStack is designed to read configuration by parsing /config/www/.env for environment variables. Variables defined in the container's environment are also applied. A value defined in the container environment will override a different value for the same variable in the file.

To improve container repeatability, we define these variables in a stack.env file adjacent to the docker-compose.yml file. This file is loaded into the container's environment by setting env_file: stack.env for the bookstack service in the Compose file.

The contents of the stack.env file are listed below. The comments in the file explain the settings well, so they will not be explained again on this page. More settings are available, and are documented in the Configuration section of BookStack's documentation.

# Application URL
# This must be the root URL that you want to host BookStack on.
# All URLs in BookStack will be generated using this value
# to ensure URLs generated are consistent and secure.
# If you change this in the future you may need to run a command
# to update stored URLs in the database. Command example:
# php artisan bookstack:update-url https://old.example.com https://new.example.com
APP_URL=https://books.kasad.com/

# Database connection parameters
DB_HOST=bookstack_db
DB_DATABASE=bookstackapp
DB_USERNAME=bookstack
DB_PASSWORD=[redacted]

# Mail system to use
# Can be 'smtp' or 'sendmail'
MAIL_DRIVER=smtp

# Mail sender details
MAIL_FROM_NAME="Kasad BookStack"
MAIL_FROM=no-reply@books.kasad.com

# SMTP mail options
# These settings can be checked using the "Send a Test Email"
# feature found in the "Settings > Maintenance" area of the system.
MAIL_HOST=mail.kasad.com
MAIL_PORT=587
MAIL_ENCRYPTION=tls
MAIL_USERNAME=bookstack
MAIL_PASSWORD=[redacted]

# OpenID Connect authentication
AUTH_METHOD=oidc

# Control if BookStack automatically initiates login via your OIDC system
# if it's the only authentication method. Prevents the need for the
# user to click the "Login with x" button on the login page.
# Setting this to true enables auto-initiation.
AUTH_AUTO_INITIATE=true

# Set the display name to be shown on the login button.
# (Login with <name>)
OIDC_NAME="Kasad Auth Portal"

# Name of the claims(s) to use for the user's display name.
# Can have multiple attributes listed, separated with a '|' in which
# case those values will be joined with a space.
# Example: OIDC_DISPLAY_NAME_CLAIMS=given_name|family_name
OIDC_DISPLAY_NAME_CLAIMS=name

# OpenID Connect server parameters
OIDC_CLIENT_ID=[redacted]
OIDC_CLIENT_SECRET=[redacted]
OIDC_ISSUER=https://auth2.kasad.com/application/o/bookstack/
OIDC_ISSUER_DISCOVER=true

# Within BookStack there are a few different options for storing files:
#    local (Default) - Files are stored on the server running BookStack. Images are publically accessible, served by your websever, but attachments are secured behind BookStack’s authentication.
#    local_secure - Same as local option but images are served by BookStack, enabling authentication on image requests. Provides higher security but is more system resource intensive and could induce performance issues.
#    s3 - Store files externally on Amazon S3. Images are made publically accessible on upload.
STORAGE_TYPE=local_secure

# Only send cookies over a HTTPS connection.
# Ensure you have BookStack served over HTTPS before enabling.
# Defaults to 'false'
SESSION_SECURE_COOKIE=true

# Store user session data in the database instead of in files.
# This will hopefully persist user sessions across service restarts.
SESSION_DRIVER=database

Single sign-on

BookStack supports the OpenID Connect standard for single sign-on, meaning we can use Authentik to sign in to BookStack. See the BookStack documentation on OIDC for information on configuring SSO.

Authentik OpenID provider settings

Within Authentik, we need to create an Application and an OpenID Provider for BookStack.

  • In the newly-created provider, set the Redirect URI to https://books.kasad.com/oidc/callback.
  • Under Advanced protocol settings, ensure that Issuer mode is set to Each provider has a different issuer, based on the application slug..

All other settings should be fine if left with their default values.

Configuration within BookStack

There are actually some settings that are controlled from BookStack's user interface when logged in as a user with administrator permissions. These settings don't pertain to the BookStack server's configuration, but instead to the user-facing options, e.g. custom theming and allowing public access sans authentication.

Users and roles

In BookStack, users have Roles which define what permissions they are given. Many roles can be created. Roles are not nested, though, so they don't inherit permissions from each other.

Roles are configured within the settings interface in BookStack. Default permissions for each role on a specific book/chapter/page can be overridden by setting custom permissions on said book/chapter/page. See Book/page permissions below for details.

OpenID group sync

Roles can be automatically assigned according to groups which a user belongs to in the SSO provider. See the Group Sync section of BookStack's OpenID documentation for details.

Configuring this requires defining two environment variables:

  • OIDC_USER_TO_GROUPS=true - Enable OpenID group sync
  • OIDC_GROUPS_CLAIM=groups - The OpenID resource claim which contains the list of groups a user belongs to. For Authentik, this is the groups claim.

Using BookStack

Book/page permissions

Books and pages can have custom permissions. Since the instance is publicly accessible, unauthenticated users can access the content according to the permissions assigned to the Public role. Create/modify/delete permissions should not be granted to the Public role, otherwise unauthenticated users will be able to modify content.

By default, books/pages will not be publicly visible. To make a book/page publicly visible, add custom permissions for that page and select the View permission for the Public role.

Pages and chapters will inherit permissions from the book they belong to unless they are given custom permissions. More specific permissions (e.g. page level) override less specific (e.g. book level) ones.