# Custom domains

> A folder can be served on any number of hostnames you own, such as `www.example.com` or `docs.example.com`. Add the hostname, point a CNAME record at the folder, verify it, and permahost.io serves the folder there with HTTPS.

HTML version: https://permahost.io/docs/domains/ · All docs: https://permahost.io/docs.md

1. **Add**: Add the hostname to a folder. It starts as `pending` and shows the CNAME target.
2. **Point**: Create the CNAME record at your DNS provider.
3. **Verify**: Once the record resolves, the domain turns `active` and gets a certificate.

## Add a domain

With the CLI, the web app (the globe button on a folder) or the [API](https://permahost.io/docs/api/#domains):

Shell:

```
$ permahost domain add --id k7q2m9xa3bd www.example.com
Added www.example.com to folder k7q2m9xa3bd. Create this DNS record:

  www.example.com  CNAME  k7q2m9xa3bd.file.permahost.io

then run "permahost domain verify --id k7q2m9xa3bd www.example.com".
```

A pending domain reserves nothing and costs nothing: only a verified domain is unique, so nobody can squat a hostname by adding it first.

## The DNS record

| Type | Name | Target |
| --- | --- | --- |
| CNAME | www.example.com (often entered as just `www`) | The folder's own host, such as `k7q2m9xa3bd.file.permahost.io` |

Take the target from `domain add` or `domain ls` rather than writing it by hand. Apex domains such as `example.com` can't hold a CNAME record, so use a subdomain such as `www`. If your DNS provider proxies traffic (Cloudflare's orange cloud), turn the proxy off for this record, so the CNAME is visible to public resolvers and the certificate can be issued.

## Verify

Shell:

```
$ permahost domain verify --id k7q2m9xa3bd www.example.com
www.example.com is active and serves folder k7q2m9xa3bd.
$ permahost domain ls --id k7q2m9xa3bd
ID           HOSTNAME         STATUS  CNAME TARGET               LAST ERROR
3hVt9qXc2Lm  www.example.com  active  k7q2m9xa3bd.file.permahost.io
```

The server looks the record up directly at public resolvers (1.1.1.1 and 8.8.8.8), so a record cached elsewhere doesn't matter. You don't have to run `verify` yourself: pending domains are checked every 5 minutes for 7 days. Running it checks right away. Until the record matches, `verify` fails and `domain ls` shows the last error.

## HTTPS

When a domain turns active, a Let's Encrypt certificate is obtained for it in the background (TLS-ALPN-01). Until it arrives a browser may show a certificate warning. The certificate renews on its own.

## Cost

A custom domain costs 500 credits to set up plus 500 credits a month, charged when its CNAME record is verified. Each renewal then charges the month for every active domain. If the account can't pay when the record is verified, the domain stays pending. See [credits](https://permahost.io/docs/#credits).

## Remove

Shell:

```
$ permahost domain rm --id k7q2m9xa3bd www.example.com
Removed www.example.com from folder k7q2m9xa3bd.
```

Removing a domain stops serving the folder there and stops its monthly charge from the next renewal. Delete the CNAME record too.

## Troubleshooting

| Symptom | Fix |
| --- | --- |
| verify: domain not verified | The CNAME isn't visible yet or points elsewhere. Check it with `dig +short CNAME www.example.com @1.1.1.1`; DNS changes can take a while to spread. |
| domain already in use | Another folder has already verified that hostname. Remove it there first. |
| invalid hostname | Use a full hostname such as `www.example.com`, without `https://` or a path. |
| insufficient credits | This month's credits can't pay the setup and first month. The domain stays pending until they can. |
| HTTP 402 on the site | The account's balance fell below zero at renewal, so its sites are paused until a later renewal. Nothing is deleted. |
