Last updated: 2026-02-13
Cassandra TLS/SSL Configuration Guide
This guide provides recommended TLS/SSL settings for Apache Cassandra to encrypt client-to-node and internode communication. Cassandra uses Java's JSSE for TLS, so certificates are managed through Java keystores.
Prerequisites
- Apache Cassandra 4.0 or later (for improved TLS defaults and hot-reloading of certificates)
- Java 11 or later (for TLS 1.3 support)
- SSL certificates in Java Keystore (JKS) or PKCS12 format
Certificate Setup
Cassandra uses Java keystores for certificate management. You need a keystore (containing the node's certificate and private key) and a truststore (containing the CA certificate).
Create a Node Keystore
# Generate a node keystore with a new key pair
keytool -keystore /etc/cassandra/ssl/node.keystore.jks \
-alias cassandra-node -keyalg RSA -keysize 2048 \
-genkey -validity 365 -storepass changeit \
-dname "CN=cassandra.example.com"
# Generate a CSR
keytool -keystore /etc/cassandra/ssl/node.keystore.jks \
-alias cassandra-node -certreq -file node.csr -storepass changeit
# Sign with your CA (using openssl)
openssl x509 -req -in node.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out node-signed.crt -days 365
# Import the CA certificate into the keystore
keytool -keystore /etc/cassandra/ssl/node.keystore.jks \
-alias CARoot -importcert -file ca.crt -storepass changeit -noprompt
# Import the signed certificate
keytool -keystore /etc/cassandra/ssl/node.keystore.jks \
-alias cassandra-node -importcert -file node-signed.crt -storepass changeit
Create a Truststore
keytool -keystore /etc/cassandra/ssl/node.truststore.jks \
-alias CARoot -importcert -file ca.crt -storepass changeit -noprompt
Using PKCS12 (Alternative)
Convert PEM files to PKCS12 format:
openssl pkcs12 -export -in node.crt -inkey node.key -chain -CAfile ca.crt \
-out /etc/cassandra/ssl/node.keystore.p12 -name cassandra-node -password pass:changeit
Client-to-Node Encryption
Configure client encryption in cassandra.yaml to encrypt connections from CQL clients to Cassandra nodes:
client_encryption_options:
enabled: true
optional: false
keystore: /etc/cassandra/ssl/node.keystore.jks
keystore_password: changeit
truststore: /etc/cassandra/ssl/node.truststore.jks
truststore_password: changeit
protocol: TLS
accepted_protocols:
- TLSv1.2
- TLSv1.3
cipher_suites:
- TLS_AES_256_GCM_SHA384
- TLS_AES_128_GCM_SHA256
- TLS_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
require_client_auth: false
Configuration Explained
- enabled: true -- Enables TLS for client connections.
- optional: false -- When
false, all client connections must use TLS. Set totrueto allow both encrypted and unencrypted connections during migration. - accepted_protocols -- Limits allowed TLS protocol versions.
- cipher_suites -- Restricts the allowed cipher suites to strong AEAD ciphers with forward secrecy.
- require_client_auth -- Set to
trueto require client certificates (mutual TLS).
Internode Encryption
Configure internode encryption in cassandra.yaml to encrypt gossip, streaming, and other node-to-node communication:
server_encryption_options:
internode_encryption: all
keystore: /etc/cassandra/ssl/node.keystore.jks
keystore_password: changeit
truststore: /etc/cassandra/ssl/node.truststore.jks
truststore_password: changeit
protocol: TLS
accepted_protocols:
- TLSv1.2
- TLSv1.3
cipher_suites:
- TLS_AES_256_GCM_SHA384
- TLS_AES_128_GCM_SHA256
- TLS_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
require_client_auth: true
require_endpoint_verification: true
Internode Encryption Options
- all -- Encrypt all internode traffic (recommended)
- none -- No internode encryption
- dc -- Encrypt traffic between data centers only
- rack -- Encrypt traffic between racks only
Setting require_client_auth: true and require_endpoint_verification: true for internode communication ensures mutual authentication and hostname verification between nodes.
Complete Configuration
# Client-to-node encryption
client_encryption_options:
enabled: true
optional: false
keystore: /etc/cassandra/ssl/node.keystore.jks
keystore_password: changeit
truststore: /etc/cassandra/ssl/node.truststore.jks
truststore_password: changeit
protocol: TLS
accepted_protocols:
- TLSv1.2
- TLSv1.3
cipher_suites:
- TLS_AES_256_GCM_SHA384
- TLS_AES_128_GCM_SHA256
- TLS_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
require_client_auth: false
# Internode encryption
server_encryption_options:
internode_encryption: all
keystore: /etc/cassandra/ssl/node.keystore.jks
keystore_password: changeit
truststore: /etc/cassandra/ssl/node.truststore.jks
truststore_password: changeit
protocol: TLS
accepted_protocols:
- TLSv1.2
- TLSv1.3
cipher_suites:
- TLS_AES_256_GCM_SHA384
- TLS_AES_128_GCM_SHA256
- TLS_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
require_client_auth: true
require_endpoint_verification: true
Client Connections
cqlsh
Configure cqlsh to connect over TLS by creating or editing ~/.cassandra/cqlshrc:
[connection]
ssl = true
port = 9042
[ssl]
certfile = /path/to/ca.pem
validate = true
version = TLSv1_2
For mutual TLS, add client certificate settings:
[ssl]
certfile = /path/to/ca.pem
userkey = /path/to/client-key.pem
usercert = /path/to/client-cert.pem
validate = true
version = TLSv1_2
Then connect:
cqlsh --ssl cassandra.example.com
Java Driver
CqlSession session = CqlSession.builder()
.addContactPoint(new InetSocketAddress("cassandra.example.com", 9042))
.withSslContext(sslContext)
.withLocalDatacenter("dc1")
.build();
Configure the SSL context in application.conf:
datastax-java-driver {
advanced.ssl-engine-factory {
class = DefaultSslEngineFactory
truststore-path = /path/to/client.truststore.jks
truststore-password = changeit
}
}
Verification
Test the TLS connection with openssl:
openssl s_client -connect cassandra.example.com:9042
Check the node status and verify encryption is active:
nodetool status
nodetool info | grep -i ssl
Verify the connection with cqlsh:
cqlsh --ssl cassandra.example.com -e "SHOW VERSION"
Check Cassandra logs for TLS activity:
grep -i ssl /var/log/cassandra/system.log