Skip to main content
Version: Unreleased

TLS/SSL Setup for Elasticsearch

This guide explains how TLS certificates are generated and configured for the Elasticsearch server in the development environment.

Overview

Elasticsearch uses xpack security with TLS/SSL for encrypting communications. The setup includes:

  • CA Certificate: Root certificate authority for signing server certificates
  • Server Certificate: Certificate for the Elasticsearch server with proper SAN (Subject Alternative Name)

Certificate Location

Certificates are stored in ./es/:

./es/
├── ca.crt # CA public certificate
├── ca.key # CA private key (keep secure)
├── server.crt # Server certificate
├── server.key # Server private key
├── openssl.cnf # OpenSSL config for server certificate
└── openssl-ca.cnf # OpenSSL config for CA certificate

Certificate Generation

Step 1: Generate CA Certificate

Create a CA certificate with basicConstraints = CA:TRUE to allow it to sign other certificates.

openssl-ca.cnf:

[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn

[dn]
C = US
ST = State
L = City
O = Organization
OU = IT
CN = Moki CA

[x509_extensions]
basicConstraints = critical, CA:TRUE
keyUsage = critical, keyCertSign, cRLSign

Generate CA:

openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 365 -key ca.key -out ca.crt -config openssl-ca.cnf

Step 2: Generate Server Certificate

Create a server certificate with SAN for the es hostname (used in Docker networking).

openssl.cnf:

[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext

[dn]
C = US
ST = State
L = City
O = Organization
OU = IT
CN = es

[req_ext]
subjectAltName = @alt_names

[alt_names]
DNS.1 = es
IP.1 = 127.0.0.1

[v3_ext]
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = critical, CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

Generate server certificate:

# Generate private key
openssl genrsa -out server.key 2048

# Generate CSR
openssl req -new -key server.key -out server.csr -config openssl.cnf

# Sign with CA
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -extfile openssl.cnf -extensions v3_ext

Docker Configuration

The certificates are mounted into the Elasticsearch container via docker-compose.dev.yml:

services:
es:
image: docker.elastic.co/elasticsearch/elasticsearch:9.1.5
volumes:
- ./es:/usr/share/elasticsearch/config/certs:ro
environment:
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.certificate=certs/server.crt
- xpack.security.http.ssl.key=certs/server.key
- xpack.security.transport.ssl.enabled=true
- xpack.security.transport.ssl.certificate=certs/server.crt
- xpack.security.transport.ssl.key=certs/server.key
- xpack.security.transport.ssl.verification_mode=certificate
- xpack.security.transport.ssl.certificate_authorities=certs/ca.crt
- ES_PASSWORD=moki

Client Configuration

Node.js Server

The Moki server connects to Elasticsearch using HTTPS with CA verification:

services:
server:
environment:
- NODE_EXTRA_CA_CERTS=/certs/es/ca.crt
volumes:
- ./es:/certs/es:ro

The NODE_EXTRA_CA_CERTS environment variable tells Node.js to use the CA certificate for verifying the Elasticsearch server's certificate. The volume mount makes the CA certificate available inside the container.

cURL

curl --cacert ./es/ca.crt -u elastic:moki https://es:9200/

Kibana

Kibana requires similar TLS configuration:

elasticsearch.hosts: ["https://es:9200/"]
elasticsearch.ssl.verificationMode: certificate
elasticsearch.ssl.certificateAuthorities:
[/usr/share/kibana/config/certs/ca.crt]
elasticsearch.username: elastic
elasticsearch.password: moki

Verification

Check that Elasticsearch is serving HTTPS:

curl --cacert ./es/ca.crt -u elastic:moki https://localhost:9292/

Expected response:

{
"name" : "es",
"cluster_name" : "moki-dev",
"cluster_uuid" : "...",
"version" : {
"number" : "9.1.5",
...
},
...
}

Troubleshooting

Certificate verification failed

Ensure the CA certificate is correct and the server certificate was signed by it:

openssl x509 -in server.crt -text -noout | grep "Issuer:"
openssl x509 -in ca.crt -text -noout | grep "Subject:"

The issuer of the server certificate should match the subject of the CA certificate.

Connection refused on HTTPS

Verify Elasticsearch is listening on HTTPS:

netstat -tlnp | grep 9200
openssl s_client -connect localhost:9292 -CAfile ./es/ca.crt

Wrong password

The default password is moki (set in ES_PASSWORD environment variable). To reset:

  1. Delete the Elasticsearch data directory
  2. Restart the container
  3. Use docker compose exec es /usr/share/elasticsearch/bin/elasticsearch-reset-password -b

Security Notes

  • Never commit private keys to version control
  • The ca.key should be kept secure and backed up
  • In production, use a proper CA (e.g., Let's Encrypt or internal PKI)
  • Rotate certificates before expiration (365 days in this setup)
  • Use strong passwords (avoid moki in production)