To build with TLS support you'll need OpenSSL development libraries (e.g. libssl-dev on Debian/Ubuntu).
To build TLS support as Redis built-in:
Run make BUILD_TLS=yes.
Or to build TLS as Redis module:
Run make BUILD_TLS=module.
Note that sentinel mode does not support TLS module.
To run Redis test suite with TLS, you'll need TLS support for TCL (i.e.
tcl-tls package on Debian/Ubuntu).
Run ./utils/gen-test-certs.sh to generate a root CA and a server
certificate.
Run ./runtest --tls or ./runtest-cluster --tls to run Redis and Redis
Cluster tests in TLS mode.
Run ./runtest --tls-module or ./runtest-cluster --tls-module to
run Redis and Redis cluster tests in TLS mode with Redis module.
To manually run a Redis server with TLS mode (assuming gen-test-certs.sh was
invoked so sample certificates/keys are available):
For TLS built-in mode:
./src/redis-server --tls-port 6379 --port 0
--tls-cert-file ./tests/tls/redis.crt
--tls-key-file ./tests/tls/redis.key
--tls-ca-cert-file ./tests/tls/ca.crt
For TLS module mode:
./src/redis-server --tls-port 6379 --port 0
--tls-cert-file ./tests/tls/redis.crt
--tls-key-file ./tests/tls/redis.key
--tls-ca-cert-file ./tests/tls/ca.crt
--loadmodule src/redis-tls.so
To connect to this Redis server with redis-cli:
./src/redis-cli --tls \
--cert ./tests/tls/redis.crt \
--key ./tests/tls/redis.key \
--cacert ./tests/tls/ca.crt
This will disable TCP and enable TLS on port 6379. It's also possible to have both TCP and TLS available, but you'll need to assign different ports.
To make a Replica connect to the master using TLS, use --tls-replication yes,
and to make Redis Cluster use TLS across nodes use --tls-cluster yes.
By default, Redis TLS validates only that a peer certificate chains to the
trusted CA (tls-ca-cert-file / tls-ca-cert-dir) and is not expired. It does
not verify that the certificate belongs to the specific peer being contacted.
This default is safe only under a dedicated, per-cluster CA: since that CA signs certificates exclusively for your own nodes, "chains to the CA" is equivalent to "is a legitimate peer". This is the recommended Redis TLS deployment model.
If you instead use a shared, organizational, or public CA, that CA also signs certificates for machines that are not part of your deployment. In that case CA validation alone is insufficient:
MIGRATE) and, for replication, capture the AUTH <masteruser> <masterauth>
credentials a replica sends.FAIL message that marks a healthy node as
failed.tls-expected-peer-nameTo close this gap under a shared CA, set tls-expected-peer-name. When set, the
peer certificate must additionally carry one of the configured names in its
Subject Alternative Name (SAN) field (CN is used only as a fallback), verified as
part of CA chain validation. Issue every node's certificate with a shared
cluster-identity SAN (e.g. node.my-redis-cluster.example.com) and set this
option to that name on every node; a certificate signed by the same CA but
lacking the name is then rejected.
The expected name is taken from local configuration only — never from the address dialed or from any data received over the wire (such as a gossip-announced hostname), since the whole purpose is to distinguish a real peer from an impostor.
The check is enforced in both directions of server-to-server TLS:
MIGRATE target.Because a node's outbound (client) certificate is now verified by its peers, the
identity SAN must be present on whichever certificate the node presents in both
roles. In practice this means the SAN must be on tls-client-cert-file (used
for outbound cluster/replication connections) as well as on tls-cert-file; when
no separate client certificate is configured, tls-cert-file is used for both
roles and only needs the SAN once. If a separate client certificate without the
SAN is configured, peers will reject this node's inbound cluster-bus connections
and the cluster will not form.
Notes:
tls-expected-peer-name "a.example.com b.example.com");
a match against any one of them succeeds.*.example.com) match; partial-label wildcards
(f*.example.com) do not.AUTH/ACL (and optionally
tls-auth-clients-user).X509_VERIFY_PARAM host API, available
since OpenSSL 1.0.2. Building the TLS support against an older OpenSSL fails
with an error by default. Define TLS_NO_PEER_NAME_VERIFICATION
(e.g. make BUILD_TLS=yes CFLAGS=-DTLS_NO_PEER_NAME_VERIFICATION) to compile
the feature out — either to build against an older OpenSSL, or to disable it on
any OpenSSL version. When compiled out, if tls-expected-peer-name is set each
affected connection logs a warning and proceeds without the name check (CA
chain validation still applies).The tls-groups option controls the OpenSSL named groups used
during TLS handshakes. The value is passed directly to OpenSSL, so it accepts
the syntax supported by SSL_CTX_set1_groups_list() (or the older
SSL_CTX_set1_curves_list() API), for example:
tls-groups X25519:prime256v1
Redis does not filter the list, so any group name accepted by the linked OpenSSL build can be used.
The setting applies to both the server context and Redis' client context used for replication, cluster, and other server-to-server TLS connections. The client and server must have at least one group in common for the handshake to succeed.
This option requires OpenSSL 1.0.2 or newer, which provides the
SSL_CTX_set1_curves_list() API used by Redis. Newer OpenSSL versions also
provide the equivalent SSL_CTX_set1_groups_list() API. Building TLS support
against an older OpenSSL fails with a clear compile-time error by default. To
build Redis without this option, define TLS_NO_GROUPS, for
example:
make BUILD_TLS=yes CFLAGS=-DTLS_NO_GROUPS
When the feature is compiled out, setting tls-groups causes TLS
context configuration to fail instead of silently ignoring the requested
preference.
redis-cli and redis-benchmark expose --tls-groups when built with
OpenSSL support for named group configuration. When the feature is compiled
out, the command-line option is not accepted, matching the behavior of other
TLS options that depend on OpenSSL build capabilities.
All socket operations now go through a connection abstraction layer that hides I/O and read/write event handling from the caller.
Multi-threading I/O is supported for TLS since Redis 8.0. TLS connections are assigned to I/O threads like plain TCP connections, and each I/O thread's event loop drains any connection-level pending data (typical for TLS) via the connection abstraction layer.
Sync IO for TLS is currently implemented in a hackish way, i.e. making the socket blocking and configuring socket-level timeout. This means the timeout value may not be so accurate, and there would be a lot of syscall overhead. However I believe that getting rid of syncio completely in favor of pure async work is probably a better move than trying to fix that. For replication it would probably not be so hard. For cluster keys migration it might be more difficult, but there are probably other good reasons to improve that part anyway.
Consider the implications of allowing TLS to be configured on a separate port, making Redis listening on multiple ports: