Wiki

How to Deploy BookStack 0.29.3 in Docker Swarm Behind Traefik v2.0

BookStack is a simple, self-hosted platform for organizing and storing information, allowing you to structure documentation into books, chapters, and pages.

Rajasekhar Gundala··6 min read

BookStack is a simple, self-hosted platform for organizing and storing information where content is intuitively categorized into books, chapters, and pages.

This post will guide you through deploying BookStack 0.29.3 to a Docker Swarm Cluster using the Docker Compose tool.

BookStack is a simple, self-hosted, easy-to-use platform for organizing and storing information.

You can learn more by visiting the official BookStack website and their GitHub repository.

Let’s start with the actual deployment.

Prerequisites

Please ensure you fulfill the following requirements before proceeding with the deployment:

  1. A Docker Swarm Cluster with GlusterFS configured as your persistent storage.
  2. Traefik acting as a reverse proxy to expose your micro-services to the external web.
  3. A Database stack deployed to host application databases.

Introduction to BookStack

If you are looking to self-host your product documents to reduce ticket management overhead, manage project documentation for internal teams, or maintain a private repository, BookStack is an excellent solution.

BookStack is an opinionated wiki system that provides a pleasant and simple out-of-the-box experience.

Why Choose BookStack?

BookStack is designed to be accessible. New users only require basic word-processing skills to start creating content.

BookStack is not designed as an extensible platform to be used for purposes that differ from the statement above.

In regards to development philosophy, BookStack maintains a relaxed, open, and positive approach. It is free software developed and maintained by individuals donating their free time.

The core principle of storing information within BookStack is based on the concept of a normal stack of books. Just like physical books, BookStack books can contain chapters and pages. You start by creating a “Book” that acts as the highest level of categorization. Ideally, you would have separate books for separate topics.

Within a book, you can directly create pages, or you can first create chapters. Chapters provide an additional level of grouping to keep pages organized, though they are entirely optional.

Once your library grows, you can use “Bookshelves” to organize your Books. Bookshelves can contain multiple books, and a single book can be placed on multiple Bookshelves.

Core Features

BookStack provides advanced power features for those who desire them, but they never interfere with the core, simple user experience. Here are some of the standout features:

  1. Free and Open Source: BookStack is MIT licensed. There is no cost to download and install your own instance.
  2. Simplicity: It features a clean WYSIWYG interface where content is broken into Books, Chapters, and Pages.
  3. Powerful Search: The content is fully searchable at the book level or across all books, chapters, and pages. You can link directly to any paragraph to keep documentation tightly connected.
  4. Lightweight Architecture: Built using PHP on top of the Laravel framework and MySQL, it can run comfortably on a $5 DigitalOcean VPS.
  5. Highly Customizable: You can configure BookStack to suit your use case by changing the name, logo, and registration options, as well as toggling public visibility.
  6. Authentication Integrations: Along with default email/password login, it supports social providers such as GitHub, Google, Slack, and AzureAD. Okta and LDAP options are also available for enterprise environments.
  7. Additional Perks: Multi-lingual support, an optional Markdown editor, and a robust roles/permissions system.

Persist BookStack Data

Containers are fast to deploy and make efficient use of system resources. However, there is a common misperception that containers are strictly ephemeral—meaning if we restart a container, all data is lost. While this is true by default, it is absolutely possible to containerize stateful applications.

I am using GlusterFS to overcome the ephemeral nature of containers.

I previously set up a replicated GlusterFS volume to ensure data is replicated throughout the cluster. The diagram below explains how the replicated volume works:

GlusterFS Replicated Volume

The volume is mounted on all nodes. When a file is written to the /mnt partition, the data is instantly replicated to all other nodes in the cluster.

If one of the nodes fails, the application automatically restarts on another node without losing any data. This is the beauty of a replicated volume.

Persistent application state or data needs to survive application restarts and host outages. By storing data in GlusterFS and performing periodic backups, we can confidently spin up a new application container anywhere else in case of unexpected infrastructure issues.

For BookStack, we need to persist the /var/www/bookstack/public/uploads and /var/www/bookstack/storage/uploads directories.

Create the necessary persistent folders in your /mnt directory:

