BorgBackup cwwk sharenfs BX11-02

BorgBackup cwwk sharenfs BX11-02

Notes

Posté le 2026-10-29 18:08:30 +01:00 sur ‘🖥⚙️CWWK - Serveur Debian 13’

BorgBackup dépôt cwwk-sharenfs

Création dépôt dans la boîte de stockage (repository)

Dépôt distant à travers SSH

ssh://u694796@u694796.your-storagebox.de:23/./cwwk-sharenfs

Phrase forte: /sharenfs/pc1/.borg/cwwk-sharenfs.passphrase

Initialisation dépôt distant cwwk en mode su

1
2
3
4
export BORG_PASSPHRASE="$(cat /sharenfs/pc1/.borg/cwwk-sharenfs.passphrase)"
export BORG_RSH='ssh -i /sharenfs/pc1/.borg/bx11-yann-02.borgssh'
BORG_REPOSITORY=ssh://u694796@u694796.your-storagebox.de:23/./cwwk-sharenfs
borg init --encryption=repokey $BORG_REPOSITORY

Le fichier d’exclusion /sharenfs/pc1/.borg/cwwk-sharenfs.exclusions En mode utilisateur

Créer un script de sauvegarde (notez l’usage de borg prune pour supprimer les archives trop anciennes)

1
sudo nano /sharenfs/scripts/borgbackup-cwwk-sharenfs.sh 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/bin/sh

. "/sharenfs/scripts/env/ntfy.env"

t=$(date +%s)

export BORG_PASSPHRASE="$(cat /sharenfs/pc1/.borg/cwwk-sharenfs.passphrase)"
export BORG_RSH='ssh -i /sharenfs/pc1/.borg/cwwk-sharenfs.borgssh'

BACKUP_DATE="$(date +%Y-%m-%d-%Hh%M)"
BORG_REPOSITORY="$(cat /sharenfs/pc1/.borg/cwwk-sharenfs.repository)"
BORG_EXCLUSION="/sharenfs/pc1/.borg/cwwk-sharenfs.exclusions"
BORG_PATH="/"
INFO="CWWK Debian13 + sharenfs"

CMD_CREATE="borg create -v --progress --stats --exclude-from $BORG_EXCLUSION \"${BORG_REPOSITORY}::${BACKUP_DATE}\" $BORG_PATH"
borg create -v --progress --stats --exclude-from $BORG_EXCLUSION "${BORG_REPOSITORY}::${BACKUP_DATE}" $BORG_PATH
rc_create=$?

CMD_PRUNE="borg prune -v --stats --keep-daily=7 --keep-weekly=1 --keep-monthly=1 \"${BORG_REPOSITORY}\""
borg prune -v --stats --keep-daily=7 --keep-weekly=1 --keep-monthly=1 "$BORG_REPOSITORY"
rc_prune=$?

d=$(( $(date +%s) - t ))
DUREE=$(( d / 3600 ))h$(( (d % 3600) / 60 ))m$(( d % 60 ))s

s_create="❌"
[ $rc_create -eq 0 ] && s_create="✔️"

s_prune="❌"
[ $rc_prune -eq 0 ] && s_prune="✔️"

msg_title="💾 $INFO : Borgbackup en $DUREE"

{
  echo
  echo "${s_create} ${CMD_CREATE}"
  echo
  echo "${s_prune} ${CMD_PRUNE}"
} | curl -sS -X POST \
  -H "X-Email: $NTFY_EMAIL" \
  -H "Title: $msg_title" \
  -H "Authorization: Bearer $NTFY_TOKEN" \
  -H "prio:low" \
  -H "Content-Type: text/plain; charset=utf-8" \
  --data-binary @- \
  "$NTFY_URL"

Le rendre exécutable

1
chmod +x /sharenfs/scripts/borgbackup-cwwk-sharenfs.sh

Planification de la sauvegarde en utilisant systemd timer

Le service /etc/systemd/system/borgbackup-cwwk-sharenfs.service

1
2
3
4
5
6
7
8
9
[Unit]
Description=Service borgbackup-cwwk-sharenfs

[Service]
Type=oneshot
ExecStart=/usr/bin/bash /sharenfs/scripts/borgbackup-cwwk-sharenfs.sh

[Install]
WantedBy=multi-user.target

Le timer /etc/systemd/system/borgbackup-cwwk-sharenfs.timer

1
2
3
4
5
6
7
8
9
[Unit]
Description=Timer borgbackup-cwwk-sharenfs

[Timer]
OnCalendar=*-*-* 02:40
Persistent=true

