# Custom domains

Serve an app at your own domain, with HTTPS. Every app always keeps its own address at `<app>.deplane.dev`.

## Connect a domain

In the dashboard, open the app's **Domains** tab and add the hostname, or run `deplane domains add www.example.com`. Deplane shows the two DNS records to set at your DNS provider:

| Domain | Records |
|---|---|
| A subdomain, such as `www.example.com` | `CNAME` to `<app>.deplane.dev`, **and** `TXT` `_deplane-challenge.www.example.com` with the value shown |
| A root domain, such as `example.com` (it cannot have a CNAME) | `A` to Deplane's address, **and** `TXT` `_deplane-challenge.example.com` with the value shown |

Deplane checks every 2 minutes for 48 hours (or press **Check now**). When DNS points at the app and the TXT value matches, Deplane routes the domain and gets a certificate from Let's Encrypt, usually within a minute: **Waiting for DNS**, then **Issuing certificate**, then **Active**. Certificates renew automatically.

## Why the TXT record

A domain is connected only when DNS proves that whoever controls it chose this connection. The TXT value is new each time a domain is added, so it proves the records were set for this app and this team, not left over from an app someone deleted: nobody can take over a domain whose DNS still points at Deplane after its owner moved on.

The TXT record is needed to connect the domain. After that you may keep it or remove it: a connected domain stays connected while its CNAME names the app (or, for a root domain, its A record points at Deplane).

## Re-checks

Deplane checks every connected domain again every 6 hours. If its DNS no longer points at the app, the domain shows **DNS changed** and your team gets an alert ([Custom domain no longer points here](alerts.md)). Deplane keeps serving it for 7 days, sends a second alert a day before the end, and then stops serving the domain and its certificate; it goes back to **Waiting for DNS**. When DNS points back at the app, it is served again on the next check. A DNS server that does not answer changes nothing.

If another Deplane team adds the domain and proves it with its own TXT value (the domain changed hands, and its new owner points it at their app), that team's app gets the domain at once and the old connection stops. Your team gets an alert ([Custom domain taken over](alerts.md)) saying what happened and what to check: anyone who can write the domain's `_deplane-challenge` TXT record while it points at Deplane can do this, so keep that record's DNS access to your own people.

## Limits

Up to 10 custom domains per app. A domain can be connected to one app on Deplane at a time. Deplane's own domains cannot be added. Removing a domain stops it serving the app right away; deleting an app frees its domains.

When a team removes a domain or deletes its app, another team cannot add that domain while its CNAME still points at the old app's address ([domain_dangling](errors.md#domain_dangling)): change the CNAME first. A deleted app's name stays reserved for its team for 90 days, so nothing that still points at `<app>.deplane.dev` (DNS, OAuth callbacks, webhooks) reaches another team's app.
