Skip to main content
The chainloop-ee chart can expose Chainloop through Kubernetes Gateway API HTTPRoute and GRPCRoute resources instead of, or alongside, Ingress. When the Gateway is Envoy Gateway, the chart also renders the traffic policies that long-running gRPC streams and large uploads need.
This guide is for platform operators deploying the Enterprise edition. The chart attaches routes to a Gateway you already run. It does not create the Gateway, its listeners or its public certificates.

Prerequisites

  • Gateway API CRDs that serve gateway.networking.k8s.io/v1 HTTPRoute and GRPCRoute.
  • A Gateway controller that supports HTTP/2 cleartext (h2c) to the backend Services. The chart sets appProtocol: kubernetes.io/h2c on the Services, so the controller must support HTTPRouteBackendProtocolH2C.
  • A Gateway with listeners and public TLS certificates for the hostnames listed in Hostnames.
  • For the Envoy Gateway traffic policies: the Envoy Gateway CRDs that serve gateway.envoyproxy.io/v1alpha1 BackendTrafficPolicy.
  • For TLS between the Gateway and the pods: CRDs that serve gateway.networking.k8s.io/v1 BackendTLSPolicy and a controller that supports it.

Enable Gateway API Routes

Set a base domain and the Gateway the routes attach to:
values.yaml
httpRoute.enabled turns on routes for every component. To route only some components, leave it false and set <component>.httpRoute.enabled: true instead. A component’s httpRoute.enabled: false does not turn its routes off while the global flag is true. Each component can also override hostname and parentRefs under frontend.httpRoute, backend.httpRoute, controlplane.httpRoute and cas.httpRoute.
Enabling Gateway API routes does not disable Ingress. The chart renders Ingress resources from their own flags regardless of the route settings: ingress.enabled, <component>.ingress.enabled, controlplane.ingressAPI.enabled, cas.ingressAPI.enabled, backend.mcpIngress.enabled and backend.samlDiscoverIngress.enabled. Some chart parameter descriptions say otherwise. Set these flags to false if the Gateway should be the only entry point.While Ingress is also enabled, the chart builds the backend, control plane and CAS external URLs and the CLI endpoints from the Ingress hostnames.

Hostnames

The chart prefixes the base domain for each route. If httpRoute.hostname is empty, it falls back to ingress.hostname. <component>.httpRoute.hostname replaces the derived hostname. The control plane and CAS gRPC routes use <component>.httpRouteAPI.hostname. If neither that nor a base domain is set, they use the component’s HTTP hostname. The backend URL that integrations call back to, such as the GitHub App or GitLab webhooks, is derived from these hostnames. See backend external URL.

Example: Gateway API Only, Without Ingress

This example exposes Chainloop only through an Envoy Gateway, with no Ingress resources. It assumes the release is installed in the chainloop namespace, and the Gateway runs in the infra namespace. First, create a Gateway with an HTTPS listener for all Chainloop hostnames. A single wildcard certificate for *.chainloop.example.com in the Secret chainloop-wildcard-tls covers them. The routes live in another namespace, so the listener must allow them through allowedRoutes:
gateway.yaml
Skip the GatewayClass if your Envoy Gateway installation already provides one, and use its name in gatewayClassName. To limit which namespaces can attach routes, use from: Selector instead of from: All. Then add the routes to your chart values:
values.yaml
All Ingress flags default to false, so this renders no Ingress. When you move an existing installation from Ingress to the Gateway, remove or set to false any of these flags your values still enable: ingress.enabled, frontend.ingress.enabled, backend.ingress.enabled, backend.mcpIngress.enabled, backend.samlDiscoverIngress.enabled, controlplane.ingress.enabled, controlplane.ingressAPI.enabled, cas.ingress.enabled and cas.ingressAPI.enabled. The chart renders five HTTPRoutes (app, app-api, mcp, cp and cas), three GRPCRoutes (app-api, cp-api and cas-api), and, with Envoy Gateway, one BackendTrafficPolicy per route. The CLI installer points to cp-api.chainloop.example.com:443 and cas-api.chainloop.example.com:443, or to cp. and cas. with shared endpoints. Check that no Ingress is left and that the routes are attached to the Gateway:
The first command should return no resources. Each route should report Accepted for chainloop-gateway.

