Partager :
OpenSSL · Debian 13
update-ca-certificates « 0 added, 0 removed » : la même sortie, que ton certificat soit pris ou non
Publié le · HardStacked · 9 min
Tu déposes le certificat de ta CA maison là où la doc le dit, lances sudo update-ca-certificates, et reçois 0 added, 0 removed; done. Aucune erreur, code de sortie 0. Aucune idée si ça a marché.
Quelqu'un a posé cette question sur askubuntu il y a neuf ans, encore environ 269 vues par mois :
"Update-ca-certificates: 0 added; 0 removed - how come?"
(en français : « 0 ajouté, 0 retiré, comment ça se fait ? »)
La réponse de forum, souvent : « renomme-le en .crt ». Parfois c'est le bon correctif, parfois ça ne change rien, parce que cette ligne n'est pas une erreur. C'est un compteur, et il ne compte pas ce que tu penses.
01. Le verdict en deux lignes
update-ca-certificates ne lit jamais le contenu de ton certificat pour décider si ça a marché. Il compte des liens symboliques créés dans /etc/ssl/certs. C'est tout. Donc 0 added, 0 removed sort pour un certificat déjà bien installé, et il sort, mot pour mot, pour un certificat qui a été ignoré en silence. 1 added peut sortir pour un certificat inutilisable. 0 removed sort juste après que tu en aies supprimé un. La seule façon de savoir dans quel cas tu es, c'est une commande séparée : openssl verify.
Mesuré le 2026-09-26, Debian 13 (trixie), Raspberry Pi 5, ca-certificates 20250419, openssl 3.5.7-1~deb13u2+rpt1, aucun hook dans update.d. L'outil a tourné pour de vrai, dans un espace de noms utilisateur (unshare -rm) avec des copies jetables de /etc/ssl/certs et /usr/local/share/ca-certificates : vrai binaire, vrais chemins, rien touché sur la machine réelle.
02. Même commande, deux fins différentes
Dépose un certificat qui marche en .crt dans /usr/local/share/ca-certificates/ et relance l'outil une fois qu'il est déjà installé :
Ces commandes sont fournies telles quelles, sans garantie. Teste d'abord sur une machine non critique ou sur un instantané.
.crt, déjà installé
$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
CAfile: srv1.demo.lan.pem: OK
CApath: srv1.demo.lan.pem: OK
Succès, confirmé par le test CAfile/CApath ajouté pour ce banc (pas affiché par update-ca-certificates lui-même). Même chose, même certificat, en .pem plutôt qu'en .crt :
même certificat, en .pem
$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
CAfile: error srv2.demo.lan.pem: verification failed
CApath: error srv2.demo.lan.pem: verification failed
Relis les quatre premières lignes de chaque bloc : identiques. Un certificat est dans le magasin de confiance. L'autre n'a jamais été regardé, faute de l'extension cherchée.
03. Le pourquoi, vérifié dans le script
/usr/sbin/update-ca-certificates est un script shell de 224 lignes, et le mécanisme est là, lisible :
- Ligne 169 :
find ... -name '*.crt' dans /usr/local/share/ca-certificates. Seule extension cherchée (récursif). .pem ou .cer jamais vus. Toute la cause du bloc ci-dessus.
- Lignes 103-106 : « added » s'incrémente quand un lien
/etc/ssl/certs/<nom>.pem est créé ou modifié. Lien déjà là, rien compté. Contenu jamais validé, donc un certificat enregistré dans un format que le magasin ne sait pas lire (DER, plus bas) compte quand même comme « added ».
- Ligne 109 : le bundle
ca-certificates.crt est reconstruit depuis les fichiers présents, à chaque passage. Un fichier supprimé sort de la reconstruction sans toucher au compteur (décrémenté seulement pour les lignes ! de /etc/ca-certificates.conf). D'où « 0 removed » sur un vrai retrait.
- Lignes 178-192 :
openssl rehash ne tourne que si added ou removed est non nul. Rien changé, dossier haché intact.
- Ligne 71 :
--help n'annonce que [--verbose] [--fresh], alors que le script accepte aussi --etccertsdir, --localcertsdir et --sysroot.
04. Trois autres voyants qui mentent pareil
Place le certificat en .crt mais au mauvais endroit, /usr/share/ca-certificates/, sans l'inscrire nulle part :
.crt dans /usr/share, non inscrit
$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
CAfile: error srv6.demo.lan.pem: verification failed
CApath: error srv6.demo.lan.pem: verification failed
Même ligne « 0 added, 0 removed », troisième cause pour elle ici. Correctif : ajouter le chemin dans /etc/ca-certificates.conf, ce qui fait passer ça à 1 added, 0 removed, et ça marche.
Enregistre le certificat en DER (binaire) au lieu de PEM, dépose-le en .crt :
DER enregistré en .crt
$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
rehash: warning: skipping ca-certificates.crt, it does not contain exactly one certificate or CRL
rehash: warning: skipping chain.pem, it does not contain exactly one certificate or CRL
rehash: warning: skipping der-ca.pem, it does not contain exactly one certificate or CRL
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
CAfile: error srv4.demo.lan.pem: verification failed
CApath: error srv4.demo.lan.pem: verification failed
1 added, le chiffre que tu prendrais pour un feu vert, et le certificat n'est pas utilisable. Un témoin connu bon se vérifie correctement juste après, ce qui écarte un bundle corrompu. L'outil a posé le lien et ajouté le fichier au bundle sans jamais regarder son format.
Supprime un certificat réellement installé :
certificat installé supprimé
$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
CAfile: error srv1.demo.lan.pem: verification failed
CApath: error srv1.demo.lan.pem: verification failed
Disparu du magasin de confiance, et l'outil dit quand même « 0 removed ». Ses liens restent dans /etc/ssl/certs, pointés vers le vide.
05. Les liens faits à la main qui disparaissent sans bruit
Il y a une deuxième question, sur Unix & Linux Stack Exchange (807031, Debian 12 et 13, aucune réponse acceptée), qui décrit exactement ce mécanisme vu du côté de celui qui le subit :
« But when I update the package my links get lost. »
(traduction : « mais quand je mets à jour le paquet, mes liens disparaissent »)
Dans cette question, les certificats supplémentaires sont rangés dans /etc/ssl/certs/myown/, et des liens hachés comme 098712345.0 sont posés à la main dans /etc/ssl/certs pour pointer vers eux : la même forme de nom que les liens gérés par openssl rehash. Reproduit ici avec un certificat et un lien fait à la main. Mesuré : un passage qui ne change rien laisse le lien tranquille.
lien fait main, rien ne change
$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
$ ls /etc/ssl/certs/8d9873f6.0
/etc/ssl/certs/8d9873f6.0
Le passage suivant qui ajoute un seul certificat, même sans rapport, l'efface. Une mise à jour du paquet ca-certificates qui apporte une nouvelle CA est exactement ce genre de passage :
le passage suivant ajoute un certificat
$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
rehash: warning: skipping ca-certificates.crt, it does not contain exactly one certificate or CRL
rehash: warning: skipping chain.pem, it does not contain exactly one certificate or CRL
rehash: warning: skipping der-ca.pem, it does not contain exactly one certificate or CRL
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
$ ls /etc/ssl/certs/8d9873f6.0
ls: cannot access '/etc/ssl/certs/8d9873f6.0': No such file or directory
CAfile: error srv5.demo.lan.pem: verification failed
CApath: error srv5.demo.lan.pem: verification failed
man openssl-rehash (local) dit pourquoi : « all links in it that have a name in that syntax are first removed, even if they are being used for some other purpose » (les liens portant ce nom sont d'abord supprimés, même s'ils servent à autre chose). Et rien n'a recréé le lien ensuite : rehash a refait les liens des fichiers posés dans /etc/ssl/certs, pas celui de myown/ (mesuré, le lien reste absent). Correctif : rien à la main dans /etc/ssl/certs. Mets le certificat dans /usr/local/share/ca-certificates/ en .crt, laisse l'outil posséder ce dossier.
06. Le test qui dit la vérité
Arrête de lire la sortie de update-ca-certificates comme un verdict. Vérifie la vraie chaîne contre un vrai certificat de serveur signé par ta CA :
openssl verify, OK
$ openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt server.pem
server.pem: OK
ou
openssl verify, échec
$ openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt server.pem
CN=srv4.demo.lan
error 20 at 0 depth lookup: unable to get local issuer certificate
error server.pem: verification failed
Vérifie d'abord le format du fichier :
$ grep -c 'BEGIN CERTIFICATE' my-pem-ca.crt
1
$ grep -c 'BEGIN CERTIFICATE' my-der-ca.crt
0
$ file my-pem-ca.crt
my-pem-ca.crt: PEM certificate
$ file my-der-ca.crt
my-der-ca.crt: Certificate, Version=3
Piège : openssl x509 -in fichier -noout -subject affiche un sujet pour un DER sans broncher, sans -inform DER :
DER lu sans -inform DER
$ openssl x509 -in /usr/local/share/ca-certificates/der-ca.crt -noout -subject
subject=CN=Demo DER CA
OpenSSL 3 devine le format tout seul. Ça dit que le fichier est lisible, rien sur le fait que update-ca-certificates peut s'en servir. Pas le test.
07. Les correctifs, tous mesurés
Convertis le DER en PEM sur place et relance :
DER converti en PEM
$ sudo openssl x509 -inform DER -in /usr/local/share/ca-certificates/der-ca.crt -out /usr/local/share/ca-certificates/der-ca.crt
$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
$ openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt server.pem
server.pem: OK
0 added, sur un correctif qui a marché, parce que le lien pour ce nom existait déjà depuis la tentative précédente, cassée. La ligne openssl verify à la fin dit que c'est corrigé, pas le compteur au-dessus.
Renomme un .pem en .crt :
.pem renommé en .crt
$ sudo mv /usr/local/share/ca-certificates/pemca.pem /usr/local/share/ca-certificates/pemca.crt
$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
rehash: warning: skipping ca-certificates.crt, it does not contain exactly one certificate or CRL
rehash: warning: skipping chain.pem, it does not contain exactly one certificate or CRL
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
$ openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt server.pem
server.pem: OK
Pour un certificat dans /usr/share/ca-certificates/ sans être inscrit, ajoute son chemin dans /etc/ca-certificates.conf, ce qui fait passer le cas plus haut de 0 added à 1 added, 0 removed et fonctionnel. dpkg-reconfigure ca-certificates est le front-end officiel pour ce fichier ; pas exécuté ici, traite-le comme l'outil documenté, pas comme une sortie mesurée.
La ligne rehash: warning: skipping ca-certificates.crt, it does not contain exactly one certificate or CRL est du bruit à chaque ajout réussi. Le bundle vit dans le dossier haché que rehash scanne, et ce n'est pas un certificat unique, donc il est sauté. Pas un échec.
08. Ce que ça couvre, et ce que ça ne couvre pas
Le mécanisme ci-dessus est le chemin de code de Debian 13. Le script de Debian 12 (20230311+deb12u1) montre la même logique à la lecture, pas par un banc lancé là-bas. Celui de Debian unstable (20260816) est identique à celui de ce Pi.
Ce test valide seulement le magasin système. Firefox, Java, un venv Python, Node ont souvent leur propre magasin. Pas mesuré ici. Navigateur qui fait confiance à la CA et curl non (ou l'inverse) ? Regarde quel magasin chacun lit avant d'accuser cet outil.
Cas de bord : un .crt qui contient deux certificats ne sert que par le bundle. rehash saute tout fichier qui ne contient pas exactement un certificat, il n'entre donc jamais dans le dossier haché.
Si tu es la personne derrière la question 807031 : cet article donne le mécanisme et le test, pas un diagnostic de ton certificat intermédiaire précis. Lance openssl verify dessus, lis l'erreur. C'est l'étape suivante, hors périmètre ici.
La même forme traverse le reste de cette série, où le système déclare une chose et en fait une autre : un systemctl enable qui annonce un échec alors que le service finit activé quand même et un pare-feu que l'unité systemd déclare activé alors qu'il est éteint.
Partager :