cd /mnt
sudo mkdir -p buploads
sudo mkdir -p bsuploads

Please watch the below video for a visual walkthrough of the GlusterFS Replicated Volume Setup.


Prepare the BookStack Environment

Create a dedicated folder in the /opt directory to place your Docker Compose .yml configuration file.

cd /opt
sudo mkdir -p bookstack
cd bookstack
sudo touch bookstack.yml

BookStack Docker Compose Configuration

Open the bookstack.yml file using the nano editor:

sudo nano bookstack.yml

Copy and paste the following code into bookstack.yml. This represents the full Docker Swarm stack configuration for BookStack.

version: "3.7"

services:
  bookstack:
    image: solidnerd/bookstack
    ports:
      - '8081:8080'
    volumes:
      - /mnt/buploads:/var/www/bookstack/public/uploads
      - /mnt/bsuploads:/var/www/bookstack/storage/uploads
    secrets:
      - mysql_root_password
    environment:
      - DB_HOST=db:3306
      - DB_DATABASE=bookstack
      - DB_USERNAME=root
      - DB_PASSWORD_FILE=/run/secrets/mysql_root_password
      - APP_URL=[https://bookstack.example.com](https://bookstack.example.com)
      - STORAGE_TYPE=local_secure
      - AUTH_METHOD=standard
      - APP_AUTO_LANG_PUBLIC=true
      - APP_VIEWS_BOOKS=grid
      - CACHE_DRIVER=file
      - SESSION_DRIVER=file
      - SESSION_LIFETIME=120
      - SESSION_COOKIE_NAME=book_session
      - SESSION_SECURE_COOKIE=false
      - CACHE_PREFIX=bookstack
    networks:
      - proxy
    deploy:
      placement:
        constraints: [node.role == worker]
      replicas: 1
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
      labels:
        - "traefik.enable=true"
        - "traefik.docker.network=proxy"
        - "traefik.http.routers.bookstack.rule=Host(`bookstack.example.com`)"
        - "traefik.http.routers.bookstack.tls=true"
        - "traefik.http.routers.bookstack.tls.certresolver=default"
        - "traefik.http.routers.bookstack.entrypoints=websecure"
        - "traefik.http.services.bookstack.loadbalancer.server.port=8080"

secrets:
  mysql_root_password:
    external: true

volumes:
  buploads:
    driver: "local"
  bsuploads:
    driver: "local"

networks:
  proxy:
    external: true

As mentioned in the prerequisites, I am using a MariaDB database that was previously deployed to our Docker Swarm environment.

There are many configuration options available via environment variables. Please check the official documentation for the full list of parameters.

If you prefer community-maintained Docker setups, check out these alternatives:

LinuxServer.io

Solidnerd

Deploy BookStack using Docker Compose

Please ensure that you have created the bookstack database within your MariaDB instance before deploying this stack.

Now, deploy the stack to your Swarm using the following command:

docker stack deploy --compose-file bookstack.yml bookstack

You can name the stack anything you prefer; I have simply named it bookstack.

Check the status of the stack deployment:

docker stack ps bookstack

Once the container is running, open any browser and navigate to https://bookstack.example.com (or whichever URL you specified in the APP_URL and Traefik labels).

Ensure you have created a DNS A-Record or CNAME entry pointing bookstack.example.com to your Traefik load balancer IP address.

You will be greeted by the BookStack login screen. Use the default credentials to log in:

  • Email: admin@admin.com
  • Password: password

BookStack Login Screen

Make sure to immediately change the admin email address and password in the Edit Profile settings.

Edit Admin Profile

Here is a preview of the Shelves view:

Shelves View

And the Books view:

Books View

Finally, explore the Settings panel to customize your instance:

BookStack Settings

I hope you found this tutorial helpful! Please share your thoughts or ask any questions in the comments below. Your feedback helps me bring more open-source, self-hosted deployment guides to the blog.

Stay tuned for more deployments in upcoming posts!

Share
Written by
Rajasekhar Gundala

Senior Infrastructure & Web Platform Leader.

Continue reading

Weekly Engineering Notes.

A weekly digest on infrastructure, observability, Rust, and the open web. No spam, just technical signals.

Free. Unsubscribe in one click.