Skip to main content
A direct data plane endpoint lets the cwsandbox client carry exec, log, and file operations straight to the runner. These operations use mutual Transport Layer Security (mTLS) instead of passing through the CoreWeave Sandboxes gateway. Lifecycle and management calls still go through the gateway. This page is for administrators who operate a managed runner on a CoreWeave Kubernetes Service (CKS) cluster. Use this page to learn about the following topics:
  • How the direct path reaches the runner.
  • How to choose and configure an exposure mode.
  • How to route the endpoint through your own ingress controller.
  • How to confirm the endpoint is ready.

Direct connection path to the runner

Each managed runner can serve one stable data-plane endpoint that fronts all of its replicas. The platform resolves the endpoint’s address from the runner’s dataPlane configuration and issues the runner a server certificate for that address. The CoreWeave Sandboxes gateway returns the address to clients together with a sandbox-scoped client certificate. The following properties of this path shape the configuration choices on this page:
  • The TLS session terminates at the runner: The runner authenticates every connection by client certificate. Intermediaries must forward the Transmission Control Protocol (TCP) stream unchanged. These include load balancers, ingress controllers, and virtual private networks (VPNs). A proxy that terminates TLS and re-encrypts, or that replaces the client identity with a header, breaks the direct path.
  • The server certificate is issued for the advertised address: The platform derives the certificate’s subject alternative names from the address you configure. Clients verify the runner against that name, so the address must be stable and must resolve to the endpoint.
  • The data-plane Service exposes one port: Every enabled exposure mode creates a Service for only the data-plane listener, TCP port 9443. A custom ingress can publish a different port, such as 443, and forward it to this Service. The data-plane Service doesn’t expose health, metrics, or control ports.
Clients that use the default AUTO transport policy can fall back to the gateway if direct connection setup is unavailable. A PERMISSION_DENIED or UNAUTHENTICATED error from credential issuance still fails. If a direct certificate lacks permission for an operation, AUTO can use the gateway. Fallback isn’t a guarantee that an operation already sent to the runner can be retried safely.

Prerequisites

Before you configure the direct data plane, complete the following prerequisites:
  • Deploy a managed runner and confirm that installStatus is RUNNER_INSTALL_STATUS_READY. In the examples, replace RUNNER_ID with your runner ID. For deployment instructions, see Deploy and manage a runner.
  • Authenticate the CoreWeave Intelligent CLI or export a CoreWeave API access token for curl, as described in Before you begin on the runner page. The examples on this page use the same $TOKEN variable.
  • Use a token with the sandbox_admin permission to read or update the runner.
  • Have kubectl access to the CKS cluster that hosts the runner. Runner resources live in the cw-sandbox-system Namespace. For the custom exposure examples, also install Helm and have permission to manage cluster-scoped resources such as CustomResourceDefinitions (CRDs) and GatewayClass.

Choose an exposure mode

The spec.data_plane field selects exactly one exposure mode. When you leave the field unset, the runner inherits the platform default for its release channel. Set disabled explicitly to opt out of an enabled default. In the following addresses, replace SERVICE_NAME with the runner Service name and HOSTNAME with the configured hostname. The platform names the Service after its internal identifier for the runner, so read the name from the cluster rather than deriving it. The Service carries the label sandbox.coreweave.com/component=data-plane:
The following constraints apply to changes:
  • After a nonempty load_balancer.load_balancer_class is set, you can’t change or clear it in place, including by switching to another enabled exposure mode. Set disabled first, wait for the Service to be removed, then apply the new configuration.
  • A change in exposure mode can change the advertised address and interrupt active direct operations. Verify connectivity again after the change.

Expose the endpoint with a LoadBalancer Service

The load_balancer mode creates a LoadBalancer Service that forwards TCP port 9443 to the runner without terminating TLS. Set the intended reachability with scope and configure the provider’s address selection through annotations or load_balancer_class. Pass client network ranges in classless inter-domain routing (CIDR) notation through source_ranges. The provider must support and enforce those source ranges. hostname is required. The platform includes it in the server certificate, advertises https://HOSTNAME:9443 to clients, and sets the external-dns.alpha.kubernetes.io/hostname annotation on the Service for clusters that run ExternalDNS. On CKS, publish the name through the External Hostname Controller instead. Add the service.beta.kubernetes.io/external-hostname annotation and set hostname to the fully qualified name that CKS allocates. The short annotation value runner-a produces runner-a.ORG_ID-CLUSTER_NAME.coreweave.app. Follow only the DNS allocation instructions in Create a public DNS name. The runner provides its TLS certificate, so don’t configure ingress TLS termination for this endpoint. For a public address on CKS, also add service.beta.kubernetes.io/coreweave-load-balancer-type: public. With the default CKS address configuration, omitting this annotation assigns a private address. For address selection details, see Expose a Service. A PRIVATE scope requires either a load_balancer_class or a provider annotation, because the platform can’t infer how your provider selects a private address. Replace ORG_ID and CLUSTER_NAME with your organization ID and the cluster name, and replace CLIENT_CIDR in source_ranges with the CIDR of a network your clients connect from.
data-plane.yaml
After the update, the runner rolls out with the new configuration and the Service appears in the cw-sandbox-system Namespace. Check the Service address and DNS, then verify from a client. A successful configuration update doesn’t confirm network reachability.

