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

108 lines
4.0 KiB
Markdown

# 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](index.md).
## 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
```json
{
"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.
## Related docs
- [Connector index](index.md) — interface contract, registry, deploy primitive
- [NGINX](nginx.md) — separate-file deploy contract counterpart
- [Apache](apache.md) — separate-file deploy contract with `apachectl configtest`
- [Migration: ACME from HAProxy](../../migration/acme-from-caddy.md) — pattern for pointing edge proxies at certctl's ACME server (Caddy walkthrough; HAProxy ACME plumbing is similar)