# Add a custom domain

Attach your own hostname, configure DNS, verify ownership, and issue its TLS certificate.

Canonical: https://docs.deliberate.space/deploy/custom-domains/

Use a custom domain when the generated deliberate. hostname should not be your
customer-facing address. A domain belongs to one Project Environment and points
at an explicit route in that same Environment.

## 1. Declare the hostname and route

Add both resources below `.deliberate/`:

```yaml
resource: domain
hostname: app.example.com

---
resource: route
host: app.example.com
visibility: public
rules:
  - path: /
    to: app
```

The `hostname` and route `host` must match. Apply them together:

```sh
deliberate apply --env production
```

## 2. Add the DNS records

Inspect the instructions generated for this binding:

```sh
deliberate domains show app.example.com --env production
```

For a subdomain, the command prints the CNAME target. For an apex domain, it
prints the required A and ownership TXT records instead. Add exactly those
records at your DNS provider.

DNS changes can take time to reach the resolver used for verification. Check the
current state without changing it:

```sh
deliberate domains list --env production
deliberate domains show app.example.com --env production
```

## 3. Verify and issue TLS

After the records resolve, verify ownership:

```sh
deliberate domains verify app.example.com --env production
```

Verification starts certificate issuance. Re-run `domains show` to inspect the
binding status and any last error. Once active, HTTPS traffic for the hostname
is sent to the matching route.

## Change or remove a domain

Treat a hostname change as an ordinary desired-state change: add the replacement
domain and route, configure and verify its DNS, switch users to it, then remove
the old declarations and apply again. This avoids dropping the working hostname
before its replacement is ready.

`deliberate domains delete <hostname> --env <env>` is an explicit operational
detach. For version-controlled configuration, remove the resources from YAML and
apply so the repository continues to describe the Environment.

## Current security boundary

Custom domains receive TLS, but they are not currently covered by the tenant
origin WAF. Platform-generated public hostnames are covered. In either case, the
WAF is only a safety net and never replaces security inside your application.
Read [Troubleshoot blocked web traffic](/operate/web-traffic/) for the precise
coverage and responsibility boundary.

## Next steps

- [Configure application alerts](/operate/alerts/)
- [Review public-route security controls](/security/)
- [Make an administrative route private](/private-net/connect/)
