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

# Gateway API with the ngrok Kubernetes Operator

> Learn how to use Gateway API resources with the ngrok Kubernetes Operator to configure ingress and routing for your services.

The following guide will help give an overview of using Gateway API resources to configure the ngrok Kubernetes Operator.
This guide aims to offer a few high-level examples and explanations about how the Operator uses Gateway API resources, but more specific examples of using the Gateway API resources can be found in the various other guides for the specific actions you are looking to perform.

This guide assumes that you have already installed the Operator and the Gateway API CRDs following the [installation guide](/k8s/installation/helm).
If you've already installed the Operator without Gateway API support and would like to enable it, simply install the Gateway API CRDs and ngrok `GatewayClass` following the installation guide and restart the ngrok Kubernetes Operator so that it can detect the newly installed Gateway API CRDs.

<Note>
  Request mirror filters are not yet supported with the ngrok Kubernetes Operator.
</Note>

## How does the ngrok Operator use Gateway API?

The ngrok Kubernetes Operator consumes Gateway API resources and translates them into the native ngrok `CloudEndpoint` and `AgentEndpoint` custom resources.
Each hostname from the listeners on the `Gateway` resources you configure will cause the Operator to create a `CloudEndpoint` for the listener's hostname.
Each unique upstream service you reference using `HTTPRoute` resources will cause the Operator to create an `AgentEndpoint` with an `internal` binding so that it is not accessible directly on the internet.
The Operator then generates ngrok [Traffic Policy](/traffic-policy/) configuration on those `CloudEndpoint` to perform all the routing and actions specified in your Gateway API configuration and route to the internal `AgentEndpoint` resources that handle forwarding traffic to your upstream services.
When you create/update/delete Gateway API resources, the Operator will automatically handle creating/updating/deleting the `CloudEndpoint` and `AgentEndpoint` resources as needed.

## Using `NgrokTrafficPolicy` with Gateway API resources

The Operator will consume `Gateway` and `HTTPRoute` resources as necessary and build endpoints to provide the desired routing behavior.
The Gateway API filters on the `HTTPRoute` resources can be used to configure commonly used features such as redirecting requests and manipulating headers, but there may still be other use-cases and features
that are not natively supported by the Gateway API that you would like to use. This is where you can take advantage of ngrok's Traffic Policy system to extend the functionality of your Gateway API resources.

### Using `NgrokTrafficPolicy` on `Gateways`

You can supply an `NgrokTrafficPolicy` custom resource on your `Gateway` resources using an annotation.
When configured this way, the rules from your Traffic Policy will run for all requests matching any of the hostnames from the listeners on your `Gateway`.
The Traffic Policy may "terminate" the request by sending back a response or forwarding the request to another endpoint using the `forward-internal` action, but if this happens then the request will not be processed further and will not be routed using any configuration from any matching `HTTPRoutes`.
This is most commonly done to enforce policy across an entire `Gateway` such as enforcing authentication or manipulating headers where you do not care which `HTTPRoute` the request matches.

The following example showcases using a `Gateway` with an `NgrokTrafficPolicy` supplied via annotation.
The `NgrokTrafficPolicy` must be in the same namespace as the `Gateway`

```yaml theme={null}
apiVersion: ngrok.k8s.ngrok.com/v1alpha1
kind: NgrokTrafficPolicy
metadata:
  name: remove-header
  namespace: default
spec:
  policy:
    on_http_request:
      - name: Remove Bad Header
        actions:
          - type: remove-headers
            config:
              headers:
                - "X-Removed-Header"
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: example-gateway
  namespace: default
  annotations:
    k8s.ngrok.com/traffic-policy: remove-header
spec:
  gatewayClassName: ngrok
  listeners:
    - name: example-hostname
      hostname: "example-hostname.ngrok.io"
      port: 443
      protocol: HTTPS
```

### Use `NgrokTrafficPolicy` on `HTTPRoutes`

You can also use `NgrokTrafficPolicy` on `HTTPRoute` resources as an external ref filter if you have Traffic Policies that should only be run for certain routes.

The following example showcases using an `HTTPRoute` with an `NgrokTrafficPolicy` filter.
They can also be used at the backend filter level which is useful if you have more than one upstream service in a group and you would like to run different Traffic Policy configurations depending on which backend was selected.
The `NgrokTrafficPolicy` must be in the same namespace as the `Gateway`.
While redundant, this example showcases both methods.

