Configuring End-to-End TLS Encryption in Redis: Server, Client, Rotation
AI generated
SET
TTL
Redis / Security & Operations
Configuring End-to-End TLS Encryption in Redis
Server and client setup, performance overhead, and certificate rotation without downtime

Redis transmits connection data unencrypted by default, a state many internal networks tolerated for years because the instances mostly ran behind a firewall. But once cloud environments, container orchestration, or compliance requirements enter the picture, relying purely on network segmentation is no longer enough. Since Redis 6, TLS can be configured natively, including mutual authentication between client and server. This article covers how to set up end-to-end encryption cleanly on both the server and client side, what performance overhead TLS termination actually causes, how connection reuse and session resumption noticeably cut that overhead, and how certificate rotation succeeds in production without interrupting the connection.

11 min read TLS Setup Certificate Rotation

1. Why unencrypted Redis connections are a real risk

Redis was originally designed to operate inside a trusted internal network, where clients and server belonged to the same security zone. That model works fine in a classic server farm with a fixed network topology, but it quickly runs into limits in modern environments. Container orchestration, dynamic cloud networks, and multi-tenant infrastructure mean traffic between application and Redis instance increasingly crosses network segments that are no longer fully under your own control.

Without transport encryption, the entire traffic between application and Redis can be captured, including session data, credentials for other systems stored in the cache, and potentially sensitive business data from the product catalog. Particularly in regulated industries with requirements like PCI DSS or privacy-compliant processing of personal data, a plain firewall rule no longer counts as proof of encryption in transit, which is why TLS is increasingly treated as a baseline requirement rather than an optional hardening measure.

2. Server-side TLS configuration in redis.conf

Since Redis 6, the server ships with native TLS support activated through its own configuration directives, instead of requiring a front-end proxy like stunnel as before. The classic plaintext port can be disabled entirely, leaving only the encrypted TLS port available for incoming connections. Certificate, private key, and the trusted certificate authority are configured as file paths.

The tls-auth-clients directive controls whether the server requires a valid client certificate from every client, enforcing real mutual TLS, or whether one-directional encryption without client authentication is sufficient. For production environments with multiple application services, mutual TLS is recommended, because it not only encrypts the transport path but also cryptographically verifies the identity of every connecting service, something a plain password can never provide.


# redis.conf: enable TLS port, disable plaintext port
port 0
tls-port 6379
tls-cert-file /etc/redis/tls/redis.crt
tls-key-file /etc/redis/tls/redis.key
tls-ca-cert-file /etc/redis/tls/ca.crt
tls-auth-clients yes
tls-protocols "TLSv1.2 TLSv1.3"

3. Client-side TLS configuration and mutual TLS

On the client side, redis-cli for diagnostics as well as every application library needs to know the TLS parameters: its own certificate and private key for mutual TLS, and the CA certificate to verify the server's identity. Without server verification, traffic can still be encrypted, but a man-in-the-middle attack using a forged server certificate would go undetected, which is why CA verification should never be skipped, not even temporarily inside a supposedly safe internal network.

In a Magento context, the actual connection usually runs through phpredis as a PHP extension, which accepts TLS through a stream context array. The relevant options correspond to the same parameters as redis-cli, just as a PHP array instead of a command line flag, and they can be maintained centrally in the Magento deployment's env.php for the cache, session, and full page cache backend together.


# Connection test with redis-cli over TLS including a client certificate
redis-cli --tls \
  --cert /etc/redis/tls/client.crt \
  --key /etc/redis/tls/client.key \
  --cacert /etc/redis/tls/ca.crt \
  -h redis.internal -p 6379 PING

4. How much performance TLS termination actually costs

The most noticeable cost of TLS is not the ongoing traffic, but the initial handshake of a new connection. That handshake relies on asymmetric cryptography, negotiating a session key, and several network round trips before the actual payload can even flow. For short-lived connections that are established and closed again for every single request, this handshake can significantly outweigh the actual payload transfer in terms of time.

