Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.coreweave.com/llms.txt

Use this file to discover all available pages before exploring further.

CKS supports private API server access through a CoreWeave-managed Tailscale proxy. When you enable this feature, CKS creates a proxy that joins your tailnet and forwards requests to your cluster’s Kubernetes API server. This lets you access private clusters without exposing the API server to the public internet.

Authentication modes

Before you begin, choose the authentication mode that matches how your team manages Kubernetes access. The proxy supports three authentication modes:
ModeDescription
Tailscale Managed AuthThe proxy uses your Tailscale client identity to authenticate requests. User identity and groups come from Tailscale tags. You manage authorization using Kubernetes RBAC.
CoreWeave Managed AuthThe proxy routes requests through the CoreWeave API gateway. Authentication uses the Cloud Console API access token embedded in the kubeconfig.
Direct AuthThe proxy forwards raw packets directly to the API server. Use this mode with kubeconfigs that contain embedded client certificate credentials (client-certificate-data and client-key-data).

Prerequisites

Before you begin, make sure you have the following:

Configure Tailscale

The following steps configure your tailnet to allow the CoreWeave proxy to join. Enabling HTTPS certificates and setting up access controls are one-time tailnet tasks. Creating a trust credential is required once for each CKS cluster.

Enable HTTPS certificates

The CoreWeave proxy uses a Tailscale HTTPS certificate to secure communication over your tailnet. You must enable HTTPS certificates on your tailnet before the proxy can obtain one.
  1. Navigate to the Tailscale DNS settings.
  2. Scroll to the HTTPS Certificates section and click Enable HTTPS.

Configure access controls

The CoreWeave proxy needs permission to join your tailnet and register a Tailscale service without requiring manual approval each time.
  1. Navigate to the Tailscale access controls editor.
  2. Add the following entries to your tailnet policy JSON:
{
  "autoApprovers": {
    "services": {
      "tag:coreweave": [
        "tag:coreweave"
      ]
    }
  },
  "tagOwners": {
    "tag:coreweave": []
  }
}
The tagOwners entry with an empty array prevents individual users from manually assigning the tag:coreweave tag. Only machines provisioned through workload identity federation can claim this tag. The autoApprovers entry lets the proxy register a Tailscale service automatically.

Create a trust credential

The proxy authenticates to your tailnet using workload identity federation. Your CKS cluster acts as an OIDC (OpenID Connect) issuer, and the proxy exchanges a short-lived OIDC token for a Tailscale API token. No long-lived credentials are stored or distributed. You need one trust credential per CKS cluster. The issuer URL includes the cluster ID (https://oidc.cks.coreweave.com/id/[CLUSTER-ID]), which means the trust credential is unique to each cluster. This is intentional: the kube-apiserver is configured with --service-account-issuer=https://oidc.cks.coreweave.com/id/[CLUSTER-ID], so tokens are not trusted across clusters even within the same organization. This design ensures a strong security boundary on both the CoreWeave and Tailscale sides. The practical consequence is a one-time ordering constraint: you must create the trust credential in Tailscale before you can enable Tailscale VPN on the cluster, because the credential requires the cluster ID that only exists after the cluster is created. Once the credential exists, you can enable Tailscale on the cluster. The issuer URL for each cluster has the following format, where [CLUSTER-ID] is your cluster’s ID:
https://oidc.cks.coreweave.com/id/[CLUSTER-ID]
To find your cluster ID, open the cluster detail dialog in the Cloud Console. The console also provides a button to copy the full OIDC issuer url directly. To create a trust credential:
  1. Navigate to Tailscale trust credentials settings.
  2. Click + Credential and select Open ID Connect.
  3. Fill in the form with the following values:
    FieldValue
    DescriptionA name for this credential, for example, the cluster name
    IssuerCustom Issuer
    Issuer URLhttps://oidc.cks.coreweave.com/id/[CLUSTER-ID]
    Subjectsystem:serviceaccount:cw-tailscale:tailscale
    Audiencehttps://oidc.cks.coreweave.com/id/[CLUSTER-ID]
    The Subject value is always system:serviceaccount:cw-tailscale:tailscale for all CKS clusters.
  4. Click Continue.
  5. On the scopes page, grant the following two scopes. For each scope, add tag:coreweave as the associated tag:
    • Write Access for General > Services
    • Write Access for Keys > Auth Keys
  6. For both of these settings, from the Add tags menu, choose tag:coreweave.
  7. Click Generate credential.
After saving, note the Client ID that Tailscale displays. Use this value when you enable Tailscale on your cluster.

Optional: Terraform alternative

You can provision the trust credential using the Tailscale Terraform provider with the tailscale_federated_identity resource. Replace [CLUSTER-ID] with your cluster’s ID.
resource "tailscale_federated_identity" "cks_cluster" {
  description = "[YOUR-DESCRIPTION]"
  issuer      = "https://oidc.cks.coreweave.com/id/[CLUSTER-ID]"
  audience    = "https://oidc.cks.coreweave.com/id/[CLUSTER-ID]"
  subject     = "system:serviceaccount:cw-tailscale:tailscale"
  scopes = [
    "auth_keys",
    "services"
  ]
  tags = ["tag:coreweave"]
}

Enable Tailscale VPN for a cluster

With your tailnet configured, enable the Tailscale proxy on your CKS cluster using the CKS API to set the Tailscale client ID.

Get your cluster ID and API key

To find your CKS cluster ID, open the CoreWeave Cloud Console.
  1. Go to Compute > Clusters in the Cloud Console.
  2. Find your cluster, then open its details page.
  3. Open the JSON view.
  4. Copy the id value.
To create a new API key for your cluster, see Create a new API access token.

Enable Tailscale

Set the following environment variables, replacing the placeholders with your values:
export CLUSTER_ID="[CLUSTER-ID]"
export API_ACCESS_TOKEN="[API-ACCESS-TOKEN]"
Send the PATCH request, replacing [CLIENT-ID] with the client ID from the trust credential you created in the preceding section.
curl -X PATCH "https://api.coreweave.com/v1beta1/cks/clusters/$CLUSTER_ID" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $API_ACCESS_TOKEN" \
  -d '{
    "updateMask": "tailscale.clientId",
    "tailscale": {
      "clientId": "[CLIENT-ID]"
    }
  }'
