Skip to content
ssldays

Guide

openssl s_client -showcerts and expiry

Use openssl s_client check expiry on every certificate in the served chain—leaf and intermediates—with -showcerts piped to x509 for complete dates.

Updated Apr 10, 2026 805 words

openssl s_client check expiry with -showcerts lists each certificate the server sends so you can read notAfter on the leaf and every intermediate—not only the first PEM in the stream.

Browsers build a chain from the leaf to a trusted root. Operators who inspect only the leaf often miss an expired intermediate still configured on the load balancer. The -showcerts flag prints the whole TLS certificate message in PEM form, ready for repeated openssl x509 calls.

This how-to suits incident responders validating renewals, auditors comparing vendor bundles, and engineers debugging “cert looks fine” screenshots that hide a short chain.

You need OpenSSL CLI and the correct HOST plus SNI. Save full transcripts in tickets; serial numbers on each cert segment prove which file finally reached production.

Renewal post-mortems should attach a saved -showcerts capture from before and after deploy. The diff in PEM block count and serial numbers is clearer than narrative claims that “nginx was restarted.”

What to check

For openssl s_client check expiry, walk certificates in presentation order: leaf first, then intermediates. Record notAfter on each. Trust failures happen when any link is outside its validity window or when an intermediate is missing entirely.

Also note chain depth versus your CA documentation. A single certificate returned often means the server is not sending intermediates—symptoms overlap with Certificate chain incomplete in the browser.

Compare results to PEM files on disk after renewal. Dates and serials should align when configuration is correct.

Note whether the server sends optional cross-signed roots. They can inflate PEM block counts without helping clients. Each extra block still needs a valid notAfter if clients attempt to build through it.

When migrating CAs, you may temporarily see two valid paths. Track which intermediate the majority of clients use and align your bundle with CA guidance rather than maximizing PEM size.

Step-by-step

Capture full chain to a file

HOST=www.example.com
openssl s_client -connect "${HOST}:443" -servername "${HOST}" -showcerts </dev/null 2>/dev/null \
  > /tmp/"${HOST}"-chain.pem

The file may include human-readable handshake text before PEM blocks; split on BEGIN CERTIFICATE when scripting.

Label captures with timestamp and vantage point. A chain collected during maintenance may differ from peak traffic when autoscaling adds nodes.

Read leaf dates quickly

openssl x509 -in /tmp/"${HOST}"-chain.pem -noout -dates -serial -issuer 2>/dev/null

The first PEM block OpenSSL reads is usually the leaf when the file contains only certs; if parsing fails, split blocks explicitly.

Split and inspect every certificate

csplit -f /tmp/cert- -b '%02d.pem' /tmp/"${HOST}"-chain.pem '/-----BEGIN CERTIFICATE-----/' '{*}'
for f in /tmp/cert-*.pem; do
  [ -s "$f" ] || continue
  echo "===== $f ====="
  openssl x509 -in "$f" -noout -dates -subject -issuer
done

On systems without csplit, use the awk loop from the OpenSSL expiry date guide.

One-liner without temp files

echo | openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts 2>/dev/null \
  | awk '/BEGIN CERT/{i++} {print > ("/tmp/c" i ".pem")}'
for f in /tmp/c*.pem; do openssl x509 -in "$f" -noout -dates -subject 2>/dev/null; done

Verify you reached the right host

echo | openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts 2>/dev/null \
  | openssl x509 -noout -ext subjectAltName

SANs must include the public hostname.

After splitting, pipe each intermediate through openssl x509 -noout -purpose if you suspect role confusion. Server and CA certificates carry different basic constraints; misordered files sometimes show up during manual bundle assembly.

How to read the output

Leaf notAfter: Drives browser expiry warnings when in the past. Renew and reload the terminating service.

Intermediate notAfter: May expire on a different calendar day than the leaf, especially after CA migrations. Clients fail with untrusted or incomplete chain messages even when the leaf is fresh.

Issuer / subject pairs: Each intermediate’s subject should match the next certificate’s issuer. A break in that linkage means wrong bundle order in your fullchain.pem.

Count of PEM blocks: Compare to CA guidance (typically leaf plus one or two intermediates for public CAs). Only one block strongly suggests missing chain configuration.

