Multi-tenant onboarding¶
You will create a second tenant on an Ampora server, scope an OIDC group to it, and walk a brand-new operator through their first login. The two tenants share nothing at the data layer beyond the database itself — PostgreSQL Row-Level Security keeps every query honest.
Time: ~ 20 minutes.
When to do this¶
- You operate Ampora on behalf of multiple internal teams (each is a tenant), or
- you offer Ampora as a service to multiple external customers, or
- you run staging and production on the same server (each is a tenant).
If you only ever have one team / project / environment, stay single-tenant — it is simpler and equally supported.
Prerequisites¶
- Admin access to your OIDC provider (Keycloak, Okta, AzureAD, …).
- Admin access to Ampora (in the primary tenant).
- Database has Row-Level Security enabled (ADR-036) — set
MultiTenant:Mode = HardIsolationin your config. See Operator → Configuration → Settings.
1. Create the tenant¶
In Ampora, Settings → Tenants → New tenant:
- Name:
acme-eu(used in URLs, must be DNS-safe). - Display name:
ACME Europe. - Description: optional.
- Theme: pick a primary colour and optionally upload a logo. The tenant-specific theme is applied for users scoped to this tenant.
Click Create. The tenant has its own UUID; rows owned by it carry TenantId = <that UUID>.
2. Map an OIDC group to the tenant¶
Tenants are selected by OIDC claims. The default mapping is tenant from the ID token, but you can map by any claim or any group membership.
In Ampora, Settings → Tenants → acme-eu → Identity mapping:
- Discriminator claim:
groups(ortenant, or any custom claim). - Match values:
acme-eu-admins,acme-eu-operators,acme-eu-viewers. - Role mapping:
acme-eu-admins→Adminacme-eu-operators→Operatoracme-eu-viewers→Viewer
In your OIDC provider, create the three groups and add the relevant users to them.
3. Issue a tenant-scoped certificate (optional but recommended)¶
If you have hard isolation enabled, you can also bind agents to a tenant by bootstrap-token-pool: a pool issues tokens that all share the same tenant scope (ADR-040).
In Ampora, Settings → Tokens → Pools → New pool:
- Name:
acme-eu-edge. - Tenant:
acme-eu. - Default group (optional): a group new agents will land in.
- TTL: how long each issued token is valid.
The pool exposes an admin endpoint to issue tokens. Hand the endpoint URL + pool secret to whoever automates agent rollout for that tenant.
4. Verify tenant isolation¶
Log out, log back in as a user in acme-eu-admins. You should see:
- only the configurations belonging to
acme-eu(none yet — fresh tenant), - only the agents bound to
acme-eu, - the
ACME Europebrand on the login wall and in the top-left logo, - the tenant name in the user menu.
Switch back to a primary-tenant Admin. You should see your own tenant's data, with no leak from acme-eu.
The most reassuring check is at the database layer:
returns the count for the current tenant only, even though the table contains all tenants' rows. RLS makes this true at the storage layer, not just in the application.
5. Onboard your first tenant operator¶
Send your tenant's first Admin a welcome email with:
- The Ampora URL.
- Their OIDC username (or instructions to enrol).
- The User Manual link.
- A sample bootstrap token from the pool you created in step 3, so they can connect their first agent without bothering you.
That is it. From here the new tenant runs independently of the primary tenant. Configurations, rollouts, groups, audit logs, lint rules and policies are all per-tenant.
What you learned¶
- How to create a tenant and map OIDC claims to its roles.
- How RLS guarantees isolation at the database layer.
- How bootstrap-token pools simplify per-tenant agent rollout.
- The minimum welcome packet for a new tenant operator.
Next¶
- Tighten the tenant theme: User → Tenant settings.
- Move single-tenant data into a tenant if you started without isolation: Operator → Operations → Multi-tenant migration.
- Federate tenants across regions: Federate two clusters.