Sélectionner une page
ShareX, mon nouvel outil de capture d’écran

ShareX, mon nouvel outil de capture d’écran

J’ai perdu l’outil de capture d’écran que j’utilisais jusqu’ici, pratique au quotidien. Je me suis tournée vers ShareX, un logiciel gratuit et open source pour Windows, riche en fonctionnalités.

Pourquoi ShareX

ShareX permet de capturer une zone d’écran, de l’annoter directement, puis de la copier ou de l’enregistrer. Il propose beaucoup plus de possibilités qu’un simple outil de capture basique, notamment un éditeur d’annotation complet. Voir toutes les possibilités sur le site : https://getsharex.com/

Le raccourci de capture

J’utilise le raccourci prédéfini Ctrl + Impr écran pour lancer une capture de zone.

Configurer les tâches après la capture

Par défaut, ShareX propose plusieurs actions automatiques une fois la capture réalisée. Dans le menu « Tâches après la capture », seules « Copier l’image dans le presse-papier » et « Enregistrer l’image comme fichier » étaient cochées.

J’ai ajouté l’option « Afficher le menu des tâches rapides ». Elle ouvre l’éditeur d’annotation juste après la capture, avant toute copie ou sauvegarde. Cela permet d’annoter l’image immédiatement, ce qui est très utile pour expliquer une manipulation ou pointer un élément précis à l’écran.

Les outils d’annotation

L’éditeur intégré propose de nombreux outils de dessin. Sur l’exemple ci-dessous, on retrouve :

  1. Flèche, pour pointer un élément précis
  2. Forme, ici un rectangle, pour encadrer une zone
  3. Trait libre, pour dessiner à main levée
  4. Surligner, pour mettre en évidence du texte ou une zone
  5. Pixeliser une zone, combiné ici avec une boîte de texte et un émoticône, pour flouter une information tout en la commentant

En résumé

ShareX est un outil complet, gratuit, qui va bien au-delà de la simple capture d’écran. L’ajout du menu de tâches rapides après la capture m’a fait gagner du confort : je peux annoter à chaud, sans étape supplémentaire.

Automatiser des sauvegardes cloud à cloud avec rclone

Automatiser des sauvegardes cloud à cloud avec rclone

Tu synchronises déjà tes fichiers en temps réel entre plusieurs appareils, mais une synchronisation n’est pas une sauvegarde : une erreur ou une suppression accidentelle se propage aussi vite que le reste. Voici comment mettre en place une sauvegarde périodique automatisée d’un service cloud vers un autre, avec un script simple et fiable.

Cet article suppose que rclone est déjà installé sur ta machine. Si ce n’est pas encore le cas, la procédure d’installation est détaillée dans cet article sur la sauvegarde automatique de containers Docker.

Étape 1 : configurer un remote vers une source Nextcloud

rclone config

Voici la séquence de réponse dans l’assistant interactif de rclone :

InviteRéponse
n) New remoten
name>nextcloud
Storage> (liste des types)Cherche et sélectionne le numéro correspondant à webdav
url>https://cloud.tondomaine.com/remote.php/dav/files/USER
vendor>Sélectionne nextcloud dans la liste proposée
user>USER
y) Yes type in my own passwordy, puis saisis le mot de passe Nextcloud (il sera masqué et stocké de façon obscurcie dans rclone.conf, pas en clair)
bearer_token>Laisse vide, valide
Edit advanced config?n
Keep this remote?y
q) Quit configq

Pour vérifier que c’est ok :

rclone lsd nextcloud:OBSIDIAN-sync

Tu dois voir le contenu de ton dossier OBSIDIAN-sync dans Nextcloud.

Étape 2 : configurer un remote vers la destination, limité à un dossier particulier

Par prudence, plutôt que de donner à rclone un accès à l’intégralité de ton espace de stockage de destination, il est possible de limiter un remote à un seul dossier, appelons le « folder », grâce à son identifiant unique.

Récupérer l’identifiant du dossier

  1. Ouvre le dossier cible dans Google Drive, depuis un navigateur
  2. Copie la chaîne de caractères qui suit folders/ dans l’URL, par exemple :
https://drive.google.com/drive/folders/USER_FOLDER_ID

Créer le remote limité à ce dossier

rclone config

Choisis de créer un nouveau remote « gdrive-scope », sélectionne drive comme type de stockage, laisse les champs client_id et client_secret vides (valeurs par défaut), puis, à l’étape des réglages avancés (réponds y à la question Edit advanced config?), renseigne le champ root_folder_id avec l’identifiant récupéré à l’étape précédente.

Autoriser l’accès sans navigateur local (connexion SSH)

Si tu configures ce remote depuis une session SSH sans interface graphique, l’assistant propose une autorisation manuelle : il faut alors lancer rclone authorize "drive" sur une machine disposant d’un navigateur, se connecter avec le compte Google concerné, puis copier le jeton généré dans le terminal SSH en attente.

Vérifier l’accès

bash

rclone lsd gdrive-scope:

Cette commande devrait lister directement le contenu du dossier ciblé, sans que tu aies besoin de préciser de chemin.

