> ## 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.

# Browser-less CLI Login

> Authenticate with the Control Plane CLI using service account tokens for headless environments.

Use the CLI without an interactive browser login by authenticating with a [service account](/reference/serviceaccount) token. This is ideal for SSH sessions, containers, CI/CD pipelines, and other headless environments.

## Prerequisites

<AccordionGroup>
  <Accordion title="Required permissions">
    The user setting this up must be a member of the [superusers group](/reference/group#built-in-groups) or have a [policy](/reference/policy) targeting [service accounts](/reference/serviceaccount) with these permissions:

    * `create`
    * `edit`
    * `addKey`
  </Accordion>

  <Accordion title="CLI installed">
    Install the Control Plane CLI before proceeding. See [Installation](/cli-reference/installation).
  </Accordion>
</AccordionGroup>

## Setup

<Steps>
  <Step title="Create a service account">
    <Tabs>
      <Tab title="Console">
        1. Navigate to **Service Accounts** in the left menu
        2. Click **New** or use the **Create** dropdown
        3. Enter a unique name and optional description
        4. Assign to a group (e.g., `superusers`, `viewers`, or a custom group) to grant initial permissions
        5. Click **Create**
      </Tab>

      <Tab title="CLI">
        ```bash theme={null}
        cpln serviceaccount create --name automation --description "Browser-less CLI access"
        ```
      </Tab>
    </Tabs>

    <Info>
      See the [Create a Service Account](/guides/create-service-account) guide for detailed instructions.
    </Info>
  </Step>

  <Step title="Generate a key">
    <Tabs>
      <Tab title="Console">
        1. Open the service account you created
        2. Click the **Keys** link
        3. Enter a key description and click **Add**
        4. Copy and securely store the generated key
      </Tab>

      <Tab title="CLI">
        ```bash theme={null}
        cpln serviceaccount add-key automation --description cli-access
        ```

        Save the returned key securely.
      </Tab>
    </Tabs>

    <Warning>
      Store this key securely. It cannot be retrieved after creation.
    </Warning>
  </Step>

  <Step title="Grant permissions">
    Create [policies](/reference/policy) to grant the service account access to the resources it needs (GVCs, workloads, secrets, etc.).

    <Tabs>
      <Tab title="Console">
        See the [Policy guide](/guides/policy) for creating policies via the console.
      </Tab>

      <Tab title="CLI">
        ```bash theme={null}
        # Create a policy granting access to a GVC
        cpln policy create --name automation-policy \
          --targetKind gvc \
          --targetLinks //gvc/my-gvc \
          --permissions view,edit

        # Add the service account as a principal
        cpln policy add-binding automation-policy \
          --principalLinks //serviceaccount/automation
        ```
      </Tab>
    </Tabs>

    <Tip>
      For testing, you can add the service account to the `superusers` [group](/reference/group#built-in-groups) for full access, then scope down permissions later.
    </Tip>
  </Step>

  <Step title="Create a CLI profile">
    Configure the CLI to use the service account token:

    ```bash theme={null}
    cpln profile create automation --token <your-token> --org <org-name> --gvc <gvc-name> --default
    ```

    <Note>
      When using `--token`, always include `--gvc` to set a default GVC context for your commands.
    </Note>
  </Step>
</Steps>

<Check>
  Your CLI is now configured for browser-less access. Test it with:

  ```bash theme={null}
  cpln workload get
  ```
</Check>

## Alternative: Environment variables

Instead of creating a profile, you can use environment variables:

```bash theme={null}
export CPLN_TOKEN=<your-token>
export CPLN_ORG=<org-name>
export CPLN_GVC=<gvc-name>

cpln workload get
```

This is useful for CI/CD pipelines and containers where you don't want to persist a profile.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Commands fail with permission errors">
    If CLI commands fail with permission errors:

    1. **Test with superusers**: Temporarily add the service account to the `superusers` [group](/reference/group#built-in-groups)
    2. **Verify commands work**: If they now work, the issue is missing permissions
    3. **Add specific permissions**: Create [policies](/guides/policy) granting access to the required resources
    4. **Remove from superusers**: Once policies are in place, remove the service account from superusers
  </Accordion>

  <Accordion title="Wrong profile is being used">
    Verify the correct profile is set as default:

    ```bash theme={null}
    cpln profile get
    ```

    Set the correct profile as default:

    ```bash theme={null}
    cpln profile set-default automation
    ```
  </Accordion>

  <Accordion title="Token not working">
    1. Verify the token is correct and hasn't been revoked
    2. Generate a new key if needed:
       ```bash theme={null}
       cpln serviceaccount add-key automation --description new-key
       ```
    3. Update your profile with the new token:
       ```bash theme={null}
       cpln profile update automation --token <new-token>
       ```
  </Accordion>
</AccordionGroup>

<Info>
  For more troubleshooting help, see the [Troubleshooting](/cli-reference/using-cli/troubleshooting) page.
</Info>

## Next steps

<CardGroup cols={2}>
  <Card title="CI/CD Usage" href="/cli-reference/ci-cd-development/ci-cd" icon="code">
    Automate deployments with the CLI
  </Card>

  <Card title="Profiles" href="/cli-reference/get-started/profiles" icon="user">
    Manage multiple authentication contexts
  </Card>

  <Card title="Service Accounts" href="/guides/create-service-account" icon="key">
    Create and manage service accounts
  </Card>

  <Card title="Policies" href="/guides/policy" icon="shield">
    Configure access permissions
  </Card>
</CardGroup>
