#!/usr/bin/env bash set -euo pipefail ####################################### # Chemins fixes du script ####################################### SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ENV_FILE="/home/matt/vaultwarden/scripts/Scripts-Serveur/backup_vaultwarden/.env" LOG_FILE="/var/log/vaultwarden_backup.log" mkdir -p "$(dirname "$LOG_FILE")" touch "$LOG_FILE" log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE" } ####################################### # Vérification fichier .env ####################################### [[ -f "$ENV_FILE" ]] || { echo "ERROR: Fichier .env introuvable : $ENV_FILE" >&2 exit 1 } ####################################### # Chargement du .env ####################################### set -a source "$ENV_FILE" set +a ####################################### # Variables obligatoires ####################################### : "${WEBHOOK_URL:=}" : "${DATA_DIR:?Variable DATA_DIR manquante dans .env}" : "${LOCAL_BACKUP:?Variable LOCAL_BACKUP manquante dans .env}" : "${REMOTE_USER:?Variable REMOTE_USER manquante dans .env}" : "${REMOTE_HOST:?Variable REMOTE_HOST manquante dans .env}" : "${REMOTE_DIR:?Variable REMOTE_DIR manquante dans .env}" : "${SSH_KEY:?Variable SSH_KEY manquante dans .env}" ####################################### # Variables backup ####################################### DATE="$(date +'%Y-%m-%d_%H-%M-%S')" BACKUP_PREFIX="vaultwarden-backup" BACKUP_NAME="${BACKUP_PREFIX}-${DATE}.tar.gz" LOCAL_BACKUP_DIR="$LOCAL_BACKUP" LOCAL_BACKUP_FILE="${LOCAL_BACKUP_DIR}/${BACKUP_NAME}" RETENTION_DAYS=10 SSH_OPTS=(-i "$SSH_KEY" -o IdentitiesOnly=yes -o BatchMode=yes -o ConnectTimeout=10) mkdir -p "$LOCAL_BACKUP_DIR" ####################################### # Notification Discord ####################################### discord_ping() { local success="$1" local details="${2:-}" [[ -z "$WEBHOOK_URL" ]] && return 0 local icon status_line if [[ "$success" == "true" ]]; then icon="🟢" status_line="✅" else icon="🔴" status_line="❌" fi local msg msg="**@here ${icon} Backup Vaultwarden**\n" msg+="Backup: ${BACKUP_NAME}\n" msg+="Data transfer: ${status_line}\n" [[ -n "$details" ]] && msg+="Détails: ${details}" python3 - </dev/null || true import json print(json.dumps({"content": """$msg"""})) PY } ####################################### # Fonction erreur ####################################### fail() { local detail="$1" log "ERROR: $detail" discord_ping "false" "$detail" exit 1 } ####################################### # Vérifications préalables ####################################### [[ -d "$DATA_DIR" ]] || fail "Le dossier source n'existe pas : $DATA_DIR" [[ -f "$SSH_KEY" ]] || fail "La clé SSH est introuvable : $SSH_KEY" log "Début du backup Vaultwarden" log "Source : $DATA_DIR" log "Archive locale : $LOCAL_BACKUP_FILE" log "Destination distante : ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}" ####################################### # Création du backup ####################################### tar -czf "$LOCAL_BACKUP_FILE" -C "$(dirname "$DATA_DIR")" "$(basename "$DATA_DIR")" \ || fail "Erreur lors de la compression du dossier $DATA_DIR" log "Backup local créé : $LOCAL_BACKUP_FILE" ####################################### # Création dossier distant ####################################### ssh "${SSH_OPTS[@]}" "$REMOTE_USER@$REMOTE_HOST" "mkdir -p '$REMOTE_DIR'" \ || fail "Impossible de créer le dossier distant $REMOTE_DIR" ####################################### # Envoi du backup ####################################### scp "${SSH_OPTS[@]}" "$LOCAL_BACKUP_FILE" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/" \ || fail "Erreur lors de l'envoi du backup vers $REMOTE_HOST" log "Backup envoyé sur $REMOTE_HOST:$REMOTE_DIR" ####################################### # Rotation distante - suppression > 10 jours ####################################### ssh "${SSH_OPTS[@]}" "$REMOTE_USER@$REMOTE_HOST" \ "find '$REMOTE_DIR' -type f -name '${BACKUP_PREFIX}-*.tar.gz' -mtime +$RETENTION_DAYS -delete" \ || fail "Erreur lors de la rotation distante des sauvegardes" log "Rotation distante OK" ####################################### # Nettoyage local ####################################### rm -f "$LOCAL_BACKUP_FILE" || fail "Impossible de supprimer le backup local $LOCAL_BACKUP_FILE" ####################################### # Fin ####################################### log "Backup $BACKUP_NAME terminé et envoyé sur $REMOTE_HOST:$REMOTE_DIR" discord_ping "true" "Backup envoyé avec succès vers $REMOTE_HOST" echo "Backup $BACKUP_NAME terminé et envoyé sur $REMOTE_HOST:$REMOTE_DIR"