Skip to content

[stable/redis-ha] Add optional encrypted communication between HAProxy and Redis/Sentinel#391

Open
meteozond wants to merge 1 commit intoDandyDeveloper:masterfrom
meteozond:feature/improve-haproxy-tls
Open

[stable/redis-ha] Add optional encrypted communication between HAProxy and Redis/Sentinel#391
meteozond wants to merge 1 commit intoDandyDeveloper:masterfrom
meteozond:feature/improve-haproxy-tls

Conversation

@meteozond
Copy link

@meteozond meteozond commented Mar 6, 2026

What this PR does / why we need it:

Problem: HAProxy ignores TLS settings and always connects to Redis/Sentinel backends via plaintext. Even when TLS is enabled (redis.tlsPort, sentinel.tlsPort), traffic between HAProxy and backends remains unencrypted. If plaintext ports are disabled (redis.port: 0, sentinel.port: 0), HAProxy breaks entirely as it has no TLS fallback. Specifically:

  1. Sentinel port is hardcoded as 26379sentinel.port/sentinel.tlsPort values are ignored
  2. HAProxy backend connections to Sentinel (check_if_redis_is_master_*) have no TLS support — no ssl, no ca-file options
  3. HAProxy backend connections to Redis (bk_redis_master, bk_redis_slave) always use redis.port, ignoring redis.tlsPort
  4. HAProxy frontend TLS (haproxy.tls.enabled) replaces plaintext on containerPort — there is no option to serve both plaintext and TLS simultaneously on separate ports

Solution:

  • Backend Sentinel TLS: Replace hardcoded 26379 with sentinel.tlsPort (when set) or sentinel.port. Add ssl verify required ca-file and crt (client certificate) to server lines when sentinel.tlsPort is set.
  • Backend Redis TLS: Use redis.tlsPort (when set) instead of redis.port. Add ssl verify required ca-file and crt (client certificate) to server lines when redis.tlsPort is set.
  • Backend mTLS: HAProxy presents a client certificate when connecting to Redis/Sentinel backends (required when tls-auth-clients is enabled on Redis). The init container generates a combined PEM (backend-tls.pem) from tls.certFile + tls.keyFile.
  • Health checks: tcp-check connect default is used for all backends, which inherits SSL settings from the server line (including ca-file and crt). This replaces the previous plain tcp-check connect.
  • Dedicated frontend TLS port: New value haproxy.tlsPort. When set together with haproxy.tls.enabled, plaintext stays on containerPort and TLS binds to tlsPort. When not set, current behavior is preserved (TLS replaces plaintext on containerPort).
  • Certificate mounting: When backend TLS is active, the tls.secretName secret is mounted into the HAProxy pod at /tls-certs/ (both init and main containers).

All changes are fully backward compatible — new behavior requires explicit
opt-in via tlsPort values that default to nil.

Special notes for your reviewer:

Backward compatibility verified: helm template output is identical for all existing CI value files (haproxy-enabled-values.yaml, multi-value-configs-values.yaml) and default render (no values) before and
after changes.

New values summary:

Value Default Description
haproxy.tlsPort ~ (nil) Dedicated TLS frontend port. When set with haproxy.tls.enabled, serves plaintext on containerPort and TLS on tlsPort

Existing values that now affect HAProxy backend behavior:

Value Effect on HAProxy
sentinel.tlsPort HAProxy connects to Sentinel via TLS on this port
redis.tlsPort HAProxy connects to Redis via TLS on this port
tls.secretName Secret mounted into HAProxy pod for backend TLS certs
tls.caCertFile CA cert filename used in HAProxy ssl ca-file directive
tls.certFile Client cert filename, combined with key into backend-tls.pem
tls.keyFile Client key filename, combined with cert into backend-tls.pem

Testing

  • Added ci/tls-enabled-values.yaml — CI test values covering the full TLS scenario: HAProxy with backend TLS to Redis (6479) and Sentinel (26479), frontend TLS on dedicated port (6381), and plaintext on default port (6379)
  • Updated .github/workflows/test.yaml:
    • Generate self-signed TLS certificates (openssl req -x509) before tests
    • Create a combined PEM (tls.pem) and CA cert (ca.crt) from the same cert
    • Create test-tls-secret in a fixed ct-test namespace with all cert files
    • Run ct install --namespace ct-test so all test releases can access the secret
  • All three CI value files pass ct lint and ct install: haproxy-enabled-values.yaml, multi-value-configs-values.yaml, tls-enabled-values.yaml

Values changes

  • Added haproxy.tlsPort (default ~) — dedicated TLS frontend port
  • Changed haproxy.tls.keyName default from empty to tls.pem
  • Changed tls.secretName from commented-out to explicit empty string ""
  • Changed haproxy.affinity and affinity from multiline | to ""
  • Added serviceAnnotations, podAnnotations to top-level values
  • Added commented-out examples for securityContext.sysctls, containerSecurityContext.runAsUser, capabilities.add, redis.lifecycle.postStart
  • Changed exporter.sslEnabled from commented-out to explicit false

Additional changes

  • Added values.schema.json with JSON Schema validation for haproxy, redis, sentinel, and tls sections
  • Chart version bumped from 4.35.10 to 4.36.0

Checklist

[Place an '[x]' (no spaces) in all applicable fields. Please remove unrelated
fields.]

  • DCO
    signed
  • Chart Version bumped
  • Variables are documented in the README.md
  • Title of the PR starts with chart name (e.g. [stable/mychartname])

@meteozond meteozond force-pushed the feature/improve-haproxy-tls branch 3 times, most recently from ffec1e8 to ca3ae48 Compare March 6, 2026 21:48
…y and Redis/Sentinel

Signed-off-by: Alexander Klimenko <alex@erix.ru>
@meteozond meteozond force-pushed the feature/improve-haproxy-tls branch from ca3ae48 to 2ff178d Compare March 6, 2026 21:50
@DandyDeveloper
Copy link
Owner

I'll try to jump on this during the week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants