From f0ff1ec42b54780b0c1f73365f6fe9ea4f06bc0b Mon Sep 17 00:00:00 2001 From: matthieu Date: Thu, 2 Apr 2026 09:50:56 +0200 Subject: [PATCH] feat: add automated backup script with Discord notifications Daily backup at 19h, zips data/ to backup/, keeps 2 max, notifies via Discord webhook. Co-Authored-By: Claude Opus 4.6 (1M context) --- .gitignore | 5 ++++ README.md | 40 ++++++++++++++++-------------- backup-vaultwarden.sh | 57 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 .gitignore create mode 100755 backup-vaultwarden.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..daccd87 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/data +/data_backup_* +/backup +/logs +.env diff --git a/README.md b/README.md index 8207c40..f52379e 100644 --- a/README.md +++ b/README.md @@ -51,32 +51,33 @@ docker compose pull docker compose up -d ``` -## Sauvegarde +## Sauvegarde automatique -Le dossier `./data` contient toutes les donnees : -- `db.sqlite3` : base de donnees (comptes, mots de passe chiffres) -- `attachments/` : fichiers joints -- `sends/` : fichiers Send -- `config.json` : configuration -- `rsa_key.pem` : cle RSA du serveur +Un script de backup automatique est inclus : `backup-vaultwarden.sh`. -### Exporter une sauvegarde +- **Frequence** : tous les jours a 19h (cron) +- **Format** : zip du dossier `data/` dans `backup/` +- **Retention** : 2 backups max (rotation automatique) +- **Notification** : Discord via webhook + +### Lancer manuellement ```bash -# Arreter le conteneur pour eviter la corruption de la BDD -docker compose down - -# Copier le dossier data -cp -r ./data ./data_backup_$(date +%Y%m%d) - -# Relancer -docker compose up -d +./backup-vaultwarden.sh ``` -### Compresser pour transfert +### Installer le cron ```bash -tar czf vaultwarden_backup_$(date +%Y%m%d).tar.gz ./data +crontab -e +# Ajouter : +0 19 * * * /usr/bin/bash /home/matt/vaultwarden/backup-vaultwarden.sh >> /home/matt/vaultwarden/logs/cron_vaultwarden.log 2>&1 +``` + +### Sauvegarde manuelle + +```bash +zip -r vaultwarden-backup-$(date +%Y%m%d).zip ./data ``` ## Restauration / Migration @@ -126,9 +127,12 @@ Tout est restaure : comptes, mots de passe, fichiers joints. . ├── docker-compose.yml # Definition du service Docker ├── setup-vaultwarden-https.sh # Script de configuration NGINX + HTTPS +├── backup-vaultwarden.sh # Script de backup automatique ├── .env # Variables d'environnement (non versionne) ├── .env.example # Exemple de configuration ├── data/ # Donnees Vaultwarden (non versionne) +├── backup/ # Backups zip (non versionne) +├── logs/ # Logs de backup (non versionne) └── README.md ``` diff --git a/backup-vaultwarden.sh b/backup-vaultwarden.sh new file mode 100755 index 0000000..89882e8 --- /dev/null +++ b/backup-vaultwarden.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -euo pipefail + +DATA_DIR="/home/matt/vaultwarden/data" +BACKUP_DIR="/home/matt/vaultwarden/backup" +RETENTION=2 +WEBHOOK_URL="https://discord.com/api/webhooks/1478503102888935506/YCtJM09QZiKNMiCe5u7vCQb52VcLjHAd9wwEsKNltlJVcy7sKvoMTOJkvEKOOrk-Wpkh" +LOG_FILE="/home/matt/vaultwarden/logs/vaultwarden_backup.log" + +DATE="$(date +'%Y-%m-%d_%H-%M-%S')" +BACKUP_NAME="vaultwarden-backup-${DATE}.zip" +BACKUP_FILE="${BACKUP_DIR}/${BACKUP_NAME}" + +mkdir -p "$BACKUP_DIR" "$(dirname "$LOG_FILE")" + +log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"; } + +discord() { + local color="$1" title="$2" msg="$3" + [[ -z "$WEBHOOK_URL" ]] && return 0 + curl -fsS -H "Content-Type: application/json" -d "{ + \"embeds\": [{ + \"title\": \"${title}\", + \"description\": \"${msg}\", + \"color\": ${color} + }] + }" "$WEBHOOK_URL" >/dev/null 2>&1 || true +} + +fail() { + log "ERROR: $1" + discord 16711680 "Backup Vaultwarden - ECHEC" "$1" + exit 1 +} + +# Verifications +[[ -d "$DATA_DIR" ]] || fail "Dossier source introuvable : $DATA_DIR" +command -v zip &>/dev/null || fail "zip n'est pas installe" + +log "Debut backup - source: $DATA_DIR" + +# Zip du dossier data +cd "$(dirname "$DATA_DIR")" +zip -r -q "$BACKUP_FILE" "$(basename "$DATA_DIR")" || fail "Erreur lors de la compression" + +SIZE="$(du -h "$BACKUP_FILE" | cut -f1)" +log "Backup cree : $BACKUP_FILE ($SIZE)" + +# Rotation - garde les 2 derniers +mapfile -t old < <(ls -1t "${BACKUP_DIR}"/vaultwarden-backup-*.zip 2>/dev/null | tail -n +$((RETENTION + 1))) +for f in "${old[@]}"; do + rm -f "$f" + log "Rotation : supprime $f" +done + +log "Backup termine : $BACKUP_NAME" +discord 65280 "Backup Vaultwarden - OK" "Backup **${BACKUP_NAME}** cree (${SIZE})"