101 lines
3.2 KiB
Django/Jinja
101 lines
3.2 KiB
Django/Jinja
#!/bin/bash
|
|
# CRM SITECONSEIL - Backup script (database + files)
|
|
# Usage: /usr/local/bin/crm-siteconseil-backup.sh
|
|
# Schedule via cron (ex: every 30 minutes)
|
|
|
|
set -euo pipefail
|
|
|
|
#######################################
|
|
# Configuration
|
|
#######################################
|
|
APP_DIR="{{ app_dir | default('/var/www/crm-siteconseil') }}"
|
|
COMPOSE_FILE="${APP_DIR}/docker-compose-prod.yml"
|
|
BACKUP_DIR="{{ backup_dir | default('/var/backups/crm-siteconseil') }}"
|
|
KEEP_DAYS="{{ backup_keep_days | default(7) }}"
|
|
|
|
DB_SERVICE="{{ db_service | default('db-master') }}"
|
|
DB_USER="{{ db_user | default('crm-siteconseil') }}"
|
|
DB_NAME="{{ db_name | default('crm-siteconseil') }}"
|
|
|
|
DATE="$(date +%Y%m%d_%H%M%S)"
|
|
TARGET_DIR="${BACKUP_DIR}/${DATE}"
|
|
LOG_PREFIX="[$(date '+%Y-%m-%d %H:%M:%S')]"
|
|
|
|
#######################################
|
|
# Helpers
|
|
#######################################
|
|
log() { echo "${LOG_PREFIX} $*"; }
|
|
fail() { echo "${LOG_PREFIX} ERROR: $*" >&2; exit 1; }
|
|
|
|
mkdir -p "${TARGET_DIR}"
|
|
|
|
#######################################
|
|
# 1. Database (PostgreSQL custom format)
|
|
#######################################
|
|
DB_FILE="${TARGET_DIR}/database.dump"
|
|
log "Dumping database ${DB_NAME} from service ${DB_SERVICE}..."
|
|
|
|
if ! docker compose -f "${COMPOSE_FILE}" exec -T "${DB_SERVICE}" \
|
|
pg_dump -U "${DB_USER}" -d "${DB_NAME}" --format=custom --no-owner --no-acl \
|
|
> "${DB_FILE}"; then
|
|
fail "pg_dump failed"
|
|
fi
|
|
|
|
if [ ! -s "${DB_FILE}" ]; then
|
|
fail "database dump is empty"
|
|
fi
|
|
|
|
log "DB Backup OK: $(du -h "${DB_FILE}" | cut -f1)"
|
|
|
|
#######################################
|
|
# 2. Files: public/uploads
|
|
#######################################
|
|
UPLOADS_FILE="${TARGET_DIR}/uploads.tar.gz"
|
|
if [ -d "${APP_DIR}/public/uploads" ]; then
|
|
log "Archiving public/uploads..."
|
|
if tar -czf "${UPLOADS_FILE}" -C "${APP_DIR}/public" uploads; then
|
|
log "Uploads Backup OK: $(du -h "${UPLOADS_FILE}" | cut -f1)"
|
|
else
|
|
log "WARNING: uploads archive failed"
|
|
fi
|
|
else
|
|
log "WARNING: ${APP_DIR}/public/uploads not found, skipping"
|
|
fi
|
|
|
|
#######################################
|
|
# 3. Files: var/share (APP_SHARE_DIR)
|
|
#######################################
|
|
SHARE_FILE="${TARGET_DIR}/share.tar.gz"
|
|
if [ -d "${APP_DIR}/var/share" ]; then
|
|
log "Archiving var/share..."
|
|
if tar -czf "${SHARE_FILE}" -C "${APP_DIR}/var" share; then
|
|
log "Share Backup OK: $(du -h "${SHARE_FILE}" | cut -f1)"
|
|
else
|
|
log "WARNING: share archive failed"
|
|
fi
|
|
else
|
|
log "WARNING: ${APP_DIR}/var/share not found, skipping"
|
|
fi
|
|
|
|
#######################################
|
|
# 4. Manifest
|
|
#######################################
|
|
MANIFEST="${TARGET_DIR}/manifest.txt"
|
|
{
|
|
echo "CRM SITECONSEIL backup"
|
|
echo "Date : ${DATE}"
|
|
echo "Hostname : $(hostname)"
|
|
echo "DB : ${DB_NAME}@${DB_SERVICE}"
|
|
echo "Files :"
|
|
ls -lh "${TARGET_DIR}" | tail -n +2
|
|
} > "${MANIFEST}"
|
|
|
|
log "Backup directory: ${TARGET_DIR} ($(du -sh "${TARGET_DIR}" | cut -f1))"
|
|
|
|
#######################################
|
|
# 5. Retention (delete backups older than KEEP_DAYS)
|
|
#######################################
|
|
log "Cleaning backups older than ${KEEP_DAYS} days..."
|
|
find "${BACKUP_DIR}" -mindepth 1 -maxdepth 1 -type d -mtime "+${KEEP_DAYS}" -exec rm -rf {} +
|
|
log "Done."
|