Restic : Dormez tranquille, vos serveurs sont sauvegardés

janv. 12, 2026·
Benjamin Rabiller
Benjamin Rabiller
· 5 min. de lecture
restic

Dans mon environnement de production, même s’il s’agit d’un usage personnel, je considère que la sauvegarde de mes données est primordiale. Tout perdre à la suite d’un incident serait, pour moi, un immense gaspillage de temps personnel précieux. Dans cet article, je vous partage la manière dont j’orchestre mes sauvegardes depuis mon serveur principal (OVH) vers un second serveur de stockage hébérgé chez moi en utilisant Restic.

Pourquoi j’ai choisi Restic ?

Restic est pour moi l’outil idéal : il est moderne, simple, rapide, propose le chiffrement par défaut et gère nativement la déduplication. C’est exactement ce qu’il me fallait pour mon infrastructure self-hosted afin d’optimiser l’espace disque tout en garantissant un bon niveau de sécurité.


1. Ma stratégie de sélection des données

Attention

Ne sauvegardez pas l’ensemble du contenu de /var/lib/docker.

Voici ce que je sauvegarde :

  • Docker-compose & Configs : Tout ce qui définit mon infra (.yml, .env, fichiers de conf nginx/traefik).
  • Dumps de base de données : Mes exports SQL compressés, effectués via le service databasus.
  • Data Volumes : Mes fichiers statiques (images, documents, etc.).
  • Home : Mes configurations utilisateurs (/home/user).

Mon automatisation des Dumps SQL avec Databasus

Pour garantir que mes bases de données sont sauvegardées de manière cohérente, j’utilise Databasus. C’est un outil conteneurisé que j’ai intégré pour créer des dumps de mes bases (PostgreSQL, MySQL, etc.) à intervalles réguliers sans scripts “complexes” qu’il faudrait maintenir.

Je le configure simplement pour qu’il dépose les dumps dans un volume partagé, que Restic récupère ensuite.

Voici ma configuration dans mon compose.yml pour databasus :

services:
  databasus:
    container_name: databasus
    image: databasus/databasus:latest
    volumes:
      - ./databasus-data:/databasus-data # C'est ici que je stocke mes dumps
    restart: unless-stopped

2. Comment je prépare mes environnements

Ma cible (Serveur de stockage)

Je m’assure que mon répertoire de stockage est prêt et accessible via SSH :

# Sur ma machine de destination
sudo mkdir -p /var/restic-backup
sudo chown <SSH_USER>:<SSH_USER> /var/restic-backup

Ma source (Mon serveur OVH)

Je sécurise le mot de passe de mon dépôt dans un fichier aux permissions restreintes :

sudo mkdir -p /etc/restic
sudo vim /etc/restic/password
sudo chmod 400 /etc/restic/password

J’initialise ensuite mon dépôt (une seule fois) :

restic -r sftp:<SSH_USER>@<SERVER-IP>:/var/restic-backup \
  --password-file /etc/restic/password init

3. Mon script d’orchestration : run-backup.sh

J’ai conçu ce script pour réaliser trois actions clés : le backup des fichiers, l’application de ma politique de rétention, et l’envoi d’alertes en cas d’échec. Les alertes sont directement envoyées à alertmanager. Alertmanager est configuré pour m’envoyer des notifications PUSH.

#!/bin/bash
set -e
set -o pipefail

# --- MA CONFIGURATION ---
REPO="sftp:<SSH_USER>@<SERVER-IP>:/srv/restic-backup"
PASS_FILE="/etc/restic/password"
BACKUP_PATHS="/home /opt/docker /var/backups/db-dumps" 
RETENTION_DAYS="7"
ALERTMANAGER_URL="http://<ALERTMANAGER_IP>:9093/api/v2/alerts"

# Ma fonction de notification Alertmanager
notify_alertmanager() {
    local status=$1
    local message=$2
    local severity="info"
    [ "$status" == "failure" ] && severity="critical"

    curl -s -X POST "$ALERTMANAGER_URL" \
        -H "Content-Type: application/json" \
        -d "[{
            \"labels\": { 
                \"alertname\": \"ResticBackupStatus\",
                \"severity\": \"$severity\",
                \"instance\": \"bracloud-ovh\",
                \"job\": \"restic-nightly\"
            }, 
            \"annotations\": {
                \"summary\": \"Backup $status\",
                \"description\": \"$message\"
            }
        }]" || true
}

