Configure TLS between AGS and Aerospike Database
The example on this page demonstrates how to encrypt communication between Aerospike Graph Service (AGS) and the Aerospike Database cluster. AGS-to-Database TLS protects vertex and edge data as it moves between the graph layer and storage layer.
Generate certificates
The example includes a script that creates certificates for both AGS and the Aerospike Database server.
-
Navigate to the
AGS-to-AerospikeDBdirectory.Terminal window cd ../AGS-to-AerospikeDB -
Run the certificate generation script.
Terminal window ./make-certs.shExample response Checking system for openssl command./usr/bin/opensslFound OpenSSL 3.0.0 7 sep 2021Generating CA key 'security/ca.key'.Generating self-signed CA cert 'security/ca.crt'.Generating server key 'security/server.key'.Signing server CSR with CA.Signing server CERT with CA.Removing intermediate files.Files generated:ca.key — your CA private keyca.crt — your CA certificateserver.key — your server private keyserver.crt — your server certificateIf the script lacks execute permissions, enable them and rerun the command:
Terminal window chmod +x make-certs.sh./make-certs.shAll certificates are created in the
security/directory.
Understanding the Aerospike Database configuration
The aerospike.conf file defines a TLS context and enables TLS for client connections.
Key configuration elements:
service { cluster-name exampleCluster}
network { tls exampleCluster { ca-file /opt/aerospike/etc/ca.crt cert-file /opt/aerospike/etc/server.crt key-file /opt/aerospike/etc/server.key }
service { port 3000 # Non-TLS port tls-port 4000 # TLS port for client connections tls-name exampleCluster tls-authenticate-client false }
fabric { tls-port 4001 # TLS port for inter-node fabric tls-name exampleCluster }}What each block does:
cluster-name exampleClusterand the matchingtls exampleCluster { ... }block bind the TLS assets to a logical name. Aerospike clients reference that name when they connect over TLS.tlsdefines where Aerospike finds the CA (ca-file), certificate (cert-file), and private key (key-file). If any path is wrong, the database refuses to start.serviceexposes two ports:port 3000for legacy/plaintext traffic andtls-port 4000for TLS. Settingtls-name exampleClustertells the service block which TLS context to load, andtls-authenticate-client falsekeeps client authentication disabled (matching the current AGS support matrix).fabricreuses the same TLS context for inter-node messaging on port 4001, ensuring replication and cluster-status traffic between Aerospike nodes is encrypted just like client traffic.
Understanding the Docker configuration
The docker-compose.yaml file mounts the certificates into both containers and configures AGS to connect via TLS.
For the database container:
volumes: # Mount certificates into the database container - ./security:/opt/aerospike/etc/ # Mount custom configuration file - ./aerospike.conf:/opt/aerospike/etc/aerospike.confcommand: ["--config-file", "/opt/aerospike/etc/aerospike.conf"]Mounting the entire security/ directory into /opt/aerospike/etc/ gives the database container read-only access to every certificate the config references, while the custom aerospike.conf replaces the stock configuration with one that enables TLS.
For the AGS container:
volumes: # Mount CA and server certificates for AGS to use as a client - ./security/ca.crt:/opt/aerospike-graph/aerospike-client-tls/ca.crt - ./security/server.crt:/opt/aerospike-graph/aerospike-client-tls/server.crt
environment: # Specify the TLS endpoint (host:tls-name:tls-port) aerospike.client.host: tls-aerospike-db:exampleCluster:4000 # Enable TLS for the database client aerospike.client.tls: "true"Here AGS receives the same CA and server certificate that the database is using. The Aerospike Java client only needs the CA (ca.crt) to verify the server, but mounting server.crt keeps the example data set in sync with the database container.
The aerospike.client.host variable follows the HOST:TLS_NAME:TLS_PORT format, so exampleCluster matches the tls definition in aerospike.conf and 4000 matches the database TLS port. Setting aerospike.client.tls: "true" tells AGS to build TLS sockets instead of plaintext ones; omit or set to "false" and the client ignores the mounted certificates.
Start the services
-
Start the Docker containers.
Terminal window docker-compose up -dExample response [+] Running 3/3✔ Network tls-asgraph-net Created✔ Container tls-aerospike-db Healthy✔ Container tls-aerospike-graph-service Started -
Check that both containers report a healthy status (approximately 15 seconds).
Terminal window docker psWait until
tls-aerospike-dbshowshealthybefore proceeding. -
Verify the Aerospike database TLS endpoint with
asinfo.Terminal window asinfo -h tls-aerospike-db:exampleCluster:4000 \--tls-enable \--tls-cafile=/opt/aerospike/etc/ca.crt \-v statusBecause
asinfois part of the Aerospike Tools package (not a default macOS/Linux binary), run it from inside the database container:Terminal window docker exec tls-aerospike-db \asinfo -h localhost:exampleCluster:4000 \--tls-enable \--tls-cafile=/opt/aerospike/etc/ca.crt \-v status(Inside the container,
localhostresolves to the database itself, so TLS verification still succeeds.)A successful TLS health check prints
ok. Any other response indicates the server could not complete the TLS handshake; inspect the database logs for details.
Verify the connection
The tls_example.py script connects to AGS over an unencrypted WebSocket (the client-to-AGS connection is not encrypted in this example) and runs a traversal. The traversal data is encrypted between AGS and the database.
-
Run the Python example.
Terminal window python3 ./tls_example.pyExample response Attempt 1/5: Connecting to Graph...Connection established and healthy.Values:['aerospike', 'unlimited']Connected and Queried Successfully, TLS between AGS and Aerospike DB is set up! -
Verify that the script output includes “TLS between AGS and Aerospike DB is set up!”.
How AGS connects to the database
AGS acts as a client to Aerospike Database. The environment variables in docker-compose.yaml configure the Aerospike Java client embedded in AGS:
environment: aerospike.client.host: tls-aerospike-db:exampleCluster:4000 aerospike.client.tls: "true" aerospike.client.namespace: testPutting it together:
aerospike.client.hostpoints to the Docker service name (tls-aerospike-db), the TLS context (exampleCluster), and the TLS port (4000). AGS embeds the Aerospike Java client, so this value tells that client exactly which certificate to expect when it dials the database.aerospike.client.tls: "true"enables TLS mode within the Aerospike Java client. When true, the client looks for certificates under/opt/aerospike-graph/aerospike-client-tls/(where the Compose file mounted them).aerospike.client.namespace: testensures AGS talks to the correct Aerospike namespace after the TLS handshake succeeds.
Because AGS handles the database handshake internally, Gremlin clients do not need to change anything for this layer; the WebSocket connection to AGS can remain the same while AGS encrypts its backend traffic.
Troubleshooting
If AGS fails to connect to the database:
TLS handshake failures:
- Check database logs:
docker logs tls-aerospike-db | grep -i tls - Verify the cluster name matches in three places:
aerospike.conf:cluster-name exampleClusteraerospike.conf:tls exampleCluster { ... }docker-compose.yaml:aerospike.client.host: tls-aerospike-db:exampleCluster:4000
- Ensure certificates are signed by the same CA
Certificate path issues:
- Confirm volume mounts are correct in
docker-compose.yaml - Verify file permissions: certificates must be readable by the container user
- Check that certificate files exist:
ls -l security/
AGS startup failures:
- AGS logs will indicate TLS errors:
docker logs tls-aerospike-graph-service - Common error: “Failed to connect to Aerospike” indicates database TLS is not ready
- Wait for database health check to pass before expecting AGS to connect successfully
Clean up
When you’re finished, stop and remove the containers:
docker-compose downThe generated certificates in security/ remain for future use. To regenerate certificates (for example, after expiration), delete the security/ directory and rerun ./make-certs.sh.
Combining both TLS layers
For production deployments, enable both client-to-AGS and AGS-to-Database TLS to provide end-to-end encryption.
-
Generate certificates for both layers..
You can reuse the same Certificate Authority (CA) for both TLS scenarios. Run both certificate generation scripts to create:
security/ca.crtandsecurity/ca.key(CA certificates)g-tls/server.crtandg-tls/server.key(for AGS WebSocket endpoint)security/server.crtandsecurity/server.key(for Aerospike Database)
-
Create a combined Docker Compose configuration..
Merge the volume mounts and environment variables from both examples:
services:aerospike-db:image: aerospike/aerospike-server-enterprise:8.0.0.7volumes:- ./security:/opt/aerospike/etc/- ./aerospike.conf:/opt/aerospike/etc/aerospike.confcommand: ["--config-file", "/opt/aerospike/etc/aerospike.conf"]aerospike-graph-service:image: aerospike/aerospike-graph-service:latestdepends_on:aerospike-db:condition: service_healthyvolumes:# AGS WebSocket TLS (client-to-AGS)- ./g-tls:/opt/aerospike-graph/gremlin-server-tls:ro- ./security/ca.crt:/opt/aerospike-graph/gremlin-server-ca/ca.crt:ro# Database client TLS (AGS-to-Database)- ./security/ca.crt:/opt/aerospike-graph/aerospike-client-tls/ca.crt- ./security/server.crt:/opt/aerospike-graph/aerospike-client-tls/server.crtenvironment:# Enable WebSocket TLSaerospike.graph-service.ssl.enabled: "true"# Enable database client TLSaerospike.client.host: aerospike-db:exampleCluster:4000aerospike.client.tls: "true"aerospike.client.namespace: test -
Update your Gremlin client to use secure connections..
Modify your Python client to use
wss://(WebSocket Secure) with an SSL context:import sslfrom gremlin_python.driver.driver_remote_connection import DriverRemoteConnectionssl_context = ssl.create_default_context(cafile="./security/ca.crt")ssl_context.check_hostname = Falseconnection = DriverRemoteConnection('wss://localhost:8182/gremlin', # Secure WebSocket'g',ssl_context=ssl_context) -
Verify end-to-end encryption..
When both TLS layers are active:
- Gremlin queries travel over encrypted WebSocket (client → AGS)
- Graph traversal data moves over encrypted connections (AGS → Database)
- Certificates are validated at both boundaries
This configuration provides defense in depth: even if an attacker gains access to the internal network, they cannot intercept unencrypted traffic between AGS and the database.