# Custom domains

Put your site on your own domain — add two DNS records where you bought the domain, and HTTPS is set up and renewed for you.

Every site is online straight away at its own address, like
`mysite.one9x.app`. To use a domain you own instead — `example.com` or
`www.example.com` — you add **two DNS records** where you bought the domain.
It takes about five minutes.

DNS changes are not instant. After you add the records it is normal to wait a
few minutes before the domain works; that is the internet catching up, not
something broken.

Custom domains are a paid-plan feature — see [Certificates](#certificates)
below for how many each plan includes.

## Link a domain in the dashboard

1. Open your site and go to the **Domains** tab.
2. Press **Add domain**, type the domain you want to use — for example
   `www.example.com` — and press **Link**.
3. The dashboard shows two records, each with a copy button: a **TXT** record
   that proves the domain is yours, and a **CNAME** record that points it at
   your site. Keep this page open.
4. In another tab, sign in where you bought the domain and add both records.
   [Where to add the records](#where-to-add-the-records) has a short note for
   the common registrars.
5. Come back and press **Check DNS**. If it isn't ready yet, wait a few minutes
   and press it again — pressing it more than once is fine.

When the records are found, the domain shows **issuing certificate** and then
**live**. The HTTPS certificate is set up for you, and renewed for you, with
nothing to install.

> **Using the bare domain, with no `www`?** Many registrars won't accept a
> CNAME record there. [The two DNS records](#the-two-dns-records) below explains
> what to add instead.

## Where to add the records

Every registrar has the same three steps: open your domain's settings, find
DNS management, and add a record. Add the TXT record and the CNAME record from
the dashboard one at a time, copying the name and the value exactly.

Many registrars add your domain to the end of the name for you. If the
dashboard shows `_one9x-challenge.example.com`, you may only need to type
`_one9x-challenge` — look at the records already on the page to see which form
they use.

Each registrar's own help page, linked below, has screenshots of these screens.

### GoDaddy

Sign in to your **Domain Portfolio**, select the domain, then select **DNS**.
Select **Add New Record**, choose the record type from the **Type** menu, fill
in the name and value, and select **Save**. ([GoDaddy: add a CNAME
record](https://www.godaddy.com/help/add-a-cname-record-19236), [add a TXT
record](https://www.godaddy.com/help/add-a-txt-record-19232))

GoDaddy has no ALIAS record, and its CNAME records can't use the bare domain
(`@`). For the bare domain, use the A record listed under [The two DNS
records](#the-two-dns-records). ([GoDaddy: add an A
record](https://www.godaddy.com/help/add-an-a-record-19238))

### Hostinger

In the Hostinger dashboard, choose **Domains** in the left sidebar, then
**DNS**, and select the domain. Add each record on the DNS records page.
([Hostinger: manage DNS
records](https://www.hostinger.com/support/1583249-how-to-manage-dns-records-at-hostinger/))

Hostinger supports ALIAS records, so for the bare domain add an ALIAS record
instead of the A record. ([Hostinger: ALIAS
records](https://www.hostinger.com/support/10067986-how-to-manage-alias-records-at-hostinger/))

DNS management here only works while the domain uses Hostinger's nameservers.
If it uses another provider's, add the records there instead.

### Namecheap

Select **Domain List** in the left sidebar, select **Manage** next to the
domain, then open the **Advanced DNS** tab. Select **Add New Record**, choose
the type, and fill in **Host** and **Value**. ([Namecheap: set up host
records](https://www.namecheap.com/support/knowledgebase/article.aspx/434/2237/how-do-i-set-up-host-records-for-a-domain/))

Namecheap supports ALIAS records: for the bare domain, add an **ALIAS Record**
with `@` as the host. Remove any A, AAAA, CNAME or URL Redirect record already
on `@` first, or they conflict. ([Namecheap: create an ALIAS
record](https://www.namecheap.com/support/knowledgebase/article.aspx/10128/2237/how-to-create-an-alias-record/))

If the **Advanced DNS** tab has no host records section, the domain uses another
provider's nameservers, so add the records there instead.

### Cloudflare

In the Cloudflare dashboard, open the domain, go to **DNS → Records**, and
select **Add record**. Choose the type, fill in the fields, and select
**Save**. ([Cloudflare: create DNS
records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/))

**Set Proxy status to DNS only** (the grey cloud) on the CNAME record. When a
record is **Proxied**, the domain shows Cloudflare's addresses instead of
ours, so **Check DNS** can't find your site and the certificate is never
issued. The TXT record is always DNS only. ([Cloudflare: proxy
status](https://developers.cloudflare.com/dns/proxy-status/))

Cloudflare accepts a CNAME record on the bare domain (`@`) and answers it
correctly on its own, so you can use the CNAME there too. ([Cloudflare: CNAME
flattening](https://developers.cloudflare.com/dns/cname-flattening/))

### Google Domains and Squarespace

Domains registered with Google Domains are now managed by Squarespace. Open your
domains dashboard and select the domain, then **DNS → DNS Settings**. Scroll
down to **Custom Records** and select **Add record**. Squarespace asks for your
password again before saving. ([Squarespace: DNS records for web
hosting](https://support.squarespace.com/hc/en-us/articles/31119879125645-DNS-records-for-web-hosting))

Squarespace doesn't allow a CNAME on the bare domain (`@`), but it does support
ALIAS records there. Before adding one, go to **DNS → DNSSEC** and turn **DNS
Security Extensions** off, as Squarespace's instructions say.

## Details and CLI

Every site is reachable immediately at its platform subdomain
(`mysite.one9x.app`) over HTTPS, with no setup. To serve it on your own domain,
link the domain to the site, prove you own it with a DNS record, and point your
DNS at us — we issue and renew the TLS certificate automatically.

`domains` is a top-level command, not part of `pages`: a domain points at a
*site*, whatever product runs it.

```console title="custom domain"
$ one9x domains link example.com --site mysite
1. TXT    _one9x-challenge.example.com  ->  9f2a…
2. CNAME  example.com  ->  sites.one9x.app
$ one9x domains verify example.com --site mysite
✓ verified · certificate issued
→ https://example.com/
```

`link` prints both records with your own token filled in — copy them from there
rather than from this page.

### The two DNS records

Both are required.

**Ownership.** A TXT record at `_one9x-challenge.example.com` holding the token
`link` gave you. Only whoever controls the domain's DNS can publish it, which is
what makes it proof — pointing DNS at us shows that *someone* did, not who.

**Routing.** A CNAME from your domain to `sites.one9x.app`. DNS does not allow a
CNAME at the apex (`example.com` with no subdomain), so there the record depends
on what your DNS provider supports:

| Name | Type | Value |
| --- | --- | --- |
| `_one9x-challenge` | TXT | the token `link` printed |
| `www` (or any subdomain) | CNAME — **preferred** | `sites.one9x.app` |
| `@` (apex, ALIAS support) | ALIAS / ANAME — **preferred** | `sites.one9x.app` |
| `@` (apex, no ALIAS) | A — fallback | `167.104.222.9` |

**Prefer ALIAS or ANAME at the apex where you can.** Cloudflare, Namecheap,
Hostinger, Squarespace, Route 53 and DNSimple all support it; GoDaddy does not,
which is why the A record exists. The
difference matters over time: an ALIAS follows us if our edge address ever
changes, while an A record is a number in your zone file that only you can
update. We will give notice before ever changing it, but a record we can follow
is better than a record you have to remember.

Order does not matter, and neither record expires. Verification is checked
against public resolvers rather than our own, so give a new record a minute to
propagate before running `verify` — and if it fails, the message names what we
actually saw, which is usually enough to spot a typo or a proxy that is
intercepting the name.

### Certificates

The certificate is issued the moment ownership is proved, loaded on the first
request to your domain, and renewed for you — there's nothing to install or
rotate.

A domain and its www count as one, so `example.com` and `www.example.com`
together use a single slot.

> **Custom domains are a paid-plan feature** — Starter includes one, Pro five,
> Business 25 — and the free tier serves `*.one9x.app` only. Choose a plan from
> **Plan & billing** in the dashboard at any time. The slot is yours the moment
> the payment clears.

### Taking a domain off a site

Two commands, and the difference matters.

`domains unlink example.com` stops the domain routing but you keep the name and
its certificate — so linking it again later, to this site or another one, is
usually instant. It stays in `domains list` as unlinked.

`domains release example.com` gives the name up entirely: the record and its
certificate are deleted and another account may claim it. That one can't be
undone, so it asks for confirmation first.

Neither takes `--site`; the owning site is looked up from the name.