#!/bin/sh # Dumps the Siftlode Postgres database to backups/siftlode-.dump (custom format). # Run from the project root: ./scripts/backup.sh # # A dump is only HALF a backup. The other half is your `.env` — it holds TOKEN_ENCRYPTION_KEY, # without which every encrypted value in the restored database (Google credentials, SMTP password, # Plex token, stored refresh tokens) is unreadable. See docs/self-hosting.md § Backups. set -e # `docker compose` finds docker-compose.yml on its own and honours $COMPOSE_FILE. The documented # self-host layout (docs/self-hosting.md § Get the files) has NEITHER — just the selfhost file — so # without this the command below failed there with "no configuration file provided". if [ -z "${COMPOSE_FILE:-}" ] && [ ! -f docker-compose.yml ] && [ -f docker-compose.selfhost.yml ]; then COMPOSE_FILE=docker-compose.selfhost.yml export COMPOSE_FILE fi USER_NAME="${POSTGRES_USER:-siftlode}" DB_NAME="${POSTGRES_DB:-siftlode}" mkdir -p backups TS=$(date +%Y%m%d-%H%M%S) OUT="backups/siftlode-$TS.dump" # Write to a temp name and only promote it on success: a failed pg_dump would otherwise leave a # truncated (often 0-byte) file sitting in backups/ that looks exactly like a real backup. TMP="$OUT.part" if ! docker compose exec -T db pg_dump -U "$USER_NAME" -Fc "$DB_NAME" > "$TMP"; then rm -f "$TMP" echo "BACKUP FAILED — pg_dump returned an error; no file was written." >&2 exit 1 fi if [ ! -s "$TMP" ]; then rm -f "$TMP" echo "BACKUP FAILED — pg_dump produced an empty file; no backup was written." >&2 exit 1 fi mv "$TMP" "$OUT" echo "Wrote $OUT" echo "Remember: back up your .env too (TOKEN_ENCRYPTION_KEY) — this dump alone cannot be fully restored."