Portal address
By default a portal opens at /p/{address} on the Console host. An operator can give portals a host of their own instead, for example https://acme.portal.example.com/hr-desk. Nothing changes unless one of the settings below is set.
Enterprise module
Portals are part of the enterprise edition. See Licensing.
This page is for the operators who install Console. Administrators who create portals only see the result: the link in the portal list, the link preview and the Open action all use the new address.
Choose a mode
| Mode | Settings | Portals open at |
|---|---|---|
| Wildcard | PORTAL_BASE_DOMAIN=portal.example.com | https://{workspace slug}.portal.example.com/{portal address}, one host per workspace |
| Fixed host | PORTAL_HOST=assistant.example.com and, optionally, PORTAL_HOST_TENANT={workspace slug} | https://assistant.example.com/{portal address}, for one workspace |
The host's root page / is a portal chooser. A person with exactly one portal goes straight into it; with none, they see a note to ask their administrator.
With a fixed host, PORTAL_HOST_TENANT names the workspace the host serves (compared without case). Leave it empty and the host serves the workspace of the person's own session, the way /p does. Choose one mode per installation.
The settings are trimmed and lower-cased. A leading *. is accepted (*.portal.example.com means portal.example.com). They are listed with the other variables in Configuration.
Rules and boot errors
| Rule | Message |
|---|---|
| At most 253 characters | PORTAL_BASE_DOMAIN is longer than 253 characters. |
| At least two labels | PORTAL_BASE_DOMAIN must have at least two labels (e.g. portal.example.com). |
| Host name only: letters, digits and hyphens per label; no scheme, port or path | PORTAL_BASE_DOMAIN must be a host name only: letters, digits and hyphens per label, no scheme, port or path. |
Must not contain the Console host (from APP_URL) | PORTAL_BASE_DOMAIN must not contain the Console host (<host>, from APP_URL). Use a domain of its own, e.g. portal.<base>. |
| Must not be the Console host | PORTAL_HOST must not be the Console host (APP_URL): portals need a host of their own. |
| A tenant needs a host | PORTAL_HOST_TENANT is set without PORTAL_HOST. |
PORTAL_HOST follows the same length, label and host-name rules, with its own name in the message. Each error is logged as Config error: {KEY} - {message}. With NODE_ENV=production Console then refuses to start: "{N} config validation error(s): {KEYS}. Refusing to start in production - fix the reported keys." Outside production it only warns and starts.
For example, with APP_URL=https://console.example.com, a base of example.com fails because it contains the Console host, and portal.example.com works.
The addresses people get
Portal links use the scheme and port of APP_URL, so production needs an https APP_URL.
- Wildcard: the workspace's slug is the first label. The slug is made from the company name when the workspace is created: lower-case, every run of characters other than
a-zand0-9becomes one hyphen. Letters outside ASCII are not transliterated, they are dropped ("Acme Çay" becomesacme-ay), so the slug can differ from the company name. A slug must be a valid DNS label (up to 63 characters) to get a portal host; otherwise that workspace's portals stay at/p/{address}on the Console host. - Portal address: the portal's own address (3 to 48 characters) is the path, in lower case.
Old links keep working. On the Console host, /p and /p/{address} send a signed-in person on to the portal host, with the query string kept, so deep links still work. The exception is an administrator's Open as test session, which stays on /p/{address} on the Console host. On a portal host, /p and /p/{address} redirect to / and /{address}.
Signing in and out
People sign in on the Console host, exactly as before. Password, LDAP and SSO are unchanged, so identity providers need no new redirect URI.
- A person opens the portal host without a session and is sent to Console's sign-in page.
- After signing in (or straight away when already signed in) they come back to the portal host with a single-use code that is valid for 60 seconds.
- The portal host stores its own session cookie and takes them to the page they asked for, deep-link query included.
Things to know:
- Each workspace host has its own session. Signing in at one portal host does not sign the person in at another.
- A person who is signed in to Console on a different workspace is asked to sign in again for this one.
- A disabled account loses access immediately, without waiting for the session to expire.
- The session lasts as long as a Console session (
JWT_EXPIRES_IN), capped at 7 days. - Sign out on the portal host also ends the person's Console session. Signing out of Console does not end a portal session.
- The portal host never accepts the Console cookie, and Console never accepts the portal cookie.
What a portal host serves
| Path | Answer |
|---|---|
/ and /{address} | The portal chooser and the portal chat. |
/api/portal/* | The portal chat API. |
/api/portal-host/* | Sign-in and sign-out. |
| Any other page | Plain "Not found". |
Any other /api/* and all of /api-embed/* | 404 route_not_found, whatever credentials are sent. |
The embedded chat is not affected. It stays on the Console host and keeps working as before.
Infrastructure checklist
| Item | What to do |
|---|---|
| DNS | Wildcard mode: a record for *.portal.example.com that points to the same load balancer as Console. Fixed mode: one record for PORTAL_HOST. Without it, the browser shows a "site cannot be reached" error after the redirect and Console cannot tell. |
| Certificate | Wildcard mode: a certificate for *.portal.example.com. It covers one label only, so not portal.example.com itself or a.b.portal.example.com. Your Console certificate alone does not cover it. |
| HTTPS | Required in production. Portal cookies are Secure with the __Host- prefix, and browsers drop them over plain HTTP. |
| Proxy | Must pass Host or X-Forwarded-Host unchanged. If the proxy rewrites it to the Console host, the portal host is not recognised. Also pass WebSocket and streaming traffic as for Console. |
APP_URL | Must be the real public Console address, with the right scheme and port. |
| Environment | Set the variables on the Console container. In the Helm charts, add them to the env: map in your values. |
Helm ingress
The Kubernetes Ingress in the on-prem charts takes a list of hosts and one certificate setting:
ingress.hostslists one rule per host. Add the Console host and also"*.portal.example.com"(or the fixed host).ingress.tlsmust be a map (enabled,secretName). With the defaulttls: [], an enabled ingress fails to render (can't evaluate field enabled), so always setingress.tls.enabledexplicitly.- The TLS block lists only
ingress.host, a single host name. Use a secret whose certificate covers both the Console host and the portal hosts (a SAN or wildcard certificate), or add a second Ingress for the portal hosts. Check it in a browser after install.
ingress:
enabled: true
host: console.example.com
hosts:
- console.example.com
- "*.portal.example.com"
tls:
enabled: true
secretName: console-and-portal-tls
env:
APP_URL: "https://console.example.com"
PORTAL_BASE_DOMAIN: "portal.example.com"Troubleshooting
| Symptom | Likely cause |
|---|---|
Console does not start and names PORTAL_BASE_DOMAIN or PORTAL_HOST | A rule above failed. Read the Config error: lines in the log. |
| The browser says the site cannot be reached after opening a portal | The DNS record is missing. |
| Certificate warning on the portal host | The certificate does not cover {slug}.{base}. |
| A web-server or ingress 404 page, not Console's | The host is not routed to Console. Add it to ingress.hosts or your proxy rules. |
Portal host behaves like Console (shows /login) | The proxy rewrites Host. Pass it through. |
| "There are no portals at this address." | The first label is not an existing workspace slug, or PORTAL_HOST_TENANT names one that does not exist. |
| "This account cannot open the portals at this address." | The person belongs to a different workspace than the host serves. |
| "This sign-in was started in another window or has expired." | The browser dropped the cookie (plain HTTP in production, cookies blocked or cleared), or sign-in was started in another browser. |
| "This sign-in link has expired." or "...already used." | More than 60 seconds passed, or the link was opened twice. Press Try again. |
| Links go to the wrong scheme or port | APP_URL is wrong. |
A workspace's portals still open at /p/... | Its slug is not a valid DNS label (over 63 characters), or no setting is configured. |
See also Portals troubleshooting.

