transport.publish_host is the address an Elasticsearch node publishes to peers as the contact point for its transport layer. Peers store the published address and use it for all subsequent communication. The setting matters whenever the bind address (transport.host) differs from the address other nodes should use to reach the node - the canonical example being a container with one internal IP and a different external IP, or any host behind NAT.
- Default: Auto-detected from the bind address. Works for simple flat networks
- Scope: Per-node, static - requires a restart
- Possible values: IP address, hostname, or special value like
_site_
How transport.publish_host Works
At startup, each node selects a publish address using this priority:
transport.publish_hostif settransport.hostif set and unambiguous- The first non-loopback bind address
The selected address is broadcast to every peer the node joins. From that point, peers use that address - not the bind address - to open new connections. Discovery, cluster state updates, and shard requests all flow over the published address.
When the bind address is reachable internally (e.g. inside a Docker network) but a different address is needed externally, peers must be told the externally-reachable address. That's transport.publish_host.
Configuring transport.publish_host
In elasticsearch.yml:
transport.host: 0.0.0.0 # Bind to all interfaces inside the container
transport.publish_host: 10.0.5.12 # Advertise the host-routable address
Verify:
GET /_nodes/_local?filter_path=**.transport.publish_address
In Docker Compose, the typical pattern uses an environment variable mapped to the host IP:
environment:
- network.host=0.0.0.0
- transport.publish_host=${HOST_IP}
In Kubernetes, ECK handles publish_host automatically via the pod IP. Custom manifests should set transport.publish_host from the downward API.
When You Need transport.publish_host
| Environment | Likely need |
|---|---|
| Bare-metal flat network | No - auto-detect works |
| Cloud VM, single NIC, public IP routed to a private IP | Possibly - depends on whether nodes use public or private IPs |
| Docker host networking | No - bind and publish are the same |
| Docker bridge networking | Yes - container IP differs from host-reachable IP |
| Kubernetes with ECK | No - ECK configures this |
| Kubernetes with custom StatefulSet | Yes - usually pod IP from downward API |
| Behind NAT | Yes - publish the NAT'd address peers can reach |
Common Pitfalls
- Publishing
127.0.0.1orlocalhostin a multi-node cluster. Other nodes get the loopback address and can't reach the node. - Publishing a hostname that doesn't resolve consistently across nodes. Some peers see one IP, others see another, leading to flapping discovery.
- Forgetting to update
transport.publish_hostafter migrating a node to a new network. Peers continue trying to reach the old address. - Using the auto-detected address on hosts with multiple NICs. Auto-detection picks the first non-loopback address, which may be the wrong network.
Operational Notes
Inspect what each node is publishing:
GET /_cat/nodes?v&h=name,host,transport.address,transport.bind,transport.publish
Pulse tracks publish addresses across cluster restarts and alerts when a node starts publishing an unexpected address - a common cause of partial cluster splits where some peers can reach the node and others can't. The publish-vs-bind mismatch is one of the more time-consuming networking issues to debug manually; surfacing it directly saves an hour of log archaeology.
Frequently Asked Questions
Q: What does transport.publish_host do in Elasticsearch?
A: transport.publish_host is the address a node advertises to peers as its transport contact point. Peers then use that address to open connections. It's necessary when the bind address differs from the address peers can reach, like in containers or behind NAT.
Q: What's the difference between transport.host and transport.publish_host?
A: transport.host is the address the node binds to for incoming transport connections. transport.publish_host is the address advertised to peers as the connect-back point. They're often the same; they differ in NAT and container environments.
Q: Do I need to set transport.publish_host in Docker?
A: Only with bridge networking, where the container's bind address (an internal Docker network IP) differs from the host-routable IP peers should use. With host networking they're the same and the setting is unnecessary.
Q: Can I use a hostname for transport.publish_host?
A: Yes - any value that resolves to a reachable IP works. The risk is inconsistent DNS resolution across nodes, which causes flapping discovery. Static IPs are more reliable.
Q: What happens if transport.publish_host points to an unreachable address?
A: The node joins the cluster but peers can't open new connections to it. Existing connections survive until they break, then the cluster sees the node as disconnected and shards reallocate. Usually surfaces as flapping yellow/red cluster state.
Q: Is transport.publish_host required in Kubernetes?
A: Not when using the ECK operator - it sets publish_host automatically. With a custom StatefulSet or manifest, set publish_host to the pod IP from the Kubernetes downward API.
Related Reading
- Elasticsearch transport.host Setting: Transport bind address
- Elasticsearch network.host Setting: Default bind setting
- Elasticsearch Discovery Seed Hosts: Cluster discovery
- Elasticsearch Nodes Keep Disconnecting Troubleshooting: Connectivity issues
- Elasticsearch Docker Guide: Containerized deployment