Étape 3 : le script de sauvegarde

Le script copie le contenu source dans un dossier temporaire, le compresse en une seule archive, puis envoie cette archive vers la destination. Il prend en paramètre le nom du sous-dossier à sauvegarder, ce qui permet de le réutiliser pour plusieurs contenus différents avec une seule et même logique. En cas de besoin, l’archive se décompresse normalement pour retrouver les fichiers d’origine.

Attention, il faudra que tu modifies SOURCE_REMOTE (nextcloud:chemin-source/) et DEST_REMOTE (gdrive-scope:destination/) et tu remplaces USER par ton nom d’utilisateur dans le mini PC

#!/bin/bash
# Sauvegarde d'un dossier source (cloud A) vers un dossier destination (cloud B)
# Usage : backup-cloud-to-cloud.sh <nom-du-dossier>
# Exemple : backup-cloud-to-cloud.sh mon-dossier

set -e

FOLDER_NAME="$1"

if [ -z "$FOLDER_NAME" ]; then
  echo "Erreur : nom du dossier manquant. Usage : backup-cloud-to-cloud.sh <nom-du-dossier>"
  exit 1
fi

TIMESTAMP=$(date +%Y%m%d_%H%M%S)
TMP_BASE="/home/USER/tmp/cloud-backup"
TMP_DIR="${TMP_BASE}/${FOLDER_NAME}"
ARCHIVE_NAME="${FOLDER_NAME}_${TIMESTAMP}.tar.gz"
ARCHIVE_PATH="${TMP_BASE}/${ARCHIVE_NAME}"
SOURCE_REMOTE="nextcloud:chemin-source/${FOLDER_NAME}"
DEST_REMOTE="gdrive-scope:destination/${FOLDER_NAME}/"

echo "=== Sauvegarde ${FOLDER_NAME} - $(date) ==="

# Nettoyage préalable au cas où une exécution précédente aurait échoué
rm -rf "$TMP_DIR"
mkdir -p "$TMP_DIR"

# Copie depuis le cloud source vers un dossier temporaire local
echo "Copie depuis la source..."
rclone copy "$SOURCE_REMOTE" "$TMP_DIR" --transfers 4 --checkers 8 --fast-list

# Compression en une seule archive
echo "Compression..."
tar -czf "$ARCHIVE_PATH" -C "$TMP_BASE" "$FOLDER_NAME"

# Upload de l'archive unique vers la destination
echo "Upload vers la destination..."
rclone copy "$ARCHIVE_PATH" "$DEST_REMOTE" --transfers 1

# Nettoyage
rm -rf "$TMP_DIR"
rm -f "$ARCHIVE_PATH"

echo "=== Terminé - $(date) ==="

Rends le script exécutable :

bash

chmod +x /home/USER/scripts/backup-cloud-to-cloud.sh

Un point d’attention sur sudo

Si ce script tourne sur une machine où tu utilises sudo pour d’autres tâches, ne l’utilise jamais avec rclone. La commande sudo rclone réécrit le fichier de configuration rclone.conf avec les droits root lors du renouvellement d’un jeton d’accès, ce qui casse ensuite l’utilisation normale de rclone en tant qu’utilisateur courant. Seule une éventuelle commande tar nécessitant des droits élevés (rare dans ce cas précis, puisque le script travaille dans le dossier personnel de l’utilisateur) justifierait sudo, jamais rclone lui-même.

Étape 4 : planifier avec cron

Pour une sauvegarde hebdomadaire, chaque dimanche à 4h du matin :

bash

crontab -e

Ajoute la ligne suivante :

0 4 * * 0 /home/USER/scripts/backup-cloud-to-cloud.sh mon-dossier >> /home/USER/scripts/logs/cloud-backup.log 2>&1

Pour un contenu moins critique, une fréquence mensuelle (le 1er de chaque mois) suffit :

0 4 1 * * /home/USER/scripts/backup-cloud-to-cloud.sh autre-dossier >> /home/USER/scripts/logs/cloud-backup.log 2>&1

La fréquence gagne à être adaptée à la criticité du contenu : un document en cours d’écriture active justifie un rythme hebdomadaire, un dossier de veille alimenté plus occasionnellement peut se contenter d’un rythme mensuel.

Assure-toi que le dossier de logs existe avant la première exécution planifiée :

bash

mkdir -p /home/USER/scripts/logs

Étape 5 : tester avant de laisser cron s’en charger

Un test manuel permet de vérifier le bon fonctionnement avant de dépendre entièrement de la planification automatique :

bash

/home/USER/scripts/backup-cloud-to-cloud.sh mon-dossier

Vérifie ensuite, dans l’interface web du service de destination, que l’archive est bien apparue au bon endroit, avec un nom cohérent incluant l’horodatage.

Ce que ce schéma permet au-delà de ce cas précis

Ce principe (remote limité à un dossier, compression en une seule archive, upload unique, planification cron) se réutilise pour n’importe quelle paire de services cloud supportés par rclone, pas seulement Nextcloud vers Google Drive. C’est un schéma générique de sauvegarde périodique, applicable à d’autres contenus que des notes ou des documents.

