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:
- Delete the Elasticsearch data directory
- Restart the container
- Use
docker compose exec es /usr/share/elasticsearch/bin/elasticsearch-reset-password -b
Security Notes
- Never commit private keys to version control
- The
ca.keyshould 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
mokiin production)