È uno dei guasti di certificato più disorientanti, proprio perché a te funziona. I browser da scrivania tengono in cache i certificati intermedi visti su altri siti e colmano il vuoto in silenzio; un telefono che quell'intermedio non l'ha mai visto, e qualunque client da riga di comando, non possono farlo.

Il sintomo

  • A posto sul tuo portatile, non attendibile su un telefono.
  • curl dice unable to get local issuer certificate.
  • Un gateway di pagamento o un webhook non riesce a collegarsi mentre i browser sono contenti.

Confermalo

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

Devi vedere elencati almeno due certificati — il tuo e l'intermedio — e Verify return code: 0 (ok). Un solo certificato insieme a un errore di verifica è esattamente questo guasto.

La causa è un nome di file

Servire cert.pem invece di fullchain.pem. cert.pem è il tuo certificato da solo; fullchain.pem è il tuo certificato seguito dall'intermedio. È una parola nella configurazione, ed è quasi sempre l'intero problema.
# 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

Ricarica e ricontrolla

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

Prova da qualcosa che non abbia cache

curl su una macchina che il sito non l'ha mai visitato, oppure un telefono con la rete dati e i dati del sito cancellati. Il tuo browser è l'unico client che non può darti la risposta — vedi Funziona in wifi ma non con la rete dati.