Hedgii
Un hérisson en Bash, piloté par un simple fichier JSON, qui sauvegarde mes serveurs chaque nuit, chiffre tout, et vérifie qu'on sait vraiment restaurer.
Le contexte
Hedgii est né à l'été 2025, chez Kalya Santé. Il me fallait sauvegarder des serveurs Linux vers un stockage cloud, avec des données qui ne devaient jamais en sortir autrement que chiffrées. Un script Bash, GPG pour le chiffrement, rclone pour l'envoi, une configuration en JSON : la première version est sortie en deux jours.
Sauf qu'une sauvegarde qui tourne toutes les nuits ne prouve qu'une chose : qu'elle tourne. La seule question qui compte, c'est celle qu'on se pose le jour où un disque lâche, où une mise à jour casse une base, où quelqu'un supprime le mauvais dossier : est-ce que je sais remettre les données en place, là, maintenant ?
C'est autour de cette question que Hedgii a été entièrement repris en octobre 2026.
Quinze mois de fausse tranquillité
En octobre 2026, j'ai décidé de sortir mes serveurs de Cloudron pour passer sur un déploiement Docker plus léger. Avant de toucher à quoi que ce soit, il fallait des sauvegardes solides. Hedgii était déjà là, alors j'ai fait ce que je n'avais jamais fait : je l'ai audité comme si c'était le code de quelqu'un d'autre.
Le verdict a été vexant, et instructif.
- Le script de restauration ne savait pas lire les archives par défaut. La configuration fournie produisait des archives ZIP, alors que
decrypt.shne savait ouvrir que dutar.gz. Autrement dit, une installation standard fabriquait chaque nuit des sauvegardes que son propre outil de restauration était incapable d'ouvrir. Personne ne s'en était rendu compte, parce que personne n'avait essayé de restaurer. - Le disque se remplissait sans jamais se vider. Les archives locales s'accumulaient, nuit après nuit, jusqu'à saturer le serveur.
- La connexion au cloud était fragile. L'historique de la v1 contient un commit intitulé
fix: onedrive config (again3). Je vous laisse imaginer les deux précédents.
Rien de spectaculaire, aucune fuite, aucune perte. Juste un outil qui donnait l'impression de protéger, sans jamais le démontrer. Seize issues détaillées plus tard, la version 2 était sur les rails.
Une nuit ordinaire
Chaque nuit, Hedgii se « roule en boule » autour des données du serveur (la commande s'appelle d'ailleurs hedgii curl), puis les envoie à l'abri.
flowchart LR
A["🔎 Vérifier<br/>l'espace disque"] --> B["🐘 Dumper<br/>les bases"]
B --> C["📦 Archiver<br/>les volumes"]
C --> D["🔐 Chiffrer<br/>(GPG AES-256)"]
D --> E["☁️ Envoyer<br/>et vérifier"]
E --> F["🧹 Nettoyer<br/>ce qui est à l'abri"]
F --> G["📣 Prévenir<br/>si ça coince"]
style A fill:#2A212C,color:#E7E4E7
style B fill:#777EFF,color:#fff
style C fill:#777EFF,color:#fff
style D fill:#00055C,color:#D2D6FF
style E fill:#74BCFF,color:#00055C
style F fill:#2A212C,color:#E7E4E7
style G fill:#FFA629,color:#2A212C
Voici à quoi ressemble une vraie exécution, en version courte :
🦔 [INFO] 📏 Estimated size of the sources: 782KB
🦔 [INFO] 🔧 Executing: 🐘 Dump PostgreSQL
🦔 [INFO] ✓ Command successful
🦔 [INFO] Curling up into a protective ball... 🦔
🦔 [INFO] Encryption successful: hedgii_backup_20261019_225812.tar.gz.gpg
🦔 [INFO] ✅ rclone upload completed successfully
🦔 [INFO] Upload verified on remote
✨ [HEDGII] 🎉 Backup completed successfully! Your data is safe! (≧◡≦)
Et, une fois par semaine, la commande qui change tout :
✨ [HEDGII] 🔍 Verifying the latest remote backup...
🦔 [INFO] 📥 Downloading hedgii_backup_20261019_225812.tar.gz.gpg (786KB)...
🦔 [INFO] 🔓 Decrypting and checking...
🦔 [INFO] ✅ Archive OK: 42 files (report: 42)
hedgii verify récupère la dernière archive depuis le cloud, la déchiffre, l'ouvre, et compte ses fichiers pour les comparer au rapport rédigé au moment de la sauvegarde. Si un seul chiffre ne colle pas, je reçois une alerte. La restauration n'est plus une hypothèse : elle est testée tous les sept jours, sans que j'y pense.
Pourquoi ne pas utiliser restic, Borg ou Kopia ?
C'est la question que tout développeur se pose en lisant cette page, et elle est légitime. Ces outils sont excellents, et sur plusieurs points, meilleurs que Hedgii. Je préfère le dire franchement :
| restic, Borg, Kopia | Hedgii | |
|---|---|---|
| Ajouter quelque chose à sauvegarder | Un chemin, et pour le reste des hooks ou un outil de plus | Une ligne : un chemin ou une commande |
| Déduplication, incrémental | Oui, c'est leur force | Non : une archive complète par nuit |
| Format des sauvegardes | Un dépôt dans leur propre format | Un simple fichier .tar.gz.gpg (ou .zip.gpg) |
| Pour restaurer | Il faut l'outil, dans une version compatible | gpg et tar, présents sur presque toutes les machines |
| Bases de données | Via des hooks, un wrapper ou des intégrations dédiées | N'importe quelle commande de dump ; un dump vide fait échouer la nuit |
| Preuve de restauration | Commande de vérification du dépôt | Téléchargement, déchiffrement, comptage, alerte |
| Ce qu'il faut lire pour comprendre | Un projet complet en Go ou en Python | Un script Bash |
Hedgii repose sur deux choix : une configuration que n'importe qui comprend en trente secondes, et des archives que n'importe quelle machine sait ouvrir. Le jour où j'ai besoin d'une sauvegarde, je ne veux dépendre de rien, pas même de Hedgii.
Un fichier Hedgii, c'est une archive tout à fait ordinaire, chiffrée avec un standard qui existe depuis plus de vingt ans. Sur un ordinateur qui n'a jamais vu Hedgii, deux commandes suffisent :
gpg --decrypt hedgii_backup_20261019_225812.tar.gz.gpg | tar -xz
Pas de dépôt à reconstruire, pas d'index à réparer, pas de version d'outil à retrouver dans l'urgence. Je l'ai refait pour écrire cette page : l'archive s'ouvre, le dump SQL est là, les fichiers aussi.
La déduplication, elle, je n'en ai pas besoin. Hedgii ne sauvegarde que ce qui ne se retrouve nulle part ailleurs : les bases de données et les volumes Docker. Le code est déjà versionné dans Git, il n'a rien à faire dans une sauvegarde. Sur l'un de mes serveurs, ce simple changement a fait passer l'archive nocturne de 2,2 Go en 13 minutes à 53 Mo en 50 secondes. À cette taille, une archive complète chaque nuit ne coûte presque rien, et un stockage de sauvegarde, par définition, doit avoir de la place.
Des chemins et des commandes, rien d'autre
C'est là que Hedgii se distingue vraiment. restic, Borg ou Kopia sauvegardent des dossiers, et le font très bien. Mais tout ce qui n'est pas un simple dossier (vider proprement une base, exporter le contenu d'un conteneur, récupérer des données par une API) doit être orchestré autour : des hooks, un script d'enrobage, ou carrément un outil supplémentaire comme borgmatic ou resticprofile, avec sa propre configuration à apprendre.
Hedgii part du principe inverse : tout ce qui s'écrit dans un terminal peut se sauvegarder. Sa configuration ne connaît que deux listes. Des chemins à copier, et des commandes dont la sortie est rangée dans l'archive. Voici à quoi ressemble celle d'un serveur complet :
{
"backup_sources": [
{ "source": "/var/lib/docker/volumes/app_uploads", "destination": "volumes/uploads",
"description": "📸 Fichiers des utilisateurs" },
{ "source": "/opt/stacks", "destination": "stacks",
"description": "🐳 Compose et .env", "exclude": ["*.log"] }
],
"custom_commands": [
{ "command": "docker exec postgres pg_dumpall -U postgres", "output_file": "databases/postgres.sql",
"description": "🐘 Bases PostgreSQL", "timeout": 900, "continue_on_error": false },
{ "command": "docker exec mongo mongodump --archive", "output_file": "databases/mongo.archive",
"description": "🍃 Base MongoDB" },
{ "command": "crontab -l", "output_file": "system/crontab.txt",
"description": "⏰ Tâches planifiées" }
],
"settings": {
"encrypt_passphrase_file": "/etc/hedgii/gpg_passphrase",
"rclone_remote": "gdrive:backups/sandbox/"
}
}
C'est tout. Une base PostgreSQL dans un conteneur, une base MongoDB, la liste des tâches planifiées : Hedgii ne connaît aucun de ces outils, et n'a pas besoin de les connaître. Il exécute la commande, range ce qu'elle produit à l'endroit indiqué, et chiffre le tout. MySQL, SQLite, Redis, l'export JSON d'une application métier, la configuration d'un routeur récupérée en SSH : tant qu'une commande sait l'écrire, Hedgii sait le sauvegarder.
Le jour où j'ajoute un service sur un serveur, sa sauvegarde suit en une ligne. Pas de plugin à attendre, pas de connecteur à mettre à jour, pas de documentation à relire. Et chaque entrée se règle finement quand il le faut : un délai maximal, un dossier de travail, des exclusions propres à une source, et surtout le choix de rendre une commande bloquante (si le dump de la base principale échoue, inutile d'envoyer une sauvegarde incomplète) ou non (si l'inventaire des conteneurs plante, la nuit continue).
La destination suit la même logique. Passer de Google Drive à un stockage S3, à OneDrive ou à un serveur SFTP, c'est modifier une seule ligne : rclone s'occupe du reste.
Cette simplicité sert aussi le jour de la panne. Un fichier de configuration qui se lit en trente secondes, c'est un fichier qui dit exactement ce que contient chaque sauvegarde, sans avoir à fouiller dans un dépôt pour le deviner.
Cinq règles sur lesquelles Hedgii ne transige pas
Hedgii est mignon dans ses messages. Dans son comportement, il est intraitable.
- Ne jamais supprimer ce qui n'est pas à l'abri ailleurs. Une archive locale n'est effacée qu'après avoir été envoyée et retrouvée sur le cloud. Une archive qui n'a pas pu partir reste sur le disque, et Hedgii le rappelle à chaque exécution jusqu'à ce que le problème soit réglé.
- Un dump vide est un échec. Si la commande de sauvegarde d'une base produit un fichier vide, la nuit est marquée en échec. Un fichier
.sqlde zéro octet, c'est le genre d'erreur qu'on ne découvre que trop tard. - Vérifier la place avant de commencer. Hedgii estime la taille de ce qu'il doit copier et refuse de démarrer s'il risque de remplir le disque du serveur qu'il est censé protéger.
- Un seul hérisson à la fois. Si une sauvegarde est déjà en cours, la seconde s'arrête aussitôt et le signale, plutôt que de se battre avec la première pour le même disque.
- Dire quand ça va mal, et quand rien ne se passe. Discord, Telegram, ou une URL de surveillance (Uptime Kuma, healthchecks.io). Cette dernière couvre le cas le plus sournois : celui où la sauvegarde ne s'est tout simplement pas lancée, et où personne n'envoie donc d'alerte.
Chaque code de sortie a un sens précis (2 : collecte, 3 : chiffrement, 4 : envoi, 7 : disque plein…), ce qui permet de brancher Hedgii sur n'importe quel système de supervision sans parser des logs.
Un hérisson, sérieusement ?
Oui. Parce qu'un hérisson qui se roule en boule, c'est littéralement ce que fait une sauvegarde : se refermer autour de ce qui compte, piquants dehors.
Les commandes suivent la métaphore : curl pour sauvegarder, peek pour jeter un œil à l'état des archives, prune pour faire le ménage, guard pour l'état de protection. Les logs sont parsemés de 🦔 et de kaomojis.
C'est un choix qui fait sourire certains développeurs, et c'est voulu. Un outil de sauvegarde, on ne l'ouvre que deux fois : quand on l'installe, et quand tout va mal. Le premier jour, un peu de douceur rend la configuration moins aride. Le jour de la panne, des messages lisibles, qui disent clairement ce qui a marché et ce qui a échoué, valent mieux que n'importe quelle trace technique. Le ton est léger, la rigueur, elle, ne l'est pas : c'est ce que l'illustration en tête de page essaie de raconter.
La v2, en un week-end
La refonte s'est jouée en grande partie le dimanche 18 octobre 2026 : 58 commits, des versions 2.0.0 à 2.0.3, et quatre serveurs passés sous Hedgii dans la foulée.
flowchart LR
A["🔍 Audit du code"] --> B["📝 16 issues<br/>détaillées"]
B --> C["🤖 Corrections<br/>(PR revues)"]
C --> D["🧪 Tests de<br/>sauvegarde/restauration"]
D --> E["🖥️ Déploiement<br/>sur 4 serveurs"]
E -->|"bugs réels"| B
style A fill:#2A212C,color:#E7E4E7
style B fill:#777EFF,color:#fff
style C fill:#00055C,color:#D2D6FF
style D fill:#74BCFF,color:#00055C
style E fill:#FFA629,color:#2A212C
La boucle du bas compte autant que le reste. Une fois Hedgii déployé sur de vrais serveurs, trois bugs que les tests n'avaient pas vus sont apparus : des noms de fichiers accentués qui cassaient l'archivage, des liens physiques mal comptés pendant la vérification, et des fichiers de log qui disparaissaient en pleine sauvegarde. Chacun a donné lieu à une issue, un correctif, un test, puis un redéploiement.
Aujourd'hui, chaque modification du code déclenche plus d'une centaine de vérifications automatiques : de vraies sauvegardes, de vrais envois, de vraies restaurations, mais aussi les pannes (disque plein, envoi qui échoue, dump vide, archive tronquée, deux exécutions simultanées). La suite complète tourne en moins d'une minute.
Ce qui est humain, ce qui est IA. Les 33 commits de la v1 portent ma signature. Pour la v2, l'essentiel du code a été produit par des agents IA : l'audit et les issues, une partie des corrections confiées à GitHub Copilot, le reste écrit avec Claude. Mais les décisions qui font de Hedgii ce qu'il est n'ont rien d'automatique : ne sauvegarder que les données et pas le code, garder un format que n'importe qui peut ouvrir, refuser de supprimer ce qui n'est pas à l'abri, exiger une preuve de restauration chaque semaine. Ça, ce sont des choix d'administrateur, pas de générateur de code. L'IA écrit vite. Savoir quoi écrire, et vérifier que c'est vrai sur de vrais serveurs, reste mon travail.
En production
Hedgii protège aujourd'hui les quatre serveurs de mon infrastructure, dont celui qui héberge mes mails. Chacun a sa propre configuration : les bases de données et volumes Docker qui lui sont propres, une rétention adaptée, des alertes en cas d'échec ou d'avertissement, et une vérification hebdomadaire de la dernière archive envoyée sur Google Drive.
Une précaution que je recommande à quiconque l'installe : la phrase de passe de chiffrement doit être conservée en dehors des serveurs sauvegardés. Une sauvegarde parfaitement chiffrée dont la clé a brûlé avec le serveur, c'est un coffre-fort sans combinaison.
Hedgii est open source, sous licence MIT. Si vous avez un serveur Linux, des données qui comptent et l'envie de dormir tranquille, il vous attend sur GitHub.
Stack technique
| Couche | Technologie | Pourquoi ce choix |
|---|---|---|
| Moteur | Bash (un seul script, sans démon) | Présent sur tout serveur Linux, lisible et auditable de bout en bout |
| Chiffrement | GPG, AES-256 symétrique | Standard ouvert, déchiffrable sans Hedgii |
| Archives | tar.gz ou zip | Formats universels ; zip pour les collègues sous Windows |
| Envoi | rclone (Google Drive, OneDrive, S3, SFTP…) | Des dizaines de fournisseurs, sans réécrire une ligne |
| Collecte | rsync, ou archivage direct sans copie | Le mode direct évite de doubler l'espace disque nécessaire |
| Configuration | Un fichier JSON (lu avec jq) | Deux listes, des chemins et des commandes : tout ce qu'un terminal sait produire |
| Alertes | Discord, Telegram, ping HTTP | Prévenir en cas d'échec, et aussi en cas de silence |
| Qualité | ShellCheck + tests d'intégration en CI | Sauvegarde, envoi et restauration réels testés à chaque modification |
| Exécution | cron (sauvegarde nocturne, vérification hebdo) | Rien à faire tourner en permanence |