Externalisation hors ligne des backups Proxmox
Contexte
Section intitulée « Contexte »Pour des raisons de sécurité, les sauvegardes doivent être externalisées sur des disques externes. L’objectif est double :
- garder une copie hors ligne, physiquement isolée du site ;
- pouvoir remonter l’infrastructure rapidement en cas d’incident majeur.
Les contraintes
Section intitulée « Les contraintes »| Contrainte | Détail |
|---|---|
| Volumétrie | Plus de 20 To de sauvegardes |
| Cloisonnement | Plusieurs réseaux à sauvegarder séparément |
| Disponibilité | Le disque ne doit être monté que sur une plage horaire définie |
La solution retenue
Section intitulée « La solution retenue »Les sauvegardes sont découpées en deux namespaces sur le serveur Proxmox Backup Server (PBS) :
Reseau AReseau B
Chaque namespace est externalisé sur son propre disque de 24 To. Deux disques ont donc été achetés — ce qui représente un budget conséquent en 2026.
Prérequis
Section intitulée « Prérequis »Matériel
Section intitulée « Matériel »- Un serveur Proxmox Backup Server opérationnel.
- Un ou plusieurs disques externes dimensionnés pour la volumétrie à externaliser.
- Un accès root en SSH sur le PBS.
PBS est basé sur Debian : la plupart des outils sont déjà présents, mais gdisk et les outils du système de fichiers choisi doivent généralement être installés.
apt updateapt install -y gdisk btrfs-progs| Paquet | Fournit | Utilisé pour |
|---|---|---|
gdisk | gdisk | Créer la table de partition GPT |
btrfs-progs | mkfs.btrfs, btrfs | Formater et étiqueter le disque |
util-linux | lsblk, mount, umount, findmnt, mountpoint, blkid | Identifier et monter le disque (déjà installé) |
bsdutils | logger | Journaliser le script d’automatisation (déjà installé) |
udev | udevadm | Attendre la détection du disque (déjà installé) |
cron | /etc/crontab | Planifier le montage et le démontage (déjà installé) |
proxmox-backup-server | proxmox-backup-manager | Piloter les datastores (déjà installé) |
Étape 1 — Préparer le disque
Section intitulée « Étape 1 — Préparer le disque »-
Identifier le nouveau disque
Insérer le disque dans le serveur PBS, puis lister les périphériques bloc :
Fenêtre de terminal lsblkFenêtre de terminal NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTSsda 8:0 0 45G 0 disk├─sda1 8:1 0 1G 0 part /boot└─sda2 8:2 0 44G 0 part├─rl_heal-root 253:0 0 40,5G 0 lvm /└─rl_heal-swap 253:1 0 3,5G 0 lvmsdb 8:16 0 200G 0 diskDans cet exemple, le nouveau disque est
sdb. Adapter toutes les commandes suivantes à ce nom. -
Créer la table de partition
Fenêtre de terminal gdisk /dev/sdbEnchaîner les commandes interactives suivantes :
Touche Action dSupprimer les partitions existantes (à répéter s’il y en a plusieurs) oCréer une nouvelle table de partition GPT nCréer une nouvelle partition — valider toutes les valeurs par défaut avec EntréewÉcrire les modifications sur le disque et quitter -
Formater la partition
Fenêtre de terminal mkfs.btrfs /dev/sdb1 -
Étiqueter le disque
L’étiquette (label) permet de retrouver le disque quel que soit le nom attribué par le noyau (
sdb,sdc…). C’est indispensable pour la rotation, et fortement recommandé même avec un seul disque.Fenêtre de terminal btrfs filesystem label /dev/sdb1 offline-disk-1Vérifier :
Fenêtre de terminal blkid -L offline-disk-1
Étape 2 — Initialiser le datastore PBS
Section intitulée « Étape 2 — Initialiser le datastore PBS »Un datastore PBS a besoin d’une arborescence spécifique (.chunks, .lock…) sur le disque. Cette arborescence est créée automatiquement à la création du datastore dans l’interface.
La marche à suivre diffère selon qu’il s’agit du premier disque ou d’un disque de rotation.
-
Créer le point de montage et monter le disque
Fenêtre de terminal mkdir -p /mnt/datastore/OFFLINEmount /dev/sdb1 /mnt/datastore/OFFLINE/ -
Créer le datastore définitif dans l’interface PBS
Dans l’interface web : Datastore → Add Datastore, en pointant sur
/mnt/datastore/OFFLINE.
Le disque est prêt : passer directement à l’Étape 3.
Le datastore OFFLINE existe déjà et pointe sur /mnt/datastore/OFFLINE. Le nouveau disque doit donc être initialisé via un datastore temporaire, qui sera supprimé ensuite.
-
Monter temporairement le disque
Fenêtre de terminal mkdir -p /tmp/testmount /dev/sdb1 /tmp/test/ -
Créer un datastore temporaire dans l’interface PBS
Dans l’interface web : Datastore → Add Datastore, en pointant sur
/tmp/test.
-
Mettre le datastore temporaire hors ligne et le démonter
Fenêtre de terminal proxmox-backup-manager datastore update TEST --maintenance-mode offline && \sleep 30 && \umount /tmp/test -
Monter le disque sur le datastore définitif
Fenêtre de terminal mount /dev/sdb1 /mnt/datastore/OFFLINE/proxmox-backup-manager datastore update OFFLINE --delete maintenance-mode -
Supprimer le datastore temporaire
Fenêtre de terminal vim /etc/proxmox-backup/datastore.cfg# Supprimer la section « datastore: TEST »
Étape 3 — Automatiser le montage et le démontage
Section intitulée « Étape 3 — Automatiser le montage et le démontage »Le disque ne doit rester monté que pendant la fenêtre de sauvegarde. Deux tâches planifiées sont nécessaires :
gantt
title Cycle quotidien du disque d'externalisation
dateFormat YYYY-MM-DD HH:mm
axisFormat %Hh
tickInterval 3hour
section Disque externe
Démonté — débranchable :crit, 2026-01-01 08:00, 9h
Monté — sur /mnt/datastore :active, 2026-01-01 17:00, 15h
section Sauvegardes PBS
Datastore en maintenance :crit, 2026-01-01 08:00, 9h
Fenêtre de sauvegarde :active, 2026-01-01 17:00, 15h
- 17:00 — montage. Le script détecte le disque branché par son label, le monte, puis lève le mode maintenance du datastore. Les sauvegardes peuvent démarrer.
- 08:00 — démontage. Le datastore passe en maintenance, PBS termine ses tâches en cours, puis le disque est démonté. Il peut alors être débranché et emporté hors site.
Démontage automatique
Section intitulée « Démontage automatique »Le démontage est simple : une seule ligne dans la crontab suffit.
vim /etc/crontab0 8 * * * root proxmox-backup-manager datastore update OFFLINE --maintenance-mode offline && sleep 180 && umount /mnt/datastore/OFFLINEMontage automatique
Section intitulée « Montage automatique »Il n’existe pas de solution idéale pour le montage. Les règles udev ont été testées mais se sont révélées trop instables. Le script ci-dessous est la solution retenue : il cherche le disque par son label, vérifie son système de fichiers, le monte et lève le mode maintenance du datastore.
-
Déposer le script sur le serveur
Fenêtre de terminal vim /root/auto-mount-backup-disk.shchmod +x /root/auto-mount-backup-disk.sh/root/auto-mount-backup-disk.sh #!/bin/bashset -uo pipefail################################ CONFIGURATION ################################ Zone -> labels candidats, par ordre de préférencedeclare -A LABELS=([OFFLINE]="offline-disk-1 offline-disk-2 offline-disk-3"120 collapsed lines)# Zone -> point de montage (peut différer du nom du datastore)declare -A MOUNTPOINT=([OFFLINE]="/mnt/datastore/OFFLINE")# Zone -> datastore PBS correspondantdeclare -A DATASTORE=([OFFLINE]="OFFLINE")MOUNTOPTS="rw,relatime,space_cache=v2,max_inline=0,nosuid,nodev,noexec"WAIT_SECS=30 # attente max de l'apparition d'un label (remplace le sleep fixe)SET_MAINTENANCE_IF_ABSENT=1 # 1 = passe le datastore en maintenance quand le disque est absentMAINTENANCE_MSG="Disque externe non branché"################################################################################TAG="auto-mount-backup-disk"rc=0log() { printf '[%s] %s\n' "$(date '+%F %T')" "$*"; logger -t "$TAG" -- "$*" 2>/dev/null; }warn() { printf '[%s] ATTENTION: %s\n' "$(date '+%F %T')" "$*" >&2; logger -t "$TAG" -p user.warning -- "$*" 2>/dev/null; }find_device() {local zone="$1" label dev deadline=$(( SECONDS + WAIT_SECS ))while :; dofor label in ${LABELS[$zone]}; dodev="$(blkid -L "$label" 2>/dev/null)"if [ -n "$dev" ]; thenprintf '%s\t%s\n' "$label" "$dev"return 0fidone(( SECONDS >= deadline )) && return 1sleep 2done}pbs_maintenance_off() {local ds="$1"proxmox-backup-manager datastore update "$ds" --delete maintenance-mode \&& log "Datastore $ds : maintenance-mode retiré." \|| { warn "Datastore $ds : échec du retrait du maintenance-mode."; rc=1; }}pbs_maintenance_on() {local ds="$1"[ "$SET_MAINTENANCE_IF_ABSENT" -eq 1 ] || return 0proxmox-backup-manager datastore update "$ds" \--maintenance-mode "type=offline,message=$MAINTENANCE_MSG" \&& log "Datastore $ds : passé en maintenance (offline)." \|| warn "Datastore $ds : échec du passage en maintenance."}process_zone() {local zone="$1"local mp="${MOUNTPOINT[$zone]}" ds="${DATASTORE[$zone]}"local found label dev fstype src# Déjà monté ? on vérifie juste et on lève la maintenanceif mountpoint -q "$mp"; thensrc="$(findmnt -no SOURCE "$mp")"log "[$zone] $mp déjà monté ($src)."pbs_maintenance_off "$ds"return 0fiif ! found="$(find_device "$zone")"; thenwarn "[$zone] aucun disque trouvé parmi : ${LABELS[$zone]}"pbs_maintenance_on "$ds"rc=1return 1filabel="${found%%$'\t'*}"dev="${found##*$'\t'}"fstype="$(blkid -o value -s TYPE "$dev" 2>/dev/null)"if [ "$fstype" != "btrfs" ]; thenwarn "[$zone] $label ($dev) n'est pas en btrfs (type=$fstype) — montage annulé."pbs_maintenance_on "$ds"rc=1return 1fi# Le disque est-il déjà monté ailleurs ?if findmnt -no TARGET --source "$dev" >/dev/null 2>&1; thenwarn "[$zone] $dev est déjà monté sur $(findmnt -no TARGET --source "$dev" | paste -sd' ')."rc=1return 1fimkdir -p "$mp"log "[$zone] montage de $label ($dev) sur $mp..."if mount -t btrfs -o "$MOUNTOPTS" "$dev" "$mp"; thenlog "[$zone] montage OK."pbs_maintenance_off "$ds"elsewarn "[$zone] échec du montage de $dev sur $mp."pbs_maintenance_on "$ds"rc=1return 1fi}# --- main ---------------------------------------------------------------------if [ "$(id -u)" -ne 0 ]; thenwarn "Ce script doit être exécuté en root."exit 1ficommand -v udevadm >/dev/null && udevadm settle --timeout=10 >/dev/null 2>&1zones=( "$@" )[ ${#zones[@]} -eq 0 ] && zones=( "${!LABELS[@]}" )for zone in "${zones[@]}"; doif [ -z "${LABELS[$zone]:-}" ]; thenwarn "Zone inconnue : $zone (zones définies : ${!LABELS[*]})"rc=1continuefiprocess_zone "$zone"doneexit $rc -
Adapter la configuration
Seul le bloc
CONFIGURATIONen haut du script est à modifier :Variable Rôle LABELSLabels des disques acceptés pour la zone, par ordre de préférence (rotation) MOUNTPOINTPoint de montage de la zone DATASTORENom du datastore PBS correspondant MOUNTOPTSOptions de montage WAIT_SECSDurée max d’attente de l’apparition d’un label SET_MAINTENANCE_IF_ABSENT1= bascule le datastore en maintenance si aucun disque n’est trouvéPour gérer plusieurs réseaux, ajouter une entrée par zone dans les trois tableaux :
Fenêtre de terminal declare -A LABELS=([RESEAU_A]="reseau-a-disk-1 reseau-a-disk-2"[RESEAU_B]="reseau-b-disk-1 reseau-b-disk-2")declare -A MOUNTPOINT=([RESEAU_A]="/mnt/datastore/RESEAU_A"[RESEAU_B]="/mnt/datastore/RESEAU_B")declare -A DATASTORE=([RESEAU_A]="RESEAU_A"[RESEAU_B]="RESEAU_B") -
Tester le script à la main
Fenêtre de terminal /root/auto-mount-backup-disk.shfindmnt /mnt/datastore/OFFLINEIl est aussi possible de ne traiter qu’une zone :
Fenêtre de terminal /root/auto-mount-backup-disk.sh RESEAU_A -
Planifier l’exécution
Fenêtre de terminal vim /etc/crontab/etc/crontab 0 17 * * * root /root/auto-mount-backup-disk.sh
Récapitulatif
Section intitulée « Récapitulatif »Répertoire/mnt/datastore/
RépertoireOFFLINE/ point de montage du disque externe
- …
Répertoire/root/
- auto-mount-backup-disk.sh script de montage automatique
Répertoire/etc/
- crontab planification montage (17h) / démontage (8h)
Répertoireproxmox-backup/
- datastore.cfg configuration des datastores PBS
| Heure | Action | Déclencheur |
|---|---|---|
| 08:00 | Datastore en maintenance puis démontage | cron |
| 17:00 | Détection du disque, montage, sortie de maintenance | cron + auto-mount-backup-disk.sh |
Dépannage
Section intitulée « Dépannage »| Symptôme | Piste |
|---|---|
aucun disque trouvé parmi : … | Le disque n’est pas branché, ou son label ne correspond pas — vérifier avec blkid -L <label> |
n'est pas en btrfs (type=…) | Le disque n’a pas été formaté, ou l’a été dans un autre système de fichiers |
est déjà monté sur … | Démonter le disque avant de relancer le script : umount <point_de_montage> |
| Le datastore reste en maintenance | Lever le mode manuellement : proxmox-backup-manager datastore update OFFLINE --delete maintenance-mode |
umount: target is busy | Une tâche PBS tourne encore — augmenter le sleep de la crontab de démontage |
Les messages du script sont également envoyés au journal système :
journalctl -t auto-mount-backup-disk -n 50