Skip to content

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

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

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

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