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 = Monitor 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
- ELASTIC_PASSWORD=monitor

Client Configuration

Node.js Server

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

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

The ES_TLS_CA environment variable is used by Monitor to verify the Elasticsearch server certificate. The mounted CA certificate is also used by Vector Elasticsearch sinks for TLS validation during data ingestion.

info

It is encouraged to use NODE_EXTRA_CA_CERTS for any custom CA certificates to ensure that all Node.js processes can properly verify the server certificate. Example:

cat es/ca.crt other/ca.crt > combined.crt
# NODE_EXTRA_CA_CERTS=./combined.crt

cURL

curl --cacert ./es/ca.crt -u elastic:monitor 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: monitor

Verification

Check that Elasticsearch is serving HTTPS:

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

Expected response:

{
"name" : "es",
"cluster_name" : "monitor-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 monitor (set in ELASTIC_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 monitor in production)