You should see output similar to the following:
{
  "cluster": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "example-cluster",

    . . .

    "status": "STATUS_UPDATING",
    "apiServerEndpoint": "abc123-def45678.k8s.us-east-04a.coreweave.com",
    "createdAt": "2025-01-01T00:00:00Z",
    "updatedAt": "2025-01-01T00:05:00Z",
    "isUpgradeable": true
  }
}
After CKS receives the client ID, it creates a Tailscale proxy for your cluster. The proxy joins your tailnet and appears in the Tailscale admin console under Services. To verify the client ID is set, retrieve your cluster:
curl -H "Authorization: Bearer $API_ACCESS_TOKEN" \
     -H "Content-Type: application/json" \
     "https://api.coreweave.com/v1beta1/cks/clusters/$CLUSTER_ID"
A cluster with Tailscale VPN enabled includes a tailscale field in the response. Once provisioning is complete, the response also includes a tailnetDomain field:
{
  "cluster": {
    "tailscale": {
      "clientId": "[CLIENT-ID]",
      "tailnetDomain": "[TAILNET-DOMAIN].ts.net"
    }
  }
}
Due to how the system propagates values, tailnetDomain can take up to 10 minutes to appear in the API response after provisioning completes.
You can also confirm provisioning status using the Tailscale admin console:
  • Trust credential status: Go to https://login.tailscale.com/admin/settings/trust-credentials?q=[CLIENT-ID]. The credential detail page shows an authentication error if the proxy cannot authenticate to your tailnet, for example, due to a mistyped issuer URL or missing scopes.
  • Service status: Go to https://login.tailscale.com/admin/services/svc:[SERVICE-NAME]. The service detail page shows the service definition and its proxy hosts once they are provisioned.
Together with tailscale status on your local machine, these pages give you a complete view of provisioning progress.

Disable Tailscale

To disable the Tailscale proxy on a cluster, set the client ID to null:
curl -X PATCH "https://api.coreweave.com/v1beta1/cks/clusters/$CLUSTER_ID" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $API_ACCESS_TOKEN" \
  -d '{
    "updateMask": "tailscale.clientId",
    "tailscale": {
      "clientId": null
    }
  }'

Connect with the Tailscale client

With the proxy running on your cluster, connect your local machine to the tailnet so it can reach the proxy. If you use the Tailscale desktop app, open the app and log in through the GUI. The app handles authentication and route acceptance automatically. Skip to the verification step below. If you use the tailscaled CLI, start the daemon:
sudo tailscaled
If you have not previously connected to your tailnet, authenticate:
tailscale login
Follow the URL in the output to complete authentication in your browser. Enable route acceptance so your machine can reach the proxy:
tailscale set --accept-routes=true
Verify the proxy is visible in your tailnet:
tailscale status
The output includes the proxy nodes for your cluster:
100.104.110.46  [SERVICE-NAME]-proxy-0  tagged-devices  linux  -
100.103.104.80  [SERVICE-NAME]-proxy-1  tagged-devices  linux  -
For example: cw123a-us-east-04a-my-cluster-proxy-0. The Tailscale service name for your cluster follows the pattern [ORG-ID]-[ZONE]-[CLUSTER-NAME], where the zone is lowercased with hyphens (for example, US-EAST-04A becomes us-east-04a). Your organization ID prefix is visible in the Cloud Console.

