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

# 1. Deploy Your First Workload

> Create a GVC, deploy a sample web application as a workload, and access it via a globally load-balanced TLS endpoint.

## Overview

This quickstart guides you through deploying your first application on Control Plane. You'll create a Global Virtual Cloud ([GVC](/reference/gvc)), deploy a [Workload](/reference/workload), and access it via a globally load-balanced endpoint.

**What you'll accomplish:**

* Create a GVC spanning multiple cloud providers and locations.
* Deploy a sample web application as a workload.
* Access your application via a TLS-secured, geo-routed global endpoint.

<Tabs>
  <Tab title="Console">
    ## Prerequisites

    * [Sign up](https://console.cpln.io/signup) for Control Plane and create a [billing account](/concepts/billing).
    * An existing [org](/reference/org), or permission to [create an org](/guides/create-org).

    ## Step 1: Log in to the Console

    1. Navigate to [console.cpln.io](https://console.cpln.io).
    2. Select your SSO provider and authenticate.
    3. You'll be directed to your organization's dashboard.

    ## Step 2: Create a GVC

    A [GVC](/reference/gvc) defines where your workloads run across cloud providers and regions.

    <Steps>
      <Step title="Open the Create GVC form">
        Click the `Create` dropdown in the upper right corner and select `GVC`.
      </Step>

      <Step title="Configure the GVC name">
        Enter a name for your GVC (e.g., `quickstart-gvc`).
      </Step>

      <Step title="Select locations">
        Click `Locations`, then click `Add Location`. Choose the locations where your workload will be deployed. For this quickstart, select:

        * `aws-us-west-2`
        * `gcp-us-east1`

        This deploys your application across both AWS and GCP.
        Click `OK`.
      </Step>

      <Step title="Create the GVC">
        Click `Create`. You can click `Set as Current Context` to make this GVC your current context. This allows you to browse its workloads, identities, and volumesets from the sidebar.
      </Step>
    </Steps>

    ## Step 3: Create a Workload

    A [workload](/reference/workload) is your application running on Control Plane.

    <Steps>
      <Step title="Navigate to Workloads">
        Click `Workloads` in the left menu, then click `New`.
      </Step>

      <Step title="Configure basic settings">
        Enter a name (e.g., `hello-world`). Make sure the GVC dropdown under the description field has `quickstart-gvc` selected.
      </Step>

      <Step title="Configure the container">
        Click `Containers`. For the image source, select `External`, then enter:

        ```text theme={null}
        gcr.io/knative-samples/helloworld-go
        ```

        Under `Ports`, ensure there is a port configured with:

        * Protocol: `http`
        * Number: `8080`
      </Step>

      <Step title="Make the workload public">
        Click `Firewall`, then click the `Make Public` button at the top to allow external access.
      </Step>

      <Step title="Create the workload">
        Click `Create`. The workload summary page opens.
      </Step>
    </Steps>

    ## Step 4: Access Your Application

    <Steps>
      <Step title="Wait for deployment">
        After 1-2 minutes, the workload health shows `Ready`.
      </Step>

      <Step title="Open the canonical endpoint">
        In the summary, under `Endpoints`, click the link next to `Canonical Endpoint`. Your application opens in a new window, served from the location nearest to you.
      </Step>

      <Step title="View individual deployments">
        Click `Deployments` in the left pane to see each location's endpoint. Click `Open` next to any location to access that specific deployment.
      </Step>
    </Steps>
  </Tab>

  <Tab title="CLI">
    ## Prerequisites

    * [Sign up](https://console.cpln.io/signup) for Control Plane and create a [billing account](/concepts/billing).
    * An existing [org](/reference/org), or permission to [create an org](/guides/create-org).

    ## Step 1: Install the CLI

    Choose your preferred installation method:

    <Tabs>
      <Tab title="npm">
        ```bash theme={null}
        npm install -g @controlplane/cli
        ```

        <Note>Requires [Node.js](https://nodejs.org/en/download/) version 18+ (an active LTS release is recommended).</Note>

        For other installation options, see [Installation](/cli-reference/installation).
      </Tab>

      <Tab title="Homebrew">
        ```bash theme={null}
        brew tap controlplane-com/cpln && brew install cpln
        ```

        For other installation options, see [Installation](/cli-reference/installation).
      </Tab>

      <Tab title="Binary">
        See the [Installation page](/cli-reference/installation#binary) to download the binary for your platform.
      </Tab>
    </Tabs>

    ## Step 2: Verify the Installation

    Confirm the CLI is installed and accessible:

    ```bash theme={null}
    cpln --version
    ```

    You should see the CLI version number.

    ## Step 3: Authenticate

    Log in to Control Plane:

    ```bash theme={null}
    cpln login
    ```

    This opens your browser for authentication. After successful login, you can close the browser.

    Set your default organization:

    ```bash theme={null}
    cpln profile update default --org YOUR_ORG_NAME
    ```

    ## Step 4: Create a GVC

    Create a GVC with locations in AWS and GCP:

    ```bash theme={null}
    cpln gvc create --name quickstart-gvc \
      --location aws-us-west-2 \
      --location gcp-us-east1
    ```

    Set it as your default GVC:

    ```bash theme={null}
    cpln profile update default --gvc quickstart-gvc
    ```

    ## Step 5: Create and deploy a workload

    Create a public workload with the sample application:

    ```bash theme={null}
    cpln workload create --name hello-world \
      --image gcr.io/knative-samples/helloworld-go \
      --port 8080 \
      --public
    ```

    ## Step 6: Access Your Application

    Wait for the workload to become ready:

    ```bash theme={null}
    cpln workload get hello-world
    ```

    Once the `READY` column shows `true`, open the application:

    ```bash theme={null}
    cpln workload open hello-world
    ```

    <Tip>
      You can also view the workload's global endpoint URL in the output of `cpln workload get`.
    </Tip>

    ### View Deployment Status

    Check deployments across all locations:

    ```bash theme={null}
    cpln workload get-deployments hello-world
    ```
  </Tab>

  <Tab title="Terraform">
    ## Prerequisites

    * [Sign up](https://console.cpln.io/signup) for Control Plane and create a [billing account](/concepts/billing).
    * An existing [org](/reference/org), or permission to [create an org](/guides/create-org).
    * [Terraform](https://www.terraform.io/downloads.html) installed.

    ## Step 1: Authenticate

    The Terraform provider needs credentials to interact with Control Plane. Choose one of the following methods:

    <Tabs>
      <Tab title="CLI Profile">
        If you have the [Control Plane CLI](/cli-reference/installation) installed, log in first:

        ```bash theme={null}
        cpln login
        ```

        This creates a profile named `default` with your credentials. You'll reference this profile in the provider configuration.
      </Tab>

      <Tab title="Service Account Token">
        For CI/CD pipelines or environments without the CLI, create a service account token:

        1. In the [Console](https://console.cpln.io), click `Service Accounts` in the left menu, then `New`.
        2. Enter a name, select `superusers` from the `Assign to Group` dropdown, and click `Create`.
        3. Click `Keys`, add a description, and click `Add`.
        4. **Copy the generated key**. It won't be shown again.

        Set the token as an environment variable:

        ```bash theme={null}
        export CPLN_TOKEN=your-service-account-key
        ```
      </Tab>
    </Tabs>

    ## Step 2: Configure the Provider

    Create a new directory and add `main.tf` with the provider configuration:

    <Tabs>
      <Tab title="CLI Profile">
        ```hcl theme={null}
        terraform {
          required_providers {
            cpln = {
              source = "controlplane-com/cpln"
            }
          }
        }

        provider "cpln" {
          org     = "YOUR_ORG_NAME"
          profile = "default"
        }
        ```
      </Tab>

      <Tab title="Service Account Token">
        ```hcl theme={null}
        terraform {
          required_providers {
            cpln = {
              source = "controlplane-com/cpln"
            }
          }
        }

        provider "cpln" {
          org = "YOUR_ORG_NAME"
          # Token is read from CPLN_TOKEN environment variable
        }
        ```
      </Tab>
    </Tabs>

    Initialize Terraform:

    ```bash theme={null}
    terraform init
    ```

    For more authentication options, see [Terraform Provider](/iac/terraform).

    ## Step 3: Define the GVC

    Add the GVC resource to `main.tf`:

    ```hcl theme={null}
    resource "cpln_gvc" "quickstart" {
      name        = "quickstart-gvc"
      description = "Quickstart GVC"

      locations = [
        "aws-us-west-2",
        "gcp-us-east1"
      ]
    }
    ```

    ## Step 4: Define the workload

    Add the workload resource to `main.tf`:

    ```hcl theme={null}
    resource "cpln_workload" "hello_world" {
      gvc  = cpln_gvc.quickstart.name
      name = "hello-world"
      type = "standard"

      container {
        name   = "helloworld-go"
        image  = "gcr.io/knative-samples/helloworld-go"
        cpu    = "50m"
        memory = "128Mi"

        ports {
          number   = 8080
          protocol = "http"
        }
      }

      options {
        capacity_ai     = true
        timeout_seconds = 5

        autoscaling {
          metric      = "disabled"
          target      = 95
          min_scale   = 1
          max_scale   = 1
        }
      }

      firewall_spec {
        external {
          inbound_allow_cidr = ["0.0.0.0/0"]
        }
      }
    }

    output "canonical_endpoint" {
      value = cpln_workload.hello_world.status[0].canonical_endpoint
    }
    ```

    ## Step 5: Deploy

    Review the plan:

    ```bash theme={null}
    terraform plan
    ```

    Apply the configuration:

    ```bash theme={null}
    terraform apply
    ```

    Type `yes` when prompted. After deployment completes, the canonical endpoint URL is displayed.

    ## Step 6: Access Your Application

    Open the canonical endpoint URL in your browser. To view it again:

    ```bash theme={null}
    terraform output
    ```

    <Tip>
      View the full list of workload configuration options in the [Terraform Registry documentation](https://registry.terraform.io/providers/controlplane-com/cpln/latest/docs/resources/workload).
    </Tip>
  </Tab>

  <Tab title="Pulumi">
    ## Prerequisites

    * [Sign up](https://console.cpln.io/signup) for Control Plane and create a [billing account](/concepts/billing).
    * An existing [org](/reference/org), or permission to [create an org](/guides/create-org).
    * [Pulumi CLI](https://www.pulumi.com/docs/iac/download-install/) installed.

    ## Step 1: Authenticate

    The Pulumi provider needs credentials to interact with Control Plane. Choose one of the following methods:

    <Tabs>
      <Tab title="CLI Profile">
        If you have the [Control Plane CLI](/cli-reference/installation) installed, log in first:

        ```bash theme={null}
        cpln login
        ```

        This creates a profile named `default` with your credentials.
      </Tab>

      <Tab title="Service Account Token">
        For CI/CD pipelines or environments without the CLI, create a service account token:

        1. In the [Console](https://console.cpln.io), click `Service Accounts` in the left menu, then `New`.
        2. Enter a name, select `superusers` from the `Assign to Group` dropdown, and click `Create`.
        3. Click `Keys`, add a description, and click `Add`.
        4. **Copy the generated key**. It won't be shown again.

        Set the token as an environment variable:

        ```bash theme={null}
        export CPLN_TOKEN=your-service-account-key
        ```
      </Tab>
    </Tabs>

    ## Step 2: Create a New Project

    Create a new directory and initialize a Pulumi project:

    <Tabs>
      <Tab title="TypeScript">
        ```bash theme={null}
        mkdir cpln-quickstart && cd cpln-quickstart
        pulumi new typescript
        ```

        Follow the prompts in the terminal to complete project setup. Then install the Control Plane provider:

        <Tabs>
          <Tab title="npm">
            ```bash theme={null}
            npm install @pulumiverse/cpln
            ```
          </Tab>

          <Tab title="pnpm">
            ```bash theme={null}
            pnpm add @pulumiverse/cpln
            ```
          </Tab>

          <Tab title="yarn">
            ```bash theme={null}
            yarn add @pulumiverse/cpln
            ```
          </Tab>

          <Tab title="bun">
            ```bash theme={null}
            bun add @pulumiverse/cpln
            ```
          </Tab>
        </Tabs>
      </Tab>

      <Tab title="Python">
        ```bash theme={null}
        mkdir cpln-quickstart && cd cpln-quickstart
        pulumi new python
        ```

        Follow the prompts in the terminal to complete project setup. Activate the virtual environment and install the Control Plane provider:

        <Tabs>
          <Tab title="pip">
            ```bash theme={null}
            source venv/bin/activate
            pip install pulumiverse-cpln
            ```
          </Tab>

          <Tab title="poetry">
            ```bash theme={null}
            poetry add pulumiverse-cpln
            ```
          </Tab>

          <Tab title="uv">
            ```bash theme={null}
            source .venv/bin/activate
            uv add pulumiverse-cpln
            ```
          </Tab>
        </Tabs>
      </Tab>

      <Tab title="Go">
        ```bash theme={null}
        mkdir cpln-quickstart && cd cpln-quickstart
        pulumi new go
        ```

        Follow the prompts in the terminal to complete project setup. Then install the Control Plane provider:

        ```bash theme={null}
        go get github.com/pulumiverse/pulumi-cpln/sdk/go/cpln
        ```
      </Tab>

      <Tab title="C#">
        ```bash theme={null}
        mkdir cpln-quickstart && cd cpln-quickstart
        pulumi new csharp
        ```

        Follow the prompts in the terminal to complete project setup. Then install the Control Plane provider:

        ```bash theme={null}
        dotnet add package Pulumiverse.Cpln --version 1.0.0
        ```
      </Tab>
    </Tabs>

    ## Step 3: Configure the Provider

    Set your organization and authentication method:

    <Tabs>
      <Tab title="CLI Profile">
        ```bash theme={null}
        pulumi config set cpln:org YOUR_ORG_NAME
        pulumi config set cpln:profile default
        ```
      </Tab>

      <Tab title="Service Account Token">
        ```bash theme={null}
        pulumi config set cpln:org YOUR_ORG_NAME
        pulumi config set --secret cpln:token $CPLN_TOKEN
        ```

        Or paste the token directly:

        ```bash theme={null}
        pulumi config set cpln:org YOUR_ORG_NAME
        pulumi config set --secret cpln:token your-service-account-key
        ```
      </Tab>
    </Tabs>

    ## Step 4: Define the Infrastructure

    <Tabs>
      <Tab title="TypeScript">
        Replace `index.ts` with:

        ```typescript theme={null}
        import * as cpln from "@pulumiverse/cpln";

        // Create a GVC
        const gvc = new cpln.Gvc("quickstart-gvc", {
          name: "quickstart-gvc",
          description: "Quickstart GVC",
          locations: ["aws-us-west-2", "gcp-us-east1"],
        });

        // Create a Workload
        const workload = new cpln.Workload("hello-world", {
          gvc: gvc.name,
          name: "hello-world",
          type: "standard",
          containers: [
            {
              name: "helloworld-go",
              image: "gcr.io/knative-samples/helloworld-go",
              cpu: "50m",
              memory: "128Mi",
              ports: [
                {
                  number: 8080,
                  protocol: "http",
                },
              ],
            },
          ],
          options: {
            capacityAi: true,
            timeoutSeconds: 5,
            autoscaling: {
              metric: "disabled",
              target: 95,
              minScale: 1,
              maxScale: 1,
            },
          },
          firewallSpec: {
            external: {
              inboundAllowCidrs: ["0.0.0.0/0"],
            },
          },
        });

        // Export the canonical endpoint
        export const canonical_endpoint = workload.statuses.apply(
          (s) => s?.[0]?.canonicalEndpoint
        );
        ```
      </Tab>

      <Tab title="Python">
        Replace `__main__.py` with:

        ```python theme={null}
        import pulumiverse_cpln as cpln
        import pulumi

        # Create a GVC
        gvc = cpln.Gvc("quickstart-gvc",
            name="quickstart-gvc",
            description="Quickstart GVC",
            locations=["aws-us-west-2", "gcp-us-east1"])

        # Create a Workload
        workload = cpln.Workload("hello-world",
            gvc=gvc.name,
            name="hello-world",
            type="standard",
            containers=[cpln.WorkloadContainerArgs(
                name="helloworld-go",
                image="gcr.io/knative-samples/helloworld-go",
                cpu="50m",
                memory="128Mi",
                ports=[cpln.WorkloadContainerPortArgs(
                    number=8080,
                    protocol="http",
                )],
            )],
            options=cpln.WorkloadOptionsArgs(
                capacity_ai=True,
                timeout_seconds=5,
                autoscaling=cpln.WorkloadOptionsAutoscalingArgs(
                    metric="disabled",
                    target=95,
                    min_scale=1,
                    max_scale=1,
                ),
            ),
            firewall_spec=cpln.WorkloadFirewallSpecArgs(
                external=cpln.WorkloadFirewallSpecExternalArgs(
                    inbound_allow_cidrs=["0.0.0.0/0"],
                ),
            ))

        # Export the canonical endpoint
        pulumi.export("canonical_endpoint", workload.statuses.apply(
            lambda s: s[0].canonical_endpoint if s else None
        ))
        ```
      </Tab>

      <Tab title="Go">
        Replace `main.go` with:

        ```go theme={null}
        package main

        import (
        	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
        	"github.com/pulumiverse/pulumi-cpln/sdk/go/cpln"
        )

        func main() {
        	pulumi.Run(func(ctx *pulumi.Context) error {
        		// Create a GVC
        		gvc, err := cpln.NewGvc(ctx, "quickstart-gvc", &cpln.GvcArgs{
        			Name:        pulumi.String("quickstart-gvc"),
        			Description: pulumi.String("Quickstart GVC"),
        			Locations: pulumi.StringArray{
        				pulumi.String("aws-us-west-2"),
        				pulumi.String("gcp-us-east1"),
        			},
        		})
        		if err != nil {
        			return err
        		}

        		// Create a Workload
        		workload, err := cpln.NewWorkload(ctx, "hello-world", &cpln.WorkloadArgs{
        			Gvc:  gvc.Name,
        			Name: pulumi.String("hello-world"),
        			Type: pulumi.String("standard"),
        			Containers: cpln.WorkloadContainerArray{
        				&cpln.WorkloadContainerArgs{
        					Name:   pulumi.String("helloworld-go"),
        					Image:  pulumi.String("gcr.io/knative-samples/helloworld-go"),
        					Cpu:    pulumi.String("50m"),
        					Memory: pulumi.String("128Mi"),
        					Ports: cpln.WorkloadContainerPortArray{
        						&cpln.WorkloadContainerPortArgs{
        							Number:   pulumi.Int(8080),
        							Protocol: pulumi.String("http"),
        						},
        					},
        				},
        			},
        			Options: &cpln.WorkloadOptionsArgs{
        				CapacityAi:     pulumi.Bool(true),
        				TimeoutSeconds: pulumi.Int(5),
        				Autoscaling: &cpln.WorkloadOptionsAutoscalingArgs{
        					Metric:   pulumi.String("disabled"),
        					Target:   pulumi.Int(95),
        					MinScale: pulumi.Int(1),
        					MaxScale: pulumi.Int(1),
        				},
        			},
        			FirewallSpec: &cpln.WorkloadFirewallSpecArgs{
        				External: &cpln.WorkloadFirewallSpecExternalArgs{
        					InboundAllowCidrs: pulumi.StringArray{pulumi.String("0.0.0.0/0")},
        				},
        			},
        		})
        		if err != nil {
        			return err
        		}

        		// Export the canonical endpoint
        		ctx.Export("canonical_endpoint", workload.Statuses.Index(pulumi.Int(0)).CanonicalEndpoint())
        		return nil
        	})
        }
        ```
      </Tab>

      <Tab title="C#">
        Replace `Program.cs` with:

        ```csharp theme={null}
        using Pulumi;
        using Pulumiverse.Cpln;
        using Pulumiverse.Cpln.Inputs;
        using System.Collections.Generic;

        return await Deployment.RunAsync(() =>
        {
            // Create a GVC
            var gvc = new Gvc("quickstart-gvc", new GvcArgs
            {
                Name = "quickstart-gvc",
                Description = "Quickstart GVC",
                Locations = new[] { "aws-us-west-2", "gcp-us-east1" }
            });

            // Create a Workload
            var workload = new Workload("hello-world", new WorkloadArgs
            {
                Gvc = gvc.Name,
                Name = "hello-world",
                Type = "standard",
                Containers = new[]
                {
                    new WorkloadContainerArgs
                    {
                        Name = "helloworld-go",
                        Image = "gcr.io/knative-samples/helloworld-go",
                        Cpu = "50m",
                        Memory = "128Mi",
                        Ports = new[]
                        {
                            new WorkloadContainerPortArgs
                            {
                                Number = 8080,
                                Protocol = "http"
                            }
                        }
                    }
                },
                Options = new WorkloadOptionsArgs
                {
                    CapacityAi = true,
                    TimeoutSeconds = 5,
                    Autoscaling = new WorkloadOptionsAutoscalingArgs
                    {
                        Metric = "disabled",
                        Target = 95,
                        MinScale = 1,
                        MaxScale = 1
                    }
                },
                FirewallSpec = new WorkloadFirewallSpecArgs
                {
                    External = new WorkloadFirewallSpecExternalArgs
                    {
                        InboundAllowCidrs = new[] { "0.0.0.0/0" }
                    }
                }
            });

            // Export the canonical endpoint
            return new Dictionary<string, object?>
            {
                ["canonical_endpoint"] = workload.Statuses.Apply(s => s[0].CanonicalEndpoint)
            };
        });
        ```
      </Tab>
    </Tabs>

    ## Step 5: Deploy

    Preview the changes:

    ```bash theme={null}
    pulumi preview
    ```

    Deploy the infrastructure:

    ```bash theme={null}
    pulumi up
    ```

    Select `yes` when prompted. After deployment, the canonical endpoint URL is displayed.

    ## Step 6: Access Your Application

    Open the canonical endpoint URL in your browser. To view it again:

    ```bash theme={null}
    pulumi stack output
    ```

    <Note>
      If the canonical endpoint doesn't appear, run `pulumi up` again to refresh the state.
    </Note>

    <Tip>
      View the full list of resources in the [Pulumi Registry documentation](https://www.pulumi.com/registry/packages/cpln/).
    </Tip>
  </Tab>
</Tabs>

## What You Deployed

Your application is now:

* **Globally distributed** across AWS and GCP.
* **Automatically load balanced** with geo-routing to the nearest healthy location.
* **TLS secured** with automatic certificate management.
* Running in each selected location with one replica per location.

<CodeGroup>
  ```text aws-us-west-2 theme={null}
  Hello World!

  Provider: aws
  Location: /org/YOUR_ORG/location/aws-us-west-2
  ```

  ```text gcp-us-east1 theme={null}
  Hello World!

  Provider: gcp
  Location: /org/YOUR_ORG/location/gcp-us-east1
  ```
</CodeGroup>

## Continue

<Card title="2. Deploy Your Own Application" icon="rocket" href="/quickstart/quick-start-2-deploy-application" horizontal>
  Build and deploy your own containerized application to Control Plane.
</Card>

<Card title="Want your AI assistant to do the next deploy for you?" icon="robot" href="/ai/plugin" horizontal>
  Install the **Control Plane AI Plugin** for Claude Code, Codex, or Antigravity CLI. It knows the workload types, secret access chain, firewall defaults, and deploy waits — so you can describe what you want instead of writing manifests.
</Card>

## Clean Up

If you want to stop here instead, delete the resources created in this quickstart:

<Tabs>
  <Tab title="Console UI">
    Navigate to your GVC and click `Delete` from the `Actions` pulldown menu. This removes the GVC and all associated workloads.
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    cpln gvc delete quickstart-gvc
    ```
  </Tab>

  <Tab title="Terraform">
    ```bash theme={null}
    terraform destroy
    ```
  </Tab>

  <Tab title="Pulumi">
    ```bash theme={null}
    pulumi destroy
    ```
  </Tab>
</Tabs>