Pour aller plus loin

Si ce projet t’intéresse, deux articles complémentaires détaillent la suite :

Synchroniser Obsidian entre PC et Android avec Nextcloud

Synchroniser Obsidian entre PC et Android avec Nextcloud

Tu veux consulter et modifier ton coffre Obsidian aussi bien sur ton ordinateur que sur ton téléphone, sans payer d’abonnement ni confier tes notes à un serveur tiers inconnu. Voici comment construire cette synchronisation avec un Nextcloud auto-hébergé, en évitant les pièges que j’ai moi-même rencontrés en cours de route.

Le contexte : un coffre de veille, accessible partout

Ce projet concerne un coffre Obsidian dédié à la veille professionnelle : des liens, des extraits, des notes de lecture, à consulter et enrichir aussi bien devant ton ordinateur que dans les transports avec ton téléphone. Contrairement à d’autres coffres qui restent sur PC, celui-ci a une contrainte supplémentaire : l’accès mobile est indispensable.

L’architecture retenue

Le principe : un seul mécanisme de synchronisation actif par appareil, jamais deux en parallèle sur le même dossier. C’est une règle que j’ai apprise à mes dépens en laissant tourner par erreur une synchronisation Google Drive et le plugin Remotely Save simultanément sur le même coffre, un scénario à risque de doublons et de conflits de fichiers.

AppareilMécanisme
PC (Windows)Client officiel Nextcloud, synchronisation au niveau du système de fichiers
AndroidObsidian + plugin Remotely Save, connexion WebDAV directe à Nextcloud

Sur PC, Obsidian n’ouvre qu’un dossier local classique, sans aucun plugin de synchronisation. Sur mobile, Remotely Save devient nécessaire parce qu’Android ne permet pas à Obsidian d’accéder en arrière-plan à un dossier synchronisé par une autre application.

Étape 1 : installer Nextcloud Hub chez un hébergeur

La plupart des hébergeurs web proposent un installeur applicatif en un clic pour Nextcloud. Voici la démarche générale (les noms d’écran peuvent varier légèrement selon l’hébergeur) :

  1. Dans le panneau d’administration de ton hébergement, ajoute un nouveau site
  2. Choisis un sous-domaine dédié, par exemple cloud.tondomaine.com
  3. Si ton nom de domaine est géré ailleurs que chez ton hébergeur (registrar différent), crée les enregistrements DNS nécessaires (type A et AAAA) pointant vers l’adresse fournie par l’hébergeur
  4. Dans le catalogue d’applications, sélectionne Nextcloud Hub
  5. Renseigne un nom d’utilisateur et un mot de passe administrateur robustes, à conserver dans ton gestionnaire de mots de passe
  6. Laisse la mise à jour automatique sur « mises à jour mineures et sécurité », un bon compromis entre stabilité et protection
  7. Une fois l’installation terminée, active un certificat HTTPS gratuit (Let’s Encrypt) pour sécuriser les échanges

Choisir un nom de sous-domaine discret

Plutôt qu’un nom explicite comme nextcloud.tondomaine.com, qui annonce directement la nature du service à quiconque le croise, un nom neutre (cloud., espace., docs.) apporte un léger renfort de sécurité par obscurité, en complément de l’authentification.

Préparer l’arborescence de dossiers

Avant de connecter quoi que ce soit, crée une arborescence dédiée dans Nextcloud, par exemple un dossier parent OBSIDIAN-sync contenant un sous-dossier par coffre :

/OBSIDIAN-sync/veille-2026

Ça garde tes coffres regroupés et lisibles, même si tu en ajoutes d’autres plus tard.

Étape 2 : connecter le PC via le client Nextcloud officiel

Télécharge le client officiel Nextcloud pour Windows depuis le site nextcloud.com.

À la connexion, un point de vigilance : le champ d’adresse serveur attend uniquement la racine du site, sans aucun chemin après :

https://cloud.tondomaine.com

Une fois connecté, configure la synchronisation du dossier OBSIDIAN-sync vers un dossier local dédié, par exemple D:\NextCloud\OBSIDIAN-sync. Le sous-dossier veille-2026 apparaîtra automatiquement dedans une fois la synchronisation active.

Dans Obsidian, choisis « Ouvrir un dossier existant », et pointe vers ce sous-dossier local. Répète l’opération sur chaque PC que tu utilises.

Étape 3 : connecter le téléphone avec Remotely Save

Sur Android, la logique est différente : Obsidian ne peut pas s’appuyer sur un dossier synchronisé en arrière-plan par une autre application, il faut donc un plugin de synchronisation intégré.

  1. Installe Obsidian depuis le Play Store, crée un coffre vide
  2. Va dans Paramètres > Plugins communautaires, recherche et installe Remotely Save, puis active-le
  3. Dans les réglages du plugin, choisis la méthode WebDAV

Trouver l’adresse WebDAV

L’adresse WebDAV de Nextcloud suit ce format, avec ton identifiant de connexion à la fin (pas ton adresse e-mail) :

