Skip to content
ssldays

Guide

HAProxy terminate SSL with expired cert

Fix HAProxy terminate SSL when the frontend certificate expired: ssl bind lines, ALPN, crt bundles, backend plain HTTP, and post-reload openssl checks.

Updated May 30, 2026 819 words

When HAProxy terminate SSL serves an haproxy ssl certificate expired leaf, clients fail at the proxy while backends on plain HTTP may still look healthy in logs.

Terminate mode ends TLS on the frontend bind, then forwards decrypted traffic to backend servers. Certificate expiry is entirely a frontend problem unless you also re-encrypt to upstreams with ssl verify.

Operators confuse passthrough with terminate during incidents, running openssl against a backend Apache instance while users hit HAProxy’s expired bind. This guide focuses on terminate SSL frontends and the PEM paths they load.

Terminate SSL designs often pair with Web Application Firewall inspection on decrypted HTTP headers. WAF vendors may still initiate separate TLS sessions upstream; keep a diagram of TLS hops pinned in the wiki so haproxy ssl certificate expired drills do not send teams fixing Apache unnecessarily.

Product microservices behind HAProxy may log only HTTP layer errors when terminate mode fails—aggregated 502 rates without TLS detail should trigger external openssl from synthetic monitoring.

What to check

Confirm the frontend bind includes ssl and references crt, a certificate directory, or crt-list. Note ALPN and HTTP mode settings—they affect client behavior but not expiry diagnosis.

Backends using httpchk without SSL will stay green while TLS clients see expired certificates on port 443.

If http-request set-header X-Forwarded-Proto https is present, applications may think TLS is fine even when the public bind expired—trust external probes, not app logs alone.

Identify whether corporate clients pin certificates or use custom trust stores; renewal may require distributing new roots separate from HAProxy PEM work.

When HAProxy injects client certificates to backends for identity, do not conflate those client cert expiries with the terminate bind cert users see in browsers.

Step-by-step

Prove expiry on the terminate frontend

HOST=app.example.com
echo | openssl s_client -connect "${HOST}:443" -servername "${HOST}" 2>/dev/null \
  | openssl x509 -noout -dates -serial -subject

Map frontend to backend topology

awk '/^frontend|^backend|^bind|^server/ {print}' /etc/haproxy/haproxy.cfg

Terminate layouts show mode http or tcp frontends with bind :443 ssl crt and backends on private HTTP ports.

Update concat PEM for the ssl bind

DOMAIN=app.example.com
sudo bash -c "cat /etc/letsencrypt/live/${DOMAIN}/fullchain.pem \
  /etc/letsencrypt/live/${DOMAIN}/privkey.pem \
  > /etc/haproxy/certs/${DOMAIN}.pem"
sudo chown root:haproxy /etc/haproxy/certs/${DOMAIN}.pem
sudo chmod 640 /etc/haproxy/certs/${DOMAIN}.pem

Align crt-list if the hostname uses SNI mapping instead of directory defaults.

Config test and graceful reload

sudo haproxy -c -f /etc/haproxy/haproxy.cfg
sudo systemctl reload haproxy

Watch systemctl status haproxy for reload success on both nodes in HA pairs.

Validate application path

curl -sI --connect-timeout 10 "https://${HOST}/"

For deeper client perspective, see curl SSL certificate expired symptoms alongside openssl.

Document which frontends use tcp mode inspection versus full terminate so junior engineers pick the right PEM directory during overnight pages.

Optional upstream re-encrypt checks

When backends use server ... ssl, probe upstream certificates separately—they are not the terminate bind cert users complain about first.

How to read the output

openssl notAfter in the past on port 443 confirms terminate frontend expiry. curl failures with certificate errors align with browser reports when HAProxy is the TLS endpoint.

serial change after reload proves new material is served. Unchanged serial with updated files means reload missed a node or crt-list still aims at an old path.

Backend server lines without ssl indicate plain HTTP behind terminate—do not waste time renewing backend PEMs unless a second TLS hop exists.

haproxy -c success is mandatory; bind errors referencing missing key files usually mean bad concat order or permissions.

Common mistakes

Renewing backend nginx certificates while HAProxy terminate SSL bind still serves the expired enterprise cert customers pin.

Using TCP mode frontend with ssl bind but forgetting crt on secondary public IPs per anycast POP.

Health checks over HTTP to backends masking TLS outages at the edge.

Mixing terminate and passthrough frontends on the same IP without SNI planning—default cert expiry breaks miscellaneous hostnames.

Reloading only one HAProxy peer in active-active Anycast while BGP steers users to the stale member.

Applying HTTP to HTTPS redirects in backends without fixing HAProxy expired cert first—clients never reach redirects.

Session persistence cookies set at HAProxy survive cert fixes but confused testers using old browser tabs may cache HSTS failures—document retest steps with fresh profiles.

Finance APIs behind terminate SSL often require partner notification when leaf issuers change even if expiry was the incident driver—add comms steps beside technical renew.

Run tabletop exercises where developers propose fixing application code first; good drills reinforce that HAProxy terminate SSL expiry is solved at the bind before any hotfix deploy pipeline runs.

Post-incident reviews should list every frontend name, not only the hostname marketing reported. Latent alternate names on the same bind may still serve expired defaults until the next partner integration test.

Keep a printed one-page map of terminate frontends above the NOC desk during holiday freeze periods when contractor staff cover pages.

When to use automation

Terminate SSL architectures centralize trust at HAProxy. A single missed frontend PEM affects every backend application behind it.

ssldays performs live TLS checks against public hostnames, surfacing expiry and chain issues at the edge where terminate mode ends the handshake. RDAP helps align long domain renewals with shorter certificate lifetimes. Alerts at 30, 14, 7, and 1 days give lead time for HA pair reloads. Email included everywhere; Slack and Discord webhooks on paid plans. Free monitors three domains daily; Starter 25 hourly; Pro 100 hourly.

After openssl shows fresh dates on live check, register production URLs at register. For bind path drift, pair with Haproxy SSL certificate expired and path renewal docs in the same change.

Frequently asked questions

Do backends need certificates?

Not for plain HTTP backends. They need certs only when server ... ssl re-encrypts to upstreams.

Can I terminate at HAProxy and Cloud CDN?

Often CDN is another TLS hop. Fix the layer openssl hits from the public internet—CDN cert versus HAProxy cert diagnoses differ.

Does HTTP/2 require special renew steps?

ALPN on the bind survives reload. Expiry breaks both HTTP versions equally once the leaf is invalid.

When should I use passthrough instead?

When you want backends to own TLS lifecycle. Passthrough shifts this guide’s steps to those servers instead of HAProxy binds.

Monitor this hostname on a schedule

Live certificate checks and renewal reminders — not guesswork from PEM files.