Skip to main content

Custom domains

Every Serverpod Cloud project gets default domains automatically. A project named my-app is reachable at:

ServiceDefault domain
Webhttps://my-app.serverpod.space/
APIhttps://my-app.api.serverpod.space/
Insightshttps://my-app.insights.serverpod.space/

Custom domains let you replace any of those with your own URL. Serverpod Cloud provisions and renews TLS certificates automatically; the only setup required is a DNS record and a verification step.

Attach a custom domain

A custom domain points at one of the three surfaces:

  • web: a Flutter web app or other content served by Serverpod's web server
  • api: Serverpod endpoints your Flutter app or other clients call
  • insights: the Serverpod Insights app (typically on a separate subdomain like insights.example.com)

Attach the domain to your project, specifying the target surface:

scloud domain attach example.com --target web

After attaching, the CLI prints DNS records to add at your registrar. For an apex domain like example.com, two records are needed:

Custom domain attached successfully!

Complete the setup by adding the records to your DNS configuration

┌────────────────────────────────────────────────────────────────────────────────┐
│ Record type | Domain name | Value │
│ ------------+-------------+--------------------------------------------------- │
│ ANAME | example.com | my-app.api.serverpod.space │
│ TXT | example.com | scloud-verify=cbe1f5cc-f176-4183-8142-e0585ad15999 │
│ │
└────────────────────────────────────────────────────────────────────────────────┘

Each row corresponds to one record to add at your registrar:

  • ANAME (or ALIAS): points the domain at the Serverpod Cloud surface
  • TXT: carries a verification token that Serverpod Cloud uses to confirm ownership

Plain CNAMEs aren't valid at the zone apex, which is why ANAME or ALIAS is required there. Cloudflare, Route 53, and DNSimple all support ANAME or ALIAS records.

For a subdomain like api.example.com, a single CNAME record is enough:

Custom domain attached successfully!

Complete the setup by adding the records to your DNS configuration

┌────────────────────────────────────────────────────────────┐
│ Record type | Domain name | Value │
│ ------------+-----------------+--------------------------- │
│ CNAME | api.example.com | my-app.api.serverpod.space │
│ │
└────────────────────────────────────────────────────────────┘

Verify the domain

DNS changes typically propagate within a few minutes but can take up to 48 hours. Once propagation completes, Serverpod Cloud verifies the domain automatically.

To force a verification attempt without waiting:

scloud domain verify example.com

A successful verification triggers TLS certificate provisioning, which usually completes within the hour. Certificates are renewed automatically.

Once the domain is active, point your client at the new URL:

final client = Client('https://api.example.com');

List custom domains

Show the domains attached to a project, with their target surface and verification status:

scloud domain list

Detach a custom domain

Remove a custom domain from a project. The CLI prompts for confirmation before removing:

scloud domain detach example.com

Troubleshooting

Verification fails. DNS records may be missing or still propagating. Confirm the records are in place at your registrar, then wait up to 48 hours and retry with scloud domain verify <domain>.

Can't attach the domain. The domain is already attached to another project. Detach it from that project first.

TLS certificate errors. TLS provisioning is still in progress. It usually completes within an hour of successful verification.