Reading TLS handshakes for fun and debugging
Most TLS problems look like "it does not connect". A few openssl flags turn that into a specific answer.
The basics
openssl s_client -connect example.com:443 -servername example.com
Look at three lines: the protocol version, the certificate subject, and Verify return code. If the protocol is TLS 1.2 when you expected 1.3, the cipher list or the client is the problem. If the subject does not match the SNI, the server is serving the wrong certificate.
ALPN
openssl s_client -connect example.com:443 -servername example.com -alpn h2
If the output says No ALPN negotiated, the server does not speak HTTP/2 on that port, whatever its documentation claims.
Chain problems
openssl s_client -connect example.com:443 -showcerts
A valid leaf with a missing intermediate is the most common "works in curl, fails in the browser" bug. The fix is on the server, not the client.
When the error is the point
Verify return code: 18 (self-signed certificate) is not a failure when you are testing a private service. It is the expected answer. Read the code before you change the config.