Guide
nginx OCSP stapling with expiring certificates
Fix nginx ssl stapling problems near or past certificate expiry: verify ssl_stapling, resolver, chain files, and live OCSP responses after renew and reload.
Updated May 30, 2026 843 words
nginx ssl stapling failures often masquerade as mysterious handshake errors when the server leaf is near expiry, the OCSP responder returns revoked, or stapling still advertises a response tied to the previous certificate.
Nginx operators enable stapling for performance and privacy, then forget that stapled OCSP must track leaf renewal. After Certbot or a commercial reissue, nginx may present a fresh notAfter while ssl_stapling still caches an OCSP blob for the old serial.
This guide centers on nginx ssl stapling during expiry incidents—not generic cipher tuning. You will confirm the served leaf, validate the stapled response with openssl, and reload nginx only after chain files and resolver settings align.
Stapling regressions cluster around renewal weekends: operators replace leaf PEMs Friday evening, reload nginx once, and leave without -status verification. Saturday morning mobile clients with aggressive OCSP stapling validation fail while desktop browsers without staple checks appear fine. Bake stapling smoke tests into deploy pipelines beside notAfter assertions.
nginx ssl stapling interacts with short-lived Let’s Encrypt leaves because responders expect fresh stapling fetches every reload cycle. Longer commercial certs still need resolver health checks quarterly—DNS firewall changes can silently kill OCSP reachability months before expiry.
What to check
Compare three clocks: leaf notAfter, OCSP thisUpdate and nextUpdate, and nginx worker reload time. Stapling problems can appear before the leaf expires if responders revoke early or cache files go stale.
Ensure ssl_trusted_certificate points at the issuer chain nginx needs to verify OCSP signatures. Missing intermediates break stapling verification in clients even when the leaf date looks fine.
Distinguish edge CDN TLS from nginx origin. External monitors must hit the layer users reach; stapling on origin does not help if the CDN serves a different cert.
If nginx ssl stapling is off, clients still fetch OCSP—symptoms differ. This guide assumes stapling is on and misbehaving around renewal windows.
Review error.log for resolver or upstream OCSP warnings during the incident window. Stapling failures often log before clients complain. When nginx runs in containers, confirm resolvers inside the container match host networking expectations after orchestrator CNI upgrades.
Step-by-step
Capture live leaf and stapling status
HOST=www.example.com
echo | openssl s_client -connect "${HOST}:443" -servername "${HOST}" -status 2>/dev/null \
| openssl x509 -noout -dates -serial
The -status flag prints OCSP Response Data when nginx staples successfully.
Inspect nginx TLS configuration
sudo nginx -T 2>/dev/null | grep -A5 ssl_stapling
Confirm ssl_stapling on, ssl_stapling_verify on, ssl_trusted_certificate, and resolver with valid IPv4 or IPv6 DNS for the CA’s OCSP URL.
Verify PEM paths match the renewed bundle
sudo openssl x509 -in /etc/letsencrypt/live/example/fullchain.pem -noout -dates -serial
grep ssl_certificate /etc/nginx/sites-enabled/example.conf
Paths must reference fullchain.pem for stapling verification, not only cert.pem.
Test OCSP manually for the current leaf
openssl ocsp -issuer /etc/letsencrypt/live/example/chain.pem \
-cert /etc/letsencrypt/live/example/cert.pem \
-url "$(openssl x509 -in /etc/letsencrypt/live/example/cert.pem -noout -ocsp_uri)" \
-header "Host" "$(openssl x509 -in /etc/letsencrypt/live/example/cert.pem -noout -ocsp_uri | sed 's|https\?://||' | cut -d/ -f1)"
A revoked or unknown status while the leaf is still valid breaks stapling for strict clients.
Renew, deploy, and reload nginx
sudo certbot renew --cert-name example.com
sudo nginx -t && sudo systemctl reload nginx
After commercial renewals, copy PEMs to the paths referenced in vhosts before reload.
Re-test stapling from outside
echo | openssl s_client -connect "${HOST}:443" -servername "${HOST}" -status 2>/dev/null | grep -A12 "OCSP Response"
Align worker count with reload discipline
After systemctl reload nginx, old workers finish in-flight connections while new workers load PEM and OCSP cache state. High worker_connections with sticky clients can prolong stale staple visibility for minutes. For severe incidents, plan a controlled second reload or brief maintenance window once leaf and chain files are verified correct on disk.
How to read the output
Leaf notAfter in the past means the primary outage is expiry; fix renewal first, then revisit stapling. When dates are valid but OCSP Response Status: successful is missing, nginx did not staple—check resolver errors in error.log.
OCSP Response Data should reference the same serial as the leaf certificate block above it in s_client output. Serial mismatch means workers still cache an old staple or nginx started before new files landed.
nextUpdate in the past tells you responders consider the staple stale. Reload nginx after PEM replacement to force a new fetch.
In nginx -T output, absence of resolver while using stapling against CAs that require DNS resolution is a common root cause—nginx logs may show upstream OCSP timeouts.
Common mistakes
Reloading nginx before Certbot deploy hooks finish writing fullchain and privkey, stapling the old OCSP against a half-updated file set.
Pointing ssl_certificate at fullchain but ssl_trusted_certificate at the wrong intermediate file after a CA migration.
Using ssl_stapling on self-signed or private-CA certs without configuring responders—stapling should stay off in those designs.
Chasing stapling while the real issue is an expired leaf at a CDN; openssl from a laptop hits Cloudflare, while nginx logs on the origin look perfect.
Omitting IPv6 resolver addresses when the OCSP host resolves only to AAAA records in your region.
Skipping certbot renew failed triage when renewal never advanced notAfter before stapling tests.
Duplicating stapling directives in both http and stream blocks without testing each listener leaves SMTP or LDAP TLS frontends with different staple behavior than HTTPS vhosts on the same host. Include alternate ports in external monitoring when they terminate TLS with nginx.
When to use automation
OCSP and stapling freshness are invisible to disk-only monitoring. A renewed PEM on disk with broken resolver settings leaves users unhappy while cron mail claims success.
ssldays performs live TLS handshakes from the outside, surfacing expiry and trust behavior customers experience—including cases where CDN and origin differ. RDAP adds registrar context for names you renew with ACME. Threshold alerts at 30, 14, 7, and 1 days give runway before stapling and leaf expiry overlap badly. All plans include email; Slack and Discord webhooks land on paid tiers. Free covers three domains daily; Starter 25 hourly; Pro 100 hourly.
Validate north-south hostnames on live check, then schedule monitoring at register. After chain fixes, cross-check trust with openssl verify certificate chain before closing the ticket.
Frequently asked questions
Does stapling work with Let’s Encrypt?
Yes when ssl_trusted_certificate includes the issuer chain and resolver reaches Let’s Encrypt OCSP endpoints. Fullchain paths must stay synchronized after every renew.
Can I disable stapling during incidents?
Temporarily set ssl_stapling off and reload to isolate staple cache issues, then re-enable after leaf and chain files are correct.
Why does only Android fail?
Some mobile stacks validate staples aggressively. Compare openssl -status output with failing device captures.
Should I restart instead of reload?
reload is enough when PEM paths are stable. Use restart only when nginx workers appear wedged or error.log shows repeated OCSP fetch failures after reload.
Monitor this hostname on a schedule
Live certificate checks and renewal reminders — not guesswork from PEM files.