Custom Domains
Claim, verify, link, and unlink custom domains across functions and VMs with automatic TLS.
Every function gets a default URL at https://{function-name}.clusterbase.dev. You can also bring your own domain — claim and verify ownership once, then link it to a function or a VM service. TLS is provisioned automatically.
Domains are top-level objects scoped to an organization: a verified domain belongs to the org and is visible to every member, independent of any function or VM. Linking attaches a domain to a target; unlinking detaches it without forgetting the domain or re-running ownership verification.
The Three-Step Flow
The common path is add → set DNS → verify → link:
ccp domain add example.com
# (add the printed TXT ownership record and A routing record at your DNS provider, wait for propagation)
ccp domain verify claim_abc123
ccp domain link example.com --function fn_abc123Splitting the ownership claim, verification, and attachment lets you prove you control the domain and set DNS up front, avoiding a window where the platform routes a domain that doesn't yet resolve or isn't yours.
Start an Ownership Claim
ccp domain add example.com
# ✓ Ownership claim created for example.com
# Claim: claim_abc123
# Expires: 2025-01-15T12:00:00Z
#
# DNS Add these records in your DNS provider:
#
# Type: TXT
# Name: _clusterbase-verify.example.com
# Value: clusterbase-verify=8f14e45f-ea0f-4c2b-9c1a-3d5b7e2a6f01
#
# Type: A
# Name: example.com
# Value: 34.xx.xx.xx
#
# › After the TXT record resolves, run `ccp domain verify claim_abc123 --org-id <org>`add starts an expiring ownership claim against an organization; the domain is not yet in inventory and does not appear in ccp domain ls until it's verified. The org is resolved from cluster.toml, the --org-id flag, the CCP_ORG_ID env var, or — when ambiguous — an interactive picker:
ccp domain add example.com --org-id org_abc123add is print-only — it never prompts for project setup or writes .ccp/config.json, even when invoked outside a linked project directory.
Verify a Claim
Once the TXT record from add has propagated, complete the claim:
ccp domain verify claim_abc123 --org-id org_abc123
# ✓ Domain example.com verified
# › It is ready to link to an app or VM.verify resolves the TXT proof for a claim and, on success, admits the domain into the organization's inventory — this is the point at which it shows up in ccp domain ls. Nothing is routed yet; run link next.
Link a Domain
Attach a verified domain to a target. Pass exactly one of --function or --vm:
# Attach to a serverless function
ccp domain link example.com --function fn_abc123
# Attach to a VM service (vm_id:port)
ccp domain link api.example.com --vm vm-xyz:3000
# Inside a linked project directory: target defaults to that function
ccp domain link example.comOn success:
✓ Domain example.com binding accepted at revision rev_2
› Routing and TLS will converge automaticallyEvery mutation is fenced against the domain's current binding revision, so link always applies on top of the state you last observed. A domain can only be linked to one target at a time — linking an already-attached domain replaces its desired target on the next revision. Pass --org-id if the domain's org can't be resolved from cluster.toml.
Unlink a Domain
Detach a domain from its current target. The domain stays owned and verified, so a later link doesn't repeat ownership verification.
ccp domain unlink example.com
# ✓ Domain example.com withdrawal accepted at revision rev_3unlink submits a withdrawal of the current binding; routing disappears once the withdrawal converges, not immediately.
Use unlink when you want to move a domain to a different function or VM:
ccp domain unlink example.com
ccp domain link example.com --vm vm-xyz:3000List Domains
ls lists every verified domain owned by the resolved organization, including domains not yet linked to a target. Domains with a pending (unverified) claim don't appear until verify completes. The org is resolved the same way as add (cluster.toml, --org-id, or interactive picker). No cluster.toml or .ccp/config.json is required:
ccp domain ls
# DOMAIN REVISION
# example.com rev_2
# parked.example.com rev_0Each row shows the domain and its current binding revision — the same revision used to fence link, unlink, and rm calls. Pass --org-id to list a different org.
Each domain prints on one line, sized to fit the terminal. Pass --json for the domain's id, exact binding_revision, and complete URL with no styling — the format to script against.
Remove a Domain
rm retires the domain's ownership record outright. Confirmation is required (auto-confirms in headless mode). Works outside any project directory. Wait for an existing binding to finish withdrawing before removing — rm does not implicitly unlink first.
ccp domain rm example.com
# Remove domain example.com? (y/N): y
# ✓ Domain example.com removedUse unlink instead if you only want to detach the domain — rm deletes the ownership record entirely.
Verb Cheatsheet
| Verb | Effect |
|---|---|
add | Start an ownership claim against the resolved org. |
verify | Complete a claim's TXT proof; admits the domain into inventory. |
link | Attach a verified domain to a function or VM service. |
unlink | Withdraw from the current target; ownership + verification preserved. |
rm | Retire the domain's ownership record entirely. |
ls | List every verified domain in the resolved org. |
Compute Services
Compute services don't have a --function flag — point a domain at one via the underlying instance id and the service's port. Get the id from ccp compute status:
ccp compute status
# Compute service my-api
#
# ID 3fd25c…
# Status running
# Image ghcr.io/me/api:v3
# Port 8080
# Instance vm-7e21…Then link the domain at <instance>:<port>:
ccp domain link api.example.com --vm vm-7e21:8080The <port> is the same one you passed to ccp compute deploy --port. Routing, TLS, and revision semantics are identical to function targets — see Compute services for the full lifecycle.
Domain Requirements
- Must include a TLD (e.g.,
example.com, not justexample) - No scheme (
https://), path (/), port (:), or spaces - Must not start or end with a dot
- Maximum 253 characters
Aliases
| Command | Alias |
|---|---|
ccp domain list | ccp domain ls |
ccp domain remove | ccp domain rm |
How It Works
addopens an expiring ownership claim against the resolved organization and returns the TXT and A records to add at your DNS provider.verifyresolves the TXT proof for a claim and admits the domain into the organization's inventory, unattached.linksets the domain's desired binding to the target (function or VM service); the mutation is fenced against the domain's current binding revision and converges asynchronously.unlinksets the desired binding to withdrawn; routing and the desired target are removed once the withdrawal converges, but the domain's ownership and verification state are preserved.- TLS certificates live on the domain (not the attachment), so an
unlink→linkcycle preserves the cert and avoids a re-issue. - Deleting the function behind a linked domain (
ccp remove) is rejected while the domain is still attached —unlink(orrm) it first. This prevents a deleted function from orphaning a live route.