[Install]
WantedBy=timers.target

Exécution tous les jours

Activez/démarrez le timer, puis vérifiez qu’il est chargé et actif

1
2
3
sudo systemctl daemon-reload
sudo systemctl enable borgbackup-cwwk-sharenfs.timer --now
systemctl status borgbackup-cwwk-sharenfs.timer

Vérifiez s’il apparaît dans la liste des minuteries :

1
systemctl list-timers
1
2
NEXT                             LEFT LAST                              PASSED UNIT                         ACTIVATES                     
Fri 2026-10-30 02:40:00 CET             15h -                                       - borgbackup-cwwk-sharenfs.timer borgbackup-cww>

Lorsque vous voulez voir si les sauvegardes se sont déroulées correctement, vous pouvez consulter le journal le plus récent

1
systemctl status borgbackup-cwwk

Ou afficher tous les journaux avec :

1
sudo journalctl -u borgbackup-cwwk

Synchronisation des backup borg

Synchronisation des backup borg entre le serveur de stockage (storage box) et le disque USB partagé monté sur la freebox en utilisant systemd timer.

Le script à exécuter en mode su /sharenfs/scripts/storage-freedisk.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/bin/bash

# Paramètrage pour la notification
. "/sharenfs/scripts/env/ntfy.env"

# Pour le calcul du temps d'exécution
t=$(date +%s)

# Fichier temporaire pour mémoriser toutes les sorties
tmpfile="$(mktemp)"
# Optionnel: affiche même si le script plante
trap 'cat "$tmpfile"; rm -f "$tmpfile"' EXIT

FREEBOX="/mnt/FreeUSB2To/sauvegardes/borgbackup"

# Une ligne par boîte : nom|utilisateur|clé ssh|dossier distant des dépôts
BOXES=(
  "bx11-yann|u326239|/home/yick/.ssh/bx11-yann-ed25519|backup/borg"
  "bx11-yann02|u694796|/home/yick/.ssh/bx11-yann-02|."
)

erreurs=0

sync_box() {
  local nom="$1" user="$2" key="$3" dir="$4"
  local host="${user}@${user}.your-storagebox.de"
  local servers hote_array hote err ret src

  # Liste des dossiers (dépôts) présents sur la box, sans .ssh
  servers=$(
    sftp -P 23 -i "$key" "$host" 2>/dev/null <<EOF |
cd $dir
ls -l
EOF
    awk '$1 ~ /^d/ {print $NF}' | grep -vx -e '\.' -e '\.\.' -e '\.ssh'
  )

  if [ -z "$servers" ]; then
    echo "===== $nom : aucun dossier trouvé (ou échec sftp) : $(date -Is) =====" >>"$tmpfile"
    erreurs=$((erreurs + 1))
    return
  fi

  readarray -t hote_array <<< "$servers"

  for hote in "${hote_array[@]}"; do
    src="$host:$dir/$hote"

    {
      echo "===== RSYNC [$nom] vers $hote : $(date -Is) ====="
      echo "rsync -avz --delete --rsync-path='rsync' -e 'ssh -p 23 -i $key' $src $FREEBOX/"
      err=$(rsync -avz --delete --rsync-path='rsync' \
        -e "ssh -p 23 -i $key" \
        "$src" "$FREEBOX/" 2>&1 >/dev/null)
      ret=$?

      if [ $ret -ne 0 ]; then
        echo "ERREUR ($ret) :"
        echo "$err"
        erreurs=$((erreurs + 1))
      else
        echo "OK"
      fi
    } >>"$tmpfile"
  done
  }

for entry in "${BOXES[@]}"; do
  IFS='|' read -r nom user key dir <<< "$entry"
  sync_box "$nom" "$user" "$key" "$dir"
done

# Durée d'exécution
duree=$(( $(date +%s) - t ))
duree_fmt=$(printf '%dmin %02ds' $((duree / 60)) $((duree % 60)))

# Titre, priorité et conclusion selon le résultat
if [ "$erreurs" -gt 0 ]; then
  titre="❌ Synchro BorgBackup BX11 et BX11-02 → Freebox"
  prio="high"
  conclusion="❌ Fin synchronisation avec $erreurs erreur(s) en $duree_fmt"
else
  titre="✅ Synchro BorgBackup BX11 et BX11-02 → Freebox"
  prio="low"
  conclusion="✔️ Fin synchronisation dépôts borgbackup en $duree_fmt"
fi

