> ## Documentation Index
> Fetch the complete documentation index at: https://controlplanecorporation-majid-surface-own-hardware-deployme.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy a Workload to Your Own Hardware

> Run Control Plane workloads on bare metal, on-premises VMs, or servers in your own data center by turning them into a Control Plane location with Managed Kubernetes or BYOK.

## Overview

Control Plane workloads are not limited to public cloud regions. Your own compute — a bare-metal server in a data center or colo, on-premises VMs under VMware or vSphere, or machines in a private cloud — can become a Control Plane [location](/reference/location) that you deploy to exactly like `aws-us-east-1`.

There are two ways to get there, depending on what you already have.

<AccordionGroup>
  <Accordion title="Can I run workloads on my own servers?">
    Yes. Your servers become a Control Plane [location](/reference/location), and any [workload](/concepts/workload) configured for that location is managed by Control Plane and rolls out onto your hardware. If you already run a Kubernetes cluster, register it with [CPLN BYOK](/byok/overview). If you have servers but no cluster, the [Managed Kubernetes Generic provider](/mk8s/generic) turns any Linux server into a cluster worker node first.
  </Accordion>

  <Accordion title="Can I deploy to my own data center?">
    Yes. [CPLN BYOK](/byok/overview) gives you the benefits of Control Plane with the added flexibility and security of running in your own cloud account or data center. Physical servers in a colo, on-premises virtual machines, and private-cloud instances are all supported as cluster nodes — the [Generic provider](/mk8s/generic) is vendor-agnostic, so a Dell, HP, or Supermicro box is treated the same as a cloud instance.
  </Accordion>

  <Accordion title="Do I have to use AWS, GCP, or Azure?">
    No. Public cloud regions are the built-in locations, not the only ones. You can run entirely on your own hardware, entirely on public cloud, or across both at once from the same [GVC](/reference/gvc). Workloads that run on your own hardware still reach AWS, Azure, and GCP services through [Universal Cloud Identity](/core/accessing-cloud-resources) without embedded credentials.

    Bring-your-own-cloud (BYOC) and bring-your-own-hardware are the same mechanism here: whether the cluster sits in your own cloud account or your own data center, it registers as a Control Plane location and workloads roll out to it identically.
  </Accordion>
</AccordionGroup>

## When to use each path

| You have                                                                  | Use                                                                                          | Guide                             |
| :------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------- | :-------------------------------- |
| An existing Kubernetes cluster (EKS, GKE, AKS, k3s, RKE, or self-managed) | **BYOK** — register the cluster as a location                                                | [CPLN BYOK](/byok/overview)       |
| Linux servers, bare metal or VMs, but no cluster                          | **Managed Kubernetes, Generic provider** — turn the servers into a cluster, then register it | [Generic Provider](/mk8s/generic) |

