fix/code-review #10

Merged
Matteo merged 7 commits from fix/code-review into develop 2026-03-10 15:17:56 +00:00
8 changed files with 356 additions and 107 deletions

15
.gitignore vendored
View File

@@ -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

View File

@@ -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 dautomatiser la sauvegarde de Vaultwarden afin de conserver une copie du dossier `data`, de la transférer vers un serveur distant et denvoyer 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 larchive avec un nom daté ;
- transférer la sauvegarde vers un serveur distant ;
- envoyer une notification Discord ;
- automatiser lexé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 :
- damé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 lajouter 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 dobtenir une sauvegarde portable et compressée.
---
# 8. Transfert vers le serveur distant
Une fois larchive 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 lerreur 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 lerreur
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 danalyser 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 sexé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 davoir 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
* lexécution automatique via cron
* la configuration sécurisée via `.env`
Ce système permet dobtenir **une sauvegarde fiable, centralisée et surveillée de Vaultwarden**.
```

View File

@@ -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"

View File

@@ -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}"

View File

@@ -1,4 +1,4 @@
# Scripts Serveur MALIO
# Malio-Ops MALIO
Ce dépôt sert au **versionnement des scripts utilisés dans linfrastructure du projet Ferme**.
Lobjectif est de conserver un historique clair des scripts, suivre les évolutions et permettre leur amélioration progressive.

View File

@@ -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

View File

@@ -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 lexé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 lexé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 derreur 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
}

View File

@@ -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"
}