Deployment guide

Cassandra 5.0

Overview

Apache Cassandra 5.0 is the latest long-term-support release of the wide-column NoSQL database originally developed at Facebook and now an Apache top-level project. It is the engine behind Netflix, Apple, Instagram and Discord.

This SecureAnyCloud image runs Cassandra 5.0 LTS on Ubuntu 24.04 on Azure. It installs Cassandra from the official debian.cassandra.apache.org/50x APT suite, which redirects to the Apache JFrog Artifactory mirror. The Cassandra daemon runs under OpenJDK 17 with PasswordAuthenticator enabled by default, so there is no anonymous access.

What you get:

  • Apache Cassandra 5.0 LTS (latest 5.0.x at build time, 5.0.8) from the official Apache APT suite
  • OpenJDK 17 JRE headless (Cassandra 5.0 requires Java 11+; 17 is recommended for performance)
  • A cassandra.service systemd unit that starts automatically on boot
  • A cassandra-firstboot.service systemd oneshot. At first boot, it rotates the default cassandra/cassandra superuser password to a per-VM 32-char random password, creates a SecureAnyCloud superuser, and creates the SecureAnyCloud keyspace (SimpleStrategy, RF=1). It writes both passwords to /stage/scripts/cassandra-credentials.log (mode 0600 root only).
  • A Python 3.11 and cassandra-driver venv at /opt/cqlsh-venv for cqlsh-equivalent CLI work
  • PasswordAuthenticator and CassandraAuthorizer enabled, with CassandraRoleManager for password-backed access control
  • Default cluster name sac-cassandra (single-node by default; you reconfigure it for multi-node)
  • A CQL native protocol listener on TCP 9042
  • JMX bound to localhost:7199 only
  • Data directory /var/lib/cassandra, not /mnt. Azure mounts the ephemeral resource disk at /mnt, and that location does not survive SIG capture.
  • Ubuntu 24.04 LTS base with the latest security patches applied at build time
  • Azure Linux Agent for seamless cloud integration and SSH key injection
  • 24/7 SecureAnyCloud support with a guaranteed 24-hour response SLA

Important: cqlsh Python compatibility on Ubuntu 24.04. The cqlsh shell that ships with Cassandra 5.0 requires Python 3.6 to 3.11, but Ubuntu 24.04 (noble) ships Python 3.12. The image solves this by installing Python 3.11 from the deadsnakes PPA and creating an isolated cassandra-driver venv at /opt/cqlsh-venv. Use that Python interpreter for any cassandra-driver work, as the examples below show.

Prerequisites

  • An active Azure subscription.
  • A subscription to the Apache Cassandra 5.0 on Ubuntu 24.04 listing on Azure Marketplace.
  • An SSH public key for VM authentication.
  • A virtual network and subnet in the target region.
  • Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) for development and small single-node deployments. Production multi-node clusters should use Standard_D4s_v5 or larger, with attached Premium SSD data disks for the /var/lib/cassandra/data directory.

Cassandra is heap-sensitive. Give the JVM at least 4 GB and leave a similar amount for the page cache.

1

Deploy from the Azure Portal

In the Azure Portal, open Marketplace, search for Cassandra 5.0, select the SecureAnyCloud publisher entry, and select Create.

On the Networking tab, attach a network security group that allows inbound TCP 22 from your management IP range and TCP 9042 from your application VMs. Do not expose port 9042 to the public internet. Even with PasswordAuthenticator enabled, brute-force attacks against weak passwords are a real risk.

For multi-node clusters, also open TCP 7000 (intra-node, unencrypted) or 7001 (TLS) and 7199 (JMX) between cluster member private IPs.

Select Review + create, wait for validation, then select Create. Deployment takes around three minutes, because Cassandra's first-boot service generates the keypair and waits for native transport on 9042.

2

Deploy from the Azure CLI

RG="cassandra-prod" LOCATION="eastus" VM_NAME="cassandra-01" ADMIN_USER="azureuser" IMAGE_URN="sac1647283583153:cassandra-5-0-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION" az network vnet create --resource-group "$RG" --name cass-vnet \
  --address-prefix 10.97.0.0/16 --subnet-name cass-subnet --subnet-prefix 10.97.1.0/24 az network nsg create --resource-group "$RG" --name cass-nsg az network nsg rule create --resource-group "$RG" --nsg-name cass-nsg \
  --name allow-ssh --priority 100 \
  --source-address-prefixes "<your-mgmt-cidr>" \
  --destination-port-ranges 22 --access Allow --protocol Tcp az network nsg rule create --resource-group "$RG" --nsg-name cass-nsg \
  --name allow-cql --priority 110 \
  --source-address-prefixes 10.97.0.0/16 \
  --destination-port-ranges 9042 --access Allow --protocol Tcp
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:cassandra-5-0-ubuntu-24-04:default:latest
az vm create \
  --resource-group "$RG" --name "$VM_NAME" \
  --image "$IMAGE_URN" \
  --size Standard_B2s --storage-sku StandardSSD_LRS \
  --admin-username "$ADMIN_USER" --ssh-key-values "$SSH_KEY" \
  --vnet-name cass-vnet --subnet cass-subnet --nsg cass-nsg \
  --public-ip-sku Standard
3

Connect via SSH

ssh azureuser@<vm-ip>

cassandra.service is already running, and cassandra-firstboot.service has already rotated the superuser password and created the SecureAnyCloud keyspace.

4

Verify the Cassandra service

sudo systemctl status cassandra.service --no-pager

Expected output: active (running). Then confirm the first-boot sentinel.

sudo test -f /var/lib/sac/data/cassandra-firstboot.done && echo FIRSTBOOT_DONE

Confirm that the CQL listener is bound on port 9042.

sudo ss -tln | grep 9042
5

Retrieve the cassandra and SecureAnyCloud passwords

The cassandra superuser password and the SecureAnyCloud user password are rotated on each virtual machine and written to a root-only file. Read them with this command.

sudo cat /stage/scripts/cassandra-credentials.log

The output looks similar to this.

CASSANDRA_USER=cassandra CASSANDRA_PASSWORD=<CASSANDRA_PASSWORD> SAC_USER=sac SAC_PASSWORD=<SAC_PASSWORD> SAC_KEYSPACE=sac LISTEN_PORT=9042 CLUSTER_NAME=sac-cassandra

Store these passwords in your secret store, and rotate them as needed with ALTER USER cassandra WITH PASSWORD '<new-password>';.

6

Connect from the VM with cassandra-driver

cqlsh ships with Cassandra but requires Python 3.6 to 3.11, and Ubuntu 24.04 (noble) has Python 3.12. The image installs Python 3.11 from the deadsnakes PPA and creates an isolated venv at /opt/cqlsh-venv with the cassandra-driver Python library.

Use that venv for all cluster work from the VM.

CASS_PASS=$(sudo grep '^CASSANDRA_PASSWORD=' /stage/scripts/cassandra-credentials.log | cut -d= -f2-) /opt/cqlsh-venv/bin/python << PY from cassandra.cluster import Cluster from cassandra.auth import PlainTextAuthProvider ap = PlainTextAuthProvider(username='cassandra', password='${CASS_PASS}') session = Cluster(['127.0.0.1'], port=9042, auth_provider=ap).connect() for row in session.execute('SELECT release_version, cluster_name FROM system.local'): print(row.release_version, row.cluster_name) PY

Expected output: 5.0.8 sac-cassandra.

7

Round-trip test as SecureAnyCloud

The SecureAnyCloud superuser and the SecureAnyCloud keyspace are ready to use from first boot. Run a CREATE, INSERT and SELECT round trip as the SecureAnyCloud user.

