Includes: API (Express/TypeScript), Astro site, Python workers, document generators, FCC compliance tools, Canada CRTC formation, Ansible infrastructure, and deployment scripts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
34 lines
1.2 KiB
Django/Jinja
34 lines
1.2 KiB
Django/Jinja
#!/usr/bin/env bash
|
|
# {{ ansible_managed }}
|
|
# Daily PostgreSQL backup script
|
|
|
|
set -euo pipefail
|
|
|
|
BACKUP_DIR="{{ pg_backup_dir }}"
|
|
RETENTION_DAYS="{{ pg_backup_retention_days }}"
|
|
TIMESTAMP="$(date +%Y%m%d_%H%M%S)"
|
|
BACKUP_FILE="${BACKUP_DIR}/pw_db_${TIMESTAMP}.sql.gz"
|
|
|
|
echo "[$(date --iso-8601=seconds)] Starting PostgreSQL backup..."
|
|
|
|
# Dump the database from the Docker container and compress
|
|
docker compose -f /opt/performancewest/docker-compose.yml \
|
|
exec -T api-postgres \
|
|
pg_dump -U {{ pg_user }} -d {{ pg_database }} --no-owner --no-privileges \
|
|
| gzip > "${BACKUP_FILE}"
|
|
|
|
# Verify the backup file is not empty
|
|
if [ ! -s "${BACKUP_FILE}" ]; then
|
|
echo "[$(date --iso-8601=seconds)] ERROR: Backup file is empty, removing."
|
|
rm -f "${BACKUP_FILE}"
|
|
exit 1
|
|
fi
|
|
|
|
BACKUP_SIZE="$(du -h "${BACKUP_FILE}" | cut -f1)"
|
|
echo "[$(date --iso-8601=seconds)] Backup completed: ${BACKUP_FILE} (${BACKUP_SIZE})"
|
|
|
|
# Prune backups older than retention period
|
|
PRUNED="$(find "${BACKUP_DIR}" -name "pw_db_*.sql.gz" -type f -mtime +${RETENTION_DAYS} -print -delete | wc -l)"
|
|
echo "[$(date --iso-8601=seconds)] Pruned ${PRUNED} backup(s) older than ${RETENTION_DAYS} days."
|
|
|
|
echo "[$(date --iso-8601=seconds)] Backup process finished."
|