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

# Configure a Domain

> Configure custom domains for workloads with DNS verification, routing modes, TLS certificates, and path-based routing via Console UI and CLI manifests.

## Domain Configuration Overview

Follow the steps below to configure a custom [domain](/reference/domain) within your [org](/reference/org).

## Domain Configuration Prerequisites

* Review the [domain](/reference/domain) reference page.
* Have [permissions](/reference/policy#permissions) to configure a [domain](/reference/domain).
* Access to a domain name and the ability to update its DNS records.
* Optional:
  * Install the [CLI](/cli-reference/installation).

## Step One - APEX Domain Verification

Follow Step One in the [domain quick start](/quickstart/quick-start-2-custom-domain#step-one-register-your-apex-domain) to create and verify the apex domain name using the Console UI.

The CLI can also be used to create the apex domain for verification and routing configuration. See the [sample manifest files](#apex-verification-only) below.

Refer to [Domain Verification](/reference/domain#domain-verification) for additional details.

## Step Two - Create Domain

A [domain](/reference/domain) can be created using the following methods:

* [Console UI](#create-using-the-ui-console)
* [CLI](#create-using-the-cli)
* [Terraform Provider](https://registry.terraform.io/providers/controlplane-com/cpln/latest/docs/resources/domain)

### Create using the UI Console

Follow Step Two in the [domain quick start](/quickstart/quick-start-2-custom-domain#step-two-review-routing-modes) for detailed instructions on how to create and configure your domain name using the console UI.

### Create using the CLI

A domain can be created or updated using the [cpln apply](/guides/cpln-apply) command.

Below are a few sample domain manifests (in YAML) that can be used as input to the [cpln apply](/guides/cpln-apply) command.

After updating and saving the manifests to a local file, execute the following command to apply:

```bash theme={null}
cpln apply -f FILE_NAME.yaml --org ORG_NAME
```

<Warning>
  Before using the [CLI's apply](/guides/cpln-apply) command, the [TXT DNS records](#required-dns-records) must exist and be propagated
  **only** for the apex domain. The DNS entries for the subdomain will not be verified on creation. Routing and certificate generation will
  not occur until the records have been added, propagated, and the target workload is in a ready state and can serve requests.
</Warning>

#### APEX Verification Only

Configure a domain for APEX verification

* Substitute `example.com` with your domain.

```yaml YAML theme={null}
kind: domain
name: example.com
description: example.com
spec:
  dnsMode: cname
```

#### APEX Verification and Path Based Routing

Configure a domain for APEX verification and path-based routing.

* Substitute `example.com` with your domain, `GVC_NAME`, and `WORKLOAD_NAME`.
* The example YAML manifest below assumes there is a workload named `WORKLOAD_NAME` serving requests on port 4200 in the [GVC](/reference/gvc) named `GVC_NAME`.

```yaml YAML theme={null}
kind: domain
name: example.com
description: example.com
tags: {}
spec:
  acceptAllHosts: false
  dnsMode: cname
  ports:
    - number: 443
      protocol: http2
      routes:
        - port: 4200
          prefix: /
          workloadLink: //gvc/GVC_NAME/workload/WORKLOAD_NAME
```

#### APEX Verification and Subdomain Based Routing

Configure an apex domain for subdomain-based routing, where each workload in the GVC is served at `<workload>.example.com`.

* Substitute `example.com` with your domain and `GVC_NAME`.
* `dnsMode` is `cname` and `gvcLink` selects the GVC.
* With `certChallengeType: dns01`, Control Plane issues a wildcard certificate — no TLS secret is required.

```yaml YAML theme={null}
kind: domain
name: example.com
description: example.com
tags: {}
spec:
  dnsMode: cname
  certChallengeType: dns01
  gvcLink: //gvc/GVC_NAME
```

After the domain is created, view its `status.dnsConfig` (for example, `cpln domain get example.com -o yaml`) and create the records it lists: one `CNAME` per workload (`<workload>.example.com` → `<gvcAlias>.cpln.app`) plus the `_acme-challenge` CNAME used to issue the certificate.

To supply your own certificate instead, use `certChallengeType: http01` and configure a `tls.serverCertificate.secretLink` on each TLS port:

```yaml YAML theme={null}
kind: domain
name: example.com
description: example.com
tags: {}
spec:
  dnsMode: cname
  certChallengeType: http01
  gvcLink: //gvc/GVC_NAME
  ports:
    - number: 443
      tls:
        serverCertificate:
          secretLink: //secret/TLS_SECRET
```

#### Subdomain and Path Based Routing

Configure a subdomain for path-based routing.

* Substitute `sub.example.com` with your domain, `GVC_NAME`, and `WORKLOAD_NAME`.
* The example YAML manifest below assumes there is a workload named `WORKLOAD_NAME` in the GVC named `GVC_NAME`.

```yaml YAML theme={null}
kind: domain
name: sub.example.com
description: sub.example.com
tags: {}
spec:
  dnsMode: cname
  ports:
    - routes:
        - prefix: /
          workloadLink: //gvc/GVC_NAME/workload/WORKLOAD_NAME
```

#### Subdomain and Subdomain Based Routing

Configure a subdomain for subdomain-based routing.

* Substitute `sub.example.com` with your domain and `GVC_NAME`.
* All workloads within the GVC will have endpoints created with the subdomain in the format: `https://WORKLOAD_NAME.sub.example.com/`.

```yaml YAML theme={null}
kind: domain
name: sub.example.com
description: sub.example.com
tags: {}
spec:
  dnsMode: ns
  gvcLink: //gvc/GVC_NAME
```

#### Setting Custom Headers

Set custom headers on any domain route.

* Substitute `sub.example.com` with your domain, `GVC_NAME`, and `WORKLOAD_NAME`.
* Substitute `HEADER` with your header name and `VALUE` with your header value. You can add additional headers.
* The example YAML manifest below assumes there is a workload named `WORKLOAD_NAME` in the GVC named `GVC_NAME`.

```yaml YAML theme={null}
kind: domain
name: sub.example.com
description: sub.example.com
tags: {}
spec:
  dnsMode: cname
  ports:
    - routes:
        - prefix: /
          workloadLink: //gvc/GVC_NAME/workload/WORKLOAD_NAME
          headers:
            request:
              set:
                HEADER: VALUE
```

#### Complete Domain YAML Manifest

Use the manifest YAML templates below to create a domain per your requirements.

<Note>
  The examples above use the minimum properties required to create or update a domain based on your requirements.

  The complete YAML manifest templates below contain both the required and optional properties.

  **Notes:**

  * `dnsMode` can either be `cname` (for path-based) or `ns` (for subdomain-based). For an apex domain, it must be `cname`.
  * `acceptAllHosts` will only be active if the dedicated load balancer is enabled on the GVC.
  * For the routes configured for path-based routing, the `hostPrefix` will only be active if the dedicated load balancer is enabled on the GVC **and** the `acceptAllHosts` property is set to `true`.
</Note>

* Path-based Routing

```yaml YAML theme={null}
kind: domain
name: sub.domain.com
description: sub.domain.com
tags: {}
spec:
  acceptAllHosts: false
  dnsMode: cname
  ports:
    - cors:
        allowCredentials: true
        allowHeaders:
          - '*'
        allowMethods:
          - '*'
        allowOrigins:
          - exact: '*'
        exposeHeaders:
          - '*'
        maxAge: 24h
      number: 443
      protocol: http2
      routes:
        - hostPrefix: example
          port: 4200
          prefix: /example
          replacePrefix: /v1/example
          workloadLink: //gvc/GVC_NAME/workload/WORKLOAD_NAME_01
          headers:
            request:
              set:
                EXAMPLE_HEADER: EXAMPLE_VALUE
        - regex: /user/.*/profile
          workloadLink: //gvc/GVC_NAME/workload/WORKLOAD_NAME_02
        - prefix: /
          workloadLink: //gvc/GVC_NAME/workload/WORKLOAD_NAME_03
      tls:
        cipherSuites:
          - ECDHE-ECDSA-AES256-GCM-SHA384
          - ECDHE-ECDSA-CHACHA20-POLY1305
          - ECDHE-ECDSA-AES128-GCM-SHA256
          - ECDHE-RSA-AES256-GCM-SHA384
          - ECDHE-RSA-CHACHA20-POLY1305
          - ECDHE-RSA-AES128-GCM-SHA256
          - AES256-GCM-SHA384
          - AES128-GCM-SHA256
        clientCertificate:
          secretLink: //secret/TLS_SECRET_CLIENT_CERTIFICATE
        minProtocolVersion: TLSV1_2
        serverCertificate:
          secretLink: //secret/TLS_SECRET_SERVER_CERTIFICATE
```

* Subdomain Based Routing

```yaml YAML theme={null}
kind: domain
name: sub.example.com
description: sub.example.com
tags: {}
spec:
  acceptAllHosts: true
  dnsMode: ns
  gvcLink: //gvc/GVC_NAME
  ports:
    - cors:
        allowCredentials: false
        allowHeaders:
          - '*'
        allowMethods:
          - '*'
        allowOrigins:
          - exact: '*'
        exposeHeaders:
          - '*'
        maxAge: 24h
      number: 443
      protocol: http2
      tls:
        cipherSuites:
          - ECDHE-ECDSA-AES256-GCM-SHA384
          - ECDHE-ECDSA-CHACHA20-POLY1305
          - ECDHE-ECDSA-AES128-GCM-SHA256
          - ECDHE-RSA-AES256-GCM-SHA384
          - ECDHE-RSA-CHACHA20-POLY1305
          - ECDHE-RSA-AES128-GCM-SHA256
          - AES256-GCM-SHA384
          - AES128-GCM-SHA256
        clientCertificate:
          secretLink: //secret/TLS_SECRET_CLIENT_CERTIFICATE
        minProtocolVersion: TLSV1_2
        serverCertificate:
          secretLink: //secret/TLS_SECRET_SERVER_CERTIFICATE
```

## Required DNS Records

To successfully add a [domain](/reference/domain) to your [org](/reference/org), DNS records must be added.

The values in the sample below might not correspond to the entries necessary for your domain. Use the values shown during domain creation.

When the domain is created in the console UI, the final step will display the DNS records that need to be added.

These records should be sent to the network administrator in charge of handling the domain's DNS configuration.

**Examples:**

<AccordionGroup>
  <Accordion title="Apex Domain - CNAME Mode Only">
    | RECORD/HOST | TYPE | TTL | VALUE         |
    | :---------- | :--- | :-- | :------------ |
    | \_cpln      | TXT  | 600 | ORG\_ID\_GUID |
  </Accordion>

  <Accordion title="Subdomain (e.g., sample.domain.com) - CNAME Mode (Path Based Routing)">
    | RECORD/HOST   | TYPE  | TTL | VALUE               |
    | :------------ | :---- | :-- | :------------------ |
    | \_cpln-sample | TXT   | 600 | ORG\_ID\_GUID       |
    | sample        | CNAME | 600 | GVC\_ALIAS.cpln.app |

    **Note:** The GVC\_ALIAS can be obtained from the console UI by clicking on the GVC and it will be displayed on the `Info` page. Using the CLI, executing the command `cpln gvc get GVC_NAME` will output the alias.
  </Accordion>

  <Accordion title="Subdomain (e.g., sample.domain.com) - NS Mode (Subdomain Based Routing)">
    | RECORD/HOST   | TYPE | TTL  | VALUE          |
    | :------------ | :--- | :--- | :------------- |
    | \_cpln-sample | TXT  | 600  | ORG\_ID\_GUID  |
    | sample        | NS   | 1800 | ns1.cpln.cloud |
    | sample        | NS   | 1800 | ns2.cpln.cloud |
    | sample        | NS   | 1800 | ns1.cpln.live  |
    | sample        | NS   | 1800 | ns2.cpln.live  |
  </Accordion>
</AccordionGroup>

<Note>
  In the examples above, the TXT record for the subdomain is **only** required if the domain is created in an org that doesn't contain the apex domain. `ORG_ID_GUID` should be set to the `id` value of the org object.

  The record `_cpln-sample` is generated from the last segment of the domain, `_cpln-${lastSegment}`. In the case of an apex domain, the TXT record to add is `_cpln`.

  The TXT record can include the ID of multiple orgs in cases where the domain is allowed to be used in multiple orgs.

  The verification record can exist at any segment of the domain.

  For example, the subdomain `two.sample.domain.com` can be verified using **any** of the following TXT records:

  * \_cpln-two.sample.domain.com
  * \_cpln-sample.domain.com
  * \_cpln.domain.com
</Note>

<Tip>
  To obtain the ORG\_ID\_GUID, run the CLI command: `cpln org get ORG_NAME --output json`.

  The output of the command will display all the properties of the [org](/reference/org) object. Use the value of the `id` key for the TXT value.
</Tip>

<Note>
  After the DNS records have been created, the propagation time for the changes to take effect depends on the cache setting of your domain's DNS Start of Authority (SOA) record.

  Once the records are fully propagated, any DNS changes to your subdomain will be reflected within a few seconds.
</Note>

## Configure a Content Delivery Network (CDN) Domain

Refer to the [Configure a CDN](/guides/configure-cdn) guide.

## Advanced Mode

When editing a domain within the console UI, the following options are available when clicking the `Advanced` button:

### Dedicated Load Balancing

Refer to the following pages for details on enabling dedicated load balancing:

* Configuring the [GVC for dedicated load balancing.](/reference/gvc#dedicated-load-balancer)
* After enabling, these [additional domain configuration options](/reference/domain#dedicated-load-balancer-options) will be available for configuration.

### Domain Additional Settings

* The [accept all hosts](/reference/domain#accept-all-hosts) or [accept all subdomains](/reference/domain#accept-all-subdomains) settings (`acceptAllHosts` in the above example manifest) can be enabled when dedicated load balancing is enabled.

* [Add additional ports](/reference/domain#external-port) configured with other supported protocols (TCP, etc.) when using a dedicated load balancer.

* For each port, configure [TLS Settings](/reference/domain#tls-settings) which includes setting the TLS version, forwarding client certificates, using custom server certificates, and allowed cipher suites.

* For each port, configure custom [CORS](/reference/domain#cors-settings) settings.

* When using Path Based Routing:
  * Additional [routes](/reference/domain#path-based-routing) can be added with unique prefixes and, optionally, a replace prefix.
  * When dedicated load balancing is enabled, a [host prefix](/reference/domain#host-prefix) (`hostPrefix` in the above example manifest) can be optionally defined.
