# Add a domain and protection

> Serve a deployment on your own domain, ask visitors for a password or a Coritan sign-in, and set firewall rules, rate limits and caching.

Source: https://www.coritan.com/docs/managed-containers/domains-and-protection/

In the dashboard:

- /dashboard/deployments/…/domains: https://www.coritan.com/dashboard/deployments
- /dashboard/deployments/…/networking: https://www.coritan.com/dashboard/deployments
- /dashboard/deployments/sign-in: https://www.coritan.com/dashboard/deployments/sign-in

Every web service, static site and hybrid site answers at a platform address, and can answer at your own domains too, each with its own certificate. From the same deployment you can ask visitors for a password or a Coritan sign-in before they see it, block or limit requests with firewall rules, and let the edge cache its answers. The deployment's **Domains** tab holds its addresses, and the **Networking** tab its firewall rules and cache.

A game server or a database answers at its servers' own addresses instead: an IP address and a port, and a join address for a game ([Server settings](/docs/managed-containers/settings/)).

## Before you begin

- For your own domain, you need to be able to change its DNS records at your DNS host. If Coritan hosts its DNS, see [Add, edit and delete DNS records](/docs/websites/dns/manage-dns-records/).
- For an organization's deployment, you need the owner or admin role in the organization.
- Protection and cache settings are part of the Pro, Business and Enterprise plans. Firewall rules and rate limits count against the same allowances as your websites' rules ([Pricing](https://www.coritan.com/pricing)).

## The platform address {#platform-address}

When you create a deployment, we give it a platform address made of its name and the platform's domain for deployments, such as `web-shop.apps.example.net` (these pages use `apps.example.net` for that domain). It is ready from the start, it goes with the deployment, and you cannot remove it. Previews get addresses of their own under the same domain ([Turn on previews](/docs/managed-containers/deploy-from-git/#turn-on-previews)).

## Add a custom domain {#add-a-custom-domain}

1. Open the deployment and select the **Domains** tab.
2. Select **Add domain…**, type the hostname in **Domain**, such as `www.example.com` or `example.com`, without `https://` or a path, and select **Add domain**. Wildcard names such as `*.example.com` are not accepted.
3. Publish the TXT record the tab gives you at your DNS host, to prove the domain is yours. Its name is `_coritan-app.` followed by your hostname:

   ```dns
   _coritan-app.www.example.com.  3600  IN  TXT    "8b7c1d0e2f3a4b5c6d7e8f9012345678"
   ```

4. Point the hostname at the deployment with a CNAME record to its platform address:

   ```dns
   www.example.com.  3600  IN  CNAME  web-shop.apps.example.net.
   ```

   At the top of a zone, such as `example.com`, a CNAME is not allowed. Use your DNS host's ALIAS record or CNAME flattening to the same target.
5. Select **Verify** on the domain's row. Once we find the TXT record, the domain shows **Verified**, starts serving the deployment, and we order its certificate. If we do not find it yet, the row says **Not verified yet**: wait a few minutes for DNS to update, then verify again.

The domain gets no route until it is verified, so nothing reaches the deployment on it before then. You can remove the TXT record afterwards. A deployment can have up to 20 custom domains.

A hostname belongs to one deployment at a time. One that another deployment is still verifying is held for 72 hours after it was added; after that, the next deployment that adds it takes it over. A hostname another deployment has verified, or that another product serves, such as a [web proxy](/docs/proxies/web-proxies/), cannot be added.

## Protect a deployment {#protection}

Protection asks each visitor to prove they may see the deployment before the edge lets a request through. Choose one of two ways on the **Protection** card of the deployment's **Networking** tab, or when you order it:

Password
: Visitors type a password you set, of 8 characters or more. After ten wrong passwords from one address in five minutes, that address waits before it can try again.

