Retour au blog
    Tutoriels2026-05-0311 min de lecture

    Backup 3-2-1-1-0 avec Restic + Borg + stockage immutable : guide pratique

    Implémenter la règle 3-2-1-1-0 avec Restic et Borg, stockage immutable, scripts de rotation, vérification, restauration test. Anti-ransomware concret.

    backupresticborgransomwareimmutables3-object-lockiso-27001

    Une sauvegarde non testée n'est pas une sauvegarde. Une sauvegarde accessible en écriture par le serveur de production n'est pas une sauvegarde non plus : c'est une cible. Depuis 2020, la majorité des ransomwares modernes ciblent explicitement les répertoires de backup avant de chiffrer la production. La réponse de l'industrie tient en cinq chiffres : 3-2-1-1-0. Ce guide montre comment l'implémenter concrètement avec deux outils éprouvés, Restic et Borg, complétés par du stockage S3 verrouillé en mode compliance.

    #1. La règle 3-2-1-1-0 expliquée

    La règle 3-2-1 historique stipulait : 3 copies des données, sur 2 supports différents, avec 1 copie hors site. Elle reste valable mais devient insuffisante face aux menaces actuelles. La version étendue ajoute deux contraintes critiques :

    • 3 copies des données (la production + 2 sauvegardes minimum) ;
    • 2 supports distincts (disque local + objet S3, par exemple) ;
    • 1 copie hors site (datacenter distant ou cloud public) ;
    • 1 copie immuable (write-once-read-many, ou retention lock activé) ;
    • 0 erreur lors des tests de vérification et de restauration.

    Le « 1 immuable » casse la chaîne d'attaque : même avec les credentials du serveur de production, un attaquant ne peut pas supprimer ni chiffrer les snapshots verrouillés. Le « 0 erreur » impose un test de restauration périodique avec contrôle d'intégrité bit à bit. Sans ces deux derniers points, vous avez juste une copie de plus à perdre.

    #2. Restic vs Borg : choisir ou combiner

    Les deux outils partagent une philosophie commune (déduplication par blocs variables, chiffrement authentifié, snapshots) mais divergent sur les détails opérationnels.

    #Déduplication

    • Restic utilise CDC (Content Defined Chunking) basé sur Rabin fingerprinting, blocs entre 512 Kio et 8 Mio. Déduplication globale au repository.
    • Borg utilise le buzhash, blocs entre 19 et 23 bits par défaut. Déduplication également globale, légèrement plus efficace sur des données très répétitives (VMs, bases de données dump).

    En pratique, sur un parc mixte (fichiers utilisateurs, conteneurs, dumps PostgreSQL), Borg gagne 5 à 15 % d'espace par rapport à Restic. L'écart se réduit sur du média déjà compressé.

    #Compression

    • Restic : compression zstd activée par défaut depuis la 0.14, niveau auto.
    • Borg : compression configurable au moment du backup (lz4, zstd, zlib, lzma). zstd,3 est un excellent compromis CPU/ratio.

    #Chiffrement

    Les deux outils chiffrent côté client en AES-256 avec authentification (Poly1305 pour Restic, HMAC-SHA256 pour Borg). Les clés ne quittent jamais le client : le serveur de stockage ne voit que des blobs opaques. C'est un prérequis non négociable pour stocker chez un fournisseur tiers.

    #Backends et concurrence

    • Restic parle nativement S3, Backblaze B2, Azure Blob, GCS, Swift OVH, SFTP, REST server. Plusieurs clients peuvent écrire simultanément dans le même repo.
    • Borg est plus restrictif : SSH ou local, et un seul writer à la fois. Cela en fait l'outil idéal pour des snapshots locaux append-only, mais limite l'usage multi-sites sur un repo partagé.

    #Notre choix : combiner les deux

    Pour appliquer 3-2-1-1-0 sans gymnastique, nous déployons :

    • Restic pour les sauvegardes vers S3 (off-site, immuable) — multi-clients, multi-clouds ;
    • Borg pour les snapshots locaux append-only sur disque dédié — ultra-rapide, second support physique.

    Cette double pile protège contre les deux scénarios majeurs : compromission de la production (Borg local en append-only n'est pas vidable depuis le client) et destruction physique du site (S3 off-site avec Object Lock).

    #3. Architecture cible

    Voici l'architecture que nous déroulons systématiquement sur les infrastructures que nous gérons :

    ┌──────────────────────┐      ┌──────────────────────┐
    │  Serveur production  │      │  NAS / disque dédié  │
    │  (agents Restic +    │─────▶│  Repo Borg           │
    │   Borg client)       │ SSH  │  append-only         │
    └──────────┬───────────┘      └──────────────────────┘
               │
               │ HTTPS + AWS SigV4
               ▼
    ┌──────────────────────────────────────────────────┐
    │  Bucket S3 immuable (OVH / Scaleway / MinIO)     │
    │  Object Lock = COMPLIANCE, retention = 30j       │
    │  Versioning ON, MFA Delete ON                    │
    └──────────────────────────────────────────────────┘
    

    Trois copies : production, Borg local, S3 distant. Deux supports : disque local et stockage objet. Une copie off-site : le bucket S3. Une copie immuable : Object Lock compliance. Reste à valider le « 0 erreur » par les tests automatisés.

    #Choix du fournisseur S3

    • OVH Object Storage (S3 compatible) : Object Lock disponible depuis 2024, hébergement souverain (Roubaix, Strasbourg, Gravelines). Tarif autour de 7 €/To/mois en Standard, 4 €/To/mois en classe Cold.
    • Scaleway Glacier / Object Storage : Object Lock supporté, datacenters Paris/Amsterdam. ~5 €/To/mois en Standard, ~2 €/To/mois en Glacier.
    • MinIO self-hosted : si vous avez deux racks distants, c'est imbattable en coût marginal et vous gardez la souveraineté complète. Plus de complexité opérationnelle.

    Pour les charges critiques, doubler : Restic vers OVH et vers Scaleway. Le coût supplémentaire est marginal, l'isolation des fournisseurs est totale.

    #4. Scripts bash : init, backup, prune, check, restore-test

    Les scripts qui suivent sont volontairement minimalistes pour rester lisibles. Tous les secrets sont chargés depuis un fichier .env hors git, lui-même géré par un coffre (HashiCorp Vault, sops + age, ou pass).

    #Initialisation du repo Restic S3

    #!/usr/bin/env bash
    set -euo pipefail
    source /etc/backup/restic.env
    
    export RESTIC_REPOSITORY="s3:s3.gra.io.cloud.ovh.net/backup-prod-immuable"
    export RESTIC_PASSWORD_FILE=/etc/backup/restic.passwd
    
    restic init \
      --repository-version 2 \
      --compression auto
    
    echo "Repo Restic initialisé. Hash de la clé maître :"
    restic key list
    

    #Initialisation du repo Borg local en append-only

    #!/usr/bin/env bash
    set -euo pipefail
    export BORG_REPO=/srv/borg/prod
    export BORG_PASSPHRASE_FILE=/etc/backup/borg.passwd
    
    borg init --encryption=repokey-blake2 "$BORG_REPO"
    
    # Verrou append-only côté serveur SSH (dans authorized_keys du client)
    # command="borg serve --append-only --restrict-to-path /srv/borg/prod"
    

    L'option --append-only dans la directive SSH garantit qu'un client compromis ne peut que ajouter des archives. La suppression et la compaction nécessitent une connexion administrative séparée, depuis un autre poste.

    #Backup quotidien Restic avec vérification partielle

    #!/usr/bin/env bash
    set -euo pipefail
    source /etc/backup/restic.env
    
    HC_URL="https://hc-ping.com/UUID-PROJET"
    curl -fsS -m 10 --retry 3 "${HC_URL}/start" >/dev/null
    
    restic backup \
      --tag daily \
      --exclude-caches \
      --exclude-file=/etc/backup/exclude.txt \
      /etc /home /srv /var/lib/postgresql/backup
    
    # Vérification de 2 % des données réelles à chaque run
    restic check --read-data-subset=2%
    
    curl -fsS -m 10 --retry 3 "${HC_URL}" >/dev/null
    

    Le --read-data-subset=2% est l'astuce critique : sur un repo de 500 Go, vous lisez et vérifiez réellement 10 Go de blobs chiffrés par jour. En 50 jours, l'intégralité du repo est vérifiée bit à bit, sans ralentir la fenêtre de backup.

    #Backup quotidien Borg

    #!/usr/bin/env bash
    set -euo pipefail
    export BORG_REPO=ssh://[email protected]/srv/borg/prod
    export BORG_PASSPHRASE_FILE=/etc/backup/borg.passwd
    
    ARCHIVE="prod-$(hostname -s)-$(date +%Y%m%dT%H%M%S)"
    
    borg create \
      --stats --compression zstd,3 \
      --exclude-caches \
      --exclude-from /etc/backup/exclude.txt \
      "::${ARCHIVE}" \
      /etc /home /srv /var/lib/postgresql/backup
    

    #Prune et compact

    À exécuter depuis un poste dédié, pas depuis la production. C'est ce qui rend l'append-only utile : la production ne peut pas appeler forget.

    #!/usr/bin/env bash
    # /usr/local/bin/backup-prune.sh — exécuté depuis le bastion d'admin
    set -euo pipefail
    source /etc/backup/restic.env
    
    restic forget \
      --keep-daily 14 \
      --keep-weekly 8 \
      --keep-monthly 12 \
      --keep-yearly 5 \
      --prune
    
    # Borg équivalent
    borg prune --list \
      --keep-daily 14 --keep-weekly 8 \
      --keep-monthly 12 --keep-yearly 5 \
      ssh://[email protected]/srv/borg/prod
    borg compact ssh://[email protected]/srv/borg/prod
    

    #Check complet hebdomadaire

    #!/usr/bin/env bash
    set -euo pipefail
    source /etc/backup/restic.env
    
    # Vérifie structure + intégrité de tous les blobs (long mais exhaustif)
    restic check --read-data
    
    # Borg
    borg check --verify-data ssh://[email protected]/srv/borg/prod
    

    Ce check complet tourne le dimanche à 3 h, fenêtre de faible activité. Sur 500 Go, comptez 20 à 60 minutes selon le débit du backend.

    #5. Object Lock S3 : compliance vs governance

    Le verrouillage S3 connaît deux modes, et le choix engage votre tolérance au risque.

    #Mode COMPLIANCE

    Aucun utilisateur, pas même le compte root du fournisseur cloud, ne peut supprimer ou raccourcir la rétention avant son échéance. C'est le mode à choisir pour la « copie immuable » de la règle 3-2-1-1-0. Activation au niveau du bucket, puis sur chaque objet :

    aws --endpoint-url https://s3.gra.io.cloud.ovh.net s3api \
      put-object-lock-configuration \
      --bucket backup-prod-immuable \
      --object-lock-configuration '{
        "ObjectLockEnabled":"Enabled",
        "Rule":{"DefaultRetention":{"Mode":"COMPLIANCE","Days":30}}
      }'
    

    Restic écrit ensuite normalement, le bucket appose la rétention sur chaque PUT. Pendant 30 jours, ces blobs sont intouchables.

    #Mode GOVERNANCE — la fausse bonne idée

    Le mode GOVERNANCE permet à un utilisateur disposant de la permission s3:BypassGovernanceRetention de supprimer un objet verrouillé avant échéance. C'est commode pour corriger des erreurs, mais c'est précisément ce qu'un attaquant ayant compromis vos credentials IAM cherchera à faire. Concrètement :

    # Cette commande EFFACE un objet verrouillé en mode GOVERNANCE
    aws s3api delete-object \
      --bucket backup-prod \
      --key data/abc123 \
      --version-id xyz \
      --bypass-governance-retention
    

    N'utilisez jamais GOVERNANCE pour la copie immuable. Si vous avez besoin de flexibilité administrative, gardez deux buckets : un en GOVERNANCE pour les opérations courantes, un en COMPLIANCE strict pour la copie de dernier recours. La rétention en COMPLIANCE doit être au moins égale à votre fenêtre de détection d'incident — 30 jours est un plancher, 90 jours un standard sain pour les ransomwares à activation différée.

    #Versioning et MFA Delete

    Activez le versioning du bucket et MFA Delete sur le compte root. Cumulé à Object Lock COMPLIANCE, vous obtenez trois couches : suppression d'un objet ne le supprime pas (versioning), suppression d'une version est refusée (Object Lock), suppression du bucket exige un token MFA physique (MFA Delete).

    #6. Test de restauration mensuel automatisé

    Le « 0 » de 3-2-1-1-0 ne se déclare pas, il se prouve. Voici un test mensuel qui restaure un fichier témoin et vérifie son hash.

    #!/usr/bin/env bash
    # /usr/local/bin/restore-test.sh
    set -euo pipefail
    source /etc/backup/restic.env
    
    WORKDIR=$(mktemp -d /tmp/restore-test.XXXXXX)
    trap "rm -rf $WORKDIR" EXIT
    
    WITNESS=/etc/backup/witness.txt
    EXPECTED_HASH=$(sha256sum "$WITNESS" | awk '{print $1}')
    
    # On restaure le dernier snapshot, fichier témoin uniquement
    restic restore latest \
      --target "$WORKDIR" \
      --include "$WITNESS"
    
    ACTUAL_HASH=$(sha256sum "$WORKDIR$WITNESS" | awk '{print $1}')
    
    if [[ "$EXPECTED_HASH" != "$ACTUAL_HASH" ]]; then
      echo "ALERTE: hash divergent. Backup corrompu."
      curl -fsS "https://hc-ping.com/UUID-RESTORE/fail" >/dev/null
      exit 1
    fi
    
    echo "Restore test OK — hash $ACTUAL_HASH"
    curl -fsS "https://hc-ping.com/UUID-RESTORE" >/dev/null
    

    Le fichier witness.txt est généré une fois pour toutes (openssl rand -base64 1024 > /etc/backup/witness.txt), inclus dans chaque backup, et son hash est connu. Toute divergence signale une corruption silencieuse — bit rot disque, manipulation, ou bug du backend S3.

    Pour aller plus loin : restaurer un volume entier dans un conteneur isolé une fois par trimestre, monter, lancer un tree et un échantillonnage de hashes. Cela coûte 30 minutes et évite la mauvaise surprise du jour où tout brûle.

    #7. Métriques opérationnelles

    Voici les chiffres que nous observons sur un parc type PME (25 serveurs, 4 To de données utiles) :

    MétriqueCibleObservé
    RPO (perte de données max)24 h4 à 12 h selon la criticité
    RTO (temps de retour)4 h1 à 3 h (restore S3 vers nouvel hôte)
    Rétention quotidienne14 jours14
    Rétention long terme5 ans5 ans (1 par an)
    Taille repo Restic après dédupn/a1,8 To pour 4 To bruts
    Taille repo Borg après dédupn/a1,5 To pour 4 To bruts
    Coût mensuel S3 (OVH Standard)n/a~13 €/mois
    Coût mensuel S3 (Scaleway Glacier)n/a~4 €/mois
    Vérification quotidienne2 %2 % (~36 Go lus/jour)
    Test restore témoinmensuelmensuel automatisé

    À 4 €/To/mois en Glacier, une PME peut s'offrir la copie immuable conforme NIS2 pour le prix de deux cafés par mois. L'argument financier ne tient plus pour ne pas le faire.

    #8. Pièges récurrents et parades

    #Secrets en git

    Le passphrase Restic, la clé Borg, les credentials S3 ne doivent jamais être committés. Vu trop souvent : un restic.env exporté dans le dépôt Ansible « privé » qui finit sur GitHub lors d'une migration. Parades :

    • secrets dans HashiCorp Vault, sops + age, ou pass ;
    • pre-commit avec gitleaks ou trufflehog qui bloque le commit ;
    • rotation tous les 6 mois minimum, immédiate si suspicion.

    #Rotation des accès

    Les credentials S3 doivent être en write-only depuis la production (politique IAM s3:PutObject uniquement, pas de Delete, pas de List). La lecture et le delete sont réservés à un compte d'admin séparé, manipulé depuis un bastion. Cela rend impossible l'exfiltration des sauvegardes par un client compromis.

    #Monitoring Wazuh + Healthchecks.io

    Trois sondes minimum :

    • Healthchecks.io : ping de fin de chaque job. Pas de ping = alerte sous 1 h. Gratuit jusqu'à 20 checks.
    • Wazuh : règle custom qui scanne le journal /var/log/backup/restic.log et remonte toute occurrence de error, fatal, Load(<data/. Corrélé aux autres événements de sécurité du SIEM, cela transforme une corruption silencieuse en alerte qualifiée.
    • Métriques Prometheus : exporter custom qui publie la durée du dernier backup, la taille du repo, le nombre de snapshots. Alerte si la durée double ou si le nombre de snapshots stagne.

    #L'erreur du repo unique

    Sauvegarder vingt serveurs dans un seul repo Restic est tentant pour la déduplication globale. C'est aussi un point de défaillance unique : un passphrase compromis ouvre tout. Notre règle : un repo par périmètre de sécurité (production, dev, postes admin), passphrases distincts.

    #9. Conformité ISO 27001 et NIS2

    La règle 3-2-1-1-0 implémentée comme décrit ci-dessus couvre directement les contrôles suivants :

    • A.8.13 Sauvegarde des informations : trois copies, deux supports, un site distant, vérification automatique.
    • A.8.14 Redondance des moyens de traitement : doublement Restic + Borg, doublement OVH + Scaleway possible.
    • A.5.30 Disponibilité TIC pour la continuité d'activité : RTO de 1 à 3 h documenté et testé mensuellement.
    • A.8.16 Surveillance des activités : logs centralisés Wazuh, alertes Healthchecks, métriques Prometheus.

    Côté NIS2, l'article 21 de la directive impose des « politiques et procédures relatives à la sauvegarde, à la reprise après sinistre et à la gestion des crises ». L'application stricte de 3-2-1-1-0 avec test de restauration documenté constitue la preuve attendue lors d'un contrôle ANSSI ou d'un audit assureur cyber.

    Pour les entités importantes ou essentielles au sens NIS2, ajoutez :

    • une procédure formelle de restauration (runbook signé, version courante affichée) ;
    • un exercice annuel de simulation incident (chiffrement supposé de la production, restauration complète depuis S3 immuable, chronométrage) ;
    • une revue trimestrielle des journaux de backup et des écarts de rétention.

    Ces éléments constituent l'ossature d'un PCA / PRA technique défendable. Ils s'intègrent dans une démarche ISO 27001 plus large, mais peuvent être déployés isolément si l'urgence est uniquement la résilience anti-ransomware.

    #En résumé

    La règle 3-2-1-1-0 n'est pas une coquetterie d'architecte : c'est le minimum vital face aux menaces de 2026. Elle se déploie en quelques heures avec des outils libres et matures, pour un coût marginal de quelques euros par To et par mois. Les deux clés de voûte sont l'immuabilité réelle (Object Lock COMPLIANCE, jamais GOVERNANCE pour la copie de dernier recours) et le test de restauration automatisé (hash témoin mensuel, exercice complet trimestriel).

    Tout le reste — choix du fournisseur, niveau de compression, fréquence du --read-data-subset — relève de l'optimisation. Ne commencez pas par là. Commencez par garantir que demain matin, si le serveur de production est chiffré, vous avez une copie qu'aucun attaquant ne peut atteindre, et que vous savez la restaurer.

    On déploie ces stratégies de backup chez nos clients infogérance ISO-compliant. Voir l'infogérance ISO-compliant →

    Équipe M-KIS

    Cet article vous parle ?

    On accompagne PME, ESN et éditeurs SaaS dans leur conformité ISO 27001 / NIS2 — Lead Auditor certifié, tarifs publics, 100 % open source.

    Auteur : Équipe M-KIS