Envoy Gateway Traffic Policies

Without extra configuration, Envoy applies a 15-second timeout to every request, including gRPC streams. Its default 32 KiB connection buffer and 64 KiB HTTP/2 windows towards the backend also slow down large uploads. The chart therefore renders one Envoy Gateway BackendTrafficPolicy per route, named after the route. Each policy sets the route’s request timeout. Routes that carry gRPC also get larger buffer and HTTP/2 window settings. The defaults, available in chart 0.601.1 and later:
values.yaml
With shared endpoints, the CLI sends its gRPC traffic to the control plane and CAS HTTPRoutes. Those routes then get the gRPC timeout and flow control. The request timeout also covers streaming responses, so long-lived MCP sessions can be cut after timeouts.api. Raise it if your clients need longer sessions.

When the Policies Are Rendered

httpRoute.envoyGateway.enabled accepts three values:
  • auto (default): render the policies only when Helm sees the gateway.envoyproxy.io/v1alpha1 BackendTrafficPolicy API in the cluster.
  • true: always render them.
  • false: never render them.
helm template and GitOps pipelines that render without access to the cluster do not see the API, so auto renders nothing. In that case, set enabled: true, or pass --api-versions gateway.envoyproxy.io/v1alpha1/BackendTrafficPolicy to helm template. The same flag also gates the rate limit policy for the SAML discovery route, which is rendered when backend.samlDiscoverIngress.enabled is true. Before chart 0.601.1, that policy was rendered whenever the route was. When upgrading with auto and an offline render, set enabled: true to keep the rate limit.

Existing Policies

If you already manage BackendTrafficPolicy resources for the Chainloop routes, remove them before you enable the chart policies, or set enabled: false. Do not attach two policies to the same route.

Other Gateway Implementations

With a Gateway controller other than Envoy Gateway, keep enabled: auto or set it to false. The chart then renders no gateway.envoyproxy.io resources. Configure equivalent request timeouts and upload buffers in your controller, otherwise its defaults may cut gRPC streams and large uploads.

Client-Side Settings

The chart only configures the Gateway’s connections towards the Chainloop pods. Listener buffers, HTTP/2 windows towards clients and header handling belong to an Envoy Gateway ClientTrafficPolicy attached to the Gateway, which you manage with the Gateway itself.

Shared Control Plane and CAS Endpoints

The control plane and CAS serve HTTP and native gRPC on one HTTP port, so a single hostname per component can carry both. This requires Chainloop OSS images v1.126.0 or later. By default the chart keeps sending clients to the legacy cp-api and cas-api endpoints. To switch the backend, the control plane’s CAS client, the Kubernetes sandbox CLI and the CLI installer (/cli/install.sh) to the shared endpoints, set:
values.yaml
With the example above, the CLI then uses cp.chainloop.example.com:443 and cas.chainloop.example.com:443. Values set in backend.preconfiguredCliSettings still take precedence. This flag only changes which endpoints clients use. The legacy cp-api and cas-api routes, and the ingressAPI, httpRouteAPI and serviceAPI settings, keep working but are deprecated. CLIs that are already installed keep their saved addresses, so reconfigure them:
To go back, set useSharedEndpoints: false and reconfigure the CLIs to the legacy addresses.

TLS Between the Gateway and the Pods

By default, public TLS terminates at the Gateway and the Gateway reaches the backend, control plane and CAS pods over h2c. To encrypt that hop as well:
  1. Enable TLS in the pods with a Secret containing tls.crt and tls.key: backend.tlsConfig.secret.name, controlplane.tls.existingSecret and cas.tls.existingSecret. For the control plane and CAS, the Secret enables TLS on both the HTTP and gRPC listeners. Direct HTTP clients must then use HTTPS.
  2. Let the chart render a Gateway API BackendTLSPolicy per component, so the Gateway connects with TLS and verifies the pod certificate. This option is available in chart releases after 0.606.0.
For a release named chainloop-ee in the namespace chainloop, create the certificate Secrets and an internal-ca ConfigMap with the CA bundle in ca.crt first, then set:
values.yaml
Rules for each policy:
  • The component’s Gateway routes must be enabled. Without routes, the chart renders no policy.
  • A pod TLS Secret is required. Without one, rendering fails.
  • hostname must be a DNS name in the pod certificate’s SANs. The Gateway uses it for SNI and certificate verification.
  • Set exactly one trust source: caCertificateRefs (ConfigMaps in the release namespace, each with a ca.crt key) or wellKnownCACertificates: System (the Gateway’s system trust store). Certificate verification cannot be skipped.
The backend policy targets the backend Service http port. The control plane and CAS policies target both the shared Service http port and the legacy -api Service grpc port, with the same hostname and CA. The MCP and metrics listeners stay plaintext. The upstream TLS connection must negotiate HTTP/2 through ALPN. According to the Envoy Gateway 1.6 release notes, backend TLS includes h2 by default from that version. On older versions, set spec.backendTLS.alpnProtocols: [h2, http/1.1] on the EnvoyProxy of your GatewayClass.
If you already manage BackendTLSPolicy resources for these Services in your infrastructure, either keep the chart option disabled or remove those policies before enabling it. The chart does not install CRDs, issue certificates, create a CA or change the Gateway’s public certificates.

Trust for Internal Clients

The BackendTLSPolicy only covers the Gateway. Chainloop components also call each other directly. Add your private CA to the customCAs list so the backend, workers, control plane and CAS trust the pod certificates. Make sure the certificates cover the names those clients dial: the short Service names, the -api Service names, and the namespace-qualified names where used. The Kubernetes sandbox CLI uses one TLS setting for the platform, control plane and CAS endpoints, so either all of them use TLS or none do. Sandbox clients do not get the customCAs certificates, so provision private CA trust for them separately. Certificate renewal is not handled by the chart. Renew certificates through your issuer and restart or reload the workloads when the Secrets change, for example with Reloader. Test HTTP, native gRPC, internal calls and certificate renewal in a separate deployment before enabling pod TLS in production. Changing the listeners and the Gateway policies is not atomic.

Using Ingress Instead

The control plane and CAS Ingress resources also send HTTP/2 to the shared ports, which requires Chainloop OSS images v1.126.0 or later. The chart sets the upstream protocol annotations for community ingress-nginx (backend-protocol: GRPC, or GRPCS with pod TLS) and F5 NGINX (nginx.org/grpc-services and nginx.org/http2) on the Ingress. For Traefik it sets traefik.ingress.kubernetes.io/service.serversscheme (h2c, or https with pod TLS) on the Service. Every backend behind an ingress-nginx Ingress for these components, including extraPaths, must accept HTTP/2. Other controllers need their own HTTP/2 upstream settings. The /mcp and MCP OAuth paths are served by a separate <release>-backend-mcp-paths Ingress. F5 NGINX does not merge Ingress resources that share a host, so set backend.ingress.mcpPathsInline: true to serve those paths from the backend Ingress. Do not set it with community ingress-nginx, where the GRPC backend protocol would then apply to the MCP paths too.

Verify

Check that the routes and policies are rendered and accepted:
Routes should report Accepted and ResolvedRefs for their parent Gateway, and policies should report Accepted. Then log in with the CLI and run an attestation that uploads an artifact, to exercise the control plane and CAS gRPC paths.

Troubleshooting