Your own domain
Plugboard is designed to live on your domain, not ours. helpdesk.yourschool.org
is the normal case.
This matters beyond appearances. Staff trust a link on a domain they recognise, and a service desk sends a lot of links.
How a request finds its tenant
Section titled “How a request finds its tenant”A request is matched in this order:
- An explicit
x-tenant-slugheader, used by API clients and local development. - The
Hostheader against the tenant’sprimaryDomain. This is what makes a custom domain work. - The first label of the hostname, treated as a tenant slug
(
scots.plugboard.app). DEFAULT_TENANT_SLUG, for a single-tenant self-hosted install.
The host and the slug are offered to one lookup together rather than in sequence,
because a custom domain usually has no meaningful first label. “helpdesk” in
helpdesk.yourschool.org is a hostname label, not a tenant name.
Health and metrics endpoints skip all of this, so probes keep working when nothing else does.
Point DNS at the server
Section titled “Point DNS at the server”helpdesk.yourschool.org. A 203.0.113.10helpdesk.yourschool.org. AAAA 2001:db8::10Set the origin
Section titled “Set the origin”In .env, both must be the address people actually type:
PUBLIC_URL=https://helpdesk.yourschool.orgPUBLIC_HOST=helpdesk.yourschool.orgOn a source install the equivalent pair is:
API_URL="https://helpdesk.yourschool.org"WEB_URL="https://helpdesk.yourschool.org"PUBLIC_URL is the CORS allow-list, the base for every emailed link, the SSO
redirect target and the portal address. Setting it to an internal name produces
links your users cannot open.
Choose how TLS is terminated
Section titled “Choose how TLS is terminated”Covered in full in HTTPS and certificates. The short version:
| Situation | Approach |
|---|---|
| Publicly reachable, ports 80 and 443 open | Caddy with automatic Let’s Encrypt |
| School network you do not control | Cloudflare Tunnel, no inbound ports |
| You already own a wildcard | Point Caddy or nginx at it |
| Internal CA or AD Certificate Services | PEM or PKCS#12 straight on the application |
| You already run a reverse proxy | Start the stack with no ingress profile and proxy to it |
Internal-only deployments
Section titled “Internal-only deployments”If the desk should not be reachable from outside the school, use split-horizon DNS: the name resolves to a private address inside and to nothing outside. Use an internal CA or a DNS-01 Let’s Encrypt challenge, since HTTP-01 needs public reachability.
Remember ALLOW_PRIVATE_EGRESS=1 if you also want service monitors to check
addresses on your LAN. Plugboard blocks outbound requests to private ranges by
default so a tenant-supplied URL cannot be used to reach internal hosts.
Changing the domain later
Section titled “Changing the domain later”Supported, and there are three things to update together. Miss one and the symptom appears somewhere unrelated.
The configuration. PUBLIC_URL and PUBLIC_HOST, then restart.
Your identity provider. SSO redirect URIs are absolute. Add the new one before switching, keep both registered during the change, then remove the old one afterwards. Skipping this locks everyone out of SSO at the exact moment of cutover, which is the worst possible time.
Links already sent. Keep the old hostname resolving and redirecting for a while. Tickets contain tracking links people return to months later.
Apex domains
Section titled “Apex domains”yourschool.org with no subdomain needs a CNAME-flattening or ALIAS record,
which not every DNS provider offers. A subdomain is simpler, and schools almost
always want one anyway.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause |
|---|---|
Unknown tenant: helpdesk | primaryDomain is not set for your tenant, or does not match the Host header. It is compared lower-cased and without the port |
| CORS errors in the browser console | PUBLIC_URL does not match the address bar. Scheme and trailing slash both count |
| Emails link to the wrong host | PUBLIC_URL still points at the old origin, or the process was not restarted |
| SSO fails right after a domain change | The redirect URI at the identity provider is still the old one |
| Realtime updates arrive in bursts | A proxy is buffering /api/events/* |
| Certificate never issues | Port 80 unreachable, so the HTTP-01 challenge fails |