Skip to content

Redis over TLS: rediss:// and rediss-cluster:// URLs, and a private CA - #82

Merged
fylorn merged 1 commit into
devfrom
fix/redis-tls
Oct 5, 2026
Merged

fylorn merged 1 commit into
devfrom
fix/redis-tls

Conversation

@fylorn

@fylorn fylorn commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

rediss:// URLs did not work: fred was built without TLS, treated rediss:// as plain TCP, and the server exited at startup (Failed to connect to Redis: Protocol Error: Expected string.). Managed Redis services usually require TLS (ElastiCache with in-transit encryption, Upstash, Azure Cache, Redis Cloud), so such deployments could not start.

  • All four Redis clients take their configuration from a new common::redis_config, which sets up rustls (aws-lc-rs, system CA store via rustls-platform-verifier, the same stack reqwest uses). Enabling fred's own enable-rustls panicked in the full build, because two rustls crypto backends are compiled in. No new crates in Cargo.lock, no OpenSSL; the Docker image needs no change.
  • rediss:// and rediss-cluster:// work. REDIS_CA_CERT (a PEM path) trusts a private CA instead of the system store; Helm mounts it from redis.caSecret. No client certificates.
  • Helm README, .env.example and CHANGELOG [Unreleased] → Fixed.
  • Tested for real: two server instances over a TLS-only Redis 8 (health, config-change notices across instances), a three-primary TLS cluster, and failure cases (untrusted certificate, missing CA file). tests/redis_tls.rs runs with TEST_REDIS_TLS_URL and skips without it; the whole integration suite also passed over TLS. A flaky cluster config-notice test now re-sends until the subscriber receives it.

Local: fmt, clippy (lib/bins and tests), 740 unit tests, 404 integration tests on plain Redis and again over TLS.

🤖 Generated with Claude Code

fred was built without a TLS feature, so a rediss:// URL was dialled as
plain TCP. Against a Redis that only speaks TLS - what ElastiCache with
in-transit encryption, Upstash, Azure Cache and Redis Cloud require - the
server exited at startup with "Failed to connect to Redis: Protocol
Error: Expected string."

Turning on fred's enable-rustls alone is not enough: fred then builds
its connector with rustls's process-default crypto provider, and this
binary compiles in two (aws-lc-rs through reqwest 0.13, ring through the
reqwest 0.12 under openidconnect), so rustls panics instead of choosing.
think_watch_common::redis_config builds the connector itself, with
aws-lc-rs and rustls-platform-verifier - the stack reqwest already uses
for upstream HTTPS - and every Redis client the server makes (the
command client and the three Pub/Sub subscribers) takes its config from
there. No new crates and no OpenSSL: the static musl image is
unchanged, and the system roots it already ships for upstream HTTPS
cover the managed services' public CAs.

REDIS_CA_CERT names a PEM file for a Redis whose certificate a private
CA signed; its certificates are then the only roots trusted, as with
redis-cli --cacert. The Helm chart mounts it from a Secret
(redis.caSecret). Client certificates are not supported.

tests/redis_tls.rs runs the limit scripts, the gateway (limits,
readiness, config notices) and a refused untrusted certificate against
TEST_REDIS_TLS_URL, and skips without it. TEST_REDIS_CA_CERT lets the
whole suite and the cluster tests run against TLS too. The config
notice round-trip now resends the notice until it arrives: fred's
subscribe can return before Redis holds the subscription, and a PUBLISH
right after it was seen to reach no one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@fylorn
fylorn merged commit 4075855 into dev Oct 5, 2026
6 checks passed
@fylorn
fylorn deleted the fix/redis-tls branch October 5, 2026 09:59
@fylorn fylorn mentioned this pull request Oct 5, 2026
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.

1 participant