#!/bin/bash # Dealspace Backup Script # Runs daily via cron, keeps last 30 backups set -e BACKUP_DIR=/opt/dealspace/backups DB_PATH=/opt/dealspace/data/dealspace.db LOG_FILE=/opt/dealspace/logs/backup.log NTFY_URL="https://ntfy.inou.com/inou-alerts" NTFY_TOKEN="tk_k120jegay3lugeqbr9fmpuxdqmzx5" RETENTION_DAYS=30 TIMESTAMP=$(date +%Y%m%d-%H%M%S) BACKUP_FILE="dealspace-${TIMESTAMP}.db" BACKUP_PATH="${BACKUP_DIR}/${BACKUP_FILE}" log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" } alert() { curl -sf "${NTFY_URL}" \ -H "Authorization: Bearer ${NTFY_TOKEN}" \ -H "Title: Dealspace Backup FAILED" \ -H "Priority: high" \ -H "Tags: warning" \ -d "$1" || true } log "Starting backup..." # Check if database exists if [ ! -f "$DB_PATH" ]; then MSG="Database not found: $DB_PATH" log "ERROR: $MSG" alert "$MSG" exit 1 fi # Perform SQLite backup (hot backup, safe with WAL) if ! sqlite3 "$DB_PATH" ".backup '$BACKUP_PATH'"; then MSG="SQLite backup command failed" log "ERROR: $MSG" alert "$MSG" exit 1 fi # Verify backup was created if [ ! -f "$BACKUP_PATH" ]; then MSG="Backup file not created: $BACKUP_PATH" log "ERROR: $MSG" alert "$MSG" exit 1 fi # Compress backup if ! gzip "$BACKUP_PATH"; then MSG="Failed to compress backup" log "ERROR: $MSG" alert "$MSG" exit 1 fi BACKUP_SIZE=$(du -h "${BACKUP_PATH}.gz" | cut -f1) log "Backup created: ${BACKUP_FILE}.gz ($BACKUP_SIZE)" # Clean up old backups (keep last 30) OLD_COUNT=$(find "$BACKUP_DIR" -name "dealspace-*.db.gz" -type f -mtime +$RETENTION_DAYS | wc -l) if [ "$OLD_COUNT" -gt 0 ]; then find "$BACKUP_DIR" -name "dealspace-*.db.gz" -type f -mtime +$RETENTION_DAYS -delete log "Deleted $OLD_COUNT old backups (older than $RETENTION_DAYS days)" fi # Count remaining backups BACKUP_COUNT=$(find "$BACKUP_DIR" -name "dealspace-*.db.gz" -type f | wc -l) log "Backup complete. $BACKUP_COUNT backups retained."