Introduction Redis TLS connections fail when the client cannot validate the server's certificate chain. This commonly occurs after certificate rotation, when using self-signed certificates, or when the CA bundle is not properly distributed to all application servers connecting to Redis.
Symptoms - `ERR TLS handshake failed` in Redis server logs - Python redis-py: `ssl.SSLCertVerificationError: certificate verify failed` - Node.js ioredis: `Error: self-signed certificate in certificate chain` - Java Jedis/Lettuce: `javax.net.ssl.SSLHandshakeException: PKIX path building failed` - Connections fail immediately without any data transfer
Common Causes - Server certificate expired or not yet valid - CA certificate not in the client's trusted CA bundle - Server certificate hostname does not match the connection hostname (SAN mismatch) - Intermediate CA certificate missing from the server's certificate chain - Client configured with `ssl_cert_reqs=CERT_REQUIRED` but no CA file provided
Step-by-Step Fix 1. **Verify the server certificate details**: ```bash openssl s_client -connect redis.example.com:6380 -showcerts </dev/null 2>/dev/null | \ openssl x509 -noout -dates -subject -issuer # Check: # notBefore and notAfter for validity period # subject: CN=redis.example.com # issuer: CN=My CA ```
- 1.Check the full certificate chain:
- 2.```bash
- 3.openssl s_client -connect redis.example.com:6380 -showcerts </dev/null 2>/dev/null | \
- 4.awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/{if(/BEGIN CERTIFICATE/){c++}; print > "cert"c".pem"}'
- 5.# Verify the chain
- 6.openssl verify -CAfile cert1.pem cert2.pem cert3.pem
- 7.
` - 8.Configure Redis server with proper certificate chain:
- 9.
` - 10.# redis.conf
- 11.tls-port 6380
- 12.port 0
- 13.tls-cert-file /etc/redis/tls/redis-server.crt
- 14.tls-key-file /etc/redis/tls/redis-server.key
- 15.tls-ca-cert-file /etc/redis/tls/ca.crt
- 16.tls-auth-clients optional
- 17.
` - 18.Configure Python client with correct CA bundle:
- 19.```python
- 20.import redis
client = redis.Redis( host='redis.example.com', port=6380, ssl=True, ssl_ca_certs='/etc/redis/tls/ca.crt', ssl_certfile='/etc/redis/tls/client.crt', ssl_keyfile='/etc/redis/tls/client.key', ssl_check_hostname=True ) client.ping() ```
- 1.For development/testing, temporarily disable verification:
- 2.```python
- 3.import redis
- 4.import ssl
client = redis.Redis( host='redis.example.com', port=6380, ssl=True, ssl_cert_reqs=ssl.CERT_NONE # Only for testing! ) ```
- 1.Automate certificate renewal with certbot or ACME:
- 2.```bash
- 3.# Example with Let's Encrypt for Redis
- 4.sudo certbot certonly --standalone -d redis.example.com
- 5.sudo cp /etc/letsencrypt/live/redis.example.com/fullchain.pem /etc/redis/tls/redis-server.crt
- 6.sudo cp /etc/letsencrypt/live/redis.example.com/privkey.pem /etc/redis/tls/redis-server.key
- 7.sudo chown redis:redis /etc/redis/tls/redis-server.*
- 8.sudo systemctl reload redis-server
- 9.
`