#!/usr/bin/env bash # Backs up the Notizarr Postgres database (which holds everything, including # the VAPID keypair and session secret — see docs/phase1/06-docker-unraid-design.md) # plus the compose file itself (env vars, including secrets, are inline # there rather than in a separate .env), into the backups/ directory. # # Run from the deployment root (e.g. /mnt/tank/appdata/notizarr): # ./scripts/backup.sh # # Or point it at a different container/compose file: # POSTGRES_CONTAINER=notizarr-postgres COMPOSE_FILE=docker/docker-compose.prod.yml ./scripts/backup.sh set -euo pipefail POSTGRES_CONTAINER="${POSTGRES_CONTAINER:-notizarr-postgres-dev}" POSTGRES_USER="${POSTGRES_USER:-notizarr}" POSTGRES_DB="${POSTGRES_DB:-notizarr}" COMPOSE_FILE="${COMPOSE_FILE:-docker/docker-compose.yml}" BACKUP_DIR="${BACKUP_DIR:-backups}" TIMESTAMP="$(date +%Y%m%d-%H%M%S)" if [ ! -f "$COMPOSE_FILE" ]; then echo "Error: $COMPOSE_FILE not found. Run this from the deployment root (e.g. /mnt/tank/appdata/notizarr)." >&2 exit 1 fi mkdir -p "$BACKUP_DIR" DB_DUMP="$BACKUP_DIR/notizarr-db-$TIMESTAMP.sql.gz" echo "Dumping database from container $POSTGRES_CONTAINER to $DB_DUMP ..." docker exec -t "$POSTGRES_CONTAINER" pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" | gzip > "$DB_DUMP" COMPOSE_BACKUP="$BACKUP_DIR/notizarr-compose-$TIMESTAMP.yml.backup" echo "Copying $COMPOSE_FILE to $COMPOSE_BACKUP ..." cp "$COMPOSE_FILE" "$COMPOSE_BACKUP" chmod 600 "$COMPOSE_BACKUP" # Keep the last 14 backups of each kind; a daily cron run this way holds # roughly two weeks without the directory growing unbounded. find "$BACKUP_DIR" -maxdepth 1 -name 'notizarr-db-*.sql.gz' -type f | sort -r | tail -n +15 | xargs -r rm -- find "$BACKUP_DIR" -maxdepth 1 -name 'notizarr-compose-*.yml.backup' -type f | sort -r | tail -n +15 | xargs -r rm -- echo "Done." echo " $DB_DUMP" echo " $COMPOSE_BACKUP" echo echo "Note: $COMPOSE_BACKUP contains the database password and OIDC client secret in plain text — keep backups/ off any shared or public storage."