User guide
Custom Domains
Looking for what it does rather than how to use it? Read the Custom Domains overview .
This guide covers putting your own hostname in front of a Solidlio portal: how to add a domain, publish the DNS records that prove you own it, get a certificate issued, keep it live, and remove it. It also covers verified sending domains, which are a separate feature that uses similar DNS steps.
Audience: MSP administrators, organization administrators, and anyone supporting them.
What it is
A custom domain maps a hostname you control — portal.yourcompany.com — to one of your Solidlio portals, so your users never see a Solidlio address.
A custom domain is branding. Once it is live, the portal it serves carries your logo, colours and company name rather than Solidlio’s, resolved through the same Platform → MSP → Organization cascade the rest of your branding uses.
Concepts
| Concept | What it is |
|---|---|
| Custom domain | A hostname mapped to a portal, with its own provisioning state and DNS records. Stored in custom_domains. |
| Ownership token | A random secret issued when you add the domain. Publishing it as a TXT record is what proves you control the host. |
| Provisioning status | Where the domain is in its lifecycle — see section 4. |
| Organization pin | The organization the domain resolves to. A domain with no organization cannot resolve. |
| Failed checks | Consecutive failed re-verification sweeps. Three revokes the domain. |
| Verified sending domain | A separate claim over an email domain, used for email sending and domain-based auto-join. Stored in verified_email_domains. |
A custom portal domain and a verified sending domain are different records with different DNS names, managed on different screens. Claiming one does not claim the other.
Roles and permissions
Custom-domain management is an administrator capability. The gate is a set of roles, not a rank — MSP technician outranks organization administrator in the role hierarchy but is deliberately excluded, because managing a company’s public hostname is an administrative act rather than a technical one.
| Role | Manage custom domains | Manage sending domains |
|---|---|---|
| platform administrator | ● | ● |
| MSP administrator | ● | ● |
| MSP technician | — | — |
| organization administrator | ● | ● |
| power user | — | — |
CUSTOMER | — | — |
Anyone refused sees Administrator role required to manage custom domains.
Tenancy is enforced separately from role: every lookup is pinned to the calling account, so an administrator of one account cannot read, verify or delete another account’s domain even with a valid domain id.
The domain lifecycle
┌──────────────────────┐
add domain ───► │ PENDING_VERIFICATION │
└──────────┬───────────┘
both DNS records match
│
┌──────────▼───────────┐
│ DNS_VERIFIED │ ownership proven
└──────────┬───────────┘
provisioning job hands off
│
┌──────────▼───────────┐
│ AFD_PROVISIONING │ certificate being issued
└──────────┬───────────┘
certificate approved
│
┌──────────▼───────────┐
│ ACTIVE │ serving traffic
└──────────┬───────────┘
3 failed re-verification sweeps
or a provisioning failure
│
┌──────────▼───────────┐
│ ERROR │ ──── Retry ───► DNS_VERIFIED
└──────────────────────┘
remove ───► DEACTIVATING ───► DEACTIVATED (hostname becomes reclaimable)
| Status | What it means | What you do next |
|---|---|---|
PENDING_VERIFICATION | Added; DNS records not yet both present | Publish the records, press Verify DNS |
DNS_VERIFIED | Ownership proven; awaiting certificate | Wait; Provision SSL re-queues it |
AFD_PROVISIONING | Certificate being issued — the TXT value has changed | Republish the TXT with the new value |
ACTIVE | Live with TLS | Nothing; Re-check DNS on demand |
ERROR | Provisioning or re-verification failed | Fix DNS, press Retry |
DEACTIVATING | Removal in progress | Wait |
DEACTIVATED | Removed; hostname reclaimable | Add it again to start over |
Every status has an action or an explicit explanation in the UI. There is no state the interface leaves you stranded in.
Walkthrough — adding a custom portal domain
Where (MSP): MSP portal → Settings → Custom Domains Where (organization): Organization portal → Settings → Portal Domain
Both screens render the same manager; only the tab label and the default allowance differ.
-
Add the domain. Press Add Domain, enter the hostname (
portal.yourcompany.com) and press Add. Enter a hostname only — no scheme, no path, no port. Underscores are not valid in a hostname and are rejected. -
Copy the DNS records. The card expands to show two records. Each field has a copy button.
Type Name Value TXT _dnsauth.portal.yourcompany.comyour ownership token -
Publish them at your registrar. Both are required. Allow for propagation — most registrars are quick, but a long TTL on an existing record can delay things by hours.
-
Verify. Press Verify DNS. Solidlio checks both records. If either is missing or does not match, the domain stays
PENDING_VERIFICATIONand the response says which of the two failed. Press it again once DNS has caught up. -
The card tells you this and shows the new value. Update the TXT record at your registrar; the certificate will not be issued until you do.
The list refreshes itself every 30 seconds while any domain is in a transitional state, so you can leave the page open and watch it progress.
Walkthrough — removing and re-adding a domain
- Press the bin icon on the domain’s card and confirm.
- The row is kept for audit but disappears from the list.
- The hostname is now free. You — or anyone else — can add it again.
Re-adding issues a new ownership token. The new holder must prove control of the DNS themselves; the previous holder’s TXT record will not verify it.
A hostname that is still live under another account cannot be taken: the add is refused with domain_exists.
DNS records in detail
It is checked with an exact, case-insensitive match against the target shown on the card.
TXT at _dnsauth.<your host> — proves you control the hostname. The value is a random 24-byte token generated per domain record. It is not derived from your hostname and is not shared between tenants, so knowing the hostname does not let anyone else guess the proof.
Both must match. A CNAME alone is not accepted, on the interactive Verify DNS button or in the background job — the rule is the same on both paths.
If your DNS provider does not allow a CNAME at the record you need (some do not at a zone apex), use a subdomain such as portal. or support. rather than the bare domain.
Re-verification and revocation
Active domains are re-checked by the provisioning job, which runs every 5 minutes.
- A domain whose CNAME still matches has its failure counter reset.
- A domain whose record is definitively absent (
ENOTFOUND/ENODATA) has its failure counter incremented. - Three consecutive definitive failures revoke the domain: it moves to
ERROR,isVerifiedis cleared, andprovisioningErrorexplains what happened. - Transient DNS errors — timeouts, server failures, refused connections — are ignored entirely. A resolver blip never counts against a working domain.
To restore a revoked domain, republish the CNAME and press Retry.
You can force an immediate check on an active domain with Re-check DNS rather than waiting for the sweep.
Verified sending domains
Where: Settings → Email Domains (both the MSP and organization portals)
A verified sending domain is a claim over an email domain such as yourcompany.com. It is used for email sending and for domain-based auto-join, where a new user whose email address is at that domain is placed into your organization with a default role.
- Press Add domain and enter the email domain. Public providers (Gmail, Outlook, Yahoo, iCloud, Proton and around 50 others) are refused with
Public email provider domains cannot be claimed. - Publish the TXT record shown: name
_solidlio-verify.<your domain>, valuesolidlio-verify=<token>. - Press Verify. Unlike portal domains, a failed check here returns a 200 with
verified: falseand a message naming the exact problem — no record, or a record whose value does not match. - Set Default role to control what a user auto-joining through this domain receives:
CUSTOMER, power user or organization administrator.
Verified sending domains are re-checked daily at 04:00 UTC by the domain-reverification job, on the same three-strikes rule. Claims are capped by limits.maxSendingDomains on your plan.
Sender identity requirement
Verifying a custom domain is refused unless the entity it brands has a complete sender identity — legal name, physical address and contact details. This is the same CAN-SPAM/CASL rule applied to every other branding write, and it is checked before any DNS lookup so a refusal costs nothing.
The check is applied to the entity the domain actually brands:
- A domain pinned to an organization is checked against that organization’s identity.
- An account-level domain is checked against the account’s identity.
This matters in both directions. Checking the account for an org-scoped domain would let a domain verify and then have its branding silently dropped at render time; it would also refuse a compliant organization because of missing fields on a parent account whose branding it does not use.
If you are refused, complete the identity fields under Settings → Company for the entity named in the error.
Plan tiers
Custom domains are gated on the customDomains feature flag. The numeric allowance comes from your plan’s limits.maxCustomDomains where set; otherwise a tier that enables the flag gets a default of 5 for MSP partner plans and 1 for direct-customer plans. -1 means unlimited.
| Plan | Custom domains | Verified sending domains |
|---|---|---|
| MSP Free | — | 1 |
| MSP Starter | — | 2 |
| MSP Growth | — | 5 |
| MSP Scale | ● | 10 |
| MSP Enterprise | ● | unlimited |
| Customer Free | — | 1 |
| Customer Essentials | — | 1 |
| Customer Professional | — | 3 |
| Customer Business | ● | 5 |
| Customer Enterprise | ● | unlimited |
A managed client with no plan of its own inherits its managing MSP’s entitlement.
Where the plan does not include the feature, the Custom Domains panel says so plainly and the API returns a 403 carrying an upgrade offer rather than a bare refusal. Where the plan includes it but you have used your allowance, you get a cap message instead.
Two things are gated at different points:
Only ACTIVE domains consume the allowance on the activation path, so a limit-of-one account can always verify the one domain it has created.
The platform account carries no tier and is never plan-gated.
Troubleshooting
| Symptom / message | Cause | Fix |
|---|---|---|
Administrator role required to manage custom domains | Role is not one of platform administrator / MSP administrator / organization administrator | Use an administrator account. MSP technician is excluded by design. |
dns_not_verified with cnameVerified / txtVerified | One or both records missing or not matching | The flags say which. Check for typos and wait for propagation. |
domain_exists | The hostname is live under another account | Use a different hostname, or have the current holder remove it. |
Invalid domain format | Scheme, path, port or underscore in the value | Enter a bare hostname: portal.yourcompany.com. |
Custom domains are not included in your current plan… | The tier’s customDomains flag is off | Upgrade — the response carries the offer. |
tier_limit_reached | Plan includes the feature; the allowance is used | Remove an unused domain or upgrade. |
organization_not_in_account | The supplied organizationId belongs to another account | Omit it and let it default to your own organization. |
SENDER_IDENTITY_REQUIRED | Legal name, address or contact missing on the branded entity | Complete Settings → Company for the entity named in the error. |
Stuck at AFD_PROVISIONING | The TXT record still holds the old token | Republish the TXT with the value now shown on the card. |
Domain provisioning is in <status> state from /resolve | The domain is not ACTIVE yet | Finish the lifecycle. |
This domain is not associated with an organization | Legacy row created before domains were pinned to an organization | Remove and re-add it; new domains are pinned automatically. |
This domain is not yet verified | isVerified is false — never verified, or revoked by the sweep | Check provisioningError, restore DNS, press Retry. |
Public email provider domains cannot be claimed | Sending-domain claim on Gmail/Outlook/etc. | Claim a domain you control. |
This domain is already claimed by another organization | Sending-domain claims are globally unique | Contact support if you believe the claim is yours. |
Limits and known behaviour
-
The interface flags it at the moment it happens.
-
Ownership is proven and recorded, but nothing is served.
-
A domain must be pinned to an organization to resolve. New domains are pinned automatically to the caller’s organization. Rows created before this behaviour with a null organization cannot resolve and must be re-added.
-
Removal is a soft delete. The row is retained for audit as
DEACTIVATEDand the hostname is released for anyone to claim. -
Three strikes, definitive answers only. Transient DNS failures never count. Revocation needs three consecutive
ENOTFOUND/ENODATAresults. -
sslEnabledandredirectToHttpsare inert. Both columns exist oncustom_domainsand nothing reads them. TLS and HTTPS redirection are always on for an active domain; they are not configurable. -
No wildcard domains. Each hostname is a separate record.
-
No bulk import. Domains are added one at a time.
-
The customer portal cannot manage domains. There is no domain UI in the customer portal, by design.