Adding HTTPS to Kibana and Elasticsearch
While moving ELK to my Docker Swarm, I want to encrypt everything going over the network. This post will go over adding Kibana to my new ELK stack, enabling https, and talking to my Elasticsearch over https.
I already took care of exposing my Elasticsearch over SSL in this post: https://www.frakkingsweet.com/elasticsearch-java-ssl/
Add a Kibana service to the main docker-compose.yml
file, here is that section, see below for the full file:
version: '3.7'
services:
kibana:
image: docker.elastic.co/kibana/kibana:7.2.0
ports:
- 5601:5601
networks:
- ext
Inside of my prod
overrides file, docker-compose.prod.yml
, I add the Kibana service with the appropriate overrides. I access my Elasticsearch instance through a DNS entry that is a CNAME pointing to my docker cluster. We'll say that entry is elasticsearch.example.com
. I created another DNS entry, kibana.example.com
, that points to the docker cluster. This will make it easier in the future when I setup a reverse proxy and instead of dealing with ports like https://kibana.example.com:5601
I will be able to access it by hitting https://kibana.example.com
. No need to remember the port numbers.
Here is the Kibana services portion of the compose override file. See below for the full docker-compose.prod.yml
file. Kibana uses a different format for the environment variables than Elasticsearch. With Kibana everything is upper case and all periods are replaced with a _
. Another difference, we don't need to put the secrets in a special location, so that section is nice and simple.
version: '3.7'
services:
kibana:
environment:
- SERVER_NAME=kibana.example.com
- ELASTICSEARCH_HOSTS=https://elasticsearch.example.com:9200
- ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=/run/secrets/root.pub.pem
- SERVER_SSL_ENABLED=true
- SERVER_SSL_CERTIFICATE=/run/secrets/certificate.crt.pem
- SERVER_SSL_KEY=/run/secrets/certificate.key.pem
- SERVER_SSL_CERTIFICATEAUTHORITIES=/run/secrets/root.pub.pem
secrets:
- root.pub.pem
- certificate.key.pem
- certificate.crt.pem
And for the full, complete files.
docker-compose.yml
version: '3.7'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0
environment:
- "ES_JAVA_OPTS=-Xms7g -Xmx7g"
- discovery.type=single-node
ports:
- 9200:9200
networks:
- ext
kibana:
image: docker.elastic.co/kibana/kibana:7.2.0
ports:
- 5601:5601
networks:
- ext
networks:
ext:
docker-compose.prod.yml
version: "3.7"
services:
elasticsearch:
environment:
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.key=/usr/share/elasticsearch/config/secrets/certificate.key.pem
- xpack.security.http.ssl.certificate=/usr/share/elasticsearch/config/secrets/certificate.crt.pem
- xpack.security.http.ssl.certificate_authorities=/usr/share/elasticsearch/config/secrets/root.pub.pem
- xpack.security.transport.ssl.enabled=false
- xpack.security.transport.ssl.key=/usr/share/elasticsearch/config/secrets/certificate.key.pem
- xpack.security.transport.ssl.certificate=/usr/share/elasticsearch/config/secrets/certificate.crt.pem
- xpack.security.transport.ssl.certificate_authorities=/usr/share/elasticsearch/config/secrets/root.pub.pem
volumes:
- elasticsearchdata:/usr/share/elasticsearch/data
- elasticsearchconfig:/usr/share/elasticsearch/config
- elasticsearchlogs:/usr/share/elasticsearch/logs
secrets:
- source: root.pub.pem
target: /usr/share/elasticsearch/config/secrets/root.pub.pem
uid: '1000'
gid: '1000'
- source: certificate.key.pem
target: /usr/share/elasticsearch/config/secrets/certificate.key.pem
uid: '1000'
gid: '1000'
- source: certificate.crt.pem
target: /usr/share/elasticsearch/config/secrets/certificate.crt.pem
uid: '1000'
gid: '1000'
kibana:
environment:
- SERVER_NAME=kibana.example.com
- ELASTICSEARCH_HOSTS=https://elasticsearch.example.com:9200
- ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=/run/secrets/root.pub.pem
- SERVER_SSL_ENABLED=true
- SERVER_SSL_CERTIFICATE=/run/secrets/certificate.crt.pem
- SERVER_SSL_KEY=/run/secrets/certificate.key.pem
- SERVER_SSL_CERTIFICATEAUTHORITIES=/run/secrets/root.pub.pem
secrets:
- root.pub.pem
- certificate.key.pem
- certificate.crt.pem
secrets:
root.pub.pem:
external: true
name: certificates.example.com.ca.pub.pem
certificate.key.pem:
external: true
name: certificates.wildcard.example.com.key.pem
certificate.crt.pem:
external: true
name: certificates.wildcard.example.com.pub.pem
volumes:
elasticsearchdata:
driver: local
driver_opts:
type: nfs
device: ":/volumes/elasticsearch/data"
o: "addr=${NFSSERVER},vers=4,rw"
elasticsearchconfig:
driver: local
driver_opts:
type: nfs
device: ":/volumes/elasticsearch/config"
o: "addr=${NFSSERVER},vers=4,rw"
elasticsearchlogs:
driver: local
driver_opts:
type: nfs
device: ":/volumes/elasticsearch/logs"
o: "addr=${NFSSERVER},vers=4,rw"
As before, to deploy the updated stack:
docker stack deploy -c docker-compose.yml -c docker-compose.prod.yml prod --with-registry-auth
That's it. So far this is the easiest part of building a new ELK stack in Docker.