#!/bin/bash # ============================================================================= # FundTracker Project Backup # ============================================================================= # Backs up: # 1. Complete FundTracker project/site files # 2. FundTracker PostgreSQL database # # Creates ONE compressed archive containing both. # # Project files: # /Kingdezignsnas16/fundtracker # # PostgreSQL: # Container: fundtracker_db # Database: fundtracker # User: fundtracker # # Backup destination: # /export/kingdezignsnas-16/Public/07 - Projects/NAS16/fundtracker # # Retention: # Keeps the 10 most recent backups. # # Email: # Uses OMV Postfix / Gmail relay via sendmail. # # Designed to run as ROOT from: # OMV -> System -> Scheduled Jobs # # Backup destination: /export/kingdezignsnas-16/Public/07 - Projects/NAS16/fundtracker # Script location: /usr/scripts/fundtracker/fundtracker-backup.sh # ============================================================================= set -uo pipefail # ----------------------------------------------------------------------------- # CONFIGURATION # ----------------------------------------------------------------------------- HOSTNAME_LABEL=$(hostname -s 2>/dev/null || echo "NAS16") REPORT_TO="rufus.king@kingdezigns.com" REPORT_FROM="backup-monitor@nas16.local" # FundTracker project files PROJECT_DIR="/Kingdezignsnas16/fundtracker" # PostgreSQL container DB_CONTAINER="fundtracker_db" DB_NAME="fundtracker" DB_USER="fundtracker" # Backup destination BACKUP_ROOT="/export/kingdezignsnas-16/Public/07 - Projects/NAS16/fundtracker" # Temporary working directory TMP_BASE="/tmp/fundtracker-backup" # Keep this many completed backups RETAIN_COUNT=10 # Date/time DATE=$(date +%Y-%m-%d) TIMESTAMP=$(date +%Y-%m-%d_%H-%M-%S) REPORT_TIME=$(date "+%Y-%m-%d %H:%M:%S") TMP_DIR="${TMP_BASE}/fundtracker-${TIMESTAMP}" LOG_FILE="${BACKUP_ROOT}/backup.log" # Variable placeholder for version (populated dynamically during run) SITE_VERSION="unknown" ARCHIVE_NAME="fundtracker-backup-${TIMESTAMP}.tar.gz" # ----------------------------------------------------------------------------- # STATUS TRACKING # ----------------------------------------------------------------------------- OVERALL_STATUS="SUCCESS" SECTION_ROWS_HTML="" WARNING_COUNT=0 ERROR_COUNT=0 add_section_row() { local section="$1" local status="$2" local detail="$3" case "$status" in OK) BADGE="✓ OK" ;; WARNING) BADGE="⚠ WARNING" WARNING_COUNT=$((WARNING_COUNT + 1)) [[ "$OVERALL_STATUS" == "SUCCESS" ]] && OVERALL_STATUS="WARNING" ;; ERROR) BADGE="✗ ERROR" ERROR_COUNT=$((ERROR_COUNT + 1)) OVERALL_STATUS="FAILED" ;; SKIPPED) BADGE="— SKIPPED" ;; esac SECTION_ROWS_HTML+="
|
Filename
${ARCHIVE_NAME}
|
Size
${ARCHIVE_SIZE}
|
Retained
${BACKUP_COUNT} / ${RETAIN_COUNT}
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||