Coritan sign-in
: Visitors sign in with their Coritan account. The deployment's owner and anyone on the owner's team get in, whatever their role, and for an organization's deployment, the organization's owner and members. The edge sends a visitor to the dashboard's **Sign in to a deployment** page, which checks their account and sends them back to the address they opened.

Then choose what it covers: previews only, which keeps production public, or every address. Once a visitor is in, the edge remembers them on that address for 12 hours. Changing the mode or the password signs everyone out.

For automated tests against a protected address, create a bypass token. Send it in the `x-coritan-protection-bypass` header, and the request goes through without a password. The token is shown once; creating another replaces it. The edge takes the header and its own cookie off the request, so your app never sees them.

Turning protection off is always allowed, even when your plan no longer includes it.

## Block or limit requests {#firewall-rules}

The **Networking** tab takes the same firewall rules as a website: rules that block or challenge requests by path, country, address and more, and rate limits that slow a visitor who sends too many requests ([What a rule can match](/docs/websites/waf/#what-a-rule-can-match)). The rules apply to every address of the deployment, previews included.

A deployment can have up to 200 rules, of which up to 50 rate limits. Your plan's allowance for custom rules and rate limits counts them with your websites' rules, each rule once, however many of the deployment's addresses carry it.

## Cache answers at the edge {#cache}

With the cache on, the edge keeps copies of the deployment's answers and serves them without asking an instance. Set how long a copy is kept, up to one year, or leave it at `0` to follow the `Cache-Control` headers your app sends. Purge the cache to drop every copy at once, on every address and every edge location, up to 30 times an hour.

While part of the traffic goes to a new release, nothing is cached, so no visitor gets a copy of the other release's answer ([Send part of the traffic to a new release](/docs/managed-containers/releases/#canary)). A static site's files have their own caching rules ([Caching and compression](/docs/managed-containers/static-sites/#caching)).

## Result

A verified domain serves the deployment over HTTPS once its certificate is issued. With protection on, a visitor to a covered address sees the password form or a sign-in link before the deployment.

## Troubleshooting

`No TXT record at _coritan-app.www.example.com holds the token yet. DNS changes can take a few minutes to appear.`
: The record is not published yet, or holds another value. Check its name and value at your DNS host, wait a few minutes, then verify again.

`That hostname is in use on the platform`
: Another deployment has verified it, or added it less than 72 hours ago. If it is yours, remove it from the other deployment first.

The certificate is not issued
: The hostname does not point at the deployment yet. Check the CNAME record, or the ALIAS record at the top of a zone.

A visitor keeps seeing the password form
: The mode or the password changed, which signs everyone out, or 12 hours have passed. They enter the password again.

A test run gets `401` from a protected preview
: Send the bypass token in the `x-coritan-protection-bypass` header. If you created a new token, the old one no longer works.

## Related

- [Protect a website with the WAF](/docs/websites/waf/) explains each kind of rule.
- [Host a static site](/docs/managed-containers/static-sites/) sets redirects and headers from the site's own files.

## With the API

The routes are under `/api/v1/client/deployments/{uuid}` for your own deployment and `/api/v1/orgs/{org_slug}/deployments/{uuid}` for an organization's. Any member of an organization reads them; owners and admins change them.

`POST /domains` with `{"hostname": "www.example.com"}` adds a domain and answers the TXT record to publish. `POST /domains/{hostname}/verify` looks for it, and `DELETE /domains/{hostname}` removes the domain and its route. `GET /domains` lists the platform address first, then your domains, each with its certificate.

`PUT /protection` sets the mode (`none`, `password` or `login`), the scope (`previews` or `all`) and the password:

```bash
curl -X PUT https://api.coritan.com/api/v1/client/deployments/$DEPLOYMENT/protection \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode": "password", "scope": "previews", "password": "correct-horse-battery"}'
```

`POST /protection/bypass` answers a new bypass token this once, and `DELETE /protection/bypass` removes it. A plan without protection answers `402` for any change that leaves protection on.

`PUT /rules` with `{"rules": [...]}` makes that list the deployment's whole set of firewall rules, in the same shape as a website's; send a rule back with its `id` to keep it. `PUT /cache` takes `cache_enabled` and `cache_max_age` in seconds, and `POST /cache/purge` drops every copy.

## API

- `GET /api/v1/client/deployments/{deployment_uuid}/domains`: List domains (https://www.coritan.com/docs/api/reference/client/deployments/deployments-domains/#op-get-api-v1-client-deployments-deployment-uuid-domains)
- `POST /api/v1/client/deployments/{deployment_uuid}/domains`: Add a custom domain (https://www.coritan.com/docs/api/reference/client/deployments/deployments-domains/#op-post-api-v1-client-deployments-deployment-uuid-domains)
- `DELETE /api/v1/client/deployments/{deployment_uuid}/domains/{hostname}`: Remove domain (https://www.coritan.com/docs/api/reference/client/deployments/deployments-domains/#op-delete-api-v1-client-deployments-deployment-uuid-domains-hostname)
- `POST /api/v1/client/deployments/{deployment_uuid}/domains/{hostname}/verify`: Look for the domain's TXT record (outside any transaction) (https://www.coritan.com/docs/api/reference/client/deployments/deployments-domains/#op-post-api-v1-client-deployments-deployment-uuid-domains-hostname-verify)
- `GET /api/v1/client/deployments/{deployment_uuid}/protection`: Get protection (https://www.coritan.com/docs/api/reference/client/deployments/deployments-protection/#op-get-api-v1-client-deployments-deployment-uuid-protection)
- `PUT /api/v1/client/deployments/{deployment_uuid}/protection`: Change protection (https://www.coritan.com/docs/api/reference/client/deployments/deployments-protection/#op-put-api-v1-client-deployments-deployment-uuid-protection)
- `POST /api/v1/client/deployments/{deployment_uuid}/protection/bypass`: A new bypass token, shown this once; the one before stops working (https://www.coritan.com/docs/api/reference/client/deployments/deployments-protection/#op-post-api-v1-client-deployments-deployment-uuid-protection-bypass)
- `DELETE /api/v1/client/deployments/{deployment_uuid}/protection/bypass`: Remove the bypass token; 404 when there is none (https://www.coritan.com/docs/api/reference/client/deployments/deployments-protection/#op-delete-api-v1-client-deployments-deployment-uuid-protection-bypass)
- `GET /api/v1/client/deployments/{deployment_uuid}/rules`: Get rules (https://www.coritan.com/docs/api/reference/client/deployments/deployments/#op-get-api-v1-client-deployments-deployment-uuid-rules)
- `PUT /api/v1/client/deployments/{deployment_uuid}/rules`: Replace firewall rules (https://www.coritan.com/docs/api/reference/client/deployments/deployments/#op-put-api-v1-client-deployments-deployment-uuid-rules)
- `GET /api/v1/client/deployments/{deployment_uuid}/cache`: Get cache (https://www.coritan.com/docs/api/reference/client/deployments/deployments-cache/#op-get-api-v1-client-deployments-deployment-uuid-cache)
- `PUT /api/v1/client/deployments/{deployment_uuid}/cache`: Change cache settings (https://www.coritan.com/docs/api/reference/client/deployments/deployments-cache/#op-put-api-v1-client-deployments-deployment-uuid-cache)
- `POST /api/v1/client/deployments/{deployment_uuid}/cache/purge`: Purge cache (https://www.coritan.com/docs/api/reference/client/deployments/deployments-cache/#op-post-api-v1-client-deployments-deployment-uuid-cache-purge)
- `POST /api/v1/client/deployments/protection/sign-in`: Protection sign in (https://www.coritan.com/docs/api/reference/client/deployments/deployments/#op-post-api-v1-client-deployments-protection-sign-in)
- `GET /api/v1/orgs/{org_slug}/deployments/{deployment_uuid}/domains`: List domains (https://www.coritan.com/docs/api/reference/organizations/organization-deployments/deployments-domains/#op-get-api-v1-orgs-org-slug-deployments-deployment-uuid-domains)
- `POST /api/v1/orgs/{org_slug}/deployments/{deployment_uuid}/domains`: Add a custom domain (https://www.coritan.com/docs/api/reference/organizations/organization-deployments/deployments-domains/#op-post-api-v1-orgs-org-slug-deployments-deployment-uuid-domains)
- `DELETE /api/v1/orgs/{org_slug}/deployments/{deployment_uuid}/domains/{hostname}`: Remove domain (https://www.coritan.com/docs/api/reference/organizations/organization-deployments/deployments-domains/#op-delete-api-v1-orgs-org-slug-deployments-deployment-uuid-domains-hostname)
- `POST /api/v1/orgs/{org_slug}/deployments/{deployment_uuid}/domains/{hostname}/verify`: Look for the domain's TXT record (outside any transaction) (https://www.coritan.com/docs/api/reference/organizations/organization-deployments/deployments-domains/#op-post-api-v1-orgs-org-slug-deployments-deployment-uuid-domains-hostname-verify)
- `GET /api/v1/orgs/{org_slug}/deployments/{deployment_uuid}/protection`: Get protection (https://www.coritan.com/docs/api/reference/organizations/organization-deployments/deployments-protection/#op-get-api-v1-orgs-org-slug-deployments-deployment-uuid-protection)
- `PUT /api/v1/orgs/{org_slug}/deployments/{deployment_uuid}/protection`: Change protection (https://www.coritan.com/docs/api/reference/organizations/organization-deployments/deployments-protection/#op-put-api-v1-orgs-org-slug-deployments-deployment-uuid-protection)
- `POST /api/v1/orgs/{org_slug}/deployments/{deployment_uuid}/protection/bypass`: A new bypass token, shown this once; the one before stops working (https://www.coritan.com/docs/api/reference/organizations/organization-deployments/deployments-protection/#op-post-api-v1-orgs-org-slug-deployments-deployment-uuid-protection-bypass)
- `DELETE /api/v1/orgs/{org_slug}/deployments/{deployment_uuid}/protection/bypass`: Remove the bypass token; 404 when there is none (https://www.coritan.com/docs/api/reference/organizations/organization-deployments/deployments-protection/#op-delete-api-v1-orgs-org-slug-deployments-deployment-uuid-protection-bypass)
- `GET /api/v1/orgs/{org_slug}/deployments/{deployment_uuid}/rules`: Get rules (https://www.coritan.com/docs/api/reference/organizations/organization-deployments/deployments/#op-get-api-v1-orgs-org-slug-deployments-deployment-uuid-rules)
- `PUT /api/v1/orgs/{org_slug}/deployments/{deployment_uuid}/rules`: Replace firewall rules (https://www.coritan.com/docs/api/reference/organizations/organization-deployments/deployments/#op-put-api-v1-orgs-org-slug-deployments-deployment-uuid-rules)
- `GET /api/v1/orgs/{org_slug}/deployments/{deployment_uuid}/cache`: Get cache (https://www.coritan.com/docs/api/reference/organizations/organization-deployments/deployments-cache/#op-get-api-v1-orgs-org-slug-deployments-deployment-uuid-cache)
- `PUT /api/v1/orgs/{org_slug}/deployments/{deployment_uuid}/cache`: Change cache settings (https://www.coritan.com/docs/api/reference/organizations/organization-deployments/deployments-cache/#op-put-api-v1-orgs-org-slug-deployments-deployment-uuid-cache)
- `POST /api/v1/orgs/{org_slug}/deployments/{deployment_uuid}/cache/purge`: Purge cache (https://www.coritan.com/docs/api/reference/organizations/organization-deployments/deployments-cache/#op-post-api-v1-orgs-org-slug-deployments-deployment-uuid-cache-purge)