Once a connection is established, the ongoing encryption overhead barely registers. Modern CPUs come with AES-NI hardware acceleration for symmetric encryption, so throughput on already established TLS connections sits only a few percent below an unencrypted connection. The real performance lever therefore is not skipping TLS, but avoiding unnecessarily many new handshakes.

5. Connection reuse as the most important lever against TLS overhead

In PHP-based applications like Magento, the biggest TLS overhead often does not come from Redis itself but from the execution model: by default, every PHP-FPM process opens a new TCP and TLS connection for every request and closes it again at the end of that request. Under high request load, this repeated handshake adds up to measurable overhead that would not be visible with unencrypted connections.

phpredis supports persistent connections through pconnect, reusing the underlying TCP and TLS connection across multiple requests within the same PHP-FPM worker process. In practice, this means enabling persistent_connection specifically in the cache and session backend settings in Magento's env.php, so the expensive handshake only happens once per worker process instead of once per request.

6. Configuring TLS session resumption correctly

Even for non-persistent connections, handshake overhead can be reduced through TLS session resumption. The server remembers parameters of an already completed session in a session cache and allows a returning client an abbreviated handshake that skips the full asymmetric key exchange. That noticeably cuts both the network round trips and the CPU load of reconnecting.

In Redis, this behavior is controlled through tls-session-caching along with the associated cache size and timeout values. A cache size that is too small causes session entries to be evicted prematurely under load, largely negating the benefit, while a timeout that is too long keeps older session keys around unnecessarily, leaving a slightly larger window for compromise, which is why both values should be tuned to the actual connection pattern.


# redis.conf: enable session resumption for abbreviated handshakes
tls-session-caching yes
tls-session-cache-size 20000
tls-session-cache-timeout 300

7. Rotating certificates in production without downtime

A TLS certificate eventually expires, and a plain server restart to swap the certificate and key would interrupt every active cache and session connection in a production Magento setup. Since Redis 6.2, however, tls-cert-file and tls-key-file can be swapped at runtime through CONFIG SET, without restarting the process and without dropping existing connections.

The proven workflow is to deploy the new certificate and key on the server well before the actual expiry date, activate it through CONFIG SET, and then verify through a fresh TLS connection test that the server actually serves the new certificate. Only afterward is the old certificate marked invalid, so there is never a gap between an expired old certificate and a not-yet-active new one.


# Swap the certificate at runtime without restarting the server
redis-cli -a "$ADMIN_PASS" CONFIG SET tls-cert-file /etc/redis/tls/redis-new.crt
redis-cli -a "$ADMIN_PASS" CONFIG SET tls-key-file /etc/redis/tls/redis-new.key
redis-cli -a "$ADMIN_PASS" CONFIG REWRITE

8. Monitoring and verifying TLS handshakes

After every change to certificates or cipher configuration, it is worth verifying directly with openssl which certificate, expiry date, and negotiated cipher suite a connection actually uses. This test runs independently of the actual application and surfaces configuration mistakes before they cause connection failures in production.

In addition, certificate expiry should be tracked as its own monitoring metric, with an alert well ahead of the actual expiry, since an expired server certificate blocks all new connections while already established connections keep running for the moment but also fail once they need to reconnect. A monitoring script that checks the remaining validity window daily reliably prevents a certificate rotation from only surfacing through a production outage.


# Check negotiated TLS version, cipher, and certificate dates
openssl s_client -connect redis.internal:6379 \
  -cert client.crt -key client.key -CAfile ca.crt \
  -tls1_3 2>/dev/null | openssl x509 -noout -dates

9. Checklist for running TLS in production

A resilient production setup combines several measures: the plaintext port stays disabled entirely, mutual TLS is active for every service with write access, and the allowed cipher suites are explicitly restricted through tls-ciphers and tls-ciphersuites to modern algorithms considered secure, instead of relying on the default selection of the installed OpenSSL version.

