Self-hosting: SSO, SCIM, and updates
Single sign-on (OIDC)#
- In god mode, open Integrations → Auth provider and copy the redirect URI it shows (
<API_URL>/api/auth/oauth2/callback/oidc). - Create a confidential client at your provider with that redirect URI.
- Paste the discovery URL (
.../.well-known/openid-configuration), the client ID, and the client secret back into the page. Name the sign-in button and turn the provider on.
Credentials are stored in the database, not in .env, so enabling a provider needs no restart.
The registration mode under Authentication decides whether a first sign-in may create an account:
| Mode | Behavior |
|---|---|
open |
creates the account |
invite only |
needs a pending project invite |
closed |
refuses it — provision people with SCIM instead |
A sign-in whose address already has an account joins that account instead of creating a second one, but only if the provider reports the address as verified and the existing account has confirmed its own. Authentication → Trust addresses from sign-in providers drops both conditions — turn it on only where you control who can register at the provider, since anyone who registers an address there would take over the account that holds it here.
Once a provider works, you can turn off Authentication → Email and password. Sign-in/sign-up forms and password reset are then hidden and refused, and the provider becomes the only way in — the switch stays disabled until a provider is configured, so an instance can't be left with no way in. Passkeys keep working since they can only be added to an account that already exists.
SCIM provisioning#
An identity provider can create, update, and deactivate accounts over SCIM 2.0, and grant project access through its groups.
- In god mode, open Integrations → SCIM, generate a token (shown once), and turn provisioning on.
- Point your provider's SCIM application at
<API_URL>/scim/v2, authenticating withAuthorization: Bearer <token>. - Push users, and groups if you use them.
Deactivating someone at the provider (active: false) ends their sessions and refuses their API keys; reactivating restores them with their projects intact. The instance owner's account is outside SCIM's reach.
A pushed group grants nothing until you map it: open the group under Integrations → SCIM, add the projects its members should join, and the role they join on. Removing a project from that list removes the memberships the group granted. A membership from an invite is never touched by sync; one the sync created can't be edited from the project's members page — it changes at the identity provider.
Updating#
git pull
docker compose pull
docker compose up -dThe api applies migrations automatically on startup. Before applying anything it dumps the database into the db-backups volume (/backups in the api container) and refuses to start if the dump fails. Dumps are deleted after 30 days by default (BACKUP_RETENTION_DAYS changes the window); SKIP_PRE_MIGRATION_BACKUP=1 skips the dump for operators who back up another way.
Attachments live in RustFS. An instance set up with MinIO switches over automatically on the next docker compose up -d — nothing is copied, and files stay readable. Back up the volume first if you want a copy:
docker run --rm -v itsaplan_minio-data:/data -v "$PWD":/out alpine tar czf /out/minio-data.tgz -C /data .The project is under active development — check the changelog for API path changes before upgrading an instance that scripts or an MCP client depend on.