Partager :
Clonage SD · intégrité des données
Un clone de carte SD qui boote n'est pas un clone qui marche
2026-07-26 · HardStacked · 7 min de lecture
Vous migrez votre Raspberry Pi vers une carte endurante avec l'outil fourni. La nouvelle
carte boote — mais l'écran de mot de passe tarde, et une fois le mot de passe entré,
un long écran noir passe avant que le bureau apparaisse. Le réflexe,
« la carte est lente », pointe dans la mauvaise direction.
On a fait cette migration sur un Pi 5 sous Debian 13, d'une V30 générique vers une
SanDisk High Endurance 128 Go, en mesurant chaque étape : le clone à chaud qui a
échoué, l'autopsie octet par octet, le clone à froid qui a réussi. Voici les chiffres,
nos erreurs incluses, parce qu'elles portent les leçons.
1. Le chronomètre disait plus rapide, l'écran disait le contraire
piclone (le « SD Card Copier » préinstallé sur
Raspberry Pi OS) n'est pas un dd bit-à-bit. Dans le binaire : un
dd if=/dev/zero sur le premier secteur de la cible, un mkfs.ext4,
puis un cp -ax d'un système vivant — fichier par fichier pendant
que l'OS écrit.
Le résultat boote, et systemd-analyze annonce 24,5 s et 29,8 s sur
deux essais, contre 39,029 s pour la source. À l'écran, l'inverse exact : l'attente est
nettement plus longue qu'avant, avant comme après le mot de passe.
Les deux sont vrais. systemd-analyze arrête son chronomètre quand
graphical.target est atteint ; le greeter, puis la session, démarrent après
— hors de son périmètre. C'est précisément là que la panne se trouve. La carte
suspecte montée en lecture seule depuis un système sain, le journal la nomme :
Failed to start gvfs-daemon.service
Failed to activate service 'org.gtk.vfs.Daemon':
timed out (service_start_timeout=120000ms) ← 120 s d'attente, à chaque session
Le greeter réclame gvfs, puis la session utilisateur à son tour : D-Bus attend
120 secondes chaque fois. D'où les deux attentes — celle qui retarde le mot de
passe, avec son erreur en haut de l'écran, et celle qui suit le login. La seconde est noire
parce que c'est pcmanfm --desktop qui dessine le fond d'écran et les icônes :
tant qu'il attend gvfs, il n'affiche rien. Pourquoi gvfs meurt :
$ stat -c %s usr/libexec/gvfsd
67760 ← exactement la bonne taille
$ md5sum usr/libexec/gvfsd
593a1ef6a5d338baa4fecb47ce98e886 ← dpkg attendait 100c13dbd4613636479dc979b274b6d8
Relu trois fois avec drop_caches entre chaque : même somme. La mauvaise
donnée est gravée sur la carte, ce n'est pas une lecture instable.
L'habitude
« Ça boote » ne prouve rien, et un chronomètre qui contredit ce que
vous voyez à l'écran ne gagne pas l'arbitrage : commencez par regarder ce qu'il mesure, et
où il s'arrête. Puis montez le clone en lecture seule depuis un système sain, lisez son
journal, et comparez des binaires aux sommes md5 de dpkg avant de déclarer la copie
bonne.
2. Les octets faux ont une forme, et cette forme disculpe la carte
Le balayage complet a trouvé 69 fichiers au contenu faux, dispersés sans lien
logique : gvfsd, libcrypto.a, libnssckbi.so, un
firmware Wi-Fi, des icônes, des en-têtes de noyau. Le désordre apparent cachait un motif
parfait :
$ cmp -l gvfsd.src gvfsd.clone | awk '{print $3}' | sort -u
0 ← 100 % des octets divergents valent 0x00
Des plages contiguës, qui finissent soit à la fin du fichier, soit pile sur 2 Mio
(2 097 152). Pour gvfsd, 67 760 octets : la divergence court de
l'octet 63 673 à 67 745 — une queue de zéros.
Un média défaillant rend du bruit aléatoire. Une écriture perdue rend des zéros alignés.
La carte et le lecteur USB sont donc disculpés : c'est la copie à chaud qui a perdu
des écritures en vol.
L'habitude
Avant d'accuser le matériel, regardez la forme des octets faux avec cmp -l.
Bruit aléatoire : le média. Zéros contigus alignés : l'outil de copie.
3. Notre premier balayage se trompait d'un facteur 300
On l'avoue : le premier md5sum -c est parti sans les droits root. Verdict :
21 513 « échecs ». Le vrai chiffre : 69. Les
21 444 autres étaient juste illisibles — fichiers d'un HIDS réservés à root,
compilateurs en -rwx------. md5sum -c mélange
« contenu faux » et « pas pu ouvrir » dans le
même flux ; on a failli conclure à une carte massivement pourrie.
L'habitude
Balayez en root, et séparez toujours les échecs de lecture des échecs de contenu.
4. Notre clone à froid a failli reproduire la même panne, dans le script
La méthode qui marche : source démontée, e2fsck -fn,
e2image -ra -p (ne copie que les blocs utilisés), dd conv=fsync en
écriture intégrale, e2fsck -fp.
Deuxième aveu : le premier jet portait dd conv=sparse, attrapé à la
relecture. sparse saute les blocs de zéros : l'ancien contenu corrompu de la
cible ne serait jamais écrasé, et un fichier de vrais zéros relirait la vieille donnée.
La même panne, par un autre chemin. blkdiscard, refusé par le lecteur
USB — sans conséquence, justement parce que l'écriture est intégrale.
L'habitude
Sur une cible déjà écrite, écriture intégrale seulement — relisez votre ligne
dd, jamais conv=sparse.
5. Un verdict « zéro divergence » aurait rejeté le clone parfait
Vérification du clone à froid : 193 497 sommes md5 de paquets,
849 divergences. Sur un clone parfait. Toutes légitimes : 845 fichiers
.pyc d'un HIDS qui les recompile en runtime, 2 configs du même, un
EXTERNALLY-MANAGED pour lequel dpkg garde deux sommes (la stdlib et le paquet
Raspberry Pi qui l'écrase — faux positif structurel), un g_ether.conf.
Plus 229 « erreurs d'ouverture » : autant de fichiers inexistants
(scripts d'installation supprimés après déploiement).
Un script qui aurait exigé « 0 divergence » aurait affiché
« COPIE NON SAINE, NE PAS booter dessus » sur un clone parfaitement
bon. Le nombre de divergences ne mesure pas la corruption ; la signature de la
section 2, oui : bloc contigu de zéros de 64 Kio ou plus, ou queue de zéros de
64 Kio ou plus. Sur le clone à froid : 0 fichier flagué.
Et le détecteur doit s'auto-tester avant de juger, parce qu'un détecteur cassé rend
« 0 » lui aussi. Le test : un fichier rempli de zéros doit être
flagué, un fichier sain avec une queue de 100 k zéros aussi, un fichier aléatoire non.
Vérifié en sabotant volontairement le seuil : le refus de verdict se déclenche.
L'habitude
Jugez une copie sur la signature de la panne que vous cherchez, pas sur un compte de
divergences. Et faites échouer votre détecteur exprès une fois — s'il ne sait pas dire
« je suis cassé », son « 0 » ne vaut rien.
6. Le boot 13 secondes plus rapide, il fallait le prouver
Après la migration : 25,948 s (1,700 s noyau + 24,247 s espace
utilisateur), contre 39,029 s avant. Le gain est réel — mais le clone corrompu de
la section 1 affichait déjà 24-29 s au même chronomètre, sur une machine dont le bureau
ne s'affichait pas. Un bon chiffre de boot peut cohabiter avec un système cassé : il
ne mesure pas la santé.
Le contrôle qui tranche : compter les unités systemd activées et masquées, avant et
après. Ici 47 et 21, identiques. Même compte de services, moins de temps : un vrai gain
d'entrées/sorties. Confirmé poste à poste par systemd-analyze blame : le
service du HIDS, gourmand en I/O au démarrage, passe de 21,8 s à 12,937 s
— environ 9 des 13 secondes viennent de lui seul.
L'habitude
Un gain de boot ne se célèbre qu'après recomptage des unités enabled et
masked. Sinon votre « carte plus vite » peut être un
service qui ne se lève plus.
7. Les compteurs d'usure décrivent la source, pas la carte
$ dumpe2fs -h <partition> | grep 'Lifetime writes'
Lifetime writes: 1188 GB ← sur une carte fabriquée deux mois plus tôt
Ce compteur de dumpe2fs vit dans le superbloc — copié avec le reste.
Après un clone, tout compteur logé dans une structure copiée décrit la source. Le
recoupement rassurant : 364 661 inodes et 13 564 397 blocs utilisés, comptés
indépendamment sur deux machines, identiques.
L'habitude
L'usure se lit sur le contrôleur (/sys/block/mmcblk0/device/ :
cid, name, date), jamais dans le système de
fichiers.
Les cinq règles d'un clone honnête
- À froid seulement. Une copie d'un système vivant perd des écritures en vol,
et le résultat boote quand même.
- Écriture intégrale sur la cible, jamais
conv=sparse : les blocs
de zéros sautés laissent l'ancien contenu corrompu en place.
- Le verdict se rend sur une signature, pas sur un compte. Un clone parfait
affiche des centaines de divergences légitimes ; un clone pourri se reconnaît à ses
plages de zéros.
- Séparez « contenu faux » et « pas pu
lire ». Mélangés dans le même flux, ils gonflent le verdict d'un facteur
300.
- Auto-testez le détecteur. Cassé, il rend « 0 » lui
aussi — et un « 0 » qu'on n'a jamais su faire échouer ne
vaut rien.
De quoi a l'air un vrai clone
Mesuré sur un Pi 5 sous Debian 13, V30 générique vers SanDisk High Endurance
128 Go. Le clone à chaud bootait avec 69 fichiers faux, tous en zéros contigus ; le
clone à froid, vérifié sur 193 497 sommes md5, sort avec 0 fichier flagué et un double
comptage inodes/blocs identique sur deux machines.
Une dernière conséquence, contre-intuitive et facile à oublier : un clone à froid
fige la source à l'instant T. Tout ce qui s'écrit après le début de la copie
n'existe pas sur la carte gravée — y compris le rapport de la copie elle-même, resté
sur la machine qui la pilotait. On a cherché ce fichier sur la mauvaise carte avant de s'en
rendre compte.
La même leçon traverse toute la migration : « ça boote » n'est pas
« ça marche », « plus vite » n'est pas
« plus sain », « zéro erreur » n'est pas
« propre ». Le chiffre est l'instrument, pas la santé —
et chaque verdict doit sortir d'une mesure capable de distinguer, rendue par un instrument
qu'on a fait échouer exprès au moins une fois.
La leçon de fond
Un clone qui boote, un chronomètre qui descend, un balayage qui rend zéro : trois
signaux rassurants, et trois instruments qui ne mesuraient pas ce qu'on croyait. La
discipline qui les démasque est la même partout — savoir ce que le chiffre mesure,
chercher la signature de la panne plutôt qu'un compte, et faire échouer l'instrument
avant de lui faire confiance.
On est une boutique de sécurité, alors nos incitatifs pointent dans la même direction
que les vôtres : rien de ce qu'on vend ne dépend d'une configuration qui reste faible
chez vous. Cet alignement, c'est exactement ce que les grandes plateformes ne peuvent pas
offrir, et il est vérifiable, pas un slogan. Scannez hardstacked.net
vous-même, tout de suite, sur le même scanner.
La même philosophie porte HardVps : il applique une base de
durcissement révisée sur votre serveur, capture chaque fichier original d'abord, et
vérifie toute restauration à l'octet près par SHA-256. Une rigueur qu'on peut annuler,
c'est une rigueur qu'on ose déployer.
Voir ce que HardVps fait →
Sur un Raspberry Pi ? Commencez gratuitement avec
audit-pi, notre audit de sécurité open source.
Partager :