TLS does not replace other security mechanisms, it complements them: a combined configuration of TLS for transport encryption, ACL rules for granular permissions, and clear network segmentation produces the most resilient setup in practice. For Magento environments, that concretely means the cache, session, and full page cache connections all use the same TLS configuration, so no unnoticed plaintext connection remains as a fallback option.

Operating Mode Connection Setup CPU Overhead Recommendation
No TLS plain TCP, minimal overhead none acceptable only inside fully isolated networks
TLS without client certificate full handshake per new connection low with connection reuse standard for connections crossing network boundaries
Mutual TLS (mTLS) handshake plus client certificate verification slightly higher than plain TLS service to service traffic with high protection needs
TLS with session resumption abbreviated handshake on reconnect noticeably reduced versus a full handshake production environments with many short-lived connections
TLS with persistent connections handshake only once per worker process practically negligible PHP-FPM based applications such as Magento

Mironsoft

Cache layer setup and Magento Redis integration

Magento cache that isn't quite working or is misconfigured?

We set up Redis as a cache and session backend for Magento cleanly, tune memory usage and eviction strategies, and make sure full page cache and session storage work together reliably.

Redis Setup

Configure the cache, session, and FPC backend production-ready for Magento.

Memory Tuning

Match memory usage and eviction policies to the shop's actual load.

High Availability Setup

Set up Redis Sentinel or Cluster for resilient Magento environments.

10. Summary

TLS in Redis: Key Takeaways

Native TLS since Redis 6

No proxy like stunnel needed anymore, TLS is configured directly through redis.conf with its own directives.

Handshake drives the cost

Not the ongoing traffic but every new connection setup causes the measurable overhead.

Connection reuse as the lever

Persistent connections in phpredis drastically reduce the number of expensive handshakes.

Certificate rotation without downtime

CONFIG SET swaps certificate and key at runtime, with no server restart at all.

11. FAQ: TLS in Redis: Key Takeaways

1Does Redis absolutely need a front-end proxy like stunnel for TLS?
No, since Redis 6, TLS is natively built into the server and controlled directly through configuration directives such as tls-port and tls-cert-file, without any additional proxy component.
2What is the difference between plain TLS and mutual TLS?
With plain TLS, only the server encrypts and proves its identity via a certificate. With mutual TLS, the client also presents its own certificate, so the server cryptographically verifies the client's identity as well.
3How large is the actual performance overhead of TLS in Redis?
The ongoing encryption overhead on established connections is only a few percent thanks to hardware acceleration, the real cost is the initial handshake on every new connection setup.
4How can handshake overhead be reduced in a PHP application?
Through persistent connections using phpredis pconnect, which reuses the same TCP and TLS connection across multiple requests within one PHP-FPM worker process.
5What does TLS session resumption actually achieve?
The server remembers parameters of a completed session in a session cache and allows a returning client an abbreviated handshake without a full asymmetric key exchange.
6Can a Redis certificate be swapped without restarting the server?
Yes, since Redis 6.2 via CONFIG SET for tls-cert-file and tls-key-file at runtime, without interrupting existing connections.
7How do I detect a soon-to-expire certificate in time?
Through a monitoring script that regularly checks the served certificate's expiry date via openssl and triggers an alert well before the actual expiry.
8Is TLS alone enough to secure a Redis instance?
No, TLS only secures the transport path. A resilient setup also needs ACL rules for granular permissions and clear network segmentation.
9Which cipher suites should be preferred for Redis TLS?
Modern suites considered secure, explicitly set via tls-ciphers for TLS 1.2 and tls-ciphersuites for TLS 1.3, instead of relying on the default selection of the installed OpenSSL version.
10What happens if an expired server certificate goes unnoticed?
New connection attempts fail because clients reject the expired certificate as invalid, while already established connections keep running for now but also fail once they need to reconnect.