openssl s_client: Usage, Options & Common CI Errors
openssl s_client opens a raw TLS connection to inspect the certificate and handshake.
openssl s_client is the tool for debugging TLS failures in CI - expired certs, missing SNI, broken chains. The recurring gotchas are needing -servername for SNI and that the command waits on stdin unless you redirect it.
What it does
openssl s_client establishes a TLS connection to a host:port and prints the negotiated protocol, cipher, certificate chain, and verification result. It is the standard way to diagnose "certificate verify failed" and SNI/chain problems that break HTTPS calls in a pipeline.
Common usage
echo | openssl s_client -connect example.com:443 -servername example.com
openssl s_client -connect example.com:443 -showcerts </dev/null
# Check expiry:
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
openssl s_client -connect host:443 -tls1_2 </dev/null # force TLS 1.2
echo | openssl s_client -connect host:443 -servername host 2>/dev/null | grep 'Verify return'Options
| Flag | What it does |
|---|---|
| -connect <host>:<port> | Endpoint to connect to |
| -servername <name> | Send SNI (needed for virtual hosts) |
| -showcerts | Print the full certificate chain |
| -CAfile <file> | Verify against a specific CA bundle |
| -tls1_2 / -tls1_3 | Force a TLS version |
| -quiet / </dev/null | Avoid waiting on stdin |
Common errors in CI
s_client reads stdin and stays open, hanging the job - always feed echo | or </dev/null. "verify error:num=20:unable to get local issuer certificate" / num=21 means the chain is incomplete or the runner's CA bundle is missing the root (install ca-certificates / update-ca-certificates). "num=10: certificate has expired" is a literal expiry. Forgetting -servername makes the server return its default cert, causing a confusing hostname-mismatch - always send SNI. "Verify return code: 0 (ok)" is the pass signal to grep for.