At the end of s_client output, read Verify return code. Nonzero codes after a renewal may mean trust store gaps on your workstation even when dates look fine. Distinctly separate PKIX trust failures from expired notAfter when writing ticket summaries.

Common mistakes

Piping -showcerts directly to a single openssl x509 call and assuming intermediates were checked. That reads only the first certificate.

Omitting -servername on shared IPs. You capture a default vhost cert that is unrelated to the incident hostname.

Ignoring non-PEM lines in saved transcripts so automation parsers choke—strip headers or use sed -n '/BEGIN CERTIFICATE/,/END CERTIFICATE/p'.

Concluding renewal succeeded because the leaf dates moved forward while an old intermediate remains in the served chain.

Testing only from inside the network while customers hit a CDN edge with a different chain.

Assuming -showcerts output order matches concatenation order on disk. Some servers reorder or omit optional certificates; trust what the wire presents.

When to use automation

Parsing -showcerts output manually per host does not scale. Automate live chain checks that count presented certificates and flag any notAfter within alert thresholds at 30, 14, 7, and 1 day.

Baseline expected chain depth per hostname after deploy; alert when depth drops. ssldays validates what external clients negotiate, catching cases where your saved PEM file looks perfect but the edge still serves an old intermediate.

Store historical fingerprints of each PEM block to detect silent intermediate swaps. Some incidents begin when a CDN vendor changes default cross-signs without a customer-facing change advisory.

Scenario walkthrough

During a CA migration, leaf dates jumped forward but Android 11 devices failed trust. Saved -showcerts files showed an expired cross-signed intermediate still appended to the chain message even though the leaf was brand new. Removing the legacy intermediate from the server send buffer matched openssl s_client check expiry guidance and restored clients without reissuing the leaf.

A load balancer vendor uploaded separate chain files per listener. One listener kept an old intermediate after a bulk renew. Customers hitting /api saw a different chain depth than / because SNI maps differed. Splitting PEM blocks per listener in post-mortems exposed the asymmetry within minutes.

Penetration testers occasionally paste -showcerts captures showing intentionally expired certs on forgotten vhosts. Security champions use those captures to justify decommissioning hosts that DNS should have retired months ago.

Education teams teach junior admins to count PEM blocks before editing nginx. When only one block appears for a public site using a major CA, trainees know to download the intermediate bundle before reloading, even if the leaf notAfter looks months away.

Post-renewal verification in CI can diff the number of PEM sections against a golden value. Pipeline failure on block count beats learning about missing intermediates from Twitter screenshots during peak shopping season.

Evidence standards for change management

Change records should list the number of PEM blocks observed externally before and after deploy when openssl s_client check expiry is part of verification. Reviewers reject cosmetic descriptions like “reload nginx” without numeric chain depth.

For dual-stack sites, capture IPv4 and IPv6 separately. Some providers renew one path late, producing asymmetric reports from customers on mobile networks.

When working with vendors, request their own -showcerts paste from outside their network. Suppliers who resist often have not tested presentation, only issuance.

Rotate saved captures off laptops after incidents land in the ticket; PEM bundles are not secrets but do fingerprint infrastructure.

Encourage security champions in product teams to learn the awk splitter. Distributed knowledge prevents platform becoming a bottleneck every ninety days.

Long-lived -showcerts sessions against misbehaving hosts can hang on TLS renegotiation edges cases. Wrap commands in timeout the same way you would for production cron jobs so laptops do not freeze during bridge calls.

Compare captures before and after enabling HTTP strict transport security or CDN features that change TLS termination location. Chain depth can change even when DNS names stay constant, which surprises teams who assumed infrastructure toggles were transparent to certificates.

Wildcard deployments deserve explicit drill: request several representative subdomains in separate captures. Wildcards do not cure wrong listener mappings; each name still proves SNI routing.

Windows environments without csplit benefit from PowerShell splitting on BEGIN CERTIFICATE. Cross-platform teams should maintain equivalent scripts in internal repos so every responder uses the same block count logic.

When openssl s_client check expiry surfaces more PEM blocks after a vendor update, read release notes before deleting “extra” certificates. Vendors sometimes ship transitional bundles required for specific Android versions still in your analytics tail.

Revoked or compromised certificate rotations demand captures archived for legal holds. Saved handshakes document what the public saw during narrow windows between revocation publication and your deploy.