```yaml theme={null}
apiVersion: ngrok.k8s.ngrok.com/v1alpha1
kind: NgrokTrafficPolicy
metadata:
  name: basic-auth
  namespace: default
spec:
  policy:
    on_http_request:
      - actions:
          - type: basic-auth
            config:
              realm: sample-realm
              credentials:
                - user:password1
                - admin:password2
              enforce: true
          - type: custom-response
            config:
              status_code: 200
              headers:
                content-type: text/plain
              body: Successfully Authenticated!
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: example-route
  namespace: default
spec:
  hostnames:
  - example-hostname.ngrok.io
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: example-gateway
    namespace: default
  rules:
  - matches:
      - path:
          type: PathPrefix
          value: /
    backendRefs:
      - group: ""
        kind: Service
        name: example-service
        port: 80
        weight: 1
        filters:
        - type: ExtensionRef
          extensionRef:
            group: "ngrok.k8s.ngrok.com"
            kind: "NgrokTrafficPolicy"
            name: basic-auth
    filters:
    - type: ExtensionRef
      extensionRef:
        group: "ngrok.k8s.ngrok.com"
        kind: "NgrokTrafficPolicy"
        name: basic-auth
```

## Gateway API HTTPS upstreams

If you have an `HTTPRoute` that routes to a Service that expects HTTPS instead of HTTP, you can specify this using the `k8s.ngrok.com/app-protocols` annotation on your `Service`.
For example, the following `Service` uses the annotation to let the Operator know which ports use HTTPS

```yaml theme={null}
apiVersion: v1
kind: Service
metadata:
  name: example-service
  labels:
    app: example-app
  annotations:
    k8s.ngrok.com/app-protocols: '{"https-port":"https","http-port":"http"}'
spec:
  ports:
    - name: https-port
      port: 443
      protocol: TCP
      targetPort: 8443
    - name: http-port
      port: 80
      protocol: TCP
      targetPort: 8080
  selector:
    app: example-app
```

## Gateway API status conditions

The Gateway API has guidance on status and condition handling in [GEP-1364](https://gateway-api.sigs.k8s.io/geps/gep-1364/) and the
Gateway API [Implementer's guide](https://gateway-api.sigs.k8s.io/guides/implementers/#standard-status-fields-and-conditions). The
ngrok-operator sets status and conditions on Gateway API resources.

### Viewing gateway statuses

You can view your gateways and whether or not they have been programmed by running `kubectl get gateways.gateway.networking.k8s.io --all-namespaces`:

```shell theme={null}
NAMESPACE   NAME                           CLASS   ADDRESS                                              PROGRAMMED   AGE
infra       custom-gateway                 ngrok   vxvuakisp8tmkwmn.4ras8yu7nq6zsudp3.ngrok-cname.com   True         97d
infra       invalid-http-port-gw           ngrok   invalid-gw-2.tests.ngrok.io                          Unknown      62d
infra       invalid-https-port-gw          ngrok   invalid-gw-1.tests.ngrok.io                          Unknown      62d
infra       invalid-no-hostname-http-gw    ngrok                                                        Unknown      62d
infra       invalid-no-hostname-https-gw   ngrok                                                        Unknown      62d
infra       shared-gateway                 ngrok   gateway.my-sub-domain.ngrok.io                       True         140d
```

In this example, you can see that 2 gateways have been successfully programmed in ngrok. The first one, `custom-gateway`, is using
a [Custom Domain](./custom-domain) and shows the ngrok CNAME assigned to it. The last one, `shared-gateway`, is using an ngrok
managed domain and has also been programmed. The other Gateways you see here are invalid and not able to be programmed.

Check the reason why a gateway is invalid by checking the status condition on the gateway and the listener status conditions
with `kubectl -n infra get gateway -o yaml invalid-http-port-gw`:

```yaml theme={null}
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: invalid-http-port-gw
  namespace: infra
spec:
  gatewayClassName: ngrok
  listeners:
  - allowedRoutes:
      kinds:
      - group: gateway.networking.k8s.io
        kind: HTTPRoute
      namespaces:
        from: All
    hostname: invalid-gw-2.tests.ngrok.io
    name: http
    port: 443
    protocol: HTTP
status:
  addresses:
  - type: Hostname
    value: invalid-gw-2.tests.ngrok.io
  conditions:
  - lastTransitionTime: "2025-06-11T15:00:27Z"
    message: gateway listeners are not valid
    observedGeneration: 1
    reason: ListenersNotValid
    status: "False"
    type: Accepted
  - lastTransitionTime: "1970-01-01T00:00:00Z"
    message: Waiting for controller
    reason: Pending
    status: Unknown
    type: Programmed
  listeners:
  - attachedRoutes: 0
    conditions:
    - lastTransitionTime: "2025-06-11T15:00:27Z"
      message: ngrok only supports HTTP on port 80
      observedGeneration: 1
      reason: PortUnavailable
      status: "False"
      type: Accepted
    - lastTransitionTime: "2025-06-11T20:28:15Z"
      message: listener is not valid
      observedGeneration: 1
      reason: Invalid
      status: "False"
      type: Programmed
    name: http
    supportedKinds: []
```

The listener for this Gateway is invalid because the listener specified listening for HTTP on port 443 and
ngrok only supports HTTPS listeners on port 443.
