> ## Documentation Index
> Fetch the complete documentation index at: https://docs.boxd.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom domains

> Bring your own domain. Point it at one machine, or delegate a wildcard to your whole organization.

Every machine already gets `name.boxd.sh` automatically (see [HTTPS](/guides/https)). Custom domains let you put your own domain in front of it instead, two ways:

* **Per-machine**: point one domain you own at a single machine (e.g. `myapp.mysaas.com`).
* **Org-wide**: delegate a wildcard subdomain to your whole org, so every machine gets its own name under it (e.g. `myapp.vms.mysaas.com`, `other-app.vms.mysaas.com`, etc).

Both are self-serve. boxd verifies your DNS and issues TLS certificates automatically.

You can also set the domains via [console](https://boxd.sh/app)'s Domains page, and from the [Python](/reference/python-sdk#domains) and [TypeScript](/reference/typescript-sdk#domains) SDKs.

## Per-machine

<Steps>
  <Step title="Start adding the domain">
    ```bash theme={"theme":"github-dark"}
    boxd machine domain add myapp.mysaas.com --vm myapp
    ```

    This doesn't touch anything on the server yet. It just prints the two DNS records to add:

    ```
    A     myapp.mysaas.com      <shown to you>
    CNAME *.myapp.mysaas.com    myapp.boxd.sh
    ```

    The A record's target is the same shared address `myapp.boxd.sh` already resolves to (`boxd machine get myapp` shows it too). The wildcard CNAME is required even if you don't plan to use subdomains yet, because it's how the certificate gets issued (see below).
  </Step>

  <Step title="Add those records at your registrar">
    Add them exactly as printed, and nothing else. Delegating NS records belongs to the org-wide flow below, so skip that here.
  </Step>

  <Step title="Confirm">
    The same command is still paused in your terminal, waiting for you. Once the records are live, press Enter. Only then does boxd start checking and create anything server-side.

    Scripting it instead of running it interactively? Pass `-y`/`--confirm` up front and it skips the wait, but only do this once the records are actually live:

    ```bash theme={"theme":"github-dark"}
    boxd machine domain add myapp.mysaas.com --vm myapp --confirm
    ```
  </Step>
</Steps>

The domain starts `pending` and a background check verifies DNS and issues the certificate, typically within a minute or two of the records actually resolving. Once both the apex and wildcard certs exist, it flips to `active` and starts routing.

```bash theme={"theme":"github-dark"}
boxd machine domain list                     # domain, machine, status, error (alias: ls)
boxd machine domain remove myapp.mysaas.com  # unbind (alias: rm)
```

<Note>
  **Add the DNS records before you test the domain.** A resolver that looks up the domain too early caches the "this doesn't exist" answer, and that cached answer can outlive your fix. So a correct setup can look broken on your network even while the console shows `active`. If that happens, try another network or resolver, for example `1.1.1.1` or `8.8.8.8` under your browser's secure DNS setting.
</Note>

## Org-wide (wildcard domain)

Each org gets one domain, and the wildcard covers every machine, current and future, with no per-machine step.

<Steps>
  <Step title="Start setting the domain">
    ```bash theme={"theme":"github-dark"}
    boxd manage domain set vms.mysaas.com
    ```

    Prints the NS records to delegate:

    ```
    vms.mysaas.com.  NS  ns1.boxd.sh.
    vms.mysaas.com.  NS  ns2.boxd.sh.
    ```
  </Step>

  <Step title="Delegate at your registrar">
    These are **NS records**. Adding them at your registrar hands DNS authority for `vms.mysaas.com` to boxd, the same way `mysaas.com` as a whole is delegated to your DNS provider. From then on, boxd answers DNS for every name under `vms.mysaas.com` and issues the wildcard certificate, with nothing else to add on your side. Delegate only this one subdomain. Everything else on `mysaas.com` stays with your current DNS setup.
  </Step>

  <Step title="Confirm">
    The same command is still paused in your terminal. Press Enter once delegation is live. For scripts, pass `-y`/`--confirm` up front instead:

    ```bash theme={"theme":"github-dark"}
    boxd manage domain set vms.mysaas.com --confirm
    ```
  </Step>
</Steps>

Once active, every machine in the org is reachable at `<machine-name>.vms.mysaas.com` in addition to `<machine-name>.boxd.sh`. The default domain never stops working. The **bare** wildcard domain itself (`vms.mysaas.com` with no machine name) doesn't route anywhere, since there is no "default machine" for it.

```bash theme={"theme":"github-dark"}
boxd manage domain get     # any org member can read it
boxd manage domain clear   # admin only
```
