BookStack for Deckard
Production deployment of BookStack using the official linuxserver.io Docker image.
Overview
This setup uses:
- Official linuxserver/bookstack image - Pre-built, well-maintained
- MariaDB database - linuxserver/mariadb image
- Caddy reverse proxy - For production HTTPS
- All configuration via .env - No secrets in docker-compose files
- Persistent volumes - Data stored in
./bookstack_data
Quick Start - Production
1. Generate APP_KEY
docker run -it --rm --entrypoint /bin/bash lscr.io/linuxserver/bookstack:latest appkey
Copy the output (looks like base64:xxxxx...)
2. Configure Environment
2.1 Settings for DB/Docker
# Copy example file
cp .env.example .env
# Edit configuration
nano .env
Required changes:
- MySQL settings
PUID/PGID- Runidto get your user/group IDsTZ- Your timezone
2.2 Settings for BookStack
cp bookstack.env.example bookstack.env
REQUIRED CHANGES:
- App name / App kek
- Email settings
3. Configure Caddy
# Navigate to Caddy sites directory
cd ../server-package/deckard/caddy/sites/
# Rename template to your domain
mv wiki.yourdomain.com wiki.tss-hd.de
# Edit and update domain names
nano wiki.tss-hd.de
4. Deploy
# Return to tss-bookstack directory
cd /home/simon/source/tss-bookstack
# Create caddynet network if needed
docker network create caddynet 2>/dev/null || true
# Start services
docker compose up -d
# Check logs
docker compose logs -f
5. Reload Caddy
cd ../server-package/deckard/caddy
docker compose restart caddy
6. Access & Login
Navigate to your domain (e.g., https://wiki.tss-hd.de)
Default credentials:
- Email:
admin@admin.com - Password:
password
⚠️ CHANGE THESE IMMEDIATELY!
Quick Start - Local Testing
For testing locally without Caddy reverse proxy:
1. Generate APP_KEY
docker run -it --rm --entrypoint /bin/bash lscr.io/linuxserver/bookstack:latest appkey
2. Configure for Testing
# Copy testing example
cp .env.testing.example .env
# Edit and add your APP_KEY
nano .env
3. Start Testing Instance
# Start on port 8080 (default)
docker compose -f docker-compose.testing.yml up -d
# Or use custom port
HOST_PORT=9000 docker compose -f docker-compose.testing.yml up -d
4. Access Locally
Navigate to http://localhost:8080 (or your custom HOST_PORT)
Default credentials: admin@admin.com / password
5. Cleanup
# Stop and remove containers (keeps data)
docker compose -f docker-compose.testing.yml down
# Stop and remove everything including data
docker compose -f docker-compose.testing.yml down
rm -rf bookstack_testing_data
File Structure
tss-bookstack/
├── docker-compose.yml # Production (with Caddy)
├── docker-compose.testing.yml # Local testing (without Caddy)
├── .env.example # Production config template
├── .env.testing.example # Testing config template
├── .env # Your actual config (not in git)
├── .gitignore # Git ignore rules
├── README.md # This file
├── QUICKSTART.md # Quick reference guide
├── TESTING.md # Local testing guide
├── VOLUMES.md # Volume management guide
└── EMAIL.md # Email configuration guide
Data Storage
Production - Named Volumes
Production uses Docker named volumes (managed by Docker):
volumes:
bookstack_data: # BookStack application data
bookstack_db: # MariaDB database
Data location: /var/lib/docker/volumes/bookstack_data/_data/
# List volumes
docker volume ls | grep bookstack
# Inspect volume
docker volume inspect bookstack_data
Testing - Bind Mounts
Testing uses bind mounts (direct folder access):
bookstack_testing_data/
├── www/ # BookStack application files
│ ├── .env # BookStack configuration
│ ├── files/ # Uploaded files
│ ├── images/ # Uploaded images
│ └── themes/ # Custom themes
├── log/ # Application logs
├── backups/ # Database backups
└── db/ # MariaDB database
See VOLUMES.md for detailed information on backups and volume management
Configuration
Environment Variables
All configuration is in .env:
| Variable | Description | Example |
|---|---|---|
PUID |
User ID for file permissions | 1000 |
PGID |
Group ID for file permissions | 1000 |
TZ |
Timezone | Europe/Berlin |
APP_URL |
Your BookStack URL | https://wiki.tss-hd.de |
APP_KEY |
Encryption key (generate with appkey command) | base64:xxx... |
DB_DATABASE |
Database name | bookstack |
DB_USERNAME |
Database user | bookstack |
DB_PASSWORD |
Database password | secure_password |
MYSQL_ROOT_PASSWORD |
MySQL root password | root_password |
MAIL_DRIVER |
Mail driver (log or smtp) |
log |
Additional BookStack Configuration
To configure advanced features (LDAP, SMTP, etc.), edit the .env file inside the container:
# Access the file via container
docker exec -it bookstack nano /config/www/.env
# Or copy out, edit, and copy back
docker cp bookstack:/config/www/.env .env.bookstack
nano .env.bookstack
docker cp .env.bookstack bookstack:/config/www/.env
Then restart BookStack:
docker compose restart bookstack
See BookStack documentation for available options.
Maintenance
View Logs
# All services
docker compose logs -f
# Just BookStack
docker compose logs -f bookstack
# Just Database
docker compose logs -f bookstack-db
Update BookStack
# Pull latest images
docker compose pull
# Recreate containers
docker compose up -d
# Clean up old images
docker image prune
Backup
Backup Database
# Export database SQL dump
docker exec bookstack-db bash -c "mysqldump -u root -p\$MYSQL_ROOT_PASSWORD \$MYSQL_DATABASE" > backup-$(date +%Y%m%d).sql
Backup Named Volumes
# Backup BookStack data volume
docker run --rm \
-v bookstack_data:/data \
-v $(pwd):/backup \
alpine tar czf /backup/bookstack-data-$(date +%Y%m%d).tar.gz /data
# Backup database volume
docker run --rm \
-v bookstack_db:/data \
-v $(pwd):/backup \
alpine tar czf /backup/bookstack-db-$(date +%Y%m%d).tar.gz /data
See VOLUMES.md for restore procedures
Restore Database
# Import database
docker exec -i bookstack-db mysql -u root -p$MYSQL_ROOT_PASSWORD $DB_DATABASE < backup-20241030.sql
Access Container Shell
# BookStack container
docker exec -it bookstack bash
# Database container
docker exec -it bookstack-db bash
Change APP_URL
If you change APP_URL in .env, update the database:
docker exec -it bookstack php /app/www/artisan bookstack:update-url \
https://old-domain.com \
https://new-domain.com
Then restart:
docker compose restart bookstack
Troubleshooting
Container won't start
# Check logs
docker compose logs bookstack
# Verify .env exists and is valid
cat .env
# Check file permissions
ls -la bookstack_data/
Database connection failed
# Verify database is running
docker compose ps
# Check database logs
docker compose logs bookstack-db
# Test database connection
docker exec -it bookstack-db mysql -u $DB_USERNAME -p$DB_PASSWORD
Permission errors
The linuxserver.io images handle permissions automatically using PUID/PGID.
# Check your UID/GID
id
# Update .env with correct PUID/PGID
nano .env
# Recreate containers
docker compose up -d
Can't access via domain
# Verify container is on caddynet
docker inspect bookstack | grep caddynet
# Check Caddy config
cat ../server-package/deckard/caddy/sites/wiki.tss-hd.de
# Reload Caddy
cd ../server-package/deckard/caddy
docker compose restart caddy
Clear cache
docker exec bookstack php /app/www/artisan cache:clear
docker exec bookstack php /app/www/artisan config:clear
Differences from DIY Setup
Using linuxserver.io image instead of building from source:
| Feature | DIY Build | linuxserver.io |
|---|---|---|
| Maintenance | Manual updates | docker compose pull |
| Setup | Build from source | Pull pre-built image |
| PHP/Composer | Install on host | Included in image |
| Permissions | Manual chown |
Automatic via PUID/PGID |
| Updates | Manual git pull + rebuild | Pull new image |
| Support | Self-support | linuxserver.io community |
Security Notes
✅ No secrets in docker-compose files
✅ All configuration in .env
✅ .env should have restricted permissions (600)
✅ Change default admin credentials immediately
✅ Use strong passwords for DB_PASSWORD and MYSQL_ROOT_PASSWORD
✅ Regular backups recommended
✅ Keep images updated with docker compose pull