Configure DNS

The proxy is reachable by its Tailscale fully qualified domain name (FQDN), so your machine must be able to resolve Tailscale hostnames. The Tailscale DNS server address is 100.100.100.100. You can confirm this on the Tailscale DNS settings page. On macOS, the Tailscale app configures DNS automatically when connected. No manual steps are required. On Linux, add the DNS server to your resolvers manually. The exact method depends on your distribution’s DNS manager. For example, on systems using systemd-resolved:
resolvectl dns tailscale0 100.100.100.100
To verify the DNS server is reachable:
ping -c 1 100.100.100.100
On Linux, remove the Tailscale DNS entry from your resolvers when you finish your session.
Your machine is now connected to the tailnet and can reach the CKS proxy. The following section covers how to authenticate to the Kubernetes API server using your chosen authentication mode.

Access the cluster

How you connect to the cluster depends on the authentication mode you use.

Tailscale Managed Auth

With Tailscale Managed Auth, the proxy authenticates requests using your Tailscale client identity. Your Kubernetes username is derived from your workstation’s hostname. Your Kubernetes groups come from the Tailscale tags assigned to your device in the Tailscale admin console. Before you begin, find your service name. You can get it two ways:
  • Run tailscale status and strip the -proxy-0 suffix from either proxy node name. For example, cw123a-us-east-04a-my-cluster-proxy-0 gives a service name of cw123a-us-east-04a-my-cluster.
  • Go to the Tailscale admin console Services page and find the entry for your cluster.
To generate a kubeconfig, run the following command, passing the service name for your cluster:
tailscale configure kubeconfig [SERVICE-NAME]
The command prints the FQDN of the service it configured, for example:
kubeconfig configured for "[SERVICE-NAME].[TAILNET-ID].ts.net" at URL "https://[SERVICE-NAME].[TAILNET-ID].ts.net"
Verify access:
kubectl auth whoami
You should see output similar to the following:
ATTRIBUTE   VALUE
Username    [USERNAME]
Groups      [system:authenticated]
The username is your workstation’s hostname in uppercase. The Groups field lists the Tailscale tags assigned to your device in the Tailscale admin console. If your device has no tags, only system:authenticated appears.

Configure RBAC

Tailscale Managed Auth maps Tailscale tags to Kubernetes groups, letting you use standard Kubernetes RBAC to control what cluster access each tag grants. Any device with a given Tailscale tag is treated as a member of the corresponding Kubernetes group when it connects through the proxy. For example, to grant read-only access to any device tagged tag:view:
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: tailscale-view
subjects:
  - kind: Group
    name: "tag:view"
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: view
  apiGroup: rbac.authorization.k8s.io
EOF
Verify the binding was created:
kubectl get clusterrolebinding tailscale-view
You should see output similar to the following:
NAME             ROLE               AGE
tailscale-view   ClusterRole/view   23s

Configure grants

Tailscale Managed Auth supports grants, which let you impersonate Kubernetes groups based on Tailscale ACL (access control list) rules. Add a grant to your tailnet policy JSON to let devices with tag:admin impersonate the system:masters Kubernetes group:
{
  "src": ["tag:admin"],
  "dst": ["tag:coreweave"],
  "app": {
    "tailscale.com/cap/kubernetes": [{
      "impersonate": {
        "groups": ["system:masters"]
      }
    }]
  }
}

CoreWeave Managed Auth

With CoreWeave Managed Auth, the proxy routes requests through the CoreWeave API gateway. Authentication uses the API access token embedded in the kubeconfig you download from the Cloud Console. Download a kubeconfig from the Cloud Console for your cluster, then update the server address to the Tailscale FQDN on port 9443. Use the FQDN from the tailscale configure kubeconfig output, or find it in the Tailscale admin console under Services. To find the cluster name in your kubeconfig:
kubectl config get-clusters
Then update the server address:
kubectl config set-cluster [CLUSTER-NAME] \
  --server https://[SERVICE-NAME].[TAILNET-ID].ts.net:9443
Verify access:
kubectl auth whoami
You should see output similar to the following:
ATTRIBUTE   VALUE
Username    cwtoken-[TOKEN-ID]-[USERNAME]
Groups      [admin read write system:authenticated]
The username corresponds to the Cloud Console token used to generate the kubeconfig.

Direct Auth

Direct Auth forwards raw packets directly to the Kubernetes API server. Use this mode with kubeconfigs that contain embedded client-certificate-data and client-key-data fields. Set the server address to the short Tailscale service name on port 6443 (without the .ts.net suffix):
kubectl config set-cluster [CLUSTER-NAME] \
  --server https://[SERVICE-NAME]:6443
Verify access:
kubectl auth whoami
Last modified on May 28, 2026