Gateway Configuration
All HANGAR_GATEWAY_* variables, listeners, limits, timeouts, shutdown, tunnel config.
The gateway is configured entirely through environment variables and a few command-line flags. Only the plane URL and service token are required.
Required
| Variable | Description |
|---|---|
-plane-url / HANGAR_PLANE_URL | The plane’s base URL |
HANGAR_GATEWAY_SERVICE_TOKEN | The gateway’s service credential for the plane. Accepted on GET /v1/endpoints/resolved, GET /v1/gateway/tenants, and POST /v1/clusters/tunnel-auth only. |
Listeners
| Variable | Default | Description |
|---|---|---|
-listen | :8080 | Internal listener address (no auth; trust is the network boundary) |
HANGAR_GATEWAY_PUBLIC_LISTEN | unset (off) | Address for the public, tenant-identified listener |
HANGAR_GATEWAY_TUNNEL_LISTEN | :8443 | Where cluster agents dial; off to disable |
HANGAR_GATEWAY_METRICS_LISTEN | :9090 | Where /metrics is served; off to disable |
Internal vs public listeners
- Internal listener (
-listen): authenticates nobody. Reaching it is the proof. A tenant behind it may declareauth: none, and a caller there can reach every enabled tenant’s endpoints. Needs a NetworkPolicy to restrict access. - Public listener (
HANGAR_GATEWAY_PUBLIC_LISTEN): sits behind a*.hangar.example.comwildcard. A request is identified by itsHostheader, checked against a key when the tenant declaresauth: api_key, and scoped to that tenant’s own catalog and routing.
A disabled tenant is refused on both listeners. The gateway checks the tenant table itself instead of trusting the routing table.
Resync and coordination
| Variable | Default | Description |
|---|---|---|
-resync | 30s | How often to re-read the routing table and tenant table |
-gateways / HANGAR_GATEWAY_REPLICAS | 1 (warns) | How many gateway replicas are running; must equal the StatefulSet’s replicas |
-gateway-id / HANGAR_GATEWAY_ID | hostname | This replica’s identity, reported to agents |
HANGAR_GATEWAY_REPLICAS must match the StatefulSet’s replicas. Set too low, some replicas hold no tunnels and answer 503 no_capacity. Set too high, agents keep redialling with no harm but wasted dials.
Limits
| Variable | Default | Description |
|---|---|---|
HANGAR_GATEWAY_TENANT_MAX_IN_FLIGHT | 1024 | Requests one tenant may have in flight on one replica; 0 for no cap |
HANGAR_GATEWAY_TENANT_RPS | unset | Sustained requests per second one tenant may send to one replica; unset means no rate limit |
HANGAR_GATEWAY_TENANT_BURST | unset | Burst above the rate limit |
HANGAR_GATEWAY_MAX_BODY_BYTES | 100 MiB | Largest request body accepted; larger ones are 413 |
HANGAR_GATEWAY_MAX_BUFFERED_BYTES | 1000 MiB | Request-body memory held at once across the replica; 0 for no bound. A request that would pass it is 503 no_capacity. |
Limits are per tenant, not per key. Every key belongs to one tenant, and a tenant’s keys share its allowance. Limits are per replica, so the fleet-wide figure is the per-replica value times the replica count.
On the internal listener, an operator’s edge is usually one tenant carrying every customer, so size the in-flight cap to the edge’s own concurrency, or set it to 0.
Timeouts
| Variable | Default | Description |
|---|---|---|
HANGAR_GATEWAY_READ_HEADER_TIMEOUT | 10s | How long a caller may take to send its headers |
HANGAR_GATEWAY_BODY_READ_TIMEOUT | 2m | How long a caller may take to send its body once the headers are in; a stalled body is 408 |
HANGAR_GATEWAY_WRITE_IDLE_TIMEOUT | 2m | How long one write to the caller may block. Per write, so a long stream that keeps arriving is never cut; a caller that stops reading is. |
Shutdown
| Variable | Default | Description |
|---|---|---|
HANGAR_GATEWAY_SHUTDOWN_GRACE | 30s | The pod’s terminationGracePeriodSeconds; the drain phases are cut from it |
HANGAR_GATEWAY_DRAIN_DELAY | 5s | How long to wait while endpoint removal reaches load balancers |
HANGAR_GATEWAY_DRAIN_TIMEOUT | 16s | How long to give internal and public listeners to finish serving |
HANGAR_GATEWAY_TUNNEL_DRAIN_TIMEOUT | 5s | How long to give the tunnel listener to drain after the request listeners |
The phases are cut from HANGAR_GATEWAY_SHUTDOWN_GRACE, which must equal the pod’s terminationGracePeriodSeconds. At the default 30 seconds: 5s delay + 16s request drain + 5s tunnel drain + 1s metrics + 3s unspent before kubelet’s SIGKILL.
That budget bounds how long a generation can survive a rollout. To carry longer generations through one, raise terminationGracePeriodSeconds and HANGAR_GATEWAY_SHUTDOWN_GRACE together; the extra time goes to the request listeners.
Tunnel TLS
| Variable | Description |
|---|---|
-tunnel-cert / HANGAR_GATEWAY_TUNNEL_TLS_CERT | PEM certificate for the tunnel listener |
-tunnel-key / HANGAR_GATEWAY_TUNNEL_TLS_KEY | PEM key for the tunnel listener |
Neither set means plaintext, which requires TLS termination in front of the listener.
Tunnel listener limits
Every value has a default in libs/packages/tunnel. Set one only to change it.
| Variable | Default | Description |
|---|---|---|
HANGAR_GATEWAY_TUNNEL_MAX_PER_CLUSTER | 16 | Tunnels one cluster may hold on a replica |
HANGAR_GATEWAY_TUNNEL_MAX | 1024 | Tunnels a replica may hold across every cluster |
HANGAR_GATEWAY_TUNNEL_MAX_HANDSHAKES | 128 | Dials mid-handshake at once |
HANGAR_GATEWAY_TUNNEL_MAX_HANDSHAKES_PER_SOURCE | 32 | Of those, from one address (IPv6 by /64); off disables |
HANGAR_GATEWAY_TUNNEL_SOURCE_FAILURES | 10 | Failed dials one address may make in a minute before refused as throttled; off disables |
HANGAR_GATEWAY_TUNNEL_CACHE_TTL | 1m | How long a verified token is reused without asking the plane |
HANGAR_GATEWAY_TUNNEL_CACHE_GRACE | 15m | How long it survives a plane that cannot be reached |
HANGAR_GATEWAY_TUNNEL_REVERIFY_INTERVAL | 1m | How often an open tunnel’s token is checked again (cannot be turned off) |
HANGAR_GATEWAY_TUNNEL_BODY_IDLE_TIMEOUT | 2m | A tunnelled response body nobody reads for this long is closed; off disables |
The per-source limits key on the dial’s address. Behind a Service or load balancer that rewrites it (externalTrafficPolicy: Cluster), every agent shares a few node addresses. Keep the client address (externalTrafficPolicy: Local) or set both per-source limits to off.
Remote media
| Variable | Default | Description |
|---|---|---|
HANGAR_GATEWAY_MEDIA_URL_HOSTS | unset | Comma-separated hosts (media.example.com, *.cdn.example.net) a request’s remote media may come from. Unset allows public hosts and refuses internal ones. |
A multimodal request can name its image, video, or audio by URL, and the engine fetches it from inside the serving cluster. The gateway checks every remote media URL before the request leaves this hop.
- By default (unset): a URL must be
httporhttpsand must not name a private or cluster-internal host (loopback, private, link-local, CGNAT, unspecified addresses, numeric host forms, single-label names,.local,.localhost,.internal,.svc,.cluster.local,.lan,.home.arpa). Every public host is allowed. - With
HANGAR_GATEWAY_MEDIA_URL_HOSTS: a URL must name a host on that list, and nothing else passes.
The check is by name, so a public name that resolves to a private address gets through. It does not replace the engine’s own control or an egress NetworkPolicy. Use all three where tenants can send media URLs.
Credentials and authentication
| Variable | Description |
|---|---|
-credentials / HANGAR_GATEWAY_CREDENTIALS | JSON file of {"<credential id>": {"<header>": "<value>"}} |
-probe-token / HANGAR_GATEWAY_PROBE_TOKEN | What the conformance runner presents to mark its traffic as a probe; a comma-separated pair while rotating |
HANGAR_GATEWAY_PUBLIC_ALLOW_NO_AUTH | true serves a public tenant declaring auth: none; off by default, so such a tenant gets 401 |
The credential file is how a reference on a cluster’s serving address becomes headers on the wire. The plane stores the reference and never the secret.
Logging and debugging
| Variable | Default | Description |
|---|---|---|
HANGAR_GATEWAY_REDACT_NAMES | unset | Comma-separated names your own infrastructure goes by, redacted from quoted engine messages on top of built-in stack names |
-log-upstream-bodies / HANGAR_GATEWAY_LOG_UPSTREAM_BODIES | off | Write a discarded upstream error body to the log whole. Off in production and must stay off: an engine’s error quotes the request it refused. |
-log-upstream-bodies is a debugging switch for a cluster carrying no customer traffic. It warns on every start while on.