curl --ipv4 \
  -H "X-Email: $NTFY_EMAIL" \
  -H "Title: $titre" \
  -H "Authorization: Bearer $NTFY_TOKEN" \
  -H "prio: $prio" \
  -d "CWWK $0
$(cat "$tmpfile")
$conclusion" \
  "$NTFY_URL"

Script exécutable

1
chmod +x /sharenfs/scripts/synchro-backup.sh

Le service /etc/systemd/system/storage-freedisk.service

1
2
3
4
5
6
[Unit]
Description=Rsync storagebox vers FreeUSB2To

[Service]
Type=oneshot
ExecStart=/usr/bin/bash /sharenfs/scripts/storage-freedisk.sh

Le timer /etc/systemd/system/storage-freedisk.timer

1
2
3
4
5
6
7
8
9
[Unit]
Description=Rsync storagebox vers FreeUSB2To

[Timer]
OnCalendar=*-*-* 04:25
Persistent=true

[Install]
WantedBy=timers.target

Exécution tous les jours à 4h25 du matin

Activez/démarrez le timer, puis vérifiez qu’il est chargé et actif

1
2
3
sudo systemctl daemon-reload
sudo systemctl enable storage-freedisk.timer --now
systemctl status storage-freedisk.timer

Vérifiez qu’il a été démarré en vérifiant s’il apparaît dans la liste des minuteries :

1
systemctl list-timers
1
2
NEXT                        LEFT          LAST                        PASSED       UNIT                         ACTIVATES                     
Mon 2024-12-16 04:25:00 CET 20h left      -                           -            storage-freedisk.timer       storage-freedisk.service

Lancement manuel en mode su

1
/usr/bin/bash /sharenfs/scripts/storage-freedisk.sh

Compactage des backup borg

*Compacter les backup borg sur tous les dépôts

Vérifier présence des fichiers pour le compactage, à exécuter sur la machine cwwk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/bin/bash

. "/sharenfs/scripts/env/ntfy.env"

t=$(date +%s)

BORG_DIR="/sharenfs/pc1/.borg"
INFO="CWWK compactage dépôts"

# Une ligne par boîte : utilisateur|clé ssh|dossier distant des dépôts
BOXES=(
  "u326239|/home/yick/.ssh/bx11-yann-ed25519|backup/borg"
  "u694796|/home/yick/.ssh/bx11-yann-02|."
)

# On récupère via sftp les dossiers sauvegardés sur chaque Storage Box
hote_array=()
for entry in "${BOXES[@]}"; do
  IFS='|' read -r user key dir <<< "$entry"
  liste=$(
    sftp -P 23 -i "$key" "${user}@${user}.your-storagebox.de" 2>/dev/null <<EOF |
cd $dir
ls -l
EOF
    awk '$1 ~ /^d/ {print $NF}' | grep -vx -e '\.' -e '\.\.' -e '\.ssh'
  )
  [ -n "$liste" ] && while IFS= read -r h; do hote_array+=("$h"); done <<< "$liste"
done

nb_err=0
rapport=""

# Compactage des dépôts borg distants
for hote in "${hote_array[@]}"; do
  f_ssh="$BORG_DIR/$hote.borgssh"
  f_pass="$BORG_DIR/$hote.passphrase"
  f_repo="$BORG_DIR/$hote.repository"

  # Vérification des fichiers nécessaires
  manque=""
  for f in "$f_ssh" "$f_pass" "$f_repo"; do
    [ -e "$f" ] || manque="$manque $(basename "$f")"
  done
  if [ -n "$manque" ]; then
    nb_err=$((nb_err + 1))
    rapport="${rapport}
❌ ${hote} : fichier(s) inexistant(s) :${manque}
"
    echo "Host: $hote : fichier(s) inexistant(s) :$manque"
    continue
  fi

  export BORG_PASSPHRASE="$(cat "$f_pass")"
  export BORG_RSH="ssh -i $f_ssh"
  BORG_REPOSITORY="$(cat "$f_repo")"

  CMD="borg compact -v \"${BORG_REPOSITORY}\""
  echo "Host: $hote"
  sortie=$(borg compact -v "$BORG_REPOSITORY" 2>&1)
  rc=$?
  echo "$sortie"
  echo "--------------------------------------------------------"

  if [ $rc -eq 0 ]; then
    rapport="${rapport}
✔️ ${hote} : ${CMD}
$(echo "$sortie" | tail -n 1)
"
  else
    nb_err=$((nb_err + 1))
    rapport="${rapport}
❌ ${hote} : ${CMD}
$(echo "$sortie" | tail -n 5)
"
  fi
done

