|
| 1 | +--- |
| 2 | +title: Self-hosted Enterprise |
| 3 | +description: Run the full enterprise feature set on a self-hosted deployment without billing |
| 4 | +--- |
| 5 | + |
| 6 | +import { Callout } from 'fumadocs-ui/components/callout' |
| 7 | +import { Step, Steps } from 'fumadocs-ui/components/steps' |
| 8 | +import { Tab, Tabs } from 'fumadocs-ui/components/tabs' |
| 9 | + |
| 10 | +On Sim Cloud, enterprise features are unlocked by an Enterprise subscription. Self-hosted deployments have no subscription, so they are unlocked by environment configuration instead. |
| 11 | + |
| 12 | +There are two parts to getting this right, and skipping the second is the most common reason features appear to do nothing: |
| 13 | + |
| 14 | +1. **Enable the features** with `ENTERPRISE_ENABLED`. |
| 15 | +2. **Give them an organization to apply to.** Whitelabeling, PII redaction, permission groups, data drains, and audit scoping all read their settings from the organization that owns a workspace. A deployment where everyone works in personal workspaces has no organization for those settings to come from. |
| 16 | + |
| 17 | +## Enable the feature set |
| 18 | + |
| 19 | +Set the master switch and its client twin. Both are required — the server value decides access, and the `NEXT_PUBLIC_` value decides what the settings UI shows. |
| 20 | + |
| 21 | +```bash |
| 22 | +ENTERPRISE_ENABLED=true |
| 23 | +NEXT_PUBLIC_ENTERPRISE_ENABLED=true |
| 24 | +``` |
| 25 | + |
| 26 | +That turns on organizations, permission groups, SSO, whitelabeling, audit logs, session policies, data retention, data drains, workspace forks, and the inbox. |
| 27 | + |
| 28 | +### Turning one feature off |
| 29 | + |
| 30 | +Every feature keeps its own flag, and an explicitly set flag always wins over the master switch. To run the suite without data drains: |
| 31 | + |
| 32 | +```bash |
| 33 | +ENTERPRISE_ENABLED=true |
| 34 | +NEXT_PUBLIC_ENTERPRISE_ENABLED=true |
| 35 | +DATA_DRAINS_ENABLED=false |
| 36 | +NEXT_PUBLIC_DATA_DRAINS_ENABLED=false |
| 37 | +``` |
| 38 | + |
| 39 | +The individual flags also work on their own if you would rather opt in one at a time and leave the master switch unset. |
| 40 | + |
| 41 | +| Feature | Server variable | Client variable | |
| 42 | +|---------|-----------------|-----------------| |
| 43 | +| Everything below | `ENTERPRISE_ENABLED` | `NEXT_PUBLIC_ENTERPRISE_ENABLED` | |
| 44 | +| Organizations | `ORGANIZATIONS_ENABLED` | `NEXT_PUBLIC_ORGANIZATIONS_ENABLED` | |
| 45 | +| Permission groups | `ACCESS_CONTROL_ENABLED` | `NEXT_PUBLIC_ACCESS_CONTROL_ENABLED` | |
| 46 | +| SAML and OIDC sign-in | `SSO_ENABLED` | `NEXT_PUBLIC_SSO_ENABLED` | |
| 47 | +| Custom branding | `WHITELABELING_ENABLED` | `NEXT_PUBLIC_WHITELABELING_ENABLED` | |
| 48 | +| Audit logs | `AUDIT_LOGS_ENABLED` | `NEXT_PUBLIC_AUDIT_LOGS_ENABLED` | |
| 49 | +| Session policies | `SESSION_POLICIES_ENABLED` | `NEXT_PUBLIC_SESSION_POLICIES_ENABLED` | |
| 50 | +| Data retention deletion | `DATA_RETENTION_ENABLED` | `NEXT_PUBLIC_DATA_RETENTION_ENABLED` | |
| 51 | +| Data drains | `DATA_DRAINS_ENABLED` | `NEXT_PUBLIC_DATA_DRAINS_ENABLED` | |
| 52 | +| Workspace forks | `FORKING_ENABLED` | — | |
| 53 | +| Sim Mailer inbox | `INBOX_ENABLED` | `NEXT_PUBLIC_INBOX_ENABLED` | |
| 54 | + |
| 55 | +<Callout type="warning"> |
| 56 | + Data retention is the one feature that deletes data. Its flag controls the cleanup pass, not the settings screen — retention windows are always configurable. Nothing is ever deleted until you enable it, and even then only against windows you configured explicitly. Sim never applies the hosted plan defaults to a self-hosted deployment. |
| 57 | +</Callout> |
| 58 | + |
| 59 | +## Choose an organization model |
| 60 | + |
| 61 | +### Pattern 1: one organization for the whole instance |
| 62 | + |
| 63 | +Best when everyone on the deployment belongs to the same company. Set a name and every user joins that organization automatically at signup, with their workspaces created org-owned. |
| 64 | + |
| 65 | +```bash |
| 66 | +INSTANCE_ORG_NAME="Acme Inc" |
| 67 | +``` |
| 68 | + |
| 69 | +Optionally pin the slug and the owner: |
| 70 | + |
| 71 | +```bash |
| 72 | +INSTANCE_ORG_SLUG=acme-inc |
| 73 | +INSTANCE_ORG_OWNER_EMAIL=admin@acme.com |
| 74 | +``` |
| 75 | + |
| 76 | +The organization is created the first time a user signs up. If `INSTANCE_ORG_OWNER_EMAIL` is not set, or names a user who does not exist yet, the first user to sign up becomes the owner; move ownership later with the Admin API. Provisioning is idempotent and safe across multiple replicas. |
| 77 | + |
| 78 | +<Callout type="info"> |
| 79 | + Instance-organization mode only applies when billing is disabled. With billing enabled, organizations are created through the normal subscription flow and these variables are ignored. |
| 80 | +</Callout> |
| 81 | + |
| 82 | +#### Existing deployments |
| 83 | + |
| 84 | +Users and workspaces created before you set `INSTANCE_ORG_NAME` stay where they are. Move them across once with the backfill script, which adds every user to the organization and attaches their workspaces: |
| 85 | + |
| 86 | +```bash |
| 87 | +# Preview |
| 88 | +DATABASE_URL=... INSTANCE_ORG_NAME="Acme Inc" \ |
| 89 | + bun run apps/sim/scripts/consolidate-users-into-organization.ts |
| 90 | + |
| 91 | +# Apply |
| 92 | +DATABASE_URL=... INSTANCE_ORG_NAME="Acme Inc" \ |
| 93 | + bun run apps/sim/scripts/consolidate-users-into-organization.ts --apply |
| 94 | +``` |
| 95 | + |
| 96 | +It is a dry run unless you pass `--apply`, and it is safe to re-run. Users who already belong to a different organization are reported and skipped, since a user can only belong to one. |
| 97 | + |
| 98 | +### Pattern 2: many organizations you manage yourself |
| 99 | + |
| 100 | +Best when one deployment serves several teams that should not see each other's data. Leave `INSTANCE_ORG_NAME` unset and provision organizations through the Admin API. |
| 101 | + |
| 102 | +Set an admin key first: |
| 103 | + |
| 104 | +```bash |
| 105 | +ADMIN_API_KEY=$(openssl rand -hex 32) |
| 106 | +``` |
| 107 | + |
| 108 | +<Steps> |
| 109 | +<Step> |
| 110 | +### Create an organization |
| 111 | + |
| 112 | +The owner must not already belong to another organization. |
| 113 | + |
| 114 | +```bash |
| 115 | +curl -X POST https://sim.example.com/api/v1/admin/organizations \ |
| 116 | + -H "x-admin-key: $ADMIN_API_KEY" \ |
| 117 | + -H "Content-Type: application/json" \ |
| 118 | + -d '{"name": "Acme Inc", "ownerId": "user_123", "slug": "acme-inc"}' |
| 119 | +``` |
| 120 | +</Step> |
| 121 | + |
| 122 | +<Step> |
| 123 | +### Add members |
| 124 | + |
| 125 | +```bash |
| 126 | +curl -X POST https://sim.example.com/api/v1/admin/organizations/$ORG_ID/members \ |
| 127 | + -H "x-admin-key: $ADMIN_API_KEY" \ |
| 128 | + -H "Content-Type: application/json" \ |
| 129 | + -d '{"userId": "user_456", "role": "member"}' |
| 130 | +``` |
| 131 | +</Step> |
| 132 | + |
| 133 | +<Step> |
| 134 | +### Move a workspace into the organization |
| 135 | + |
| 136 | +Organization-scoped features only apply to workspaces the organization owns. |
| 137 | + |
| 138 | +```bash |
| 139 | +curl -X POST https://sim.example.com/api/v1/admin/dashboard/workspaces/$WORKSPACE_ID/move \ |
| 140 | + -H "x-admin-key: $ADMIN_API_KEY" \ |
| 141 | + -H "Content-Type: application/json" \ |
| 142 | + -d "{\"destinationOrganizationId\": \"$ORG_ID\"}" |
| 143 | +``` |
| 144 | +</Step> |
| 145 | + |
| 146 | +<Step> |
| 147 | +### Configure organization settings |
| 148 | + |
| 149 | +Branding, retention, and session policies can be set from the API instead of the UI. |
| 150 | + |
| 151 | +<Tabs items={['Whitelabel', 'Data retention', 'Session policy']}> |
| 152 | +<Tab value="Whitelabel"> |
| 153 | +```bash |
| 154 | +curl -X PATCH https://sim.example.com/api/v1/admin/organizations/$ORG_ID/whitelabel \ |
| 155 | + -H "x-admin-key: $ADMIN_API_KEY" \ |
| 156 | + -H "Content-Type: application/json" \ |
| 157 | + -d '{"brandName": "Acme AI", "hidePoweredBySim": true}' |
| 158 | +``` |
| 159 | +</Tab> |
| 160 | +<Tab value="Data retention"> |
| 161 | +```bash |
| 162 | +curl -X PATCH https://sim.example.com/api/v1/admin/organizations/$ORG_ID/data-retention \ |
| 163 | + -H "x-admin-key: $ADMIN_API_KEY" \ |
| 164 | + -H "Content-Type: application/json" \ |
| 165 | + -d '{"logRetentionHours": 2160}' |
| 166 | +``` |
| 167 | +</Tab> |
| 168 | +<Tab value="Session policy"> |
| 169 | +```bash |
| 170 | +curl -X PATCH https://sim.example.com/api/v1/admin/organizations/$ORG_ID/session-policy \ |
| 171 | + -H "x-admin-key: $ADMIN_API_KEY" \ |
| 172 | + -H "Content-Type: application/json" \ |
| 173 | + -d '{"maxSessionHours": 168, "idleTimeoutHours": 48}' |
| 174 | +``` |
| 175 | +</Tab> |
| 176 | +</Tabs> |
| 177 | +</Step> |
| 178 | +</Steps> |
| 179 | + |
| 180 | +Deleting an organization requires echoing its slug, because the delete cascades to members, invitations, and permission groups, and detaches its workspaces: |
| 181 | + |
| 182 | +```bash |
| 183 | +curl -X DELETE "https://sim.example.com/api/v1/admin/organizations/$ORG_ID?confirmSlug=acme-inc" \ |
| 184 | + -H "x-admin-key: $ADMIN_API_KEY" |
| 185 | +``` |
| 186 | + |
| 187 | +## Verifying it worked |
| 188 | + |
| 189 | +If a feature is enabled but nothing appears, check these in order. |
| 190 | + |
| 191 | +**The settings section is missing.** The `NEXT_PUBLIC_` twin is not set, or the app was not restarted after adding it. Client variables are read at build and boot. |
| 192 | + |
| 193 | +**The section appears but the API returns 403.** The server-side variable is missing while its client twin is set. Set both. |
| 194 | + |
| 195 | +**The feature is on but has no effect inside a workspace.** The workspace is not owned by an organization. Check `workspace_mode` and `organization_id`: |
| 196 | + |
| 197 | +```sql |
| 198 | +SELECT id, name, workspace_mode, organization_id FROM workspace; |
| 199 | +``` |
| 200 | + |
| 201 | +A workspace showing `personal` or a null `organization_id` will not pick up branding, PII redaction, permission groups, or drains. Use the backfill script or the workspace move endpoint. |
| 202 | + |
| 203 | +**Retention is configured but nothing is deleted.** `DATA_RETENTION_ENABLED` is unset. Configuring windows and running the cleanup pass are separate switches by design. |
| 204 | + |
| 205 | +## Related |
| 206 | + |
| 207 | +- [Environment variables](/platform/self-hosting/environment-variables) |
| 208 | +- [Single Sign-On](/platform/enterprise/sso) |
| 209 | +- [Access control](/platform/enterprise/access-control) |
| 210 | +- [Roles and permissions](/platform/permissions) |
| 211 | +- [Workspaces](/platform/workspaces) |
0 commit comments