# Custom domains

> The one supported flow for connecting a customer-owned domain to a Tarout app, and the DNS rules an agent must never break

# Custom domains

> **You never edit DNS.** Do not create, edit, or delete DNS records, do not
> change nameservers, and do not touch registrar settings - not with a provider
> API, not with a CLI, not through a browser. Your job is to produce the exact
> records and **relay them to the user**, who adds them themselves. This is the
> single most damaging thing an agent can get wrong here.
>
> `tarout.sa` is Tarout's own domain, never a deploy target.

> **Preflight - check auth first.** Run `tarout whoami --json`. If it does not
> return `success: true`, authenticate with the table in
> [start.md](https://tarout.sa/docs/for-ai/start.md)
> before running anything on this page - every command below fails without a
> credential, and the failure reads like a broken deploy rather than a missing
> login.

## The flow

External (customer-owned) domains connect through exactly one sequence:
**add-external → DNS records → verify → link to app.**

```sh
# 1. Register the external hostname (creates the platform record + edge hostname).
tarout --json domains add-external www.example.com

# 2. Read the exact DNS records to relay to the user.
tarout --json domains instructions www.example.com
#    Subdomain → one CNAME to the Tarout edge (e.g. proxy.tarout.app).
#    A `_tarout-verification` ownership TXT is included ONLY when the
#    platform requires one for this hostname (see below).
#    Relay the exact values - do not paraphrase, do not retype from memory.

# 3. After the user adds the records, poll verification.
#    TLS is issued automatically once verification passes.
tarout --json domains verify www.example.com
tarout --json domains wait-verified www.example.com --timeout 1800 --interval 10

# 4. Attach the verified domain to the app.
tarout --json domains app link-to-app --domain-id <domain-id> --app-id <app-id>
```

Use `--timeout 1800` (30 minutes) on `wait-verified`: that covers DNS propagation
plus automatic certificate issuance.

> **`--domain-id` gotcha.** Pass the `domainId` from the `instructions` or
> `wait-verified` output - **not** the id returned by `add-external`, which is a
> different id space. `--app-id` comes from `tarout apps list`.

## Ownership TXT record

Most hostnames need only the routing record: pointing DNS at Tarout is the proof
of control. The platform adds a `_tarout-verification.<hostname>` TXT record to
the `instructions` output only in specific cases, for example when the hostname
already routes to Tarout at the moment it is added (a leftover record from a
deleted app) or when its record is proxied through Cloudflare. If the output
contains a TXT record, relay it with the others; if it does not, do not invent
one.

## Root / apex domains

`example.com` with no subdomain connects in one of two ways. `add-external`
detects the nameservers and returns the right records:

- **DNS hosted on Cloudflare** - a root CNAME to the Tarout edge that must be
  set to **Proxied (orange cloud)**. Relay that requirement verbatim, because a
  DNS-only root record will not route.
- **Any other DNS provider** - an A record at the root pointing at Tarout's apex
  gateway. Relay the exact IP from `instructions`; never hardcode one. By
  default the gateway redirects `example.com` to `www.example.com`, so tell the
  user to connect `www.example.com` too. The user can switch the root to serve
  the app directly under **Root domain behavior** on the domain's dashboard page;
  the DNS records do not change.

## Linking shortcuts

`tarout domains link <app> <domain>` attaches an existing domain (for example
one that finished the add-external flow above) to an app by name, and is
equivalent to step 4. Hostnames under a domain the user registered *through
Tarout* use `tarout domains app link-registered` instead of the external flow
above.

## Other commands

```sh
tarout domains list
tarout domains info <domain>
tarout domains instructions <domain>
tarout domains verify <domain>
```

A custom domain needs the `feature.custom_domain` entitlement, which every paid
plan (Starter and above) includes and the free plan does not. On the free plan,
connecting a domain fails with a "Custom domains require a paid plan" error (or
`NEEDS_UPGRADE`) - see [billing.md](https://tarout.sa/docs/for-ai/billing.md).

---

## Every Tarout agent guide

- [Start Here (Agents)](https://tarout.sa/docs/for-ai/start.md)
- [Overview](https://tarout.sa/docs/for-ai.md)
- [Deploying an app](https://tarout.sa/docs/for-ai/deploy.md)
- [Databases](https://tarout.sa/docs/for-ai/database.md)
- [Object storage](https://tarout.sa/docs/for-ai/storage.md)
- [Plans and upgrades](https://tarout.sa/docs/for-ai/billing.md)
- [Troubleshooting](https://tarout.sa/docs/for-ai/troubleshoot.md)
- [Agent Onboarding](https://tarout.sa/docs/for-ai/onboarding.md)
- [CLI Reference](https://tarout.sa/docs/for-ai/cli-reference.md)
- [CLI JSON Schema](https://tarout.sa/docs/for-ai/cli-json-schema.md)

Whole corpus in one file: https://tarout.sa/llms-full.txt · index: https://tarout.sa/llms.txt
Any docs page is raw markdown at the same URL + `.md`. Short link to the entry point: https://tarout.sa/deploy.md
