Provision a tenant
Create a new organization on a running deployment and hand it to its first admin. (“Tenant” and “organization” are the same thing seen from two sides — Glossary.)
Before you start:
- Your OIDC
subis listed inKAIROS_DEPLOYMENT_ADMINS(Helm:config.deploymentAdmins). With that variable empty, the admin routes return 403 to everyone, including you. - The intended initial organization admin has logged in at least once. Users are
provisioned just-in-time at first login, so a
subthat has never authenticated does not exist yet and provisioning is refused. - You are logged in:
kairos login --url https://<host>. With a local account, add--email <your-email>. A local account is a deployment admin aslocal:<email>.
1. Confirm you hold the deployment-admin routes
Section titled “1. Confirm you hold the deployment-admin routes”kairos admin tenants listA list — even an empty one — means the routes are open to you. A 403 means your
sub is not in KAIROS_DEPLOYMENT_ADMINS; fix that first, since nothing below
will work.
2. Create the tenant
Section titled “2. Create the tenant”kairos admin tenants create --slug acme --name "Acme Inc"Or, to name a different initial admin than yourself:
kairos admin tenants create --slug acme --name "Acme Inc" \ --initial-admin <their-oidc-sub>The slug must match ^[a-z][a-z0-9_-]{1,62}$ and is permanent — it is the
schema name and, under subdomain tenancy, the hostname. The response reports
what was built: the org_acme schema, the tenant migrations applied in it, the
default boards, and the templates and metadata definitions copied in. It all
happens in one transaction, so a failed create leaves nothing behind and is safe
to retry.
Three refusals, and what to do about each (Errors has the codes):
| Response | Do |
|---|---|
409 |
The slug is taken, and slugs are not reused. Choose another. |
422, naming the slug |
Make the slug match the pattern above. |
422, naming an external_id |
Have the initial admin authenticate once, then retry. |
The same operation is available as
POST /api/admin/tenants,
and —
where you have shell access to the deployment rather than a token — as a server
subcommand:
kubectl exec deploy/kairos -- kairos-server create-tenant --slug acme --name "Acme Inc"The subcommand provisions the schema but seeds no org-admin membership. Use
it for a local or dev stack (angreal db create-tenant --slug acme wraps it),
not to hand a tenant to someone.
3. Reach the tenant
Section titled “3. Reach the tenant”How a request resolves to acme depends on how the deployment was configured —
see Configuration → Tenant resolution:
-
KAIROS_BASE_DOMAINset: browsehttps://acme.<base-domain>. Confirm wildcard DNS resolves and the certificate covers the new host before handing the URL over. -
KAIROS_SINGLE_TENANTset: that one tenant is pinned and subdomain and header resolution are skipped entirely. A second tenant provisioned on such a deployment is unreachable until the variable changes. You do not have to provision the pinned tenant. The first deployment admin to log in creates it and is its first admin.KAIROS_SINGLE_TENANT_NAMEgives its name.To let your staff join with no admin step, set
KAIROS_AUTO_JOIN_DOMAINSto the domain of their email. Each person then joins as a member when they first sign in. -
Neither set: only the
X-Tenant: acmeheader resolves a tenant. The CLI sends it for you when you pass--tenant acmetokairos login.
Verify as the new organization admin:
kairos login --url https://<host> --tenant acme # local account: add --email <email>kairos whoami # org: acme (admin)kairos boards list # the default boards4. Add its members
Section titled “4. Add its members”Any of three, and they compose:
- SCIM push from the issuer — the option that keeps joiners and leavers correct without anyone remembering. See SCIM.
kairos members add --email …— explicit, by the organization admin. The person must have logged in at least once, same as the initial admin in step 2.- Just-in-time at first login — anyone your issuer authenticates becomes a member on arrival. Adequate for a small organization, and the reason the initial admin had to log in before step 2.
From here the organization shapes its own boards and teams: Set up a board.
Removing a tenant
Section titled “Removing a tenant”kairos admin tenants delete acme --confirmThis drops the org_acme schema CASCADE and the organization row. It is
unrecoverable, and --confirm (?confirm=true on the API) is required —
without it you get a 422 CONFIRMATION_REQUIRED rather than a deletion. Take a
dump first: Back up and restore.
Related
Section titled “Related”- CLI → Deployment administration
- Configuration
- Install with Helm
- Teams and boards — what the default boards are for