digitalboard.core/roles/bookstack/templates/backup.sh.j2
Tobias Wüst 951b1822fe
feat(bookstack): add role for self-hosted BookStack deployment
Deploy BookStack with linuxserver.io images behind Traefik, including
Entra ID OIDC SSO support and a daily backup timer.

Stack:
- lscr.io/linuxserver/bookstack:version-v26.03.3
- lscr.io/linuxserver/mariadb:11.4.9
- Traefik labels for websecure entrypoint on internal network
- Healthcheck via mariadb-admin ping (LSIO image lacks healthcheck.sh)

Features:
- Persistent APP_KEY generated on first run, stored in volume dir
- Optional OIDC SSO via Microsoft Entra ID (configurable per-instance)
- Idempotent admin user creation with DB-based existence check
- Daily systemd timer backup (DB dump + uploads tar + APP_KEY)
  with configurable retention

Implementation notes:
- DB queries use --protocol=tcp with the app user because root@localhost
  uses unix_socket auth in the LSIO MariaDB image (no password) and
  root@% does not exist
- docker_container_exec uses argv: (list) instead of command: (string)
  to avoid argument-splitting issues
- Migration-wait task ensures users table exists before admin check,
  since /login returns 200 before Laravel migrations complete
- no_log: true on all tasks that reference DB or admin passwords
- artisan absolute path (/app/www/artisan) because LSIO image WORKDIR
  is not the app directory

Adds bookstack route to DMZ Traefik service registry.
2026-05-26 15:30:21 +02:00

41 lines
No EOL
1.4 KiB
Django/Jinja

#!/bin/bash
# {{ ansible_managed }}
set -euo pipefail
BACKUP_DIR="{{ bookstack_backup_dir }}"
RETENTION_DAYS={{ bookstack_backup_retention_days }}
APPDATA_DIR="{{ bookstack_appdata_dir }}"
STAMP="$(date +%Y%m%d-%H%M%S)"
mkdir -p "$BACKUP_DIR"
# --- DB dump (mariadb-dump from inside the DB container) ---
# Use the app user via TCP because root@localhost is unix_socket-auth only
# in the LSIO MariaDB image and root@% does not exist.
docker exec {{ bookstack_service_name }}-db \
mariadb-dump \
--protocol=tcp -h 127.0.0.1 \
-u "{{ bookstack_db_user }}" -p"{{ bookstack_db_password }}" \
--single-transaction --routines --triggers --quick \
"{{ bookstack_db_name }}" \
| gzip -9 > "$BACKUP_DIR/bookstack-db-$STAMP.sql.gz"
# --- File uploads (images, attachments) ---
# LSIO BookStack stores user uploads under /config/www/{uploads,storage/uploads,files}.
tar --warning=no-file-changed \
-czf "$BACKUP_DIR/bookstack-files-$STAMP.tar.gz" \
-C "$APPDATA_DIR/www" \
uploads storage/uploads files 2>/dev/null || true
# --- APP_KEY backup (critical for restore!) ---
install -m 0600 "{{ bookstack_docker_volume_dir }}/.app_key" \
"$BACKUP_DIR/bookstack-appkey-$STAMP.txt"
# --- Retention ---
find "$BACKUP_DIR" -type f \
\( -name 'bookstack-db-*.sql.gz' \
-o -name 'bookstack-files-*.tar.gz' \
-o -name 'bookstack-appkey-*.txt' \) \
-mtime +"$RETENTION_DAYS" -delete
echo "Backup complete: $STAMP"