Redis added native TLS support in version 6.0, released in April 2020. Before that, TLS for Redis required a TLS proxy (stunnel, spiped, or nginx stream proxy). If you are still running Redis without TLS because “it is on a private network”, consider that Redis commands carry your application data — including session tokens, cache entries, and queued jobs — in plaintext across any switch between your application servers and the Redis host. This article covers enabling TLS on Redis, connecting clients, and setting up TLS for Redis Sentinel and Redis Cluster.
Check your Redis version
redis-server --version
# Redis server v=7.2.0 ...
TLS requires Redis 6.0 or later. If you are on an older version, you need to either upgrade or use a TLS proxy (stunnel configuration is covered at the end of this article).
Step 1: Obtain certificates
Redis reads TLS files from disk in PEM format. You need:
redis.crt— the Redis server’s certificate (full chain)redis.key— the private keyca.crt— the CA certificate (for client verification)
# From Let's Encrypt
certbot certonly --standalone -d redis.example.com
# Or generate a self-signed certificate for internal use
openssl req -x509 -newkey rsa:4096 \
-keyout /etc/redis/redis.key \
-out /etc/redis/redis.crt \
-days 365 -nodes \
-subj "/CN=redis.example.com" \
-addext "subjectAltName=DNS:redis.example.com,IP:192.168.1.100"
Set permissions — Redis runs as the redis user:
cp /etc/letsencrypt/live/redis.example.com/fullchain.pem /etc/redis/redis.crt
cp /etc/letsencrypt/live/redis.example.com/privkey.pem /etc/redis/redis.key
cp /etc/letsencrypt/live/redis.example.com/chain.pem /etc/redis/ca.crt
chown redis:redis /etc/redis/redis.crt /etc/redis/redis.key /etc/redis/ca.crt
chmod 640 /etc/redis/redis.key
chmod 644 /etc/redis/redis.crt /etc/redis/ca.crt
Step 2: Configure TLS in redis.conf
Open /etc/redis/redis.conf:
sudo nano /etc/redis/redis.conf
Add or update these settings:
# Enable TLS port (default Redis TLS port is 6380, but any port works)
port 0
tls-port 6380
# Certificate and key files
tls-cert-file /etc/redis/redis.crt
tls-key-file /etc/redis/redis.key
# CA certificate for verifying client certificates (mutual TLS)
tls-ca-cert-file /etc/redis/ca.crt
# Minimum TLS version
tls-protocols "TLSv1.2 TLSv1.3"
# Preferred ciphers (TLS 1.2)
tls-ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305"
# Prefer server cipher order
tls-prefer-server-ciphers yes
# Client certificate verification
# "yes" = require client cert (mutual TLS)
# "optional" = accept but do not require client cert
# "no" = do not verify client cert (TLS encryption only)
tls-auth-clients no
To keep the plaintext port disabled:
port 0
To run both plaintext and TLS in parallel (useful for a migration period):
port 6379
tls-port 6380
Step 3: Restart Redis and verify
sudo systemctl restart redis
sudo systemctl status redis
# Check the TLS port is listening
sudo ss -tlnp | grep 6380
Test with openssl:
openssl s_client -connect redis.example.com:6380 -servername redis.example.com \
-CAfile /etc/redis/ca.crt </dev/null 2>&1 \
| openssl x509 -noout -subject -dates
Test with redis-cli:
redis-cli -h redis.example.com -p 6380 \
--tls \
--cacert /etc/redis/ca.crt \
PING
# Expected: PONG
If using a self-signed certificate where the CA is also the server cert:
redis-cli -h redis.example.com -p 6380 \
--tls \
--cacert /etc/redis/redis.crt \
PING
Step 4: Connecting application clients
Python (redis-py)
import redis
import ssl
r = redis.Redis(
host='redis.example.com',
port=6380,
ssl=True,
ssl_ca_certs='/etc/app/redis-ca.crt',
ssl_certfile=None, # client cert, needed for mutual TLS
ssl_keyfile=None, # client key, needed for mutual TLS
ssl_check_hostname=True,
decode_responses=True
)
print(r.ping()) # True
r.set('test-key', 'hello over TLS')
print(r.get('test-key')) # hello over TLS
Node.js (ioredis)
const Redis = require('ioredis');
const fs = require('fs');
const redis = new Redis({
host: 'redis.example.com',
port: 6380,
tls: {
ca: fs.readFileSync('/etc/app/redis-ca.crt'),
// cert: fs.readFileSync('/etc/app/client.crt'), // mutual TLS
// key: fs.readFileSync('/etc/app/client.key'), // mutual TLS
rejectUnauthorized: true,
servername: 'redis.example.com'
}
});
redis.ping().then(result => console.log(result)); // PONG
Go (go-redis)
import (
"crypto/tls"
"crypto/x509"
"os"
"github.com/redis/go-redis/v9"
)
caCert, _ := os.ReadFile("/etc/app/redis-ca.crt")
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
rdb := redis.NewClient(&redis.Options{
Addr: "redis.example.com:6380",
TLSConfig: &tls.Config{
RootCAs: caCertPool,
ServerName: "redis.example.com",
},
})
PHP (Predis)
$client = new Predis\Client([
'scheme' => 'tls',
'host' => 'redis.example.com',
'port' => 6380,
'ssl' => [
'cafile' => '/etc/app/redis-ca.crt',
'verify_peer' => true,
'verify_peer_name' => true,
'peer_name' => 'redis.example.com',
],
]);
Mutual TLS — requiring client certificates
When you want only trusted applications to connect (no password authentication):
In redis.conf:
tls-auth-clients yes
tls-ca-cert-file /etc/redis/ca.crt
Generate client certificates:
# For each application
openssl genrsa -out /etc/app/client.key 4096
openssl req -new -key /etc/app/client.key -out /tmp/client.csr -subj "/CN=myapp"
openssl x509 -req -in /tmp/client.csr -CA /etc/redis/ca.crt -CAkey /etc/redis/ca.key \
-CAcreateserial -out /etc/app/client.crt -days 365
Redis Sentinel with TLS
Redis Sentinel 6+ supports TLS. Each Sentinel instance needs its own certificate. In sentinel.conf:
tls-port 26380
port 0
tls-cert-file /etc/redis/sentinel.crt
tls-key-file /etc/redis/sentinel.key
tls-ca-cert-file /etc/redis/ca.crt
tls-replication yes
sentinel monitor mymaster redis-primary.example.com 6380 2
sentinel auth-pass mymaster YourRedisPassword
The Redis primary and replicas must also be TLS-enabled. Configure replication TLS on the replica:
tls-replication yes
Redis Cluster with TLS
In a Redis Cluster, all nodes use TLS for both client connections and inter-node communication (gossip and replication). Set in each node’s redis.conf:
tls-port 6380
port 0
tls-replication yes
tls-cluster yes
tls-cert-file /etc/redis/node1.crt
tls-key-file /etc/redis/node1.key
tls-ca-cert-file /etc/redis/ca.crt
Create the cluster using TLS endpoints:
redis-cli --tls --cacert /etc/redis/ca.crt \
--cluster create \
redis-node1.example.com:6380 \
redis-node2.example.com:6380 \
redis-node3.example.com:6380 \
--cluster-replicas 1
Certificate renewal
Create a deploy hook:
sudo nano /etc/letsencrypt/renewal-hooks/deploy/redis.sh
#!/bin/bash
DOMAIN=redis.example.com
DEST=/etc/redis
cp /etc/letsencrypt/live/${DOMAIN}/fullchain.pem ${DEST}/redis.crt
cp /etc/letsencrypt/live/${DOMAIN}/privkey.pem ${DEST}/redis.key
cp /etc/letsencrypt/live/${DOMAIN}/chain.pem ${DEST}/ca.crt
chown redis:redis ${DEST}/redis.crt ${DEST}/redis.key ${DEST}/ca.crt
chmod 640 ${DEST}/redis.key
chmod 644 ${DEST}/redis.crt ${DEST}/ca.crt
# Redis picks up new TLS certificates via CONFIG REWRITE + restart
# Redis 7.x supports TLS certificate hot-reload:
redis-cli -p 6380 --tls --cacert ${DEST}/ca.crt CONFIG SET tls-cert-file ${DEST}/redis.crt
redis-cli -p 6380 --tls --cacert ${DEST}/ca.crt CONFIG SET tls-key-file ${DEST}/redis.key
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/redis.sh
Redis 7.x supports hot-reloading TLS certificates via CONFIG SET without restarting, which means zero-downtime certificate rotation.
Using stunnel for Redis versions before 6.0
If you cannot upgrade Redis, use stunnel as a TLS proxy:
# /etc/stunnel/redis.conf
[redis-server]
accept = 6380 connect = 127.0.0.1:6379 cert = /etc/stunnel/redis.crt key = /etc/stunnel/redis.key cafile = /etc/stunnel/ca.crt verify = 2
sudo systemctl restart stunnel
Clients connect to the stunnel port (6380) as if it were a TLS-enabled Redis instance.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
ERR This Redis server does not support TLS | Redis older than 6.0 or compiled without TLS | Upgrade or use stunnel |
WRONGPASS after enabling TLS | requirepass still needed even with TLS | Provide the password alongside TLS config |
certificate verify failed | Client does not trust CA | Provide correct ca_certs or cacert path |
Connection reset by peer on TLS port | Redis not listening or TLS config error | Check redis.conf and restart |
tls-auth-clients yes locks out all clients | Clients not sending certificates | Switch to tls-auth-clients no until clients are updated |
Summary
Redis TLS is configured in redis.conf with four settings: tls-port, tls-cert-file, tls-key-file, and optionally tls-ca-cert-file. Set port 0 to disable the plaintext port once all clients are migrated. All major Redis client libraries support TLS via SSL context configuration. For Redis Cluster and Sentinel, set tls-replication yes and tls-cluster yes to encrypt inter-node traffic. Redis 7.x allows hot certificate rotation via CONFIG SET, making renewals non-disruptive.