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.
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:
- 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
monitorin production)