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

# Custom Domains

> Serve a Sailbox HTTP listener on your own domain

Custom domains make it possible to serve an HTTP listener running in a
Sailbox on a hostname you own, in addition to the generated
`https://sb-<...>.sail.box` URL every listener gets.
Sail obtains and renews the TLS certificate for you.

## Add a custom domain

### 1. Expose an HTTP listener for a Sailbox

To expose port 3000 for HTTP traffic from the CLI:

```bash theme={null}
sail box expose $SAILBOX_ID 3000
```

See [Networking](/sailboxes-networking) for details on what the invocation means.

### 2. Point your domain at your target address

Every organization has its own target address under
`sailboxes.sailresearch.com`. Pointing your domain at it is what proves your
organization controls the domain. Find your target with:

```bash Command theme={null}
sail box domain target
# Output:
# CNAME target: 1a2b3c4d5e6f7890.sailboxes.sailresearch.com
# Wildcard certificate target: 1a2b3c4d5e6f7890._acme-challenge.sailboxes.sailresearch.com
```

Create a `CNAME` record with your DNS provider:

```
app.example.com  CNAME  1a2b3c4d5e6f7890.sailboxes.sailresearch.com
```

<AccordionGroup>
  <Accordion title="Use one certificate for many subdomains">
    Add two records before you attach the first domain:

    ```text theme={null}
    *.example.com                  CNAME  1a2b3c4d5e6f7890.sailboxes.sailresearch.com
    _acme-challenge.example.com    CNAME  1a2b3c4d5e6f7890._acme-challenge.sailboxes.sailresearch.com
    ```

    * The first record sends every direct subdomain to Sail.
    * The second record lets Sail create one wildcard certificate for them.
    * Attach each hostname to a Sailbox. Do not attach `*.example.com`.

    The certificate covers names such as `app.example.com` and `api.example.com`.
    It does not cover `api.dev.example.com`.

    If you do not add the second record, Sail creates a separate certificate for
    each attached hostname.
  </Accordion>

  <Accordion title="Root/apex domains like example.com">
    Standard CNAME records are not allowed for apex domains.
    Different DNS providers provide different solutions: look for an `ALIAS`,
    `ANAME`, or `CNAME` flattening option.

    | DNS provider     | Apex option                                                                                                       |
    | ---------------- | ----------------------------------------------------------------------------------------------------------------- |
    | Cloudflare       | CNAME, flattened at the apex automatically                                                                        |
    | Namecheap        | ALIAS                                                                                                             |
    | DNSimple         | ALIAS                                                                                                             |
    | DNS Made Easy    | ANAME                                                                                                             |
    | Porkbun          | ALIAS                                                                                                             |
    | Amazon Route 53  | None for external targets (ALIAS records reach AWS resources only). Serve on a subdomain such as `www` instead.   |
    | Azure DNS        | None for external targets (alias records reach Azure resources only). Serve on a subdomain such as `www` instead. |
    | Google Cloud DNS | None. Serve on a subdomain such as `www` instead.                                                                 |

    Sail also needs a TXT record for verification, because these options return
    the target's IP address instead of `<your-target>.sailboxes.sailresearch.com`:

    ```
    example.com                 <ALIAS/ANAME/CNAME>  <your-target>.sailboxes.sailresearch.com
    _sail-domains.example.com   TXT                  <your-target>.sailboxes.sailresearch.com
    ```
  </Accordion>

  <Accordion title="Common pitfalls with DNS" defaultOpen={true}>
    * Some DNS providers proxy or accelerate traffic for a record by default.
      Turn that off for this record. On Cloudflare, set the record to "DNS only"
      so the orange proxy cloud is off.
    * These records are your standing authorization: any record that names a
      target keeps authorizing that organization. If you switch organizations or
      stop using Sail, remove the old records.
  </Accordion>
</AccordionGroup>

### 3. Add the domain to your Sailbox

Attach the domain to the Sailbox and port. Sail checks that the DNS
record is in place, then starts serving the hostname:

```bash theme={null}
sail box domain attach $SAILBOX_ID app.example.com --port 3000
# Output:
# Attached app.example.com to sb_... on guest port 3000
# https://app.example.com
```

`--port` is required and must identify an exposed HTTP listener.

You can also do this in [Sailbox dashboard](https://app.sailresearch.com/sailboxes) under "Network Listeners."

## List and remove domains

```bash theme={null}
# List the domains attached to a Sailbox.
sail box domain list $SAILBOX_ID

# Detach one domain from it.
sail box domain detach $SAILBOX_ID app.example.com
```

Detaching a domain stops routing it to the Sailbox.

## Custom domains for TCP listeners

All the setup listed in this page is for HTTP listeners. If you have a raw TCP endpoint
that you wish to point a custom domain at, you do not need to register the domain with Sail.
Just add a DNS record:

```text theme={null}
foo.example.com CNAME t1.sail.box
```

Then dial `foo.example.com:<port of tcp listener>`.

## Notes

* A domain serves one Sailbox listener at a time, but one listener can have multiple domains
  (e.g., if you want both foo.example.com and bar.example.com to point to a Sailbox, then you can do that)
* An organization can attach up to 200 total domains. If your use case needs more than that, reach out to us.
* Without the second DNS record in step 2, each different subdomain gets its own certificate, issued through Let's Encrypt.
  Let's Encrypt allows 50 new certificates per apex domain every 7 days.
  That limit is global for your domain, not specific to Sail. Spread
  large batches of new hostnames under one domain over several days, or
  contact us if your use case requires large numbers of subdomains.
* Removing a listener also detaches all of the domains registered to it.
* It takes up to 1 minute for Sail to obtain a valid certificates for your domain. If you make a
  request during the first minute after attaching a domain, you may experience latency while the certificate
  is being obtained.
* All the regular features of Sailbox networking still work:
  * A request to a sleeping
    Sailbox wakes it. Terminating the Sailbox stops its serving to
    domains.
  * Plain HTTP requests to the domain redirect to HTTPS.
  * Listener allowlists keep working behind a custom domain.
* To move a domain to a different Sailbox, attach it to that Sailbox directly.
  There is no need to detach it first, so you can swap traffic to a new
  Sailbox in one call.

```bash theme={null}
# Attach a domain to a different box
sail box domain attach $OTHER_SAILBOX_ID app.example.com --port 3000
```