Route the endpoint through your own ingress controller

If your cluster already terminates inbound traffic at an ingress controller, use custom mode for an endpoint behind the same address. The platform creates a ClusterIP Service on port 9443, and you supply the address that clients should dial as advertised_uri. The requirements are the same as for any path in front of the runner:
  • Use TLS passthrough for the route, matched on the TLS server name indication (SNI) of the connection. Don’t terminate TLS at the ingress controller.
  • Set advertised_uri to an absolute https:// origin with no path, query, or credentials, such as https://runner-a.ORG_ID-CLUSTER_NAME.coreweave.app:443. The host must resolve to the ingress controller, and the port must be the port the controller listens on.
  • Install Gateway API CRDs compatible with your controller. The CoreWeave Traefik chart and the Envoy Gateway v1.9.1 example both support TLSRoute version v1. Don’t replace a CRD bundle owned by another component without coordinating with its owner.
Both examples use a hostname under your cluster’s .coreweave.app domain. Traefik uses the cluster wildcard record. The Envoy example creates a specific record through the external-hostname annotation. Replace ORG_ID and CLUSTER_NAME with your values.

Prepare the ingress controller

Choose the controller you run. Both configurations publish a TLS passthrough listener for the runner hostname on a public LoadBalancer Service with a .coreweave.app DNS name.
The CoreWeave Traefik chart can serve Gateway API routes on the same Pods and the same LoadBalancer Service as its Ingress routes. The chart’s Service already carries service.beta.kubernetes.io/coreweave-load-balancer-type: public and service.beta.kubernetes.io/external-hostname: '*'. The wildcard resolves hostnames under *.ORG_ID-CLUSTER_NAME.coreweave.app to Traefik unless a specific DNS record takes precedence. Before using the runner hostname, confirm that it resolves to Traefik’s address. If an existing record points elsewhere, choose an unused hostname or update that record. See Gateway API for the chart’s prerequisites and CRD ownership guidance.
  1. Follow Install the Gateway API CRDs for the standard-channel bundle supported by the chart. If a compatible bundle is already installed, reuse it.
  2. Enable the Gateway API provider and add a TLS passthrough listener on the websecure entrypoint. The listener port is Traefik’s container port (8443), not the port the LoadBalancer publishes (443):
    traefik-values.yaml
    If Traefik is already installed from this chart, merge these values into your existing values file and upgrade the release.
The resulting Gateway is named traefik-gateway in the traefik Namespace. Use those values for GATEWAY_NAME and GATEWAY_NAMESPACE in the following route.

Point the runner at the ingress address

The custom.advertised_uri value is what clients dial, so it names the ingress hostname and port, not the ClusterIP Service.
  1. Set custom.advertised_uri to the address your ingress controller serves. This configuration also creates the data-plane Service that the route targets in the next step.
    data-plane.yaml
  2. Wait for the runner to roll out.
  3. Read the name of the Service it created:

Bind the route to the runner Service

Create a TLSRoute in the runner’s Namespace that binds the passthrough listener to the data-plane Service.
  1. Replace GATEWAY_NAME and GATEWAY_NAMESPACE with the values from the controller you prepared, and SERVICE_NAME with the Service name from the previous step:
    runner-tlsroute.yaml
  2. Look for Accepted: True and ResolvedRefs: True in status.parents[].conditions.
  3. Verify from a client on the network that uses the endpoint.

Check the endpoint status

Inspect the runner after any configuration change.
  1. Check installStatus, connectionStatus, and whether activeRevision has reached targetRevision.
  2. Check the data-plane Service:
    For load_balancer, confirm that the Service has an address and that the configured hostname resolves to it. For custom, check the ingress controller’s address and the TLSRoute conditions.
These checks don’t prove the client can complete mTLS. Run the client check next.

Verify from a client

The Python client needs its own token environment variable, even if you used cwic auth login for the management commands. In the following command, replace API_ACCESS_TOKEN with your CoreWeave API access token secret.
  1. Install the client in an active Python virtual environment, as described in Prepare your Python environment:
  2. Run an operation on the configured CKS runner with the client’s transport policy set to DIRECT. That mode never falls back to the gateway, so a successful call proves the direct path works from that network:
If the call raises an error while the same call under DataPlaneMode.GATEWAY succeeds, follow Troubleshooting. For the full set of client options, see Direct sandbox connections.

Disable the endpoint

Set disabled to remove the Service the platform created. New operations on AUTO can use the gateway when direct setup is unavailable. Operations pinned to DIRECT fail when they can’t establish a direct connection. Existing direct operations can be interrupted.

Troubleshooting

See also

For an overview of where the gateway and runners sit, see Sandboxes architecture.
Last modified on November 6, 2026