echo "=== Démarrage de mon Backup : $(date) ==="

# 1. Mon exécution du Backup Restic
echo ">>> Restic Backup..."
if restic -r "$REPO" --password-file "$PASS_FILE" backup $BACKUP_PATHS \
    --exclude-file /etc/restic/excludes.txt \
    --tag nightly; then
    echo "Backup Success."
else
    echo "Backup Failed."
    notify_alertmanager "failure" "Restic backup command failed on bracloud-ovh."
    exit 1
fi

# 2. Ma politique de rétention (7 jours)
echo ">>> Restic Forget & Prune..."
restic -r "$REPO" --password-file "$PASS_FILE" forget \
    --keep-daily $RETENTION_DAYS \
    --prune

# 3. Ma vérification d'intégrité légère
restic -r "$REPO" --password-file "$PASS_FILE" check --read-data-subset=5%

echo "=== Mon Backup est terminé avec succès : $(date) ==="

4. Mon automatisation avec Systemd

J’ai choisi d’abandonner la Crontab au profit des Systemd Timers. Cela me donne une bien meilleure visibilité dans journalctl.

Mon Service (/etc/systemd/system/restic-backup.service)

[Unit]
Description=Mon Service de Backup Restic
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/run-backup.sh
StandardOutput=journal

Mon Timer (/etc/systemd/system/restic-backup.timer)

Je l’ai planifié pour qu’il se déclenche tous les jours à 3h du matin :

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

[Install]
WantedBy=timers.target

5. Ma vérification d’intégrité hebdomadaire (run-check.sh)

Pour moi, un backup n’est fiable que si je suis certain de pouvoir le restaurer. En plus de la vérification légère quotidienne, j’ai automatisé une vérification complète chaque dimanche à 5h du matin. C’est une opération gourmande en ressources, d’où le choix de ce créneau.

J’utilise un script similaire (run-check.sh) et un duo Service/Timer dédié (restic-check.service / restic-check.timer) pour m’assurer que mes données stockées sur le second serveur ne sont pas corrompues.


6. Mes tests de restauration

Je me l’impose comme règle : tester régulièrement la restauration. Voici les commandes que j’utilise pour m’assurer que tout fonctionne :

  1. Lister mes snapshots : restic snapshots
  2. Vérifier l’intégrité globale : restic check
  3. Restaurer un fichier test :
restic -r <REPO> restore latest --target /tmp/restore-test --include /home/user/important.txt

7. Schéma d’architecture

graph TB subgraph "Serveur Source (OVH)" direction TB A[Systemd Timer / Service] --> B[run-backup.sh] subgraph "Données" C[(Bases de données)] -- "Dump" --> D[Databasus Container] D -- "Export SQL" --> E["/var/backups/db-dumps"] F["/home & /data"] end B --> |"Lecture"| E B --> |"Lecture"| F B --> |"Lecture"| G["/etc/restic/password"] end subgraph "Serveur de Stockage Home" H["/var/restic-backup"] end subgraph "Monitoring & Alerting" I[Alertmanager] J[Pushover / Notifications] end %% Flux de données et notifications B -- "SFTP (Chiffré & Dédupliqué)" --> H B -- "API POST (en cas d'échec)" --> I I --> J %% Styles style A fill:#f9f,stroke:#333,stroke-width:2px style H fill:#bbf,stroke:#333,stroke-width:2px style I fill:#ff9,stroke:#333,stroke-width:2px

Conclusion

En combinant Restic, Systemd et mes Dumps SQL, j’ai réussi à mettre en place une solution de sauvegarde que je considère fiable, tout en restant gratuite et sous mon contrôle total. Mon dernier conseil : n’attendez pas une catastrophe pour tester votre procédure de restauration !

Benjamin Rabiller
Auteurs
DevOps/Cloud Architect

Actuellement ingénieur DevOps/Architecte Cloud, j’étais initialement interessé par l’administration système et grâce aux entreprises dans lesquelles j’ai pu travailler Oxalide et maintenant Claranet j’ai eu la chance de découvrir l’univers du Cloud et de l’automatisation.

Je me suis décidé a publier ce blog pour vous faire partager ma passion mais également pour enrichir avec modestie tout ce que l’on peut trouver sur internet. Bonne lecture !