https://cloud.tondomaine.com/remote.php/dav/files/USER

Comme ce champ ne gère qu’un seul niveau de dossier via le réglage dédié (voir plus bas), le plus simple est d’inclure le dossier parent directement dans l’adresse serveur :

https://cloud.tondomaine.com/remote.php/dav/files/USER/OBSIDIAN-sync

Renseigne ensuite ton nom d’utilisateur et ton mot de passe Nextcloud. Si une erreur 403 apparaît lors du test de connexion, deux causes fréquentes :

  • L’adresse serveur ne contient pas ton identifiant, une erreur facile à faire en copiant une adresse générique
  • Une double authentification est activée sur ton compte Nextcloud, auquel cas il faut générer un mot de passe d’application dédié plutôt que d’utiliser ton mot de passe principal

Définir le dossier distant précis

Une fois la connexion établie, utilise le champ « Change The Remote Base Directory » pour préciser le sous-dossier exact du coffre, par exemple :

veille-2026

Ce champ n’accepte qu’un nom simple, pas un chemin avec plusieurs niveaux (le / y est refusé), d’où l’astuce d’inclure le dossier parent directement dans l’adresse serveur, comme montré plus haut.

Les réserves de sécurité à connaître sur Remotely Save

Même si Remotely Save est un choix plus rassurant que le plugin écarté au départ (pas de serveur intermédiaire propriétaire pour la connexion WebDAV, tes identifiants vont directement à ton propre Nextcloud), il mérite deux réserves.

Pas de chiffrement de bout en bout par défaut. Sans mot de passe de chiffrement configuré dans le plugin, tes notes sont stockées en clair sur le serveur Nextcloud, lisibles par quiconque y aurait un accès (administrateur du serveur, faille de sécurité éventuelle). Le protocole HTTPS protège le trajet des données, pas leur stockage.

Gestion des conflits limitée en version gratuite. Sur cette version du plugin, les seules options gratuites de résolution de conflits sont « la version la plus récente écrase l’autre » ou « la version la plus volumineuse écrase l’autre ». Il n’existe pas d’option gratuite pour créer automatiquement un fichier de conflit séparé et comparer les deux versions, cette fonctionnalité relève de l’offre payante.

Ce que ça signifie concrètement

Pour un coffre de veille, avec des liens et des notes de lecture sans caractère confidentiel, ces limites sont acceptables : la perte occasionnelle d’une modification récente en cas de conflit reste un inconvénient mineur, largement compensé par le filet de sécurité de la fonction native « Historique des fichiers » (voir plus bas).

Pour un coffre contenant des documents de travail sensibles, ces mêmes limites deviennent plus problématiques. Dans ce cas, active le chiffrement de bout en bout dans les réglages du plugin (champ « Encryption Password »), avec pour conséquence que le contenu synchronisé ne sera plus lisible directement depuis l’interface web de Nextcloud, ni exploitable tel quel par un script ou une IA sans déchiffrement préalable.

Gérer les conflits et les pertes accidentelles

En complément de Remotely Save, active la fonction native d’Obsidian, indépendante de tout cloud :

  1. Va dans Paramètres > Modules principaux
  2. Active « Récupération de fichier » (File Recovery)
  3. Réduis l’intervalle de capture à environ 2 minutes

En cas de fausse manipulation ou d’écrasement par la synchronisation, retourne dans Paramètres > Historique des fichiers > Afficher pour restaurer une version locale enregistrée par Obsidian dans son propre cache, indépendamment de ce qui s’est passé côté serveur.

Pour aller plus loin

Si ce projet t’intéresse, deux articles complémentaires détaillent la suite :

  • La mise en place d’une sauvegarde périodique automatisée avec rclone, pour ne pas dépendre uniquement de la synchronisation en temps réel : Automatiser des sauvegardes cloud à cloud avec rclone
  • L’organisation d’un coffre Obsidian dédié à l’écriture longue, avec Templater, Dataview et Longform
Google Drive sur PC : comment synchroniser (sans tout mélanger)

Google Drive sur PC : comment synchroniser (sans tout mélanger)

L’application Google Drive pour ordinateur propose deux mécanismes de synchronisation complètement différents, logés dans le même menu. Ne pas les distinguer, c’est la garantie de ne plus rien comprendre à ce qui se synchronise, où, et pourquoi. Voici comment les différencier et les utiliser correctement.

Deux outils dans une seule application

Quand tu ouvres les préférences de Google Drive, la colonne de gauche affiche deux sections qui se ressemblent, mais qui n’ont rien à voir l’une avec l’autre.

A. « Google Drive / Mon Drive » (le mode cloud natif)

C’est l’espace central. Tout ce qui réside sur ton compte Google Web est répercuté sur ton ordinateur sous forme d’un dossier virtuel (par exemple D:\Google Drive\Mon Drive).

Usage idéal : synchroniser tes fichiers de travail entre plusieurs ordinateurs (PC fixe et PC portable).

Fonctionnement : tout ajout ou modification dans ce dossier est instantanément répercuté dans le cloud et sur tes autres appareils.

