# Configure TLS routing with TLSRoute Type of document: How-to guide Product: NGINX Gateway Fabric --- Learn how to configure TLS routing with [TLSRoute](https://gateway-api.sigs.k8s.io/reference/spec/#tlsroute) using NGINX Gateway Fabric. ## Overview TLSRoute supports two TLS modes: - **Passthrough**: The Gateway reads the SNI and forwards encrypted TCP traffic to the backend. The backend holds and terminates TLS with its own certificate. Use this mode when the backend needs its own certificate, or when you can't expose the private key to the gateway. - **Terminate**: The Gateway holds the certificate, terminates TLS, and forwards plain TCP to the backend. Use this mode when the backend shouldn't handle TLS, or when it serves a non-HTTP TCP protocol. **note:** You can add an HTTPS listener on the same port that terminates TLS connections, as long as the hostname doesn't overlap with the TLS listener hostname. ## Before you begin - [Install](/ngf/install/) NGINX Gateway Fabric. Set up cert-manager and a local CA for both examples: Install cert-manager onto the cluster using Helm with Gateway API features enabled. - Add the Helm repository. ```shell helm repo add jetstack https://charts.jetstack.io helm repo update ``` - Install cert-manager, and enable the GatewayAPI feature gate: ```shell helm install \ cert-manager jetstack/cert-manager \ --namespace cert-manager \ --create-namespace \ --set config.apiVersion="controller.config.cert-manager.io/v1alpha1" \ --set config.kind="ControllerConfiguration" \ --set config.enableGatewayAPI=true \ --set crds.enabled=true ``` Create a self-signed `ClusterIssuer`, a CA `Certificate`, and a CA-backed `ClusterIssuer`. cert-manager uses the resulting `local-ca-issuer` to sign certificates in any namespace: ```yaml kubectl apply -f - < 8443/TCP 12s ``` Create a Gateway with a TLS listener in passthrough mode. Copy and paste this into your terminal: ```yaml kubectl apply -f - < ``` **Note:** In a production environment, you should have a DNS record for the external IP address that is exposed, and it should refer to the hostname that the Gateway will forward for. Create a TLSRoute that attaches to the Gateway and routes requests to `app.example.com` to the `secure-app` Service: ```yaml kubectl apply -f - < GET / HTTP/1.1 > Host: app.example.com:8443 > User-Agent: curl/8.7.1 > Accept: */* > * Request completely sent off < HTTP/1.1 200 OK < Server: nginx/1.29.1 < Date: Wed, 06 May 2026 21:25:18 GMT < Content-Type: text/plain < Content-Length: 42 < Connection: keep-alive < hello from pod secure-app-59bbd475b-phgsv ``` Note that the server certificate used to terminate the TLS connection has the subject common name of `app.example.com`. This is the server certificate that the `secure-app` is configured with and shows that the TLS connection was terminated by the `secure-app`, not NGINX Gateway Fabric. ## TLS terminate In terminate mode, NGINX Gateway Fabric holds the TLS certificate, terminates the TLS connection, and forwards plain TCP traffic to the backend. The backend doesn't need a certificate or TLS configuration. Use TLS terminate mode when: - Your backend serves a non-HTTP TCP protocol, such as a database or custom binary protocol. - You want to centralize certificate management at the gateway rather than on each backend. **note:** If your backend serves HTTP traffic and you need HTTP-level routing — such as path matching or header manipulation — use an HTTPS listener with an HTTPRoute instead. See [Configure HTTPS termination](/ngf/traffic-management/https-termination.md). ### Set up Create a `Certificate` for `app.example.com`. cert-manager creates the `gateway-tls-secret` Secret, which the Gateway uses to terminate TLS: ```yaml kubectl apply -f - < 80/TCP 10s ``` Create a Gateway with a TLS listener in terminate mode. Copy and paste this into your terminal: ```yaml kubectl apply -f - < ``` **note:** In a production environment, you should have a DNS record for the external IP address that is exposed, and it should refer to the hostname that the Gateway will forward for. Create a TLSRoute that attaches to the Gateway and routes requests to `app.example.com` to the `app` Service: ```yaml kubectl apply -f - <