#!/bin/sh # Install /etc/certificates/site.pem into the *running* HAProxy over its runtime # API — no restart, no dropped connections. # # Every answer is inspected. The runtime API reports a refusal in the reply text # and still closes the connection cleanly, so socat exits 0 either way: the # unchecked version sent set, commit and show in a row and reported success # while HAProxy went on serving the old certificate. If HAProxy ever reworded # these replies the checks would raise a false alarm, which is the safe # direction for the error to point — site.pem on the shared volume is correct # regardless, and HAProxy loads it from there on its next restart. CERT_PATH=/usr/local/etc/haproxy/certificates/site.pem SRC=/etc/certificates/site.pem # A unix socket on a volume shared with HAProxy, not a TCP port: the private key # below travels this channel in the clear, and file permissions are the only # access control a container-to-container path can have. API="UNIX-CONNECT:/var/lib/haproxy/admin.sock" update_haproxy_cert() { if [ ! -s "$SRC" ]; then echo "3-update-haproxy-cert.sh: $SRC is missing or empty, nothing to install" >&2 return 1 fi # Start transaction. The payload ends with a blank line — that is what closes # a << block on the runtime API. retry= is what waits out a HAProxy that is # still coming up. answer=$( printf 'set ssl cert %s <<\n%s\n\n' "$CERT_PATH" "$(cat "$SRC")" \ | socat - "$API,retry=30,interval=2" 2>&1 ) || { echo "3-update-haproxy-cert.sh: cannot reach the HAProxy runtime API: $answer" >&2 return 1 } case "$answer" in *"Transaction created"*) ;; *) echo "3-update-haproxy-cert.sh: HAProxy refused the certificate: $answer" >&2 return 1 ;; esac # Commit transaction answer=$(echo "commit ssl cert $CERT_PATH" | socat - "$API" 2>&1) || { echo "3-update-haproxy-cert.sh: cannot reach the HAProxy runtime API: $answer" >&2 return 1 } case "$answer" in *Success*) ;; *) echo "3-update-haproxy-cert.sh: HAProxy refused to commit the certificate: $answer" >&2 return 1 ;; esac } if update_haproxy_cert; then # Show certification info (not essential) — it is what puts the live # certificate's dates in the container log. echo "show ssl cert $CERT_PATH" | socat - "$API" 2>&1 || true else echo "3-update-haproxy-cert.sh: the running HAProxy still serves its previous certificate" >&2 fi