One subdomain per tenant
A multi-tenant product usually gives each tenant an address of its own: acme.example.com, globex.example.com, and for some tenants a domain they own, portal.acme.com. One ComputeSphere service can serve all of them. There are two ways to set it up, and most products end up using both.
| A wildcard domain | One domain per tenant | |
|---|---|---|
| What you add | *.example.com, once | Each tenant's hostname, when the tenant is created |
| Good for | Tenants on subdomains of your own domain | Tenants on domains they own |
| DNS work per new tenant | None | None for a subdomain of your own domain, if one wildcard record already points it here; one record at the tenant's DNS host for a domain they own |
| Certificate | One, issued and renewed for you | One per hostname, issued and renewed for you |
| Set up from | Console, CLI or API | API or CLI, from your own code |
A wildcard domain
Add *.example.com to the service (or the environment) once, create its DNS records, and every subdomain reaches the service from then on. A new tenant needs nothing from ComputeSphere: your app decides which subdomains exist.
The steps, the records and the limits are on the Custom domains page.
One domain per tenant
When a tenant brings a domain of their own, add each tenant's hostname as its own custom domain on the same service. Do it from your own code when the tenant is created:
csph deployments domains add portal.acme.com --deployment <id>
csph deployments domains list --deployment <id> -o json
The response carries the DNS record the tenant has to create (a CNAME to your service address) and the domain's status. Show the record to the tenant in your own product, and poll the status until it is live.
For tenants on subdomains of your own domain you can use this way too: point *.example.com at your service address with a single record in your DNS, then add each tenant's hostname as it is created. Nothing more is needed in DNS per tenant, and each hostname gets its own certificate, usually a few minutes after the last record is visible.
Remove the hostname the same way when a tenant leaves, so the name stops being served.
What your app receives
Whichever way a request arrives, your app sees the address the visitor typed:
| Header | Value |
|---|---|
Host | The tenant's exact hostname: acme.example.com, portal.acme.com |
Choose the tenant from Host. A short example:
// Express
app.use((req, res, next) => {
const host = req.hostname.toLowerCase(); // acme.example.com
const tenant = host.endsWith(".example.com")
? host.slice(0, -".example.com".length) // "acme"
: lookupTenantByDomain(host); // portal.acme.com → "acme"
if (!tenant) return res.status(404).send("Unknown address");
req.tenant = tenant;
next();
});
Treat the hostname as untrusted input: with a wildcard, any subdomain reaches your app, including ones no tenant owns. Answer names you don't know with a 404, and never build a file path or a query from the raw hostname.
Limits
- A wildcard covers one level.
*.example.comservesacme.example.com, noteu.acme.example.com. - Records must be DNS only at Cloudflare. Proxied, the certificate can't be issued and subdomains won't be served. Every record that points at ComputeSphere is DNS only.
- A tenant's own domain needs a record from the tenant. ComputeSphere can't create records in someone else's DNS; your product has to show the tenant what to add.
- A new hostname isn't instant. It's usually live a few minutes after the last record is visible.
- An account can have 50 custom domains. One domain per tenant counts each hostname; a wildcard counts as one. Contact us to increase quota.
What's next
- Custom domains — records, status and SSL for any domain.
- Cloudflare — the same, when your DNS is at Cloudflare.
- csph deployments domains — adding and listing domains from the CLI.