Quick start (5 min)
Homelab documentation falls apart fast. Static IP allocations, Docker Compose files, Proxmox firewall rules, and random Bash aliases quickly scatter across scratchpads and messy text files. BookStack fixes this mess by borrowing a physical library hierarchy: Shelves, Books, Chapters, and Pages.
With Docker Compose, you can stand up a production-ready instance in under five minutes using LinuxServer’s lightweight image and a MariaDB container. The baseline stack consumes under 250MB of RAM at idle.
First, create a dedicated project directory and switch into it:
mkdir -p ~/homelab/bookstack && cd ~/homelab/bookstack
Create your Compose file:
nano docker-compose.yml
Paste the following stack configuration:
version: "3.8"
services:
bookstack:
image: lscr.io/linuxserver/bookstack:latest
container_name: bookstack
environment:
- PUID=1000
- PGID=1000
- APP_URL=http://192.168.1.50:6875
- DB_HOST=bookstack_db
- DB_PORT=3306
- DB_USER=bookstack
- DB_PASS=SecretBookStackPassword123
- DB_DATABASE=bookstackapp
volumes:
- ./appdata:/config
ports:
- 6875:80
restart: unless-stopped
depends_on:
- bookstack_db
bookstack_db:
image: lscr.io/linuxserver/mariadb:latest
container_name: bookstack_db
environment:
- PUID=1000
- PGID=1000
- MYSQL_ROOT_PASSWORD=RootSecretPassword456
- MYSQL_DATABASE=bookstackapp
- MYSQL_USER=bookstack
- MYSQL_PASSWORD=SecretBookStackPassword123
volumes:
- ./dbdata:/config
restart: unless-stopped
Swap out http://192.168.1.50:6875 with your server’s actual LAN IP address or local DNS hostname. Do not omit the port number.
Fire up the containers in the background:
docker compose up -d
Watch the migration logs until the web server starts accepting requests:
docker compose logs -f bookstack
Once you see the Nginx confirmation lines, navigate to http://<your-server-ip>:6875 in your browser. Sign in using the default administrative account:
- Email:
[email protected] - Password:
password
Change this default password immediately. Go to Edit Profile in the top-right corner before building your first shelf.
Deep dive
Spinning up self-hosted services is the easy part. Remembering how you configured them eight months later during a hardware migration is where things break down. A dedicated wiki prevents that panic.
How BookStack structures your knowledge
Flat markdown trees and unstructured wikis often descend into chaos. BookStack enforces a strict four-tier hierarchy to keep documentation tidy:
- Shelves: Broad operational categories like Networking, Storage Pools, or Kubernetes. A shelf groups multiple related books together.
- Books: Individual systems or services, such as OPNsense Firewall, TrueNAS Core, or Media Automation.
- Chapters: Optional sections within a book. For example, VLAN Trunking or WireGuard Road-Warrior Tunnel.
- Pages: The actual technical articles holding code blocks, network diagrams, configuration diffs, and attachments.
This structure imposes guardrails. It prevents orphaned pages and keeps your documentation browsable even as your homelab grows to dozens of services.
Key environment parameters explained
Three Compose variables require attention before rolling into production:
APP_URL: BookStack uses this exact string to construct internal links, asset paths, and redirection headers. If the protocol, IP, or port differs from what sits in your browser address bar, CSS and JS assets will fail to load, and form submissions will throw CSRF errors.PUIDandPGID: These variables map internal container processes to host user IDs (usually1000:1000for the primary user on Ubuntu or Debian). This prevents the daemon from creating root-owned files on your persistent storage volumes.DB_HOST: Must match the service name defined under your database block (bookstack_db). Docker’s built-in DNS handles container-to-container routing over the default bridge network automatically.
Advanced usage
Setting up HTTPS with a reverse proxy
Plain HTTP works on a protected local subnet, but modern browsers disable secure features like clipboard copy-pasting on non-HTTPS origins. If you run a reverse proxy like Caddy or Nginx, adjust your Compose file first.
Update APP_URL to match your secure FQDN:
environment:
- APP_URL=https://wiki.lab.example.com
Here is an example Caddy block that handles SSL generation and forwards proxy headers correctly:
wiki.lab.example.com {
reverse_proxy 127.0.0.1:6875 {
header_up X-Forwarded-Proto https
}
}
For standard Nginx reverse proxies, ensure you forward the protocol and IP headers:
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 https;
}
Automating database backups
A corrupted flash drive or failed SSD shouldn’t take your runbooks down with it. A straightforward shell script running via cron creates automated daily dumps in seconds.
Create a backup script at ~/homelab/bookstack/backup.sh:
#!/usr/bin/env bash
set -euo pipefail
BACKUP_DIR="${HOME}/homelab/bookstack/backups"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
mkdir -p "${BACKUP_DIR}"
# Dump MariaDB database from the running container
docker exec bookstack_db /usr/bin/mariadb-dump \
-u bookstack \
-pSecretBookStackPassword123 \
bookstackapp | gzip > "${BACKUP_DIR}/bookstack_db_${TIMESTAMP}.sql.gz"
# Archive uploaded assets, diagrams, and attachments
tar -czf "${BACKUP_DIR}/bookstack_files_${TIMESTAMP}.tar.gz" \
-C "${HOME}/homelab/bookstack/appdata" www/storages
# Keep only backups from the past 14 days
find "${BACKUP_DIR}" -type f -name "bookstack_*" -mtime +14 -delete
echo "Backup completed: ${TIMESTAMP}"
Make the script executable:
chmod +x ~/homelab/bookstack/backup.sh
Open crontab to schedule the task:
crontab -e
Add a nightly entry to run every morning at 03:00 AM:
0 3 * * * /bin/bash /home/ubuntu/homelab/bookstack/backup.sh >> /home/ubuntu/homelab/bookstack/backup.log 2>&1
Practical tips
Configuring Markdown as your default editor
BookStack defaults to a WYSIWYG editor. While fine for general prose, it struggles with CLI outputs, shell sessions, and raw configuration blocks. Switching to Markdown gives you a split-pane interface with clean code rendering.
- Log in as an administrator.
- Navigate to Settings > Customization.
- Scroll down to Page Editor and select Markdown.
- Save the changes. Existing pages retain their original format, while all new pages open in the dual-pane Markdown editor.
Fixing CSRF token errors on login
A “Page Expired” or “Token Mismatch” error when submitting a login form points to an environment mismatch. Verify these two settings:
- Ensure
APP_URLin your Compose file matches the exact URL in your address bar. If you browse viahttp://192.168.1.50:6875, settingAPP_URL=http://localhost:6875will trigger token rejections. - When running behind HTTPS proxies, confirm that your proxy passes the
X-Forwarded-Proto httpsheader. Without it, BookStack believes the connection is unencrypted and drops the session cookie.
Drafting your first structured homelab shelf
Consistency matters from day one. Here is a battle-tested structure designed for homelab fleets:
- Shelf:
Infrastructure & Baremetal- Book:
Proxmox VE Cluster- Chapter:
Storage Pools→ Page:ZFS Scrub Schedules & Retention Policies - Chapter:
Network Bridges→ Page:VLAN Trunking on vmbr0 (10G SFP+)
- Chapter:
- Book:
Docker Hosts- Page:
Daemon JSON & Default Log Rotation - Page:
Shared Compose Templates & Subnets
- Page:
- Book:
Setting this up now guarantees that whenever an update breaks an internal service, the exact fix is only two clicks away.