CLOUD_PASS=$(sudo grep '^SAC_PASSWORD=' /stage/scripts/cassandra-credentials.log | cut -d= -f2-) /opt/cqlsh-venv/bin/python << PY from cassandra.cluster import Cluster from cassandra.auth import PlainTextAuthProvider ap = PlainTextAuthProvider(username='sac', password='${CLOUD_PASS}') session = Cluster(['127.0.0.1'], port=9042, auth_provider=ap).connect() session.execute("CREATE TABLE IF NOT EXISTS sac.users (id int PRIMARY KEY, name text)") session.execute("INSERT INTO sac.users (id, name) VALUES (1, 'alice')") row = session.execute("SELECT name FROM sac.users WHERE id = 1").one() print(row.name) session.execute("DROP TABLE sac.users") PY

Expected output: alice.

The SecureAnyCloud user has full access to the SecureAnyCloud keyspace. It can create and drop tables, and insert, select, update and delete rows.

8

Connect from a remote application

From any host inside the same virtual network with cassandra-driver installed (Python, Java, Go, Node.js, .NET, Rust and others), connect on port 9042 with the cassandra or SecureAnyCloud credentials. Here is a Python example.

pip install cassandra-driver
from cassandra.cluster import Cluster from cassandra.auth import PlainTextAuthProvider ap = PlainTextAuthProvider(username='sac', password='<SAC_PASSWORD>') cluster = Cluster(['<vm-private-ip>'], port=9042, auth_provider=ap) session = cluster.connect('sac') session.execute("INSERT INTO orders (id, sku, qty) VALUES (uuid(), 'WIDGET-1', 4)")

Do not open port 9042 to the public internet without TLS termination at a reverse proxy or VPN. Cassandra's native protocol does not encrypt by default. For production, configure client-to-node SSL with client_encryption_options in cassandra.yaml.

9

Server components

Key components and where they live:

  • Cassandra binary: /usr/sbin/cassandra
  • cqlsh (Python 3.11 or earlier only): /usr/bin/cqlsh
  • cassandra-driver Python venv: /opt/cqlsh-venv/bin/python
  • Configuration: /etc/cassandra/cassandra.yaml
  • JVM options: /etc/cassandra/jvm-server.options, /etc/cassandra/jvm17-server.options
  • Logback config: /etc/cassandra/logback.xml
  • Data directory: /var/lib/cassandra/data
  • Commit log: /var/lib/cassandra/commitlog
  • Saved caches: /var/lib/cassandra/saved_caches
  • Hints: /var/lib/cassandra/hints
  • Logs: /var/log/cassandra/system.log
  • Systemd unit: /lib/systemd/system/cassandra.service
  • First-boot script: /usr/local/sbin/cassandra-firstboot.sh
  • First-boot service: /etc/systemd/system/cassandra-firstboot.service
  • Credentials file: /stage/scripts/cassandra-credentials.log (mode 0600)
  • First-boot sentinel: /var/lib/sac/data/cassandra-firstboot.done

Inspect the running version with this command.

/usr/sbin/cassandra -v
10

Managing the Cassandra service

Check the status:

sudo systemctl status cassandra.service --no-pager

Stop, start or restart the service:

sudo systemctl stop cassandra.service
sudo systemctl start cassandra.service
sudo systemctl restart cassandra.service

View the system log:

sudo tail -f /var/log/cassandra/system.log

Inspect the node status (single-node by default, multi-node if you have added peers):

sudo nodetool status

Run a flush and compaction:

sudo nodetool flush
sudo nodetool compact

Run a repair (essential for multi-node clusters, and a safe no-op on a single node):

sudo nodetool repair
11

Scale to a multi-node cluster

The image ships configured as a single-node cluster (cluster_name: 'sac-cassandra', listening on 127.0.0.1). To convert it into a real cluster, follow these steps.

  • Stop Cassandra on every prospective node: sudo systemctl stop cassandra
  • On each node, edit /etc/cassandra/cassandra.yaml:
    • listen_address: <node-private-ip> (or comment it out and use listen_interface)
    • rpc_address: <node-private-ip>, or 0.0.0.0 to listen on all addresses
    • seed_provider.parameters.seeds: "<node1-private-ip>,<node2-private-ip>"
    • endpoint_snitch: GossipingPropertyFileSnitch (the default is SimpleSnitch, which is fine for a single AZ)
  • Wipe /var/lib/cassandra/data/system/peers* so nodes do not carry stale peer info: sudo rm -rf /var/lib/cassandra/data/system/peers*
  • Start the seed node first, then start the rest one by one with a 30-second gap between starts.
  • Verify the cluster with sudo nodetool status. All nodes should appear as UN (Up Normal).
  • Update the SecureAnyCloud keyspace replication: ALTER KEYSPACE SecureAnyCloud WITH replication = {'class': 'NetworkTopologyStrategy', 'datacenter1': 3};
  • Run a full repair: sudo nodetool repair --full

For multi-DC or large-scale clusters, refer to the official Cassandra operations guide at cassandra.apache.org/doc/.

12

Troubleshooting

cassandra.service will not start

  • Check the system log: sudo tail -100 /var/log/cassandra/system.log
  • Confirm that the JVM has enough memory: free -h should show at least 2 GB free.
  • Check for port conflicts: sudo ss -tln | grep -E ':(9042|7000|7199)'

pyo3_runtime.PanicException when running cqlsh

  • This error is the Python 3.12 ABI mismatch described in the Overview. Use /opt/cqlsh-venv/bin/python with cassandra-driver instead (see Step 6).

Authentication fails with rotated password

  • Confirm that the credentials file is current: sudo cat /stage/scripts/cassandra-credentials.log
  • Check that the auth keyspace exists: sudo nodetool describering system_auth
  • If you have forgotten the password, you can disable auth temporarily in cassandra.yaml (authenticator: AllowAllAuthenticator). Restart, set a new password, and re-enable auth.

Cassandra never bound port 9042 during first boot

  • Cassandra's default startup takes 30 to 90 seconds on a Standard_B2s. If first boot times out, check sudo journalctl -u cassandra-firstboot.service and sudo tail -100 /var/log/cassandra/system.log.
  • A larger heap (MAX_HEAP_SIZE in /etc/cassandra/jvm-server.options) requires more startup time.

Data directory filling up /var/lib/cassandra

  • Cassandra's commit log and SSTables grow without bound on heavy write workloads.
  • Attach a Premium SSD data disk and bind-mount it to /var/lib/cassandra/data (or change data_file_directories in cassandra.yaml).
  • Run sudo nodetool compact to merge SSTables, but be aware that compactions are I/O-heavy.
13

Security recommendations

  • Rotate the cassandra superuser password immediately after deployment. Step 5 shows the auto-rotated password, and you can use ALTER USER to change it.
  • Restrict the NSG so port 9042 is reachable only from your application VMs and admin networks. Never expose it to the public internet.
  • Enable client-to-node SSL in cassandra.yaml (client_encryption_options.enabled: true) for any cross-VM connection.
  • Enable internode encryption (server_encryption_options.internode_encryption: all) for multi-node clusters.
  • Restrict the cassandra superuser to admin operations only. Application code should connect as SecureAnyCloud (a regular superuser scoped to the SecureAnyCloud keyspace) or as a least-privilege role you create.
  • Enable audit logging (audit_logging_options.enabled: true) for compliance-sensitive workloads.
  • Back up /var/lib/cassandra/data regularly with nodetool snapshot, and upload the snapshots to Azure Files or Blob storage.
  • Patch the OS monthly with sudo apt-get update && sudo apt-get upgrade && sudo reboot on each cluster node, one node at a time (rolling).
14

Support and licensing

Apache Cassandra is licensed under the Apache License 2.0. There is no per-node, per-CPU or per-GB fee for any Cassandra component or for the upstream protocol.

SecureAnyCloud provides commercial support for this image separately from the upstream project.

  • Email: sales@secureanycloud.com
  • Website: secureanycloud.com
  • Support hours: 24/7, with a guaranteed 24-hour response SLA

Deploy on Azure

Launch Apache Cassandra 5.0 on Ubuntu 24.04 with 24/7 support from SecureAnyCloud.

View on Marketplace

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure

Launch Apache Cassandra 5.0 LTS on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure