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

# Custom domains

> Serve your services under your own zone instead of the platform domain.

By default a public service is served at `<service>.<platform-apps-domain>`, for example
`api.app.slipway.sh`. Claim a custom domain to serve under your own zone instead, such as
`api.acme.com`.

Domains are claimed and verified at the organization level, then referenced by name from a
project or a spec. Every plan includes unlimited custom domains.

## Claiming a domain

Open **Domains** in the sidebar and select **Add domain**, then enter the parent zone you
want to serve under, such as `acme.com` or `apps.acme.com`.

slipway gives you a CNAME target. Add it to your DNS provider as a wildcard record:

```
*.apps.acme.com   CNAME   <target-from-slipway>
```

Back in slipway, select **Verify**. slipway resolves the CNAME from the public internet to
confirm it points where it should.

Once verified, the domain is available to every project in the organization.

### Root domains

To serve at the root of a zone, such as `acme.com` itself, slipway gives you a single record
named `@` (your provider's name for the root) pointing at slipway's load balancer hostname.
DNS does not allow a plain CNAME at the root, so how you add it depends on the provider:

* **Cloudflare** has no ALIAS type. Add a `CNAME` named `@` with the target, set to
  **DNS only** (grey cloud); Cloudflare flattens a root CNAME automatically.
* **DNSimple, Namecheap, Porkbun, DNS Made Easy, NS1** — add it as an `ALIAS` or `ANAME`
  record.
* **Providers with neither** (GoDaddy; Route 53, whose ALIAS only targets AWS resources):
  serve the app on a subdomain such as `www` and redirect the root to it, or move the
  zone's DNS to a provider above.

A host **under** your domain served at itself, such as `app.acme.com`, is simpler: it is an
ordinary name in the `acme.com` zone, so slipway gives you a plain `CNAME` named `app`
pointing at the same target, which every provider supports. On Cloudflare, set it to
**DNS only**.

slipway does not hand out IP addresses for a root domain. The addresses behind the
hostname change when infrastructure is replaced, and a record pinned to them would stop
working without warning.

## Using it

**Console**

Open the project's **Settings → Domains** and pick a verified zone. Every public service
in the project is then served under it, with no spec change.

The dropdown lists only your organization's verified zones. Leave it on the default to
use the platform domain.

**slipway.yaml**

Set `domain:` on the service that has the public port.

```yaml slipway.yaml theme={"system"}
services:
  - name: web
    runtime: docker
    domain: apps.acme.com
    prefix: app
    ports:
      - port: 3000
        public: true
    healthCheckPath: /healthz
```

`domain` and `prefix` sit on the **service**, not inside a port entry. A spec that puts
them on a port fails to parse with a message saying so.

Precedence, highest first:

1. A service-level `domain:` in the spec.
2. The project's custom domain.
3. The platform apps domain.

Changing a project's domain advises a redeploy. Existing healthy deployments keep their
current URLs until they are redeployed onto the new zone.

## Choosing the subdomain

Under a verified zone you pick each service's subdomain, so an API can be served at a clean
`api.acme.com`.

Set it per public service on the project's **Settings → Domains**, or with `prefix:` in the
spec.

| Rule | Detail |
| - | - |
| Format | A single label, such as `api` or `dashboard`. It sits directly under the verified zone, so `api` becomes `api.acme.com`. |
| Uniqueness | Each label must be unique within a zone across your organization. Two services cannot both claim `api.acme.com`. |
| Default | Leave it blank and the service's name is used. |

A change takes effect on the next deploy, so the service shows a Stale badge until you
redeploy. Click the badge to see exactly which host would move.

`prefix` and `domain` both require a public surface. On a service with no port marked
`public: true`, they fail validation with `prefix/domain need a public hostname`.

## TLS

Certificates for every hostname are provisioned and renewed automatically. There is nothing
to install, rotate or monitor.

All traffic is served over HTTPS.

## Multiple domains

You can claim as many parent zones as you need. Different projects, or different services
in one project, can use different zones.

## Removing a domain

Removing a verified domain stops new deployments using it. It does not tear down
certificates or services already running on it. Tear down any healthy deployments still
using the domain first if you want a clean cut.

## Troubleshooting

**Verification fails.** The CNAME has not propagated yet, or it is not a wildcard. slipway
resolves the record from the public internet, so a record visible only inside your network
will not verify. Check with `dig '*.apps.acme.com' CNAME` from outside.

**The deploy fails with an unverified-domain error.** The `domain:` in the spec does not
match a verified zone for the organization. slipway will not issue a certificate for a zone
the organization has not proven it owns. Claim and verify the zone first.

**Two services want the same host.** Each label must be unique within a zone. slipway
records a `public_host_rejected` event naming the service and host. Give one of them a
different `prefix`.

**The URL resolves but returns 403.** That is your application rejecting the `Host` header,
not a DNS or certificate problem. See
[Troubleshooting a deploy](/deploys/troubleshooting#the-deploy-is-green-but-the-url-returns-403).

**A proxy sits in front.** If your DNS provider proxies the record, it must pass through
the original `Host` header and allow the CNAME target to answer ACME challenges, or
certificate renewal fails.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.