Managed Kubernetes is [CNCF-certified](/mk8s/overview#cncf-certified) and gives you a real Kubernetes cluster with a unified API for creation, upgrades, and scaling across every provider it supports.

<Note>
  Both paths end at the same place: a Control Plane location. Once the location exists, adding it to a GVC and deploying a workload is identical to any cloud region.
</Note>

## Prerequisites

Requirements differ by path. Check the set that applies before you start.

<Tabs>
  <Tab title="Registering an existing cluster (BYOK)">
    From the [BYOK requirements](/byok/overview#requirements):

    * At least one nodegroup labeled `cpln.io/nodeType=core`.
    * Minimum 2 CPUs per node (4 or more recommended).
    * Minimum 8 GB of RAM per node (16 GB or more recommended).
    * Minimum 2 nodes per cluster (3 or more recommended).
    * Node processor architecture `amd64` or `arm64`.
    * One of the three most recent minor Kubernetes releases.
    * Full network connectivity between all nodes, public or private.
    * Egress access for all nodes. Contact support for alternatives if this is not feasible.
    * No service mesh in the cluster — Control Plane provides an Istio-based service mesh.
    * A working load balancer controller, so at least one `Service` of type LoadBalancer can obtain an IP address.
  </Tab>

  <Tab title="Building a cluster from your servers (Generic)">
    From the [Generic provider server requirements](/mk8s/generic#step-1-server-setup) and the [Managed Kubernetes requirements](/mk8s/overview#requirements):

    * Linux, with a kernel version higher than 5.4.
    * Minimum 1 CPU core and 512 MB RAM per server.
    * Internet egress access from each server.
    * SSH access to each server.
    * Member nodes must be able to communicate with each other (same VPC, same L2 network, and so on).

    <Note>
      These are the requirements to join a server as a Kubernetes worker node. To then run Control Plane workloads on that cluster, the BYOK requirements in the other tab also apply — note the two-node minimum, and that the per-node sizing (minimum 8 GB RAM) is well above the Generic minimum. Generic clusters include a load balancer controller (MetalLB) out of the box, so that requirement is met automatically.
    </Note>
  </Tab>
</Tabs>

<Warning>
  Contact support if you want to run in an air-gapped environment or have a hard dependency on a particular Linux flavor or kernel.
</Warning>

## Step 1 - Turn your servers into a cluster

Skip this step if you already have a Kubernetes cluster; go to [Step 2](#step-2-register-the-cluster-as-a-location).

The [Generic provider](/mk8s/generic) lets Linux servers act as worker nodes whether they run in a public cloud, a private cloud, or on-premises. Follow the [Generic provider guide](/mk8s/generic) to:

1. Create the cluster from a manifest with [`cpln apply`](/cli-reference/commands/apply).
2. Generate a join script with [`cpln mk8s join`](/cli-reference/commands/mk8s#mk8s-join).
3. Run the script on each server to join it to the node pool.

<Note>
  The `location` field in a Generic cluster manifest sets where the cluster's Kubernetes **control plane** is managed. Your worker nodes are your own servers; placing them close to the control plane location is recommended for performance.
</Note>

## Step 2 - Register the cluster as a location

Your hardware becomes addressable to Control Plane when the cluster is registered as a [location](/reference/location). BYOK installs a few additional components into the cluster, which then registers as a new location in the API for your org.

<Tabs>
  <Tab title="Any Kubernetes cluster">
    Follow the [BYOK setup procedure](/byok/overview#setup-procedure):

    1. Create the location — in the Console, or with [`cpln location create --name NAME`](/cli-reference/commands/location#location-create).
    2. Generate the install command from the location's `Actions` menu — or with [`cpln location install`](/cli-reference/commands/location#location-install) — and apply it to your cluster with `kubectl`. Apply it within about five minutes: the command fetches the manifests, which contain sensitive tokens, from a signed URL that expires. If it expires, generate a fresh command.
    3. Wait for the `cpln-byok-agent` deployment in the `kube-system` namespace to become ready.

    ```shell theme={null}
    kubectl get pod -l app=cpln-byok-agent -n kube-system
    ```
  </Tab>

  <Tab title="A Managed Kubernetes cluster">
    Enable the [CPLN Platform add-on](/mk8s/add-ons/byok) on the cluster to have it register itself, either at creation or afterwards:

    ```yaml YAML theme={null}
    spec:
      addOns:
        byok: {
          location: //location/<your-location>
        }
    ```

    The `location` field is required, must point at a location you have already created, and **cannot be changed after it is set**.
  </Tab>
</Tabs>

## Step 3 - Deploy a workload to it

Once the location exists, it behaves like any other location.

1. Add the location to a [GVC](/reference/gvc) — see [Create a GVC](/guides/create-gvc), or [`cpln gvc add-location <gvc-name> --location <location-name>`](/cli-reference/commands/gvc#gvc-add-location).
2. Create a [workload](/guides/create-workload) in that GVC.

The workload rolls out to your hardware the same way it would to a cloud region: any workload configured for that location is managed by Control Plane and rolls out onto your cluster.

<Tip>
  On a BYOK location, private address ranges configured in a workload's external firewall are honored, so workloads can directly access internal resources in your data center. On Control Plane's own cloud locations those private ranges are ignored. See [Workload Settings](/byok/settings/workload).
</Tip>

## Step 4 - Verify

* The `cpln-byok-agent` pod is running in `kube-system`.
* The location appears in your org's location list and is enabled.
* The workload reports ready in the location, and its canonical endpoint serves traffic.

## When this is the wrong tool

* **A single server.** One machine can be a Generic cluster worker node, but a BYOK location expects a minimum of two nodes with a working load balancer controller. Sizing below that is not a supported location.
* **You only need to reach something on-premises.** If your workload runs on Control Plane and just needs to talk to a database or internal service inside your network, you want a [wormhole agent](/guides/setup-agent) or [native networking](/guides/native-networking/native-networking-setup), not a location on your hardware.
* **You want to manage Control Plane from `kubectl`.** That is the [Kubernetes operator](/core/kubernetes-operator), which is the opposite direction: Control Plane resources declared as Kubernetes CRDs.
* **Air-gapped environments.** Nodes require egress access. Contact support for alternatives.

## Next Steps

<CardGroup cols={2}>
  <Card title="CPLN BYOK" href="/byok/overview" icon="server">
    Register an existing Kubernetes cluster as a location
  </Card>

  <Card title="Generic Provider" href="/mk8s/generic" icon="microchip">
    Turn Linux servers into Managed Kubernetes worker nodes
  </Card>
</CardGroup>
