Files
wehub-resource-sync 4ce4204b6c
CI / Lint (push) Failing after 2s
CI / Build (push) Has been skipped
SDK CI / PHP SDK (push) Failing after 1s
Split PHP SDK / PHP SDK tests (push) Failing after 1s
CI / Test (push) Failing after 1s
CI / Dashboard (push) Failing after 0s
SDK CI / JavaScript SDK (push) Failing after 0s
SDK CI / Python SDK (push) Failing after 2s
SDK CI / Java SDK (push) Failing after 1s
Split PHP SDK / Mirror sdk/php -> rmyndharis/openwa-php (push) Has been skipped
CI / Test (PostgreSQL migrations) (push) Failing after 7m47s
CI / Docker Build (push) Has been skipped
chore: import upstream snapshot with attribution
2026-07-13 12:24:08 +08:00

98 lines
2.9 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# OpenWA backup.
#
# Captures EVERYTHING needed to restore a working install:
# - main.sqlite — auth (API keys) + audit log, ALWAYS SQLite (see app.module.ts)
# - data store — openwa.sqlite (SQLite) OR a pg_dump (when DATABASE_TYPE=postgres)
# - sessions/ — WhatsApp LocalAuth session data
# - media/ — locally-stored media (skipped automatically when using S3)
#
# The previous runbook backed up the wrong file (openwa.db) and omitted main.sqlite,
# so a "successful" backup silently lost every API key and all audit history.
#
# Usage:
# ./scripts/backup.sh
# Environment:
# OPENWA_DATA_DIR data directory (default: ./data)
# BACKUP_DIR where archives are written (default: ./backups)
# DATABASE_TYPE sqlite (default) | postgres
# For postgres: DATABASE_URL, or DATABASE_HOST/PORT/USERNAME/PASSWORD/NAME
#
set -euo pipefail
DATA_DIR="${OPENWA_DATA_DIR:-./data}"
BACKUP_DIR="${BACKUP_DIR:-./backups}"
DATABASE_TYPE="${DATABASE_TYPE:-sqlite}"
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
MAIN_DB="$DATA_DIR/main.sqlite"
DATA_DB="$DATA_DIR/openwa.sqlite"
SESSIONS_DIR="$DATA_DIR/sessions"
MEDIA_DIR="$DATA_DIR/media"
log() { echo "[backup] $*"; }
STAGE="$(mktemp -d)"
trap 'rm -rf "$STAGE"' EXIT
# Online SQLite backup (consistent without stopping the app) when sqlite3 is present,
# else a plain copy with a warning.
backup_sqlite() {
src="$1"
dest="$2"
if [ ! -f "$src" ]; then
log "WARN: $src not found — skipping"
return 0
fi
if command -v sqlite3 >/dev/null 2>&1; then
sqlite3 "$src" ".backup '$dest'"
else
log "WARN: sqlite3 not found — plain-copying $src (stop the app first for a consistent copy)"
cp "$src" "$dest"
fi
}
log "Backing up auth/audit DB (main.sqlite) — the API-key + audit store"
backup_sqlite "$MAIN_DB" "$STAGE/main.sqlite"
if [ "$DATABASE_TYPE" = "postgres" ]; then
log "Backing up data store via pg_dump"
if ! command -v pg_dump >/dev/null 2>&1; then
log "ERROR: DATABASE_TYPE=postgres but pg_dump is not installed"
exit 1
fi
if [ -n "${DATABASE_URL:-}" ]; then
pg_dump "$DATABASE_URL" >"$STAGE/database.sql"
else
PGPASSWORD="${DATABASE_PASSWORD:-}" pg_dump \
-h "${DATABASE_HOST:-localhost}" \
-p "${DATABASE_PORT:-5432}" \
-U "${DATABASE_USERNAME:-openwa}" \
"${DATABASE_NAME:-openwa}" >"$STAGE/database.sql"
fi
else
log "Backing up data store (openwa.sqlite)"
backup_sqlite "$DATA_DB" "$STAGE/openwa.sqlite"
fi
if [ -d "$SESSIONS_DIR" ]; then
log "Backing up WhatsApp sessions"
cp -r "$SESSIONS_DIR" "$STAGE/sessions"
else
log "WARN: $SESSIONS_DIR not found — skipping sessions"
fi
if [ -d "$MEDIA_DIR" ]; then
log "Backing up local media"
cp -r "$MEDIA_DIR" "$STAGE/media"
fi
mkdir -p "$BACKUP_DIR"
ARCHIVE="$BACKUP_DIR/openwa-backup-$TIMESTAMP.tar.gz"
tar -czf "$ARCHIVE" -C "$STAGE" .
log "Backup complete: $ARCHIVE"
log "Contents:"
tar -tzf "$ARCHIVE" | sed 's/^/[backup] /'