Deploying BookStack on YunoHost via Docker Compose (The Humane-Tech Method)
1. Context & Philosophy
This guide documents the installation of BookStack on a YunoHost VPS (obulou.org). Instead of a standard root-based installation, this setup prioritises a Humane-Tech approach: strictly controlling data ownership by running containers as a specific non-root administrative user to prevent permission locks and keep the system clean.
We use the LinuxServer.io images because they handle PUID/PGID mapping excellently, ensuring files in the volume mounts remain owned by the user, not root.
2. Prerequisites
-
OS: Debian 12 (Bookworm) with YunoHost installed.
-
Docker: Installed and running.
-
User Info: A non-root user (e.g.,
kalvin0x8d0) withsudoprivileges. -
PUID/PGID: Run
idto confirm (e.g.,23691). -
Target Domain:
bookstack.obulou.org(or similar). -
Target Port:
52575(arbitrary high port to avoid conflicts).
3. Directory Setup & Security Key
First, create the directory in your home folder to ensure you own the data.
mkdir -p ~/docker/bookstack
cd ~/docker/bookstack
Generate a secure unique 32-byte key. You will need this for the APP_KEY later.
Note: Ensure you include the hyphen - before base64, otherwise the command may fail.
echo "base64:$(openssl rand -base64 32)"
(Copy the output string; it will look like base64:randomcharacters...)
4. The Docker Compose Configuration
Create your compose.yaml.
Crucial Decision: Do not put the APP_KEY in this file. We learnt that Docker variables override the .env file, which can cause "Cipher Error" loops. We will add it manually to the generated config file later.
services:
bookstack:
image: lscr.io/linuxserver/bookstack:latest
container_name: bookstack
environment:
- PUID=23691 # Replace with your actual ID
- PGID=23691
- TZ=Asia/Kuala_Lumpur
- APP_URL=https://bookstack.obulou.org
- DB_HOST=bookstack_db
- DB_USER=bookstack
- DB_PASS=YourSecretPassword
- DB_DATABASE=bookstackapp
volumes:
- ./config:/config
ports:
- 52575:80
restart: unless-stopped
depends_on:
- bookstack_db
bookstack_db:
image: lscr.io/linuxserver/mariadb:latest
container_name: bookstack_db
environment:
- PUID=23691
- PGID=23691
- TZ=Asia/Kuala_Lumpur
- MYSQL_ROOT_PASSWORD=YourRootPassword
- MYSQL_DATABASE=bookstackapp
- MYSQL_USER=bookstack
- MYSQL_PASSWORD=YourSecretPassword
volumes:
- ./db_data:/config
restart: unless-stopped
5. The Installation & The "Gotcha" Fixes
This is where most installations fail. Follow these steps precisely to avoid "500 Errors" or "Access Denied" loops.
Step A: Initial Boot
Run the container to generate the initial configuration files.
docker compose up -d
Step B: Fixing the .env Conflict (The "Access Denied" Fix)
By default, the container creates a .env file populated with placeholders like DB_HOST=localhost and DB_USERNAME=database_username. This conflicts with your compose.yaml settings.
- Edit the generated file:
nano config/www/.env
- Update the Database Section: Ensure it matches your
compose.yamlexactly.
DB_HOST=bookstack_db # MUST match the container name, NOT localhost
DB_DATABASE=bookstackapp
DB_USERNAME=bookstack
DB_PASSWORD=YourSecretPassword
- Add the App Key: Paste the key you generated in Section 3 here.
APP_KEY=base64:YOUR_GENERATED_KEY
Step C: Clearing the Cache (The "White Screen" Fix)
After editing the .env file, BookStack won't see the changes until the cache is cleared.
Note: You must specify the working directory -w /app/www because the artisan file is not in the container root.
docker exec -w /app/www bookstack php artisan config:clear
docker exec -w /app/www bookstack php artisan cache:clear
6. Exposing to the Web
Since the app runs on localhost:52575, use YunoHost to bridge it to the outside world.
- Go to YunoHost Admin > Applications > Install.
- Select Redirect.
- Configure:
- Domain:
bookstack.obulou.org - Path:
/ - Destination:
http://127.0.0.1:52575
7. Post-Install: SMTP Email Setup
To ensure "Forgot Password" works, configure SMTP in config/www/.env.
Tip: If your password contains special characters, you MUST wrap it in double quotes.
MAIL_DRIVER=smtp
MAIL_HOST=smtp.yourprovider.com
MAIL_PORT=587
MAIL_ENCRYPTION=tls
MAIL_USERNAME=your_email@obulou.org
MAIL_PASSWORD="Your!Secret#Password"
MAIL_FROM=your_email@obulou.org
Remember to run the cache clear command from Step 5C again after saving!
8. Lessons Learnt
- Artisan Path: When running commands via
docker exec, theartisanbinary is located at/app/www, not the root. Using-w /app/wwwis mandatory. - Config Priority: BookStack reads the generated
.envfile first. If that file contains default placeholder database credentials, it will ignore your Docker Compose variables, leading to "Access Denied" errors. Always manually sync the.envfile. - Typo Alert: The
opensslcommand requires a hyphen (-base64), or it will fail silently or output nothing.
No comments to display
No comments to display