BookStack
BookStack organises documentation in shelves, books, chapters and pages. Two containers — the application and MariaDB.
Last run on a host 8 Nov 2026
Pinned at version-v26.09.2 (released 20 Oct 2026) · the newest upstream release
In the upstream images: 1 CRITICAL · 31 HIGH with a published fix — per image
To try it: Docker, nothing else. See Try it locally.
To deploy it behind the proxy: Traefik running and a domain.
Try it locally
Section titled “Try it locally”On your own machine, with no proxy, domain or certificate. From apps/bookstack/:
cp .env.local.example .env.local
# The secrets ship empty; generate the ones this stack needsAPP_TAG=$(sed -n 's/^APP_TAG=//p' .env.local){ echo "DB_PASSWORD=$(openssl rand -base64 32 | tr -d '\n')" echo "DB_ROOT_PASSWORD=$(openssl rand -base64 32 | tr -d '\n')" echo "APP_KEY=$(docker run --rm --entrypoint /bin/bash "lscr.io/linuxserver/bookstack:$APP_TAG" appkey)"} >> .env.local
mkdir -p volumes/local/config volumes/local/mysqlsudo chown -R 1000:1000 volumes/local/config
docker compose -f docker-compose.local.yml --env-file .env.local up -dThen open http://localhost:8080. Stop it again with the same command and down.
Installation
Section titled “Installation”From apps/bookstack/:
-
Copy the environment file and set
APP_TRAEFIK_HOST,TZandPUID/PGID:Terminal window cp .env.example .env -
Generate the Laravel application key and paste the
base64:…output intoAPP_KEYin.env:Terminal window docker run --rm --entrypoint /bin/bash \lscr.io/linuxserver/bookstack:version-v26.09.2 appkey -
Generate the database secrets and mirror the password into
.env:Terminal window mkdir -p .secretsopenssl rand -base64 32 | tr -d '\n' > .secrets/db_pwd.txtopenssl rand -base64 32 | tr -d '\n' > .secrets/db_root_pwd.txtsed -i "s|^DB_PWD_INLINE=.*|DB_PWD_INLINE=$(cat .secrets/db_pwd.txt)|" .envBookStack cannot read the password from a file, so the value exists twice — once as the secret for MariaDB, once inline.
-
Create the volumes and hand the config directory to the user the image drops to:
Terminal window mkdir -p volumes/config volumes/mysqlsudo chown -R 1000:1000 volumes/config -
Start it and wait for the first-run migrations:
Terminal window docker compose up -ddocker compose logs bookstack-app --follow -
Over the VPN, open
https://<APP_TRAEFIK_HOST>and log in with the default account —[email protected]with the passwordpassword— then change both immediately. The route ships closed (access-vpn) because that default login works on a new instance; open it for readers once the account is changed.
Verify
Section titled “Verify”docker compose ps # two services, healthyThen create a page and paste an image into it. The image is the check: page text goes to the database, the file goes to the upload directory, and only the second depends on the ownership from step 4.
Going further
Section titled “Going further”Who can reach it
Section titled “Who can reach it”The stack ships access-vpn with limit-standard and headers-standard, so
the default login above is never reachable from the internet. A wiki people are
meant to read has to be readable: once the account is changed, set
APP_TRAEFIK_ACCESS=access-public in .env and run docker compose up -d;
BookStack’s own permissions then decide who sees what. For internal content,
keep access-vpn.
Backup
Section titled “Backup”| Database | MariaDB, container bookstack-db, database bookstack, user bookstack |
| Password | .secrets/db_pwd.txt |
| State | volumes/mysql (database) · volumes/config (images, attachments) |
| Quiescing | Not needed — the dump is consistent on its own. |
Pages reference uploaded images by path, so the database and volumes/config
come back from the same backup run.
For borgmatic:
mariadb_databases: - name: bookstack container: bookstack-db username: bookstack password: "{credential file /srv/docker/apps/bookstack/.secrets/db_pwd.txt}"Page content is in the database; the images inside those pages are in
volumes/config. A database-only restore gives a wiki where every page renders
with broken images — recovered on paper, not in practice.
Restore order: database, then the application.
Updates
Section titled “Updates”-
Read the release notes.
-
Back up the database and
volumes/configtogether. -
Raise
APP_TAGin.env, then:Terminal window docker compose pull && docker compose up -ddocker compose logs bookstack-app --follow -
Open a page with an image. A migration that touched the attachment tables shows up there.
Troubleshooting
Section titled “Troubleshooting”Uploads fail with a permission error. volumes/config is not owned by the
PUID/PGID from .env. Re-run the chown from step 4.
The application reports a missing or invalid key. APP_KEY is empty or was
pasted without the base64: prefix.
Adding user: to the app service breaks startup. The image starts as root to
set up its process supervisor and drops privileges itself.
Repository files
Section titled “Repository files”apps/bookstack/README.md— setup, security model, known issuesapps/bookstack/UPSTREAM.md— source and upgrade checklist
Official sources
Section titled “Official sources”© 2026 SecDockBlueCode Apache-2.0Site content CC BY-NC 4.0