d=$(( $(date +%s) - t ))
DUREE=$(( d / 3600 ))h$(( (d % 3600) / 60 ))m$(( d % 60 ))s

if [ $nb_err -eq 0 ]; then
  msg_title="💾 $INFO BX11 et BX11-02 en $DUREE"
  prio="low"
else
  msg_title="❌ $INFO BX11 et BX11-02 : $nb_err erreur(s) en $DUREE"
  prio="high"
fi

echo "$rapport" | curl -sS -X POST \
  -H "X-Email: $NTFY_EMAIL" \
  -H "Title: $msg_title" \
  -H "Authorization: Bearer $NTFY_TOKEN" \
  -H "prio: $prio" \
  -H "Content-Type: text/plain; charset=utf-8" \
  --data-binary @- \
  "$NTFY_URL"

Le script à exécuter en mode su /sharenfs/scripts/borg-compact.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#!/bin/bash

. "/sharenfs/scripts/env/ntfy.env"

# Fichier temporaire pour mémoriser toutes les sorties
tmpfile="$(mktemp)"
# Optionnel: affiche même si le script plante
trap 'cat "$tmpfile"; rm -f "$tmpfile"' EXIT

# On récupère via sftp sous forme de tableau
# les dossiers sauvegardés sur la Storage BOX
servers=$(
  sftp -P 23 -i "/home/yick/.ssh/bx11-yann-ed25519" \
    u326239@u326239.your-storagebox.de 2>/dev/null <<'EOF' |
cd backup/borg
ls -l
EOF
  awk '$1 ~ /^d/ {print $NF}'

  sftp -P 23 -i "/home/yick/.ssh/bx11-yann-02"  \
    u694796@u694796.your-storagebox.de 2>/dev/null <<'EOF' |
ls -l
EOF
  awk '$1 ~ /^d/ {print $NF}'

)
readarray -t hote_array <<< "$servers"
# compactage des dépôts borg distants
 for hote in "${hote_array[@]}"
 do
  export BORG_RSH='ssh -i /sharenfs/pc1/.borg/'$hote'.borgssh'
  export BORG_PASSPHRASE=$(cat /sharenfs/pc1/.borg/$hote.passphrase)
  export BORG_DEPOT=$(cat /sharenfs/pc1/.borg/$hote.repository)
 {
   echo "= Dépôt $BORG_DEPOT : $(date -Is) ="
   echo "borg compact --progress \"$BORG_DEPOT\""

   err=$(borg compact --progress "$BORG_DEPOT" 2>&1 >/dev/null)
   ret=$?

   if [ $ret -ne 0 ]; then
     echo "ERREUR ($ret) :"
     echo "$err"
   else
     echo "✅"
   fi

  } >>"$tmpfile"
  done
#
# Message
#

curl --ipv4 \
-H "X-Email: $NTFY_EMAIL" \
-H "Title: 🗜 Compactage dépôts BorgBackup BX11 et BX11-02" \
-H "Authorization: Bearer $NTFY_TOKEN" \
-H "prio:low" \
-d "CWWK $0
`cat $tmpfile`
✔️ Fin compactage dépôts borgbackup" \
"$NTFY_URL"

Script exécutable

1
chmod +x /sharenfs/scripts/borg-compact.sh

Le service /etc/systemd/system/borg-compact.service

1
2
3
4
5
6
[Unit]
Description=Rsync storagebox vers FreeUSB2To

[Service]
Type=oneshot
ExecStart=/usr/bin/bash /sharenfs/scripts/borg-compact.sh

Le timer /etc/systemd/system/borg-compact.timer

1
2
3
4
5
6
7
8
9
[Unit]
Description=Compactage des dépôts borg

[Timer]
OnCalendar=Mon *-*-* 00:00:00
Persistent=true

[Install]
WantedBy=timers.target

Exécution tous les lundi à minuit Vérification syntaxe: systemd-analyze calendar 'Mon *-*-* 00:00:00'

Activez/démarrez le timer, puis vérifiez qu’il est chargé et actif

1
2
3
sudo systemctl daemon-reload
sudo systemctl enable borg-compact.timer --now
systemctl status borg-compact.timer

Vérifiez qu’il a été démarré en vérifiant s’il apparaît dans la liste des minuteries :

1
systemctl list-timers
1
2
NEXT                                   LEFT LAST                               PASSED UNIT                         ACTIVATES                     
Mon 2026-11-02 00:00:00 CET          3 days Mon 2026-10-26 00:00:01 CET             - borg-compact.timer           borg-compact.service