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

# Clusters

> Run task executors inside your own Kubernetes cluster to reach isolated hosts

Some hosts sit in network zones 2501 cannot reach — a private subnet behind your firewall, with no inbound access you are willing to open. A cluster lets 2501 operate them anyway: you register a Kubernetes cluster that sits inside that network, and for each task the engine spawns a short-lived executor pod in it. The executor connects out to the engine over TLS, reaches the host over SSH/WinRM from inside your network, and is deleted when the task ends. Nothing stays installed in your infrastructure, and no inbound connection to your network ever opens.

## How it works

Each task gets its own executor pod, created through your cluster's API - with the credentials you registered or, when the engine runs inside that cluster itself, with the engine's own service account and no stored credentials at all. The pod dials the engine back with an outbound TLS connection, authenticated by a single-use token. The token only covers this first dial: it is spent when the connection is established, and its two-minute expiry bounds how long the pod has to start and dial back, not how long the task may run. The task's commands then flow over the established connection for the length of the task.

The security properties this is built around:

* **No inbound flow.** The engine talks to your cluster's API server, and the pod connects out to the engine. Nothing from the outside ever dials into your network.
* **No credentials at rest in your cluster.** The target host's credentials are sent over the session's TLS connection when it starts; they never appear in the pod spec and are never written to disk in the cluster.
* **An unprivileged pod.** The executor runs as a non-root user with privilege escalation denied, all capabilities dropped, and no Kubernetes service-account token — it fits a `restricted` Pod Security Standard namespace.
* **Nothing resident.** The pod is deleted when the task ends. Between tasks, 2501 has no footprint in your cluster.

## Registering a cluster

Go to **Command Center** → **Clusters** → **Register Cluster**:

* **Name** — the handle hosts refer to.
* **API server** — the cluster's API URL, e.g. `https://cluster.example.com:6443`. Leave it empty to run executors in the cluster the engine itself runs in (no credentials needed).
* **Cluster CA certificate** — the CA to verify the API server against, stored as a [Credential](/0.13/configure/credentials). A remote cluster without a CA is refused unless you explicitly opt into skipping TLS verification.
* **Authentication** — either a client certificate + key pair or a bearer token, each stored as a Credential.
* **Keep finished executor pods** — off by default; on, finished pods stay in the cluster so you can inspect a run, and cleaning them up is yours to do.

The service account behind the credentials needs to create, read and delete pods in the namespaces you grant — nothing else. Scoping it is your RBAC: the grant is auditable and revocable on your side like any other external operator's.

## Network prerequisites

* The engine must reach the cluster's API server.
* Pods in the cluster must be able to open outbound connections to the engine's dial-back address, on port 443 on the engine side - traffic always flows outbound from the pod to the engine. If the cluster's only egress is an HTTP proxy, set the cluster's dial-back proxy: executors then tunnel through it, and the proxy only needs to allow CONNECT to that address — the TLS still terminates at the engine, so the proxy carries ciphertext it cannot read.
* The cluster's nodes must be able to pull the executor image from the registry your deployment publishes it to (`SATELLITE_EXECUTOR_IMAGE` on the engine; add an image pull secret in the namespace if the registry is private).

The dial-back side is part of the engine deployment: `SATELLITE_DIALBACK_URL` is the address executors dial, and the `SATELLITE_TLS_*` variables configure the TLS listener that answers them.

## Connecting a host through a cluster

On the host's **Connectivity** section, set the access method to **Via cluster** and pick the cluster. Three optional settings shape where its executors run:

* **Namespace** — where this host's executor pods are created. Left empty, they land in `default` - or, when the engine runs in that same cluster, in the engine's own namespace. The cluster's service account must have rights there.
* **Placement** — Kubernetes nodeSelector lines (`key=value`), pinning the executor to the nodes that can actually reach the host. The typical case is one cluster whose nodes span network zones: the selector names the nodes inside the host's zone.
* **Tolerations** — `key[=value]:effect` lines, needed when those nodes are tainted to keep general workloads off them.

## Testing with a dry run

The **Dry run** action on the Clusters page proves the whole round-trip without running a task or touching any host: it spawns a probe executor, waits for it to dial back and complete the handshake, then tears it down. Each stage reports live with its timing, and a failure comes with the pod's own status (such as `Unschedulable` or `ImagePullBackOff`) and a hint on where to look. You can pass a placement and tolerations to prove a host's pin schedules before that host depends on it.

## Deleting a cluster

Deleting a cluster is refused while hosts still connect through it. Point those hosts elsewhere first — their connectivity never silently degrades to a direct connection.