Pair this guide with offline verify once blocks are split. Dates can look fine while trust still fails; combining techniques answers executives asking “is it fixed yet?” with fewer adjectives.

Training scenarios should include a deliberate incomplete chain in lab. New hires who only see healthy labs panic in production; controlled failure builds muscle memory for counting PEM sections under pressure.

Platform-specific reminders

HAProxy and Envoy expose chain configuration differently, but -showcerts remains the customer truth. Platform teams should not close tickets until captures match intended bundle fingerprints regardless of control plane status.

Windows administrators can run OpenSSL from Git for Windows bundles; teach standard paths so on-call does not reinstall random binaries during incidents.

Air-gapped environments may require sneaker-net PEM transfer. Saved -showcerts files on USB still follow the same splitting discipline; label drives with hostname and capture time.

SNI mismatch bugs in homegrown proxies sometimes return correct dates for wrong brands. Always read SAN lines alongside notAfter when multiple tenants share infrastructure.

Latency-sensitive APIs benefit from archiving captures pre- and post-change with timestamps. Performance regressions correlate with accidental chain bloat when engineers add unneeded intermediates.

Include openssl s_client check expiry practice in certification paths for production access. Gates that require demonstrated chain inspection reduce rookie mistakes during first on-call rotations.

Plain-language summary

Modern TLS serves multiple certificates in one handshake message. Customers blame the brand on the leaf, but technicians must inspect the entire message to explain trust errors that mention unknown issuers.

Saving handshake transcripts creates organizational memory. Future migrations compare cleanly against captured baselines instead of relying on veteran intuition alone.

Splitting PEM blocks is a skill worth classroom time. One afternoon lab prevents week-long outages when a new intermediate ages out unexpectedly.

Executives rarely want command details; they want serial change proof. Show before and after serial numbers sourced from showcerts captures to close debates quickly.

Vendor tickets move faster when customers attach showcerts output rather than screenshots of blade admin GUIs that hide intermediates.

Chain surprises cluster after mergers when two certificate cultures combine. Unified capture standards across acquired teams accelerate integration.

Treat showcerts captures as disposable secrets-adjacent artifacts: scrub before external sharing, retain internally for audit windows only.

When automation matures, humans still perform showcerts during high-risk changes. Automation catches drift; humans judge ambiguous CA migrations.

Quarterly drills should include one deliberately misordered bundle in staging. Teams practice PEM splitting and identify issuer mismatches without customer impact.

Record chain depth baselines after every major vendor change. Depth deltas alert before customers notice trust errors that dates alone might miss temporarily.

Executive dashboards may show only leaf days remaining, but engineering dashboards must show intermediate health pulled from showcerts archives.

Cross-training Windows and Linux responders ensures at least one person per bridge can split certificates regardless of laptop type in the war room.

Run showcerts before and after disabling legacy TLS versions. Cipher negotiations can change which listener answers, accidentally surfacing forgotten vhosts.

Encourage developers to attach showcerts when requesting infra changes affecting TLS. Reviewers merge with confidence instead of guessing hidden listener effects.

Maintain a shared drive folder per major hostname containing the last twelve monthly showcerts captures. Trend review meetings spot slow chain drift before it becomes customer-visible trust failure.

Assign secondary on-call reviewers to spot-check one random showcerts capture per week. Light auditing keeps skills sharp without heavy process overhead.

Publish anonymized before-and-after capture pairs internally when chain fixes succeed. Teams learn faster from real narratives than from bare command lists alone.

Invite security champions from product squads to monthly chain review lunches. Informal conversation surfaces edge cases formal docs miss until incidents strike.

Frequently asked questions

Can I check expiry without saving files?

Yes, with awk splitting as shown, or use openssl s_client with tooling that parses multiple PEM blocks. Saved files help incident attachments.

Why do I see extra certificates?

Some servers send cross-signed roots or outdated intermediates. Evaluate each notAfter; remove unnecessary roots from the send buffer per CA instructions.

Does `-showcerts` work with TLS 1.3?

Yes for the certificate message order defined by the protocol. Some deployments encrypt more of the handshake; cert inspection still yields PEM blocks on standard HTTPS.

What about mutual TLS?

When the server requests a client certificate, s_client may need -cert and -key. Expiry on the server chain is independent; still use -showcerts for the server side.

See what the server presents right now

Free live certificate check — no signup.