A Consul Terminating Gateway is the only way to securely expose services from your Consul mesh to the outside world.
Let’s see it in action. Imagine you have a webapp service running in Consul and you want to expose it to a client outside the mesh.
First, we need a proxy service definition for the Terminating Gateway itself. This proxy.hcl file tells Consul about the gateway:
# proxy.hcl
kind = "proxy"
name = "terminating-gateway"
config {
bind_addr = "127.0.0.1:8080" # The address the gateway listens on
cert_file = "/path/to/gateway.cert"
key_file = "/path/to/gateway.key"
ca_cert_file = "/path/to/consul-ca.cert"
upstreams {
destination_name = "webapp" # The name of the service to reach
destination_addr = "10.0.0.5:9090" # The actual address of the webapp service
local_bind_port = 8080 # The port on the gateway that will proxy to webapp
}
}
Then, we register this proxy with Consul:
consul services register proxy.hcl
Now, any client outside the Consul mesh can connect to 127.0.0.1:8080 on the machine running the Terminating Gateway. The gateway, because it’s registered as a proxy kind in Consul, knows about the webapp service and will forward the request to 10.0.0.5:9090. The communication between the gateway and the webapp service is secured using Consul Connect’s mutual TLS.
The core problem this solves is secure egress from a service mesh. Without a Terminating Gateway, you’d have to manage TLS certificates and network access directly on your webapp service, which is complex and bypasses the mesh’s security posture. The Terminating Gateway acts as a single, managed exit point. It handles the TLS termination for external clients and initiates a new mTLS connection to the upstream service within the mesh.
Here’s how the data flow looks:
- External Client sends a TLS-encrypted request to
TERMINATING_GATEWAY_IP:EXTERNAL_PORT. - Terminating Gateway receives the request, terminates the TLS using its own certificate.
- Terminating Gateway looks up the
webappservice in Consul’s catalog. - Terminating Gateway initiates a new mTLS connection to the
webappservice’s IP and port using its own Consul identity. - WebApp Service receives the mTLS-encrypted request from the Terminating Gateway, verifies its identity via Consul.
- WebApp Service processes the request and sends a TLS-encrypted response back to the Terminating Gateway.
- Terminating Gateway receives the response, encrypts it for the external client, and sends it back.
The key configuration levers are:
bind_addr: The IP and port the gateway listens on for incoming connections from outside the mesh.cert_fileandkey_file: The TLS certificate and private key for the gateway itself, used to authenticate to external clients.ca_cert_file: The CA certificate used to verify the identity of upstream services within the mesh.upstreams: This block defines which internal Consul services the gateway can proxy to, mapping adestination_nameto its actualdestination_addrand specifying thelocal_bind_porton the gateway that will direct traffic to it.
A common point of confusion is that the destination_addr in the upstreams block is the actual IP address and port of the target service, not its Consul service name or registered port. The Terminating Gateway uses Consul’s service catalog to discover the target service’s IP and port, but this field provides a direct fallback or explicit mapping.
This setup allows you to control exactly which internal services are exposed externally and under what TLS constraints, all managed centrally via Consul.
The next step is often to configure a Load Balancer in front of the Terminating Gateway to provide high availability and external DNS resolution.