feat(scripts): add backup/restore scripts
This commit is contained in:
126
scripts/backup.sh
Executable file
126
scripts/backup.sh
Executable file
@@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
backup.sh [output-directory]
|
||||
|
||||
Environment:
|
||||
DEPLOY_ROOT Deployment directory. Defaults to ~/qlockify-deployment.
|
||||
|
||||
Creates a timestamped .tar.gz archive containing:
|
||||
- PostgreSQL dump from the db service
|
||||
- media files from the backend media volume
|
||||
- deployment, backend, and frontend .env files
|
||||
EOF
|
||||
}
|
||||
|
||||
log() {
|
||||
printf '[backup] %s\n' "$*"
|
||||
}
|
||||
|
||||
fail() {
|
||||
printf '[backup] %s\n' "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
require_file() {
|
||||
local path="$1"
|
||||
[[ -f "$path" ]] || fail "Required file not found: $path"
|
||||
}
|
||||
|
||||
compose() {
|
||||
docker compose -f "$DEPLOY_ROOT/docker-compose.yml" "$@"
|
||||
}
|
||||
|
||||
wait_for_db() {
|
||||
compose exec -T db sh -c '
|
||||
set -eu
|
||||
: "${POSTGRES_USER:?POSTGRES_USER is missing}"
|
||||
: "${POSTGRES_DB:?POSTGRES_DB is missing}"
|
||||
until pg_isready --username="$POSTGRES_USER" --dbname="$POSTGRES_DB"; do
|
||||
sleep 1
|
||||
done
|
||||
' >/dev/null
|
||||
}
|
||||
|
||||
copy_env_if_exists() {
|
||||
local source_path="$1"
|
||||
local target_path="$2"
|
||||
|
||||
if [[ -f "$source_path" ]]; then
|
||||
cp "$source_path" "$target_path"
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
DEPLOY_ROOT="${DEPLOY_ROOT:-$HOME/qlockify-deployment}"
|
||||
OUTPUT_DIR="${1:-$DEPLOY_ROOT/backups}"
|
||||
BACKEND_ENV="$DEPLOY_ROOT/backend/qlockify-backend-deployment/.env"
|
||||
FRONTEND_ENV="$DEPLOY_ROOT/frontend/qlockify-frontend-deployment/.env"
|
||||
DEPLOY_ENV="$DEPLOY_ROOT/.env"
|
||||
|
||||
require_file "$DEPLOY_ROOT/docker-compose.yml"
|
||||
require_file "$BACKEND_ENV"
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
WORK_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$WORK_DIR"' EXIT
|
||||
|
||||
TIMESTAMP="$(date -u +'%Y%m%d-%H%M%S')"
|
||||
ARCHIVE_NAME="qlockify-backup-$TIMESTAMP.tar.gz"
|
||||
ARCHIVE_PATH="$OUTPUT_DIR/$ARCHIVE_NAME"
|
||||
|
||||
mkdir -p "$WORK_DIR/env"
|
||||
|
||||
log "Checking Docker Compose configuration"
|
||||
compose config -q
|
||||
|
||||
log "Starting database service if needed"
|
||||
compose up -d db
|
||||
wait_for_db
|
||||
|
||||
log "Dumping database from db service"
|
||||
compose exec -T db sh -c '
|
||||
set -eu
|
||||
: "${POSTGRES_USER:?POSTGRES_USER is missing}"
|
||||
: "${POSTGRES_DB:?POSTGRES_DB is missing}"
|
||||
pg_dump \
|
||||
--username="$POSTGRES_USER" \
|
||||
--dbname="$POSTGRES_DB" \
|
||||
--format=plain \
|
||||
--clean \
|
||||
--if-exists \
|
||||
--no-owner \
|
||||
--no-privileges
|
||||
' > "$WORK_DIR/database.sql"
|
||||
|
||||
log "Archiving media files from backend media volume"
|
||||
if compose ps --status running --services | grep -qx 'backend'; then
|
||||
compose exec -T backend sh -c 'mkdir -p /app/media && tar -C /app/media -czf - .' > "$WORK_DIR/media.tar.gz"
|
||||
else
|
||||
log "Backend service is not running; using a temporary container for media volume"
|
||||
compose run --rm --no-deps --entrypoint sh backend -c 'mkdir -p /app/media && tar -C /app/media -czf - .' > "$WORK_DIR/media.tar.gz"
|
||||
fi
|
||||
|
||||
log "Copying environment files"
|
||||
copy_env_if_exists "$DEPLOY_ENV" "$WORK_DIR/env/deployment.env"
|
||||
copy_env_if_exists "$BACKEND_ENV" "$WORK_DIR/env/backend.env"
|
||||
copy_env_if_exists "$FRONTEND_ENV" "$WORK_DIR/env/frontend.env"
|
||||
|
||||
cat > "$WORK_DIR/manifest.txt" <<EOF
|
||||
name=$ARCHIVE_NAME
|
||||
created_at_utc=$TIMESTAMP
|
||||
deploy_root=$DEPLOY_ROOT
|
||||
includes=database.sql,media.tar.gz,env/deployment.env,env/backend.env,env/frontend.env
|
||||
EOF
|
||||
|
||||
log "Creating archive $ARCHIVE_PATH"
|
||||
tar -C "$WORK_DIR" -czf "$ARCHIVE_PATH" .
|
||||
|
||||
log "Backup completed: $ARCHIVE_PATH"
|
||||
Reference in New Issue
Block a user