#!/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."