C'est l'une des pannes de certificat les plus déroutantes, parce qu'elle marche chez vous. Les navigateurs de bureau gardent en cache les certificats intermédiaires vus sur d'autres sites et comblent le trou en silence ; un téléphone qui n'a jamais vu cet intermédiaire, et tout client en ligne de commande, ne le peuvent pas.

Le symptôme

  • Correct sur votre ordinateur, non fiable sur un téléphone.
  • curl dit unable to get local issuer certificate.
  • Une passerelle de paiement ou un webhook n'arrive pas à se connecter alors que les navigateurs sont contents.

Le confirmer

openssl s_client -connect yourdomain.com:443 -servername yourdomain.com < /dev/null 2>/dev/null \
  | grep -E '^ *[0-9]+ s:|Verify return code'

Vous voulez au moins deux certificats listés — le vôtre et l'intermédiaire — et Verify return code: 0 (ok). Un seul certificat accompagné d'une erreur de vérification, c'est exactement cette panne.

La cause tient à un nom de fichier

Servir cert.pem au lieu de fullchain.pem. cert.pem, c'est votre certificat seul ; fullchain.pem, c'est votre certificat suivi de l'intermédiaire. C'est un mot dans la configuration, et c'est presque toujours tout le problème.
# nginx - correct
ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# apache / litespeed
SSLCertificateFile      /etc/letsencrypt/live/example.com/cert.pem
SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem

Rechargez et vérifiez de nouveau

sudo nginx -t && sudo systemctl reload nginx
curl -sS -o /dev/null -w '%{http_code}\
' https://yourdomain.com

Testez depuis quelque chose qui n'a pas de cache

curl sur une machine qui n'a jamais visité le site, ou un téléphone en données mobiles avec les données du site effacées. Votre propre navigateur est le seul client incapable de vous donner la réponse — voir Ça marche en wifi mais pas en données mobiles.