diff --git a/.gitignore b/.gitignore index b4b4c53..105bda5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,22 +2,9 @@ # Environment / secrets ######################################## -# Fichiers .env réels (contiennent des secrets) .env -.env.* -!.env.example !.env.exemple -# Sous-dossiers -RecetteScripts/.env -CheckStorage/.env -BackupVaultWarden/.env - -# Garder les fichiers exemple -!*.env.exemple -!*.env.example -!CheckStorage/.env.exemple -!RecetteScripts/.env.exemple -!BackupVaultWarden/.env.exemple +!.env.example ######################################## # Logs diff --git a/BackupVaultWarden/README.md b/BackupVaultWarden/README.md index 9844000..5184598 100644 --- a/BackupVaultWarden/README.md +++ b/BackupVaultWarden/README.md @@ -1,54 +1,259 @@ -# FONCTIONNEMENT DU SCRIPT VAULTWARDEN -Le script de backup de vaultwarden permet une sauvegarde périodique des mots de passe et utilisateurs de celui-ci. +markdown +# README — Mise en place du script de sauvegarde Vaultwarden -## INITIALISATION DES VARIABLES DE MANIÈRE SÉCURISÉ +Ce script permet d’automatiser la sauvegarde de Vaultwarden afin de conserver une copie du dossier `data`, de la transférer vers un serveur distant et d’envoyer une notification Discord en cas de succès ou d’échec. -1. Les informations sensibles ne sont pas stockées directement dans le script. Elles sont placées dans un fichier .env +--- + +# 1. Objectif du script + +Le script de sauvegarde Vaultwarden permet de : + +- sauvegarder les données de Vaultwarden ; +- compresser l’archive avec un nom daté ; +- transférer la sauvegarde vers un serveur distant ; +- envoyer une notification Discord ; +- automatiser l’exécution via `cron`. + +Ce mécanisme permet de sécuriser les mots de passe, les utilisateurs et la configuration stockés dans le dossier `data` de Vaultwarden. + +--- + +# 2. Pré-requis + +Avant de mettre en place le script, vérifier que les éléments suivants sont disponibles sur la machine Vaultwarden : + +- `bash` +- `tar` +- `scp` +- `ssh` +- `curl` +- `cron` + +Installation sur Debian / Ubuntu : ```bash -WEBHOOK_URL=... -REMOTE_USER=... -REMOTE_HOST=... -SSH_KEY=... -DATA_DIR=... +sudo apt update +sudo apt install -y tar openssh-client curl cron +```` + +--- + +# 3. Emplacement du script + +Le script est situé dans : + +```bash +/home/matt/vaultwarden/Malio-ops/BackupVaultWarden/ ``` -2. on récupère les variables dans le script +Structure recommandée : + +```bash +/home/matt/vaultwarden/Malio-ops/BackupVaultWarden/ +├── backup-vaultwarden.sh +├── .env +└── README.md +``` + +--- + +# 4. Configuration sécurisée avec le fichier .env + +Les informations sensibles ne doivent pas être stockées directement dans le script. +Elles doivent être placées dans un fichier `.env`. + +## Exemple de fichier `.env` + +```bash +WEBHOOK_URL=https://discord.com/api/webhooks/... +REMOTE_USER=backup +REMOTE_HOST=192.168.1.50 +SSH_KEY=/home/matt/.ssh/id_ed25519_vaultwarden_backup +DATA_DIR=/opt/vaultwarden/data +REMOTE_DIR=/home/backup/backups/vaultwarden +``` + +## Description des variables + +| Variable | Description | +| ----------- | ------------------------------------------------------ | +| WEBHOOK_URL | Webhook Discord pour les notifications | +| REMOTE_USER | Utilisateur du serveur distant | +| REMOTE_HOST | Adresse IP ou DNS du serveur de sauvegarde | +| SSH_KEY | Chemin vers la clé SSH utilisée pour le transfert | +| DATA_DIR | Dossier `data` de Vaultwarden | +| REMOTE_DIR | Dossier de stockage des backups sur le serveur distant | + +--- + +# 5. Chargement des variables dans le script + +Le script récupère les variables du fichier `.env`. + +Exemple : + ```bash REMOTE_USER=$(grep -E '^REMOTE_USER=' .env | cut -d '=' -f2-) ``` -Explication: +Explication : -- grep recherche la variable dans le fichier .env -- cut récupère uniquement la valeur après = -- REMOTE_USER="user" Le script récupère >> "user" +* `grep` recherche la variable dans `.env` +* `cut` récupère uniquement la valeur après `=` +* la variable shell reçoit la valeur correspondante -Cela permet: +Cela permet : -- d’améliorer la sécurité -- d’éviter de modifier le script si un paramètre change +* d'améliorer la sécurité +* de modifier la configuration sans toucher au script -## RÉCUPÉRATION DES DONNÉES +--- + +# 6. Connexion au serveur de sauvegarde (Machine IA) + +Le transfert des sauvegardes vers la machine IA repose sur une **authentification par clé SSH**. +Cette méthode permet au script de se connecter automatiquement au serveur distant sans mot de passe. + +La clé utilisée pour ce script est : + +``` +~/.ssh/id_ed25519_bitwarden + +```` + +--- + +## 6.1 Vérifier la présence de la clé SSH + +Sur la machine exécutant le script, vérifier que la clé existe : + +```bash +ls ~/.ssh/id_ed25519_bitwarden* +```` + +Les fichiers attendus sont : + +``` +~/.ssh/id_ed25519_bitwarden +~/.ssh/id_ed25519_bitwarden.pub +``` + +* `id_ed25519_bitwarden` → clé privée utilisée par le script +* `id_ed25519_bitwarden.pub` → clé publique autorisée sur la machine IA + +--- + +## 6.2 Copier la clé publique sur la machine IA + +Envoyer la clé publique vers la machine IA : + +```bash +ssh-copy-id -i ~/.ssh/id_ed25519_bitwarden.pub backup@192.168.0.179 +``` + +Cette commande ajoute automatiquement la clé dans : + +``` +~/.ssh/authorized_keys +``` + +sur la machine IA. + +--- + +## 6.3 Ajout manuel de la clé (si ssh-copy-id n'est pas disponible) + +Afficher la clé publique : + +```bash +cat ~/.ssh/id_ed25519_bitwarden.pub +``` + +Copier son contenu puis l’ajouter sur la machine IA dans : + +``` +~/.ssh/authorized_keys +``` + +--- + +## 6.4 Vérifier les permissions SSH + +Sur la machine locale : + +```bash +chmod 700 ~/.ssh +chmod 600 ~/.ssh/id_ed25519_bitwarden +chmod 644 ~/.ssh/id_ed25519_bitwarden.pub +``` + +Sur la machine IA : + +```bash +chmod 700 ~/.ssh +chmod 600 ~/.ssh/authorized_keys +``` + +--- + +## 6.5 Tester la connexion + +Tester la connexion SSH avec la clé : + +```bash +ssh -i ~/.ssh/id_ed25519_bitwarden backup@192.168.0.179 +``` + +Si la configuration est correcte : + +* la connexion se fait **sans mot de passe** +* la machine IA accepte la clé SSH +* le script pourra envoyer les sauvegardes automatiquement + +--- + +## 6.6 Déclaration dans le fichier `.env` + +La clé utilisée par le script doit être déclarée dans `.env` : + +```bash +SSH_KEY=/home/matt/.ssh/id_ed25519_bitwarden +``` + +Cette clé sera utilisée automatiquement par `scp` lors du transfert des sauvegardes. + + +# 7. Sauvegarde des données Vaultwarden + +Le script crée une archive compressée du dossier `data` : -1. Le dossier data de Vaultwarden est dupliqué puis compressé afin de créer une archive : ```bash tar -czf "$LOCAL_BACKUP" -C "$(dirname "$DATA_DIR")" "$(basename "$DATA_DIR")" ``` -2. Transfer vers le serveur de backup +Cela permet d’obtenir une sauvegarde portable et compressée. + +--- + +# 8. Transfert vers le serveur distant + +Une fois l’archive créée : + ```bash scp "${SSH_OPTS[@]}" "$LOCAL_BACKUP" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/" ``` -La sauvegarde est envoyée vers une machine dédiée grâce à SCP. Pour éviter de saisir un mot de passe à chaque fois, une clé SSH est utilisée. -Cette clé SSH est générée sur la machine de backup et autorisée sur la machine Vaultwarden. +Le fichier est envoyé vers le serveur de sauvegarde via SCP. -## NOTIFICATION DISCORD +--- -Le script envoie une notification sur un salon Discord pour informer de l’état de la sauvegarde. Cela se fait grâce à un webhook Discord. +# 9. Notification Discord + +Le script envoie une notification Discord pour informer de l’état de la sauvegarde. + +Construction du message : -1. on défini le message ```bash local msg="**@here Backup Vaultwarden $color**\n" msg+="Backup: ${BACKUP_NAME}\n" @@ -56,61 +261,96 @@ msg+="Data transfer: $dumps_display\n" [[ -n "$details" ]] && msg+="Details: $details" ``` -2. on envoie le message sur discord avec le message et le webhook +Envoi du message : + ```bash curl -fsS -H "Content-Type: application/json" \ -d "{\"content\":\"$msg\"}" \ -"$DISCORD_WEBHOOK_URL" +"$WEBHOOK_URL" ``` -Le message indique: -- si la sauvegarde a réussi 🟢 -- si elle a échoué 🔴 -- le nom du backup -- les détails de l’erreur si nécessaire +Le message indique : -## PLANIFICATION AVEC CRON +* si la sauvegarde a réussi +* si elle a échoué +* le nom du backup +* les détails de l’erreur -Le script est exécuté automatiquement chaque jour grâce à cron. +--- + +# 10. Planification avec cron + +Le script est exécuté automatiquement tous les jours à 19h. + +Ouvrir le crontab : -1. Ouvrez le crontab pour l'édition : - ```bash - crontab -e - ``` -2. Ajoutez la ligne suivante pour exécuter le script tous les jours à 19h : ```bash - 0 19 * * * /chemin/vers/le/script/check_storage.sh +crontab -e ``` -Signification: +Ajouter : -- 0 minute 0 -- 19 19h -- * tous les jours du mois -- * tous les mois -- * tous les jours de la semaine +```bash +0 19 * * * /home/matt/vaultwarden/Malio-ops/BackupVaultWarden/backup-vaultwarden.sh >> /var/log/vaultwarden_backup.log 2>&1 +``` -Tous les jours à 19h, le script est exécuté et les logs sont enregistrés dans backup.log ce qui permet d’analyser les erreurs si un problème survient. +Signification : -## NETTOYAGE +| Champ | Valeur | +| ------------ | ------ | +| minute | 0 | +| heure | 19 | +| jour du mois | * | +| mois | * | +| jour semaine | * | -Une fois la sauvegarde envoyée sur la machine distante, le fichier temporaire est supprimé : +Le script s’exécute donc **tous les jours à 19h00**. + +--- + +# 11. Nettoyage + +Une fois la sauvegarde transférée : ```bash rm -f "$LOCAL_BACKUP" ``` -Cela permet de garder le serveur propre et éviter de remplir le disque. +Cela évite de remplir le disque de la machine Vaultwarden. -## RÉSUMÉ +--- -Le script automatise complètement les sauvegardes Vaultwarden : +# 12. Test manuel -- sauvegarde du dossier data -- compression et datation -- transfert sécurisé via SSH -- notification Discord -- exécution automatique avec cron -- sécurisation des paramètres via .env +Avant de mettre le script en cron, tester : -Cela permet d’avoir une sauvegarde quotidienne fiable et surveillée. +```bash +bash /home/matt/vaultwarden/Malio-ops/BackupVaultWarden/backup-vaultwarden.sh +``` + +--- + +# 13. Vérification des logs + +Logs : + +```bash +cat /var/log/vaultwarden_backup.log +``` + +--- + +# 14. Résumé + +Le script automatise : + +* la sauvegarde du dossier `data` +* la compression et la datation du backup +* le transfert sécurisé via SSH +* la notification Discord +* l’exécution automatique via cron +* la configuration sécurisée via `.env` + +Ce système permet d’obtenir **une sauvegarde fiable, centralisée et surveillée de Vaultwarden**. + +``` diff --git a/BackupVaultWarden/backup-vaultwarden.sh b/BackupVaultWarden/backup-vaultwarden.sh index 21e8de5..8947f9b 100644 --- a/BackupVaultWarden/backup-vaultwarden.sh +++ b/BackupVaultWarden/backup-vaultwarden.sh @@ -5,7 +5,7 @@ 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" +ENV_FILE="/home/matt/vaultwarden/Malio-ops/BackupVaultWarden/.env" LOG_FILE="/var/log/vaultwarden_backup.log" mkdir -p "$(dirname "$LOG_FILE")" @@ -68,13 +68,15 @@ discord_ping() { if [[ "$success" == "true" ]]; then icon="🟢" status_line="✅" + ping="" else icon="🔴" status_line="❌" + ping="@here " fi local msg - msg="**@here ${icon} Backup Vaultwarden**\n" + msg="**${ping}Backup Vaultwarden ${icon}**\n" msg+="Backup: ${BACKUP_NAME}\n" msg+="Data transfer: ${status_line}\n" [[ -n "$details" ]] && msg+="Détails: ${details}" @@ -147,4 +149,4 @@ rm -f "$LOCAL_BACKUP_FILE" || fail "Impossible de supprimer le backup local $LOC ####################################### 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" +echo "Backup $BACKUP_NAME terminé et envoyé sur $REMOTE_HOST:$REMOTE_DIR" \ No newline at end of file diff --git a/CheckStorage/check-storage.sh b/CheckStorage/check-storage.sh index 20b1c5a..8f6326f 100644 --- a/CheckStorage/check-storage.sh +++ b/CheckStorage/check-storage.sh @@ -1,4 +1,23 @@ #!/bin/bash +set -euo pipefail + +############################################################################### +# CHARGEMENT DU .env +############################################################################### + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ENV_FILE="${SCRIPT_DIR}/.env" + +if [[ ! -f "$ENV_FILE" ]]; then + echo "ERROR: fichier .env introuvable : $ENV_FILE" >&2 + exit 1 +fi + +set -a +# shellcheck disable=SC1090 +source "$ENV_FILE" +set +a + ############################################################################### # CONFIGURATION ############################################################################### @@ -6,14 +25,10 @@ # Limite maximale d'utilisation du disque en pourcentage limit=70 -# Récupération du webhook Discord depuis le fichier .env -WEBHOOK_URL=$(grep -E '^WEBHOOK_URL=' .env | cut -d '=' -f2-) - ############################################################################### # RÉCUPÉRATION DES INFORMATIONS DISQUE ############################################################################### -# extraction des informations read -r total_bytes used_bytes avail_bytes usage <<<"$(df -B1 / | awk 'NR==2 {gsub(/%/,"",$5); print $2, $3, $4, $5}')" # Calcul du pourcentage d'espace libre @@ -23,25 +38,24 @@ free=$((100 - usage)) # CONVERSION EN GIGAOCTETS ############################################################################### -# Conversion bytes → gigaoctets pour un affichage plus lisible used_gb=$(awk -v b="$used_bytes" 'BEGIN {printf "%.2f", b/1024/1024/1024}') total_gb=$(awk -v b="$total_bytes" 'BEGIN {printf "%.2f", b/1024/1024/1024}') avail_gb=$(awk -v b="$avail_bytes" 'BEGIN {printf "%.2f", b/1024/1024/1024}') - ############################################################################### # VÉRIFICATION DU SEUIL D'UTILISATION ############################################################################### -# Si l'utilisation dépasse la limite définie, une alerte est envoyée sur Discord if [ "$usage" -ge "$limit" ]; then msgLimit="@here\n**CHECK STOCKAGE :red_circle:**\nLimite autorisé : ${limit}%\nUtilisation actuelle: ${usage}%\nEspace restant: ${free}%\nUtilise / total: ${used_gb} GB / ${total_gb} GB\nDisponible: ${avail_gb} GB\nHeure: $(date)" + payload="$(jq -n --arg content "$msgLimit" '{content: $content}')" + curl -X POST \ -H "Accept: application/json" \ -H "Content-Type: application/json; charset=utf-8" \ - -d "{\"content\":\"$msgLimit\"}" \ + -d "$payload" \ "$WEBHOOK_URL" fi @@ -50,9 +64,6 @@ fi # AFFICHAGE DES INFORMATIONS STOCKAGE ############################################################################### -# Affichage des informations disque dans la console echo "Espace disponible : ${avail_gb} GB" echo "Espace utilise / espace total : ${used_gb} GB / ${total_gb} GB" - -# Nom de la machine exécutant le script echo "Name: ${HOSTNAME}" \ No newline at end of file diff --git a/README.md b/README.md index 5e9853d..cac788c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Scripts Serveur MALIO +# Malio-Ops MALIO Ce dépôt sert au **versionnement des scripts utilisés dans l’infrastructure du projet Ferme**. L’objectif est de conserver un historique clair des scripts, suivre les évolutions et permettre leur amélioration progressive. diff --git a/RecetteScripts/.env.exemple b/RecetteScripts/.env.exemple index 7f1218a..c0ca24f 100644 --- a/RecetteScripts/.env.exemple +++ b/RecetteScripts/.env.exemple @@ -16,7 +16,7 @@ PGHOST=localhost PGPORT=5432 # Utilisateur utilisé pour les dumps -PGUSER=backup_user +PGUSER=nom_de_user # Mot de passe PostgreSQL PGPASSWORD=change_me_secure_password @@ -29,20 +29,20 @@ DBS="sirh inventory ferme" ############################################# # Utilisateur du serveur distant -BACKUP_REMOTE_USER=backup +BACKUP_REMOTE_USER=nom_de_user # Host ou IP du serveur distant BACKUP_REMOTE_HOST=192.168.1.50 # Dossier distant pour stocker les backups -BACKUP_REMOTE_DIR=/home/backup/backups +BACKUP_REMOTE_DIR=/home/nom_de_user/backups/bdd-recette ############################################# # SSH ############################################# # Clé SSH utilisée pour envoyer les dumps -SSH_KEY=/home/backup/.ssh/id_ed25519_backup +SSH_KEY=/home/nom_de_user/.ssh/id_ed25519_backup # Timeout SSH (secondes) SSH_TIMEOUT=10 diff --git a/RecetteScripts/backup-bdd-recette.sh b/RecetteScripts/backup-bdd-recette.sh index c242f05..03a1a15 100644 --- a/RecetteScripts/backup-bdd-recette.sh +++ b/RecetteScripts/backup-bdd-recette.sh @@ -10,14 +10,15 @@ set -euo pipefail # # Fonctionnement global : # 1. charge la configuration depuis le fichier .env ; -# 2. prépare les chemins, logs et variables de connexion ; -# 3. empêche l’exécution simultanée grâce à un verrou ; -# 4. crée les dossiers de destination sur la machine distante ; -# 5. exporte les rôles PostgreSQL ; -# 6. dump chaque base au format personnalisé PostgreSQL ; -# 7. transfère chaque fichier vers le serveur distant ; -# 8. applique une rotation distante sur 10 jours ; -# 9. envoie un bilan sur Discord : +# 2. vérifie les dépendances nécessaires ; +# 3. prépare les chemins, logs et variables de connexion ; +# 4. empêche l’exécution simultanée grâce à un verrou ; +# 5. crée les dossiers de destination sur la machine distante ; +# 6. exporte les rôles PostgreSQL ; +# 7. dump chaque base au format personnalisé PostgreSQL ; +# 8. transfère chaque fichier vers le serveur distant ; +# 9. applique une rotation distante sur 10 jours ; +# 10. envoie un bilan sur Discord : # - 1 message global si tout est OK ; # - en cas d’erreur partielle : # * USERS OK -> message simple ; @@ -102,10 +103,17 @@ DISCORD_PING="${DISCORD_PING:-@here}" discord_send() { local msg="$1" - [[ -z "${DISCORD_WEBHOOK_URL:-}" ]] && return + [[ -z "${DISCORD_WEBHOOK_URL:-}" ]] && return 0 - curl -fsS -H "Content-Type: application/json" \ - -d "{\"content\":\"$msg\"}" \ + local payload + payload="$(jq -n --arg content "$msg" '{content: $content}')" || { + log "ERROR: impossible de construire le payload JSON Discord" + return 1 + } + + curl -fsS \ + -H "Content-Type: application/json" \ + -d "$payload" \ "$DISCORD_WEBHOOK_URL" >/dev/null || true } diff --git a/RecetteScripts/check-statut-recette.sh b/RecetteScripts/check-statut-recette.sh index 2eae821..380a30f 100644 --- a/RecetteScripts/check-statut-recette.sh +++ b/RecetteScripts/check-statut-recette.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -set -u +set -uo pipefail ############################################################################### # check-statut-recette.sh @@ -89,8 +89,11 @@ discord_ping() { msg+="Application: ${site}\n" msg+="Details: ${detail}" + local payload + payload="$(jq -n --arg content "$msg" '{content: $content}')" + curl -fsS -H "Content-Type: application/json" \ - -d "{\"content\":\"$msg\"}" \ + -d "$payload" \ "$DISCORD_WEBHOOK_URL" >/dev/null || true } @@ -99,11 +102,9 @@ discord_ping() { ####################################### log_line() { - # 2026-03-04 14:12:33 | LEVEL | site | message printf "%s | %s | %s | %s\n" \ "$(date +'%Y-%m-%d %H:%M:%S')" "$1" "$2" "$3" | tee -a "$LOG_FILE" - # Envoi Discord par application discord_ping "$2" "$1" "$3" }