Skip to main content
Give the gateway its own hostname, separate from the app. LLM clients and coding agents send requests to the gateway hostname; browsers use the app hostname. This guide covers the chart Ingress on ingress-nginx, a cloud load balancer in front of the Service, and the checks that prove the endpoint works. For Envoy Gateway and other Gateway API implementations, see Routing and ingress controllers.

Prerequisites

  • A DNS zone you control, for example acme.com.
  • An ingress controller, or the AWS Load Balancer Controller for the NLB option below.
  • cert-manager with a ClusterIssuer, or a certificate you provide yourself.
1

Set the ingress values

The gateway is published from the app Ingress settings. Set ingress.gateway.host next to the app hosts:
Replace both hosts. The chart renders a second Ingress, <release>-gateway-ingress, with the same className and annotations. It routes /v1 and /health on the gateway host to the gateway Service. The control plane derives the public URL CLI users get from ingress.gateway.host.With className: nginx the chart adds annotations to the gateway Ingress only. They keep streamed responses unbuffered, let a stream run for an hour, and raise the body limit to 32 MB. Keys in ingress.gateway.annotations override them.
2

Issue the certificate

With the cert-manager.io/cluster-issuer annotation, cert-manager requests a certificate for ingress.host and stores it in ingress.tls.secretName. A DNS-01 issuer works before the DNS record exists:
To bring your own certificate, create the TLS Secret yourself and drop the cert-manager.io/cluster-issuer annotation:
3

Create the DNS record

Point a CNAME at the ingress controller’s load balancer hostname:
Use a CNAME, never an A record: cloud load balancer addresses change.
4

Verify

The /health call returns {"status":"ok","checks":{"gateway":"ok","control_plane":"ok"}}. The /v1/models call returns 200 with the models your key can route to. Continue with the post-install checklist.

What the ingress publishes

/healthz, /readyz, /startupz, /debug/control-plane and /internal/* stay in-cluster. Metrics are on their own port (9464). The Gemini-native routes under /v1beta are outside the /v1 prefix and are not published by the chart Ingress. To publish them, route /v1beta to the gateway Service with your own route, as described in Routing and ingress controllers.

Cloud load balancer in front of the Service

To terminate TLS on a cloud load balancer instead of the ingress, leave ingress.gateway.host empty and turn the Service into a LoadBalancer. On AWS with the Load Balancer Controller and an ACM certificate:
Both examples terminate TLS in front of the gateway and reach port 5563 over plain HTTP, so the Authorization header that carries the virtual key crosses that last hop without encryption.The ingress terminates at the ingress controller and the network load balancer terminates at the load balancer, which puts the plaintext hop inside the cluster network in the first case and between the load balancer and the pods in the second. Both assume that network is trusted. Where it is not, run a service mesh with mutual TLS between the terminator and the gateway pods.
Request the certificate first and publish the validation CNAME records ACM prints:
Then read the load balancer hostname and point the CNAME at it:
A Service of type LoadBalancer publishes every route, including the probes and /debug/control-plane, which returns the resolved LW_GATEWAY_BASE_URL and takes no key. Put a load balancer listener rule or a security group in front of it when the address is public. Set service.internal.enabled: true to also render a ClusterIP Service named langwatch-gateway-internal for in-cluster callers, so they do not go out through the load balancer.

Other ingress controllers

Set ingress.className for your controller. The ingress-nginx annotations are added only when className is nginx. Put the controller’s equivalents in ingress.gateway.annotations so they apply to the gateway host only. Three settings matter for every controller: response buffering off, an idle or read timeout above the longest stream you allow, and a body limit of at least 32 MB. The gateway lets a provider call run up to 14 minutes. Routing and ingress controllers has the full list and an Envoy Gateway HTTPRoute. AWS ALB example. The certificate comes from ACM rather than ingress.gateway.tls.secretName, so gateway.publicUrl states the https URL the CLI should use:

Outbound endpoint policy

TLS in front of the gateway is one boundary. The other is the provider endpoints that customers configure on their own credentials. Three variables, set through gateway.security.* in the chart, control them: Both switches default to false, so a self-hosted install can route to a model server on the cluster network. Cloud metadata addresses, 0.0.0.0, :: and link-local ranges are refused with every setting. Setting ENVIRONMENT to anything other than local requires both switches to be true.

Common failures

More symptoms are on Troubleshooting.
Last modified on October 12, 2026