Skip to content

Bind Elasticsearch to a private interface

Severity: criticalApplies to: Elasticsearch 8.x / 9.xApplies to: Elasticsearch 7.x
The fix/etc/elasticsearch/elasticsearch.yml
network.host: 127.0.0.1
# or, to serve a private network explicitly:
# network.host: 10.0.1.5
# http.host: 10.0.1.5
# transport.host: 127.0.0.1
Terminal window
sudo systemctl restart elasticsearch

network.host sets the address Elasticsearch binds. The default is loopback, which is safe and useless for anything but a single-node local setup — so people change it, and the change is where the exposure comes from.

The failure mode is specific and common: someone needs a remote client to connect, sets network.host: 0.0.0.0, and now the cluster listens on every interface — including the public one, if there is one. Combined with security disabled, that is the exact configuration behind most of the Elasticsearch data breaches.

0.0.0.0 is almost never what you actually want. You want the one private interface your clients use.

Elasticsearch listens on two ports, and conflating them is a common mistake:

Port Purpose Who should reach it
9200 HTTP / REST API Your applications and Kibana
9300 Transport (inter-node) Only other cluster nodes

The transport port is the more dangerous exposure. It’s how nodes join the cluster and replicate data, and it should never be reachable from anywhere except your other nodes. You can split them:

http.host: 10.0.1.5 # apps reach the API here
transport.host: 127.0.0.1 # or the private cluster interface only

On a single node, bind transport to loopback. On a multi-node cluster, bind it to the private interface the nodes share — and nothing else.

Production mode is a safety feature, not an obstacle

Section titled “Production mode is a safety feature, not an obstacle”

This is the part worth understanding rather than working around.

When you set network.host to anything other than a loopback address, Elasticsearch switches from development mode to production mode and enforces bootstrap checks. These are hard preconditions — vm.max_map_count, heap settings, discovery configuration, file descriptor limits — and if any fails, the node refuses to start.

People hit a bootstrap check failure, find that reverting network.host to loopback makes it start, and conclude the checks are the problem. They are not. The checks are Elasticsearch saying “you are about to run this where it matters, and these settings would bite you under load.” A node that only passes because it’s bound to loopback is a node that will fall over the first time it’s stressed.

Fix the checks it names — they’re documented and specific — rather than dodging them by staying in development mode. The bootstrap checks are one of the better safety mechanisms in any service on this site.