Skip to content
agentgateway has joined the Agentic AI FoundationLearn more

For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.

Page as Markdown

BackendTLS

Originate a one-way TLS connection from the Gateway to a backend.

Warning

This feature is experimental in the upstream Kubernetes Gateway API and subject to change.

About one-way TLS

When you configure a TLS listener on your Gateway, the Gateway typically terminates incoming TLS traffic and forwards the unencrypted traffic to the backend service. However, you might have a service that only accepts TLS connections, or you want to forward traffic to a secured backend service that is external to the cluster.

You can use the Kubernetes Gateway API BackendTLSPolicy to configure TLS origination from the Gateway to a service in the cluster. This policy supports simple, one-way TLS use cases.

About this guide

In this guide, you learn how to originate one-way TLS connections for the following services:

  • In-cluster service: An NGINX server that is configured with a self-signed TLS certificate and deployed to the same cluster as the Gateway. You use a BackendTLSPolicy to originate TLS connections to NGINX.
  • External service: The httpbin.org hostname, which represents an external service that you want to originate a TLS connection to. You use a BackendTLSPolicy resource to originate TLS connections to that hostname.

Before you begin

  1. Follow the Get started guide to install agentgateway.

  2. Follow the Sample app guide to create a gateway proxy with an HTTP listener and deploy the httpbin sample app.

  3. Get the external address of the gateway and save it in an environment variable.

    Tip

    Kind cluster? Kind does not support LoadBalancer services by default. To use this option with a Kind cluster, install and run cloud-provider-kind.

    export INGRESS_GW_ADDRESS=$(kubectl get svc -n agentgateway-system agentgateway-proxy -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")
    echo $INGRESS_GW_ADDRESS  

In-cluster service

Deploy an NGINX server in your cluster that is configured for TLS traffic. Then, instruct the gateway proxy to terminate TLS traffic at the gateway and originate a new TLS connection from the gateway proxy to the NGINX server.

Create sample certificates

Create a CA and a server certificate for the example.com hostname. If you already have your own certificates such as from a CA provider, update the steps accordingly.

Warning

Self-signed certificates are used for demonstration purposes. Do not use self-signed certificates in production environments. Instead, use certificates that are issued from a trusted Certificate Authority.

  1. Create the example_certs directory and navigate to this directory.

    mkdir -p example_certs && cd example_certs
  2. Create self-signed certificates for the Certificate Authority (CA) that you later use to sign the server certificate.

    # Create CA private key
    openssl genrsa -out ca-key.pem 2048
    
    # Create CA certificate (valid for 1 year)
    openssl req -new -x509 -days 365 -key ca-key.pem -out ca-cert.pem \
      -subj "/CN=Test CA/O=Test Org"
  3. Create a server certificate for the example.com hostname that is signed by the CA that you created in the previous step.

    # Create server private key
    openssl genrsa -out server-key.pem 2048
    
    # Create server certificate signing request
    openssl req -new -key server-key.pem -out server.csr \
      -subj "/CN=example.com/O=Test Org"
    
    # Create server certificate signed by CA (valid for 1 year)
    openssl x509 -req -days 365 -in server.csr -CA ca-cert.pem -CAkey ca-key.pem \
      -CAcreateserial -out server-cert.pem \
      -extensions v3_req -extfile <(echo "[v3_req]"; \
        echo "basicConstraints=CA:FALSE"; \
        echo "keyUsage=digitalSignature,keyEncipherment"; \
        echo "extendedKeyUsage=serverAuth"; \
        echo "subjectAltName=DNS:example.com,DNS:*.example.com")

Deploy the sample app

Deploy an NGINX server that serves HTTPS traffic. The NGINX server presents the server certificate, and the gateway proxy later uses the CA certificate to verify it.

  1. Store the server certificate and key in a Kubernetes secret that the NGINX server mounts.

    kubectl create secret tls nginx-server-cert \
      --cert=server-cert.pem \
      --key=server-key.pem \
      -n agentgateway-system
  2. Deploy the NGINX server and a Service that exposes it on HTTPS port 8443.

    kubectl apply -f- <<EOF
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: nginx-conf
      namespace: agentgateway-system
      labels:
        app: nginx
    data:
      nginx.conf: |
        events {}
        http {
          server {
              listen              443 ssl;
              server_name         example.com;
              ssl_certificate     /etc/nginx/certs/tls.crt;
              ssl_certificate_key /etc/nginx/certs/tls.key;
              location / {
                return 200 "hello from nginx\n";
              }
          }
        }
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
      namespace: agentgateway-system
      labels:
        app: nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          app.kubernetes.io/name: nginx
      template:
        metadata:
          labels:
            app.kubernetes.io/name: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:stable
            ports:
            - containerPort: 443
              name: https-web-svc
            volumeMounts:
            - name: nginx-conf
              mountPath: /etc/nginx/nginx.conf
              subPath: nginx.conf
            - name: server-cert
              mountPath: /etc/nginx/certs
              readOnly: true
          volumes:
          - name: nginx-conf
            configMap:
              name: nginx-conf
          - name: server-cert
            secret:
              secretName: nginx-server-cert
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx
      namespace: agentgateway-system
      labels:
        app: nginx
    spec:
      selector:
        app.kubernetes.io/name: nginx
      ports:
      - protocol: TCP
        port: 8443
        targetPort: https-web-svc
        name: https
    EOF
  1. Verify that the NGINX server is running.

    kubectl get pods -l app.kubernetes.io/name=nginx -n agentgateway-system

    Example output:

    NAME                     READY   STATUS    RESTARTS   AGE
    nginx-7c8f9d5b4c-x2vlq   1/1     Running   0          9s

Originate TLS connections

Create a BackendTLSPolicy for the NGINX workload.

  1. Create a Kubernetes ConfigMap that has the CA certificate the Gateway uses to verify the NGINX server. The CA certificate must be in the ca.crt key.

    kubectl create configmap ca \
      --from-file=ca.crt=ca-cert.pem \
      -n agentgateway-system
  2. Create the TLS policy. Note that to use the BackendTLSPolicy, you must have the experimental channel of the Kubernetes Gateway API version 1.4 or later.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: BackendTLSPolicy
    metadata:
      name: tls-policy
      namespace: agentgateway-system
      labels:
        app: nginx
    spec:
      targetRefs:
      - group: ""
        kind: Service
        name: nginx
      validation:
        hostname: "example.com"
        caCertificateRefs:
        - group: ""
          kind: ConfigMap
          name: ca
    EOF

    Review the following table to understand this configuration. For more information, see the Kubernetes Gateway API docs.

    SettingDescription
    targetRefsThe service that you want the Gateway to originate a TLS connection to, such as the NGINX server.

    Agentgateway proxies: Even if you use a Backend for selector-based destinations, you still need to target the backing Service and the sectionName of the port that you want the policy to apply to.
    validation.hostnameThe hostname that matches the NGINX server certificate. The gateway verifies this hostname against the Subject Alternative Names (SANs) or Common Name (CN) in the server certificate.
    validation.caCertificateRefsThe ConfigMap that has the CA certificate used to verify the backend, in a ca.crt key. For the NGINX deployment in this guide, use the CA that signed the NGINX server certificate.
  3. Create an HTTPRoute that routes traffic to the NGINX server on the example.com hostname and HTTPS port 8443. Note that the parent Gateway is the sample http Gateway resource that you created before you began.

    kubectl apply -f - <<EOF
    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: HTTPRoute
    metadata:
      name: nginx-route
      namespace: agentgateway-system
      labels:
       app: nginx
    spec:
      parentRefs:
      - name: agentgateway-proxy
        namespace: agentgateway-system
      hostnames:
      - "example.com"
      rules:
      - backendRefs:
        - name: nginx
          port: 8443
    EOF
  4. Send a request to the NGINX server and verify that you get back a 200 HTTP response code.

    curl -vi http://$INGRESS_GW_ADDRESS:80/ -H "host: example.com:80"

    Example output:

    * Host localhost:8080 was resolved.
    * IPv6: ::1
    * IPv4: 127.0.0.1
    *   Trying [::1]:8080...
    * Connected to localhost (::1) port 8080
    > GET / HTTP/1.1
    > Host: example.com:8080
    > User-Agent: curl/8.7.1
    > Accept: */*
    > 
    * Request completely sent off
    < HTTP/1.1 200 OK
    HTTP/1.1 200 OK

    The HTTPRoute forwards the request to the NGINX server on port 8443, and the NGINX server accepts only TLS on that port. A 200 response means that the gateway proxy originated a TLS connection to the backend successfully. Without a valid BackendTLSPolicy and CA certificate, requests fail with invalid peer certificate: UnknownIssuer.

External service

Set up an AgentgatewayBackend resource that represents your external service. Then, use a BackendTLSPolicy to instruct the gateway proxy to originate a TLS connection from the gateway proxy to the external service.

  1. Create an AgentgatewayBackend resource that represents your external service. In this example, you use a static backend that routes traffic to the httpbin.org site. Make sure to include the HTTPS port 443 so that traffic is routed to this port.

    kubectl apply -f- <<EOF
    apiVersion: agentgateway.dev/v1alpha1
    kind: AgentgatewayBackend
    metadata:
      name: httpbin-org
      namespace: agentgateway-system
    spec:
      static:
        host: httpbin.org
        port: 443
    EOF
  2. Create a TLS policy that originates a TLS connection to the AgentgatewayBackend that you created in the previous step. To originate the TLS connection, you use known trusted CA certificates.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: BackendTLSPolicy
    metadata:
      name: httpbin-org
      namespace: agentgateway-system
    spec:
      targetRefs:
        - name: httpbin-org
          kind: AgentgatewayBackend
          group: agentgateway.dev
      validation:
        hostname: httpbin.org
        wellKnownCACertificates: System
    EOF
  3. Create an HTTPRoute that rewrites traffic on the httpbin-external.example domain to the httpbin.org hostname and routes traffic to your Backend.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin-org
      namespace: agentgateway-system
    spec:
      parentRefs:
      - name: agentgateway-proxy
        namespace: agentgateway-system
      hostnames:
      - "httpbin-external.example"
      rules:
        - matches:
          - path:
              type: PathPrefix
              value: /anything
          backendRefs:
          - name: httpbin-org
            kind: AgentgatewayBackend
            group: agentgateway.dev
          filters:
          - type: URLRewrite
            urlRewrite:
              hostname: httpbin.org
    EOF
  4. Send a request to the httpbin-external.example domain. Verify that the host is rewritten to https://httpbin.org/anything and that you get back a 200 HTTP response code.

    curl -vi http://$INGRESS_GW_ADDRESS:80/anything -H "host: httpbin-external.example" 

    Example output:

    < HTTP/1.1 200 OK
    HTTP/1.1 200 OK
    ...
    {
      "args": {}, 
      "data": "", 
      "files": {}, 
      "form": {}, 
      "headers": {
        "Accept": "*/*", 
        "Host": "httpbin.org", 
        "User-Agent": "curl/8.7.1", 
        "X-Amzn-Trace-Id": "Root=1-6881126a-03bfc90450805b9703e66e78", 
        "X-Envoy-Expected-Rq-Timeout-Ms": "15000", 
        "X-Envoy-External-Address": "10.0.X.XXX"
      }, 
      "json": null, 
      "method": "GET", 
      "origin": "10.0.X.XXX, 3.XXX.XXX.XXX", 
      "url": "https://httpbin.org/anything"
    }
    

Cleanup

You can remove the resources that you created in this guide.

In-cluster service

kubectl delete deployment,service,backendtlspolicy,configmap,httproute -A -l app=nginx
kubectl delete secret nginx-server-cert -n agentgateway-system --ignore-not-found
kubectl delete configmap ca -n agentgateway-system --ignore-not-found

Remove the certificates that you created.

cd .. && rm -rf example_certs

External service

Delete the resources that you created.

kubectl delete httproute httpbin-org -n agentgateway-system
kubectl delete backendtlspolicy httpbin-org -n agentgateway-system
kubectl delete AgentgatewayBackend httpbin-org -n agentgateway-system
Was this page helpful?
Agentgateway assistant

Ask me anything about agentgateway configuration, features, or usage.

Note: AI-generated content might contain errors; please verify and test all returned information.

Tip: one topic per conversation gives the best results. Use the + button in the chat header to start a new conversation.

Switching topics? Starting a new conversation improves accuracy.
↑↓ navigate select esc dismiss

What could be improved?

Your feedback helps us improve assistant answers and identify docs gaps we should fix.

Need more help? Join us on Discord: https://discord.gg/y9efgEmppm

Want to use your own agent? Add the Solo MCP server to query our docs directly. Get started here: https://search.solo.io/.