B. « Mon ordinateur » (le mode sauvegarde locale)

Cette option s’adresse à ceux qui veulent sauvegarder des dossiers existants sans changer leur arborescence Windows (par exemple le dossier Documents ou Images de Windows).

Usage idéal : créer une sauvegarde en arrière-plan d’un répertoire local spécifique.

Dans le cloud, ces dossiers n’apparaissent pas dans « Mon Drive », mais sous un onglet séparé nommé « Ordinateurs » sur le web.

L’erreur à éviter

N’utilise jamais la fonction « Ajouter un dossier » (dans la section Mon ordinateur) sur un dossier qui se trouve déjà dans ton dossier Mon Drive. Tu demanderais à Google Drive de synchroniser deux fois le même emplacement via deux circuits différents. Résultat : les deux mécanismes se marchent dessus, plus rien ne se synchronise comme prévu, et tu perds toute visibilité sur ce qui se passe réellement.

Streaming vs miroir : économiser l’espace de son disque dur

Dans la section Google Drive des préférences, tu dois choisir comment les fichiers de Mon Drive sont stockés physiquement sur ta machine.

ModeMise en cache et stockageAvantages et inconvénients
Accès en ligne (streaming) – recommandéLes fichiers restent hébergés sur le cloud. Seuls des raccourcis virtuels sont visibles dans l’Explorateur Windows.+ Économise l’espace disque / SSD. + Ouverture transparente des fichiers à la demande. – Nécessite une connexion Internet par défaut.
Dupliquer les fichiers (miroir)Tous les fichiers du cloud sont téléchargés et doublés en local sur ton disque dur.+ Tous les fichiers sont accessibles hors ligne. – Saturation rapide des disques durs / SSD de petite taille.

Guide pratique : rendre des dossiers disponibles hors ligne

Le mode streaming est le plus optimisé. Si tu pars en déplacement sans connexion Internet, voici comment préparer tes dossiers :

  1. Ouvre l’Explorateur de fichiers Windows et navigue dans ton dossier Mon Drive.
  2. Fais un clic droit sur le dossier ou le fichier dont tu auras besoin.
  3. Sélectionne « Accès hors connexion » puis « Disponible hors connexion ».
  4. L’application télécharge une copie locale sécurisée.

Une pastille verte avec une coche confirme la disponibilité hors ligne, tandis qu’une icône de nuage bleu indique un fichier stocké uniquement en ligne.

Dépannage : résoudre les blocages et icônes rouges

