> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo Configure TLS with Auto Redirect

> Configuring a Kubernetes Gateway to terminate TLS using a cross-namespace Secret, enable HTTP to HTTPS redirect, and route requests to a backend service.

In this lesson you will learn how to terminate TLS at a Gateway using a Kubernetes Secret, configure an HTTP→HTTPS redirect, and allow cross-namespace Secret references using a ReferenceGrant. We use a self-signed certificate for the lab so you can test HTTPS locally.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/QZ7pWzRtYdnRAGco/images/Gateway-API-with-NGINX-Fabric-Gateway/TLS-and-Cross-Namespace-Security/Demo-Configure-TLS-with-Auto-Redirect/configure-tls-auto-redirect-demo.jpg?fit=max&auto=format&n=QZ7pWzRtYdnRAGco&q=85&s=536e619bf656c565d910b3fc3ac0a7dd" alt="A presentation slide titled &#x22;Configure TLS with Auto-Redirect&#x22; with a large blue teardrop-shaped area on the right containing the word &#x22;Demo.&#x22; The slide has a clean white background and a small copyright notice for KodeKloud." width="1920" height="1080" data-path="images/Gateway-API-with-NGINX-Fabric-Gateway/TLS-and-Cross-Namespace-Security/Demo-Configure-TLS-with-Auto-Redirect/configure-tls-auto-redirect-demo.jpg" />
</Frame>

## Environment status

At the start of the lab only the `coffee` application and its Service are running — no Gateways or HTTPRoutes are present.

```bash theme={null}
# pods
~/coding/kubernetes/nginx-fabric-gateway/kodekloud/lab-3-tls
> kubectl get po
NAME                       READY   STATUS    RESTARTS   AGE
coffee-5b9c74f9d9-9rf2f    1/1     Running   0          3h15m
```

## What we'll deploy

* A Gateway (in `default`) with:
  * HTTP listener on port 80
  * HTTPS listener on port 443 with TLS termination using a Secret
* Two HTTPRoutes:
  * One on the HTTP listener that redirects requests to HTTPS (301)
  * One on the HTTPS listener that forwards `/coffee` to the `coffee` Service
* A `certificate` namespace with a TLS Secret `cafe-secret` (self-signed)
* A `ReferenceGrant` that allows the Gateway in `default` to reference the Secret in `certificate`

Files in the working directory:

```bash theme={null}
~/coding/kubernetes/nginx-fabric-gateway/kodekloud/lab-3-tls
> ls
cert.yaml                    coffee-redirect-route.yaml   gateway.yaml
coffee-https-only-route.yaml coffee-rewrite-route.yaml    ns.yaml
ref-grant.yaml               routes.yaml
```

## Quick reference — manifests and purpose

| Manifest | Resource(s) | Purpose |
| - | - | - |
| `ns.yaml` | Namespace | Creates the `certificate` namespace |
| `cert.yaml` | `Secret` (`kubernetes.io/tls`) | Self-signed TLS cert stored as `cafe-secret` in `certificate` |
| `ref-grant.yaml` | `ReferenceGrant` | Allows Gateway in `default` to reference `certificate/cafe-secret` |
| `gateway.yaml` | `Gateway` | HTTP and HTTPS listeners, TLS terminate mode, references `cafe-secret` |
| `routes.yaml` | `HTTPRoute`s | HTTP->HTTPS redirect and `/coffee` backend route |

Relevant docs:

* Gateway API overview: [https://gateway-api.sigs.k8s.io/](https://gateway-api.sigs.k8s.io/)
* ReferenceGrant: [https://gateway-api.sigs.k8s.io/spec/#referencegrant](https://gateway-api.sigs.k8s.io/spec/#referencegrant)

***

## Gateway manifest (gateway.yaml)

This Gateway uses the `nginx` GatewayClass and terminates TLS using a Secret in the `certificate` namespace.

```yaml theme={null}
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: gateway
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    port: 80
    protocol: HTTP
    hostname: "*.example.com"
  - name: https
    port: 443
    hostname: "*.example.com"
    protocol: HTTPS
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        name: cafe-secret
        namespace: certificate
  allowedRoutes:
    namespaces:
      from: All
```

### Notes on TLS mode

* `Terminate` means TLS is terminated at the Gateway; traffic to backend pods will be plain HTTP.
* Because the Secret is in a different namespace (`certificate`) than the Gateway (`default`), a `ReferenceGrant` is required to allow cross-namespace references.

## Namespace and Secret (ns.yaml & cert.yaml)

* `ns.yaml` creates the `certificate` namespace.
* `cert.yaml` contains the `kube` TLS Secret `cafe-secret` with base64-encoded `tls.crt` and `tls.key` (self-signed for lab/testing).

Example namespace:

```yaml theme={null}
apiVersion: v1
kind: Namespace
metadata:
  name: certificate
```

Example Secret (cert.yaml excerpt):

```yaml theme={null}
apiVersion: v1
kind: Secret
metadata:
  name: cafe-secret
  namespace: certificate
type: kubernetes.io/tls
data:
  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURq...  # base64-encoded cert
  tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLS0K...  # base64-encoded key
```

Apply namespace and Secret:

```bash theme={null}
~/coding/kubernetes/nginx-fabric-gateway/kodekloud/lab-3-tls
> kubectl apply -f ns.yaml
namespace/certificate created

> kubectl apply -f cert.yaml
secret/cafe-secret created
```

## ReferenceGrant (ref-grant.yaml)

A ReferenceGrant in the `certificate` namespace grants permission for Gateways in `default` to use the Secret.

```yaml theme={null}
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: access-certificate
  namespace: certificate
spec:
  to:
  - group: ""
    kind: Secret
    name: cafe-secret
  from:
  - group: gateway.networking.k8s.io
    kind: Gateway
    namespace: default
```

Apply the ReferenceGrant:

```bash theme={null}
> kubectl apply -f ref-grant.yaml
referencegrant.gateway.networking.k8s.io/access-certificate created
```

## Create the Gateway

```bash theme={null}
> kubectl apply -f gateway.yaml
gateway.gateway.networking.k8s.io/gateway created

> kubectl get gateway
NAME      CLASS   ADDRESS        PROGRAMMED   AGE
gateway   nginx   10.96.124.112  True         6s
```

## HTTPRoutes (routes.yaml)

We create two HTTPRoute resources:

1. `cafe-tls-redirect` — attached to the Gateway's HTTP listener; issues a 301 redirect to HTTPS.
2. `coffee` — attached to the Gateway's HTTPS listener; matches path prefix `/coffee` and forwards requests to the `coffee` Service on port 80.

```yaml theme={null}
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
metadata:
  name: cafe-tls-redirect
spec:
  parentRefs:
  - name: gateway
    sectionName: http
  hostnames:
  - "cafe.example.com"
  rules:
  - filters:
    - type: RequestRedirect
      requestRedirect:
        scheme: https
        port: 443
        statusCode: 301
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: coffee
spec:
  parentRefs:
  - name: gateway
    sectionName: https
  hostnames:
  - "cafe.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /coffee
    backendRefs:
    - name: coffee
      port: 80
```

Apply the routes:

```bash theme={null}
> kubectl apply -f routes.yaml
httproute.gateway.networking.k8s.io/cafe-tls-redirect created
httproute.gateway.networking.k8s.io/coffee created
```

## Verify resources

Check the Secret, ReferenceGrant, and HTTPRoutes:

```bash theme={null}
# secret in the certificate namespace
> kubectl get secret -n certificate
NAME          TYPE                DATA   AGE
cafe-secret   kubernetes.io/tls   2      10s

# ReferenceGrant in the certificate namespace
> kubectl get referencegrant -n certificate
NAME                 AGE
access-certificate   10s

# list HTTPRoutes
> kubectl get httproutes
NAME               AGE
cafe-tls-redirect  20s
coffee             20s
```

## Testing behavior with curl

In this lab the Gateway ports are exposed on localhost using mapped ports (example: 8080 for HTTP and 8443 for HTTPS). We use `--resolve` so `cafe.example.com` resolves to `127.0.0.1` at the chosen port.

1. Access HTTP (expect a 301 redirect to HTTPS)

```bash theme={null}
~/coding/kubernetes/nginx-fabric-gateway/kodekloud/lab-3-tls
> curl --resolve cafe.example.com:8080:127.0.0.1 http://cafe.example.com:8080/coffee --include
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Sat, 11 Apr 2026 23:15:34 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
Location: https://cafe.example.com/coffee

<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
```

2. Access HTTPS (Gateway terminates TLS; the cert is self-signed so `--insecure` is used here)

```bash theme={null}
~/coding/kubernetes/nginx-fabric-gateway/kodekloud/lab-3-tls
> curl --resolve cafe.example.com:8443:127.0.0.1 https://cafe.example.com:8443/coffee --insecure
Server address: 10.244.0.7:8080
Server name: coffee-5b9c74f9d9-9rf2f
Date: 11/Apr/2026:23:18:01 +0000
URI: /coffee
Request ID: 46977f9b19ff33a3535e1c3a252a4599
```

<Callout icon="lightbulb" color="#1CB2FE">
  The HTTPS curl uses `--insecure` because this lab uses a self-signed certificate. In production, use certificates signed by a trusted CA (for example via [Let's Encrypt](https://letsencrypt.org) or an internal PKI) and proper DNS; you won't need `--resolve` or `--insecure`.
</Callout>

## Summary

* The Gateway is configured to terminate TLS with a Secret stored in a separate namespace.
* A `ReferenceGrant` allows the Gateway to reference that cross-namespace Secret.
* An HTTPRoute on the HTTP listener performs a 301 redirect to HTTPS.
* The HTTPS listener forwards `/coffee` to the `coffee` backend Service.
* For production deployments use a trusted certificate and real DNS so clients can validate TLS without bypassing checks.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/gateway-api-with-nginx-fabric-gateway/module/59594ad7-a7ed-4494-97a1-25fa5b519588/lesson/e2f7d843-8eb3-4cbc-a5bf-0cdce081ab42" />

  <Card title="Practice Lab" icon="flask-conical" cta="Learn more" href="https://learn.kodekloud.com/user/courses/gateway-api-with-nginx-fabric-gateway/module/59594ad7-a7ed-4494-97a1-25fa5b519588/lesson/7abc7bf5-8ba4-4026-9984-e386ebfa11ed" />
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.