Files
certctl/docs/reference/connectors/haproxy.md
T
shankar0123 082b8cf660 docs: Phase 4 follow-on batch 3 — 5 file-based target per-pages
Extracts the file-based deploy target connectors:

- haproxy.md (107 lines) — combined-PEM (cert+chain+key) deploy with
  haproxy -c validate; multi-frontend + crt-list directory guidance
- traefik.md (105 lines) — file-provider zero-reload deploy; file
  watcher latency notes; mixing with built-in ACME guidance
- caddy.md (100 lines) — admin API mode (recommended) vs file mode;
  admin-API exposure threat model
- envoy.md (112 lines) — file SDS mode (recommended) vs static
  bootstrap; service-mesh interactions
- postfix.md (175 lines) — dual-mode (Postfix MTA / Dovecot IMAPS)
  connector with daemon-specific quirks (STARTTLS chain expectations,
  no shared session cache); Bundle 11 test pins

Index forward-list expanded to enumerate all 10 target connectors
(5 from Phase 4 structural + 5 from this batch) in alphabetical
order.

This is part 3 of 4 for the Phase 4 follow-on (per-connector page
extraction) tracked in cowork/docs-overhaul-phase-2-restructure-2026-05-04/log.md.

Net add: 5 files, 599 lines. No content removed from index.md.
2026-05-05 04:02:25 +00:00

4.0 KiB

HAProxy Connector — Operator Deep-Dive

Last reviewed: 2026-05-05

Operator-grade documentation for the HAProxy target connector. For the connector-development context (interface contract, registry, atomic deploy primitive shared across all targets), see the connector index.

Overview

HAProxy differs from NGINX and Apache in one important way: it expects all TLS material in a single combined PEM file — certificate, intermediate chain, and private key concatenated. The connector builds this combined file, writes it with 0600 permissions (since it contains the private key), optionally validates the HAProxy configuration, and reloads.

Implementation lives at internal/connector/target/haproxy/.

When to use this connector

Use the HAProxy connector when:

  • HAProxy fronts your applications and you want certctl to rotate the cert + chain + key in place atomically without hand-rolling the combined-PEM build.
  • You want validate-before-reload behaviour to keep a bad config from taking down the load balancer mid-rotation.

Look elsewhere when:

  • You're running HAProxy Enterprise's hot-cert-update API path — the connector currently uses the file-write-and-reload model; the API path is on the V3-Pro roadmap.
  • You're not running HAProxy directly but a managed load balancer (AWS ALB, Azure Application Gateway). Use the cloud-native target connector for that platform instead.

Configuration

{
  "pem_path": "/etc/haproxy/certs/site.pem",
  "reload_command": "systemctl reload haproxy",
  "validate_command": "haproxy -c -f /etc/haproxy/haproxy.cfg"
}

The combined PEM is built in this order: server certificate, intermediate / chain certificates, private key.

The validate_command is optional — if omitted, the connector skips config validation and goes straight to reload. Keeping it on is the production-recommended posture.

Deploy contract

Every cert deploy follows the Bundle I deploy.Apply(ctx, plan) flow:

  1. Idempotency check — SHA-256 over the combined PEM bytes; skip if the destination already matches.
  2. Pre-deploy backup — copy existing PEM to <pem_path>.certctl-bak.<unix-nanos>.
  3. Atomic write — temp-file + chown + atomic rename.
  4. PreCommit (validate) — runs haproxy -c -f /etc/haproxy/haproxy.cfg. Failure aborts; no live cert touched.
  5. Atomic rename — temp → final.
  6. PostCommit (reload) — runs systemctl reload haproxy (or the operator's override).
  7. Post-deploy TLS verify — dials the configured endpoint when configured; pulls leaf cert SHA-256; compares against deployed bytes. Mismatch triggers automatic rollback.

Operator playbook

Old cert served via session resumption

HAProxy keeps TLS sessions alive for the configured tune.ssl.lifetime (default 1h). Resumed clients see the OLD cert until their session expires. Post-deploy verify in certctl returns the NEW cert from a fresh handshake; warm clients see the OLD cert until session expiration.

Multi-frontend deployments

When HAProxy serves multiple frontends with different certs, configure one target per frontend's cert in the certctl control plane. Each gets its own pem_path. The reload command is shared (HAProxy reloads all frontends together), so the deploys can land in any order; the final reload picks them all up.

crt-list directories

If your HAProxy config uses a crt-list directory rather than a single PEM, set pem_path to a file inside the directory and let HAProxy enumerate it on reload. The connector treats pem_path as a single file regardless of HAProxy's directory semantics.

  • Connector index — interface contract, registry, deploy primitive
  • NGINX — separate-file deploy contract counterpart
  • Apache — separate-file deploy contract with apachectl configtest
  • Migration: ACME from HAProxy — pattern for pointing edge proxies at certctl's ACME server (Caddy walkthrough; HAProxy ACME plumbing is similar)