Skip to content

RTFM · Healthchecks

lb.saphira.https: the HTTP transaction, over TLS

Everything the http check proves, plus the full TLS handshake to the real server: protocol negotiated, cipher agreed, certificate served. Built for backends that terminate TLS themselves; the pass-through architecture.

Saphira Linux dragon mascot

What it proves

A complete HTTPS transaction against real:$4: TCP connect, TLS handshake, HTTP request, HTTP response, status (or body) verified. On a pass-through design: HAProxy or LVS forwarding encrypted bytes, webDragon owning the certificate; this is the honest end-to-end check: it exercises exactly the path a real client exercises.

Certificate verification: off by default, and why

The check does not verify the certificate chain by default. That is deliberate: backends frequently terminate TLS with service certificates issued by an internal CA, or with a name that differs from the address we dial. The check's promise is the transaction, not public PKI validation. When the backend presents a certificate the check must validate, set the knob; the failure then becomes visible instead of silent.

Knobs
VariableDefaultMeaning
LB_SAPHIRA_TLS_VERIFY01 = enforce certificate verification (drop curl's -k)
LB_SAPHIRA_HTTP_PATH/Path to request
LB_SAPHIRA_HTTP_HOST-Host: header; also drives SNI via curl
LB_SAPHIRA_HTTP_OK^(2|3)[0-9][0-9]$Status-class regex (status mode)
LB_SAPHIRA_HTTP_EXPECT-Body regex: switches to body mode when set
LB_SAPHIRA_TIMEOUT3Whole-transaction --max-time

Wiring it up

ldirectord
# /etc/ha.d/ldirectord.cf
virtual = [2001:db8:10::10]:443
    protocol = tcp
    scheduler = wlc
    real = [2001:db8:20::11]:443 gate 1
    checktype = external
    checkcommand = "/var/lib/lb/saphira/lb.saphira.https"
HAProxy
# haproxy.cfg
global
    external-check

backend app_pool
    mode tcp
    option external-check
    external-check command "/var/lib/lb/saphira/lb.saphira.https"
    server app1 192.168.20.30:443 check inter 5s fall 3 rise 2

Dual-stack works naturally: hand the check a bracketed IPv6 literal as $3 and curl talks to it directly.

Run it by hand

Manual run
LB_SAPHIRA_HTTP_HOST=www.example.com \
  /var/lib/lb/saphira/lb.saphira.https web-tls 443 192.168.20.30 443
echo $?
# 0 = TLS + HTTP transaction completed within the status class
# 1 = handshake failure, protocol failure, or status/body mismatch

Failure modes

  • Handshake alert: expired/missing certificate, no common TLS version: the TLS layer broke, tcp alone would have passed
  • Status outside the class: the app failed behind a healthy TLS layer
  • With TLS_VERIFY=1: chain or hostname failures; the certificate story changed

Did we miss something?

If this page left something unanswered, found an error, or there is another subject you would like documented, tell us. Saphira’s documentation grows from real problems people need to solve.

Send feedback or request a new section →

Prefer not to do it yourself?

Everything needed to do the work yourself is documented here and remains free; we charge for human time, not for withholding knowledge. Sometimes the missing resource is simply time. The same people who build Saphira can provide paid professional help with implementation, migration, troubleshooting and administration.

Ask about professional support →