Si la synchronisation se bloque ou si un dossier affiche une croix rouge :

  1. Fermer les applications : un fichier ouvert dans Word, Excel ou un lecteur PDF verrouille la synchronisation. Ferme l’application concernée.
  2. Vérifier les caractères spéciaux : évite les caractères interdits par Windows dans les noms de fichiers (/ \ ? * : " < > |).
  3. Réinitialisation propre : si les icônes de statut ne s’affichent plus, va dans Préférences de l’application > Paramètres > Déconnecter le compte, puis reconnecte-toi. Cela re-scanne la base de données sans retélécharger tes données déjà présentes.

Checklist récapitulative

  • Un seul point d’entrée : travaille exclusivement dans le dossier Mon Drive.
  • Espace disque : active le mode streaming pour ne pas surcharger ton SSD.
  • Déplacements : utilise le clic droit « Disponible hors connexion » de manière ciblée.
  • Sécurité : laisse la section « Mon ordinateur » vide, sauf besoin explicite de sauvegarde locale.

Sauvegarde Docker vers Google Drive avec rclone

Sauvegarde Docker vers Google Drive avec rclone

Une sauvegarde nocturne qui tournait en quelques minutes s’est mise à durer plus de 7 heures, avec des erreurs de quota Google. Voici le diagnostic et la correction : remplacer des milliers de petits fichiers par une seule archive compressée.

Cet article s’inscrit dans les séries projets Ubuntu et Domotique Home Assistant, et fait suite à l’article Sauvegarder ses containers Docker automatiquement avec rclone.

Le symptôme

La sauvegarde nocturne d’un dossier Docker (une dizaine de containers, environ 1,9 Go au total) copiait chaque nuit l’intégralité du dossier vers Google Drive, avec une rétention GFS (Grand-Père / Père / Fils, une stratégie classique qui conserve des sauvegardes quotidiennes, hebdomadaires, mensuelles et annuelles). Cette sauvegarde aurait dû se faire en quelques minutes. Un jour, elle a mis plus de 7 heures à se terminer, sans plantage visible, juste un processus qui semblait ne plus avancer.

Diagnostiquer un dépassement de quota API

Premier réflexe : regarder le fichier de log. Il s’arrêtait net, sans nouvelle ligne depuis des heures. Le processus rclone tournait pourtant toujours (ps aux | grep rclone le confirmait), mais avec un temps CPU (temps de calcul processeur réellement utilisé) dérisoire par rapport à sa durée de vie, signe qu’il passait le plus clair de son temps à attendre.

Relancer une simple commande de lecture a permis de voir l’erreur clairement :

rclone size gdrive:/daily
googleapi: Error 403: Quota exceeded for quota metric 'Queries' and limit 'Queries per minute' of service 'drive.googleapis.com'

Le quota en cause n’est pas l’espace de stockage, mais le nombre de requêtes envoyées à l’API (interface de programmation, le canal par lequel un logiciel comme rclone communique avec les serveurs de Google) Google Drive en une minute. Chaque fichier transféré, vérifié ou supprimé individuellement génère plusieurs requêtes. Un compte pour voir venir le problème :

find /home/USER/docker -type f | wc -l

Résultat : plus de 10 000 fichiers, dans un seul dossier quotidien. Multiplié par une rétention de 7 jours (plus les copies hebdomadaires, mensuelles et annuelles), le script devait gérer chaque nuit plusieurs dizaines de milliers d’opérations individuelles sur l’API. Ce n’est pas le volume de données (1,9 Go, rien d’énorme) qui posait problème, c’est le nombre d’objets.

L’effet de bord du sudo sur la configuration rclone

Un deuxième problème s’est ajouté en cours de route : le fichier de configuration rclone (rclone.conf) changeait régulièrement de propriétaire, passant de l’utilisateur normal à root, ce qui bloquait toute utilisation manuelle de rclone en dehors du script.

La cause : le script utilisait sudo rclone pour contourner des permissions sur certains fichiers Docker appartenant à root. Mais lancer rclone entièrement en root a un effet de bord : le jeton d’accès Google expire régulièrement (environ toutes les heures), et rclone le renouvelle automatiquement en réécrivant le fichier de configuration. Réécrit par un processus root, ce fichier devient la propriété de root, et l’utilisateur normal perd l’accès à sa propre configuration.

La correction : ne plus jamais faire tourner rclone lui-même avec sudo. Seule la commande qui a besoin de lire les fichiers appartenant à root (tar, dans la solution ci-dessous) utilise sudo, sans aucun rapport avec la configuration rclone.

La solution : une archive compressée plutôt que des milliers de fichiers

Plutôt que de copier des milliers de fichiers un par un, le script compresse désormais l’intégralité du dossier en une seule archive avant l’envoi. Une archive à transférer, c’est une poignée de requêtes API au lieu de dizaines de milliers.

La logique GFS reste identique, mais la rotation hebdomadaire, mensuelle et annuelle se fait par copie du fichier archive directement entre deux emplacements sur Google Drive (côté serveur, sans repasser par le Mini PC), plutôt que par un nouveau balayage de milliers de fichiers.

Le nettoyage des sauvegardes obsolètes change aussi de nature : supprimer un fichier unique par jour dépassé, au lieu de parcourir et supprimer des milliers de fichiers individuellement.

Le script complet

#!/bin/bash

# ═══════════════════════════════════════════════════════════════
# backup-docker.sh — Sauvegarde Docker vers Google Drive
# v5 - archive unique compressée (fin du problème de quota API)
#      export automatique des YAML depuis l'API Portainer
# ═══════════════════════════════════════════════════════════════

# -- Configuration ────────────────────────────────────────────────
SOURCE="/home/USER/docker"
REMOTE="gdrive:"
LOG="/home/USER/rclone-logs/backup-docker.log"
RCLONE_CONF="/home/USER/.config/rclone/rclone.conf"
PORTAINER_URL="https://192.168.1.100:9443"
PORTAINER_TOKEN=$(cat /home/USER/docker/scripts/.portainer-token)
DATE=$(date +%Y-%m-%d)
DAY=$(date +%u)     # 1=lundi ... 7=dimanche
DOM=$(date +%d)     # jour du mois (01-31)
MONTH=$(date +%m)   # mois (01-12)

ARCHIVE_NAME="docker-$DATE.tar.gz"
TMP_ARCHIVE="/tmp/$ARCHIVE_NAME"

# -- Création du dossier de log si nécessaire ─────────────────────
mkdir -p /home/USER/rclone-logs

# -- Fonction de log ──────────────────────────────────────────────
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG"
}

# -- Commande rclone de base ──────────────────────────────────────
# Important : plus de sudo ici. rclone tourne toujours en tant que
# l'utilisateur normal, son fichier de config n'est donc plus
# jamais réécrit par root. Seul tar (plus bas) a besoin de sudo
# pour lire les fichiers appartenant à root dans les volumes
# Docker.
RCLONE="rclone --config $RCLONE_CONF --log-file=$LOG"

log "=== Début sauvegarde ==="

# -- Export automatique des YAML (format de fichier de configuration
# lisible, utilisé par Docker Compose) depuis l'API Portainer ─────
log "Export des YAML depuis Portainer..."

STACKS_JSON=$(curl -sk \
    -H "X-API-Key: $PORTAINER_TOKEN" \
    "$PORTAINER_URL/api/stacks")

if [ -z "$STACKS_JSON" ] || [ "$STACKS_JSON" = "null" ]; then
    log "ERREUR : impossible de contacter l'API Portainer - les YAML ne seront pas mis à jour."
else
    STACK_COUNT=$(echo "$STACKS_JSON" | python3 -c "
import sys, json
stacks = json.load(sys.stdin)
print(len(stacks))
" 2>/dev/null)

    log "$STACK_COUNT stack(s) trouvée(s) dans Portainer."

    echo "$STACKS_JSON" | python3 -c "
import sys, json
stacks = json.load(sys.stdin)
for s in stacks:
    print(s['Id'], s['Name'])
" 2>/dev/null | while read stack_id stack_name; do

        YAML_CONTENT=$(curl -sk \
            -H "X-API-Key: $PORTAINER_TOKEN" \
            "$PORTAINER_URL/api/stacks/$stack_id/file" \
            | python3 -c "
import sys, json
data = json.load(sys.stdin)
print(data.get('StackFileContent', ''))
" 2>/dev/null)

        if [ -n "$YAML_CONTENT" ]; then
            DEST="$SOURCE/$stack_name/docker-compose.yml"
            mkdir -p "$SOURCE/$stack_name"
            echo "$YAML_CONTENT" > "$DEST"
            log "YAML exporté : $stack_name/docker-compose.yml"
        else
            log "ATTENTION : YAML vide ou inaccessible pour la stack $stack_name"
        fi
    done
fi

# -- Vérification des docker-compose.yml manquants ────────────────
# Seuls les containers gérés comme des stacks Portainer ont un
# docker-compose.yml généré automatiquement ci-dessus. Certains
# dossiers ne sont pas des containers et doivent être exclus de
# cette vérification.
log "Vérification des docker-compose.yml..."
for dir in "$SOURCE"/*/; do
    logiciel=$(basename "$dir")
    # "scripts" : pas un container Docker
    # à adapter : tout dossier qui n'est pas une stack Portainer
    # (par exemple un environnement virtuel Python) doit être
    # ajouté ici pour éviter une fausse alerte à chaque exécution
    if [ "$logiciel" = "scripts" ]; then
        continue
    fi
    compose="$dir/docker-compose.yml"
    if [ ! -f "$compose" ]; then
        log "ATTENTION : docker-compose.yml manquant dans $logiciel - à créer manuellement !"
    fi
done

# -- Création de l'archive compressée ─────────────────────────────
# sudo est nécessaire ici car certains fichiers dans les volumes
# Docker appartiennent à root. tar n'a aucun rapport avec la config
# rclone, donc rclone.conf n'est jamais impacté par ce sudo.
log "Création de l'archive $ARCHIVE_NAME..."
sudo tar --exclude="*.db-shm" --exclude="*.db-wal" -czf "$TMP_ARCHIVE" -C "$SOURCE" .
sudo chown USER:USER "$TMP_ARCHIVE"
log "Archive créée : $(du -h "$TMP_ARCHIVE" | cut -f1)"

# -- Envoi de l'archive vers Google Drive (sauvegarde quotidienne) ─
log "Copie vers daily/..."
$RCLONE copy "$TMP_ARCHIVE" "$REMOTE/daily/"

# -- Copie hebdomadaire (chaque dimanche) ──────────────────────────
# Copie côté serveur, aucun ré-upload depuis le poste local
if [ "$DAY" -eq 7 ]; then
    log "Dimanche : copie hebdomadaire"
    $RCLONE copyto "$REMOTE/daily/$ARCHIVE_NAME" "$REMOTE/weekly/$ARCHIVE_NAME"
fi

# -- Copie mensuelle (le 1er de chaque mois) ───────────────────────
if [ "$DOM" -eq 01 ]; then
    log "1er du mois : copie mensuelle"
    $RCLONE copyto "$REMOTE/daily/$ARCHIVE_NAME" "$REMOTE/monthly/$ARCHIVE_NAME"
fi

# -- Copie annuelle (le 1er janvier) ───────────────────────────────
if [ "$DOM" -eq 01 ] && [ "$MONTH" -eq 01 ]; then
    log "1er janvier : copie annuelle"
    $RCLONE copyto "$REMOTE/daily/$ARCHIVE_NAME" "$REMOTE/yearly/$ARCHIVE_NAME"
fi

# -- Nettoyage du fichier temporaire local ─────────────────────────
rm -f "$TMP_ARCHIVE"

# -- Nettoyage des anciennes sauvegardes sur Drive ─────────────────
# Suppression de fichiers uniques, plus de parcours fichier par fichier
log "Nettoyage daily > 7 jours..."
$RCLONE delete "$REMOTE/daily" --min-age 7d --include "*.tar.gz"

log "Nettoyage weekly > 28 jours..."
$RCLONE delete "$REMOTE/weekly" --min-age 28d --include "*.tar.gz"

log "Nettoyage monthly > 365 jours..."
$RCLONE delete "$REMOTE/monthly" --min-age 365d --include "*.tar.gz"

# Annuelles : conservées indéfiniment, pas de nettoyage automatique

log "=== Sauvegarde terminée ==="

Résultat mesuré après cette réécriture : script complet exécuté en 8 minutes, contre plus de 7 heures avant correction.

Un point de vigilance si tu reprends ce script : les fichiers docker-compose.yml gérés par Portainer sont écrasés chaque nuit avec la version stockée dans Portainer. Toute modification doit se faire dans l’interface Portainer, jamais directement dans le fichier local, sous peine d’être effacée à la prochaine exécution.

Un point à ne pas manquer au déploiement : ce sudo tar doit être explicitement autorisé sans mot de passe, sans quoi il échoue silencieusement lorsqu’il est lancé par cron (qui n’a pas de terminal interactif pour saisir un mot de passe). L’échec ne remonte alors aucune erreur exploitable dans le log applicatif, l’archive reste simplement vide.

Plutôt que d’autoriser tar sans restriction (ce qui donnerait un accès complet en lecture et écriture à tout le système à quiconque contrôle ce compte), la règle sudoers peut être limitée à la commande exacte utilisée par le script :

sudo visudo -f /etc/sudoers.d/backup-docker

puis remplacer le contenu par :

USER ALL=(root) NOPASSWD: /usr/bin/tar --exclude=*.db-shm --exclude=*.db-wal -czf /tmp/docker-*.tar.gz -C /home/USER/docker .

Le joker (*) dans le nom de fichier autorise uniquement la variation de la date, tout le reste de la commande doit correspondre au caractère près à ce que le script envoie. Si le script évolue plus tard (nouvelle option, chemin différent), cette règle doit être mise à jour en même temps, sinon le même échec silencieux se reproduira.

Se faire alerter automatiquement avec Home Assistant

Le script écrit un journal détaillé, mais rien ne prévenait activement en cas de souci, il fallait aller consulter le fichier manuellement. Un capteur Home Assistant permet de surveiller ce journal et de déclencher une notification par email en cas d’anomalie.

Monter le dossier de logs dans le container Home Assistant, dans la section volumes du fichier de configuration de la stack (via Portainer) :

- /home/USER/rclone-logs:/rclone-logs:ro

Le :ro (lecture seule) suffit, Home Assistant n’a pas besoin d’écrire dans ce dossier.

Créer le capteur. Depuis la version 2023.8 de Home Assistant, la syntaxe sensor: - platform: command_line ne fonctionne plus, le capteur doit être déclaré sous une clé command_line: dédiée :

command_line:
  - sensor:
      name: "Sauvegarde Docker Anomalies"
      unique_id: sauvegarde_docker_anomalies
      command: >
        awk '/=== Début sauvegarde ===/{buf=""} {buf=buf $0 ORS} END{printf "%s", buf}' /rclone-logs/backup-docker.log > /tmp/dernier-run.log;
        if grep -q "=== Sauvegarde terminée ===" /tmp/dernier-run.log; then
          COUNT=$(grep -E "ATTENTION|ERROR" /tmp/dernier-run.log | grep -vc "directory not found");
          echo "$COUNT";
        else
          echo "99";
        fi
      scan_interval: 3600

Ce capteur isole la dernière exécution du script (entre le dernier === Début sauvegarde === et la fin du fichier), puis renvoie soit le nombre de lignes d’alerte ou d’erreur trouvées, soit 99 si la ligne === Sauvegarde terminée === est absente, ce qui signale un script resté bloqué ou interrompu avant la fin.

Un piège à connaître sur cette commande : grep -c compte des lignes, mais son code de sortie (au sens Unix, pas sa sortie affichée) vaut 1 dès que ce compte est à zéro, 0 seulement s’il trouve au moins une ligne. L’intégration command_line traite tout code de sortie différent de zéro comme un échec de la commande, et dans ce cas, elle n’écrit jamais la valeur dans le capteur. Résultat contre-intuitif : le capteur reste bloqué sur unknown précisément quand tout va bien (zéro anomalie trouvée). La solution, déjà intégrée ci-dessus, consiste à isoler le comptage dans une variable puis à l’afficher avec un echo séparé, qui réussit toujours quel que soit le chiffre affiché.

Créer l’automatisation qui envoie l’alerte par email :

automation:
  - alias: "Alerte anomalie sauvegarde Docker"
    id: alerte_anomalie_sauvegarde_docker
    trigger:
      - platform: time
        at: "03:30:00"
    condition:
      - condition: numeric_state
        entity_id: sensor.sauvegarde_docker_anomalies
        above: 0
    action:
      - service: notify.email_alertes
        data:
          title: "[home ALD] Anomalie sauvegarde Docker"
          message: >
            Une anomalie a été détectée dans la sauvegarde Docker de cette nuit (code {{ states('sensor.sauvegarde_docker_anomalies') }}).
            Automatisation déclenchante : automation.alerte_anomalie_sauvegarde_docker
            Consulter le log complet sur le Mini PC : /home/USER/rclone-logs/backup-docker.log

Le déclenchement à 3h30 laisse une marge confortable après le lancement du script à 3h00, largement suffisante avec un temps d’exécution ramené à quelques minutes.

Attention si tu ajoutes une automatisation dans un fichier automations.yaml existant : chaque automatisation est un élément de liste, le tiret - qui la démarre doit être collé à gauche, sans indentation, sous peine d’erreur de chargement.

Pour aller plus loin