Skip to content

Commit 96310d4

Browse files
waleedlatif1claude
andcommitted
fix: correct the env-var and runtime-behavior claims the audit found
- White-labeling, session policies, and the inbox are already on wherever billing is disabled, which is every self-hosted deployment. The docs told operators to enable white-labeling with a flag it does not need, and listed all thirteen features as symmetric opt-ins. - `NEXT_PUBLIC_CUSTOM_CSS_URL` must be same-origin. The CSP's `style-src` is a hardcoded literal that takes no configured hosts, so both the "point them at absolute URLs" advice and my own earlier "or a host you have added to style-src" were wrong — there is no such remedy short of editing source. - Client variables are read at boot from the container environment, not baked at build. The troubleshooting note invited a pointless image rebuild. - Script migrations run with `lock_timeout = 0` and `statement_timeout = 0`, so one blocked on an app-held lock hangs forever rather than failing with `55P03`. The table described only the SQL phase. - With no mail provider the mailer logs recipient, subject, and sender at `info` and reports success — never the body, and nothing at all at the production default of `ERROR`. - A malformed storage backend stops startup; it does not fall through to a later fully configured one. - `EMAIL_PASSWORD_SIGNUP_ENABLED=false` disables sign-in and OTP too, and `SIGNUP_MX_VALIDATION_ENABLED` covers only email signup. - The Pi template accepts an immutable ref; the page forbade one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015BwsJTEQRzWJaY4BRCkPZt
1 parent dcf894a commit 96310d4

7 files changed

Lines changed: 20 additions & 17 deletions

File tree

apps/docs/content/docs/platform/enterprise/self-hosted.mdx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,23 @@ NEXT_PUBLIC_DATA_DRAINS_ENABLED=false
4040

4141
The individual flags also work on their own if you would rather opt in one at a time and leave the master switch unset.
4242

43+
Three features do not need a flag at all: **custom branding**, **session policies**, and the **Sim Mailer inbox** are already on wherever billing is disabled, which is every self-hosted deployment. They preserve behavior that predates these flags. Set the corresponding variable to `false` to turn one off.
44+
4345
| Feature | Server variable | Client variable |
4446
|---------|-----------------|-----------------|
4547
| Everything below | `ENTERPRISE_ENABLED` | `NEXT_PUBLIC_ENTERPRISE_ENABLED` |
4648
| Organizations | `ORGANIZATIONS_ENABLED` | `NEXT_PUBLIC_ORGANIZATIONS_ENABLED` |
4749
| Permission groups | `ACCESS_CONTROL_ENABLED` | `NEXT_PUBLIC_ACCESS_CONTROL_ENABLED` |
4850
| SAML and OIDC sign-in | `SSO_ENABLED` | `NEXT_PUBLIC_SSO_ENABLED` |
49-
| Custom branding | `WHITELABELING_ENABLED` | `NEXT_PUBLIC_WHITELABELING_ENABLED` |
51+
| Custom branding — on by default | `WHITELABELING_ENABLED` | `NEXT_PUBLIC_WHITELABELING_ENABLED` |
5052
| Audit logs | `AUDIT_LOGS_ENABLED` | `NEXT_PUBLIC_AUDIT_LOGS_ENABLED` |
5153
| Usage tracking | `USAGE_MONITORING_ENABLED` | `NEXT_PUBLIC_USAGE_MONITORING_ENABLED` |
5254
| Custom blocks | `CUSTOM_BLOCKS_ENABLED` | `NEXT_PUBLIC_CUSTOM_BLOCKS_ENABLED` |
53-
| Session policies | `SESSION_POLICIES_ENABLED` | `NEXT_PUBLIC_SESSION_POLICIES_ENABLED` |
55+
| Session policies — on by default | `SESSION_POLICIES_ENABLED` | `NEXT_PUBLIC_SESSION_POLICIES_ENABLED` |
5456
| Data retention deletion | `DATA_RETENTION_ENABLED` | `NEXT_PUBLIC_DATA_RETENTION_ENABLED` |
5557
| Data drains | `DATA_DRAINS_ENABLED` | `NEXT_PUBLIC_DATA_DRAINS_ENABLED` |
5658
| Workspace forks | `FORKING_ENABLED` | `NEXT_PUBLIC_FORKING_ENABLED` |
57-
| Sim Mailer inbox | `INBOX_ENABLED` | `NEXT_PUBLIC_INBOX_ENABLED` |
59+
| Sim Mailer inbox — on by default | `INBOX_ENABLED` | `NEXT_PUBLIC_INBOX_ENABLED` |
5860
| Sandboxes | `SANDBOXES_ENABLED` | `NEXT_PUBLIC_SANDBOXES_ENABLED` |
5961

6062
Sandboxes also need a remote execution provider and a dedicated Function base image before they can run anything. `SANDBOXES_ENABLED` grants the server-side entitlement; `NEXT_PUBLIC_SANDBOXES_ENABLED` projects provider readiness to the browser and exposes Shell plus custom Sandbox management. Set the public flag only after the selected provider has credentials and a valid immutable Function base configured.
@@ -247,7 +249,7 @@ curl -X DELETE "https://sim.example.com/api/v1/admin/organizations/$ORG_ID?confi
247249

248250
If a feature is enabled but nothing appears, check these in order.
249251

250-
**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.
252+
**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 boot from the container environment, so a restart is enough — no rebuild.
251253

252254
**The section appears but the API returns 403.** The server-side variable is missing while its client twin is set. Set both.
253255

apps/docs/content/docs/platform/enterprise/whitelabeling.mdx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,17 +91,17 @@ Organization white-labeling applies only to members of your organization. Public
9191

9292
## Self-hosted setup
9393

94-
Self-hosted deployments use environment variables instead of the billing/plan check.
94+
Self-hosted deployments use environment variables instead of the billing/plan check, and white-labeling is **already enabled** on one: it defaults on wherever billing is disabled. Configure branding through **Settings → Organization → White-labeling** the same way.
9595

9696
### Environment variables
9797

98+
To turn it off:
99+
98100
```bash
99-
WHITELABELING_ENABLED=true
100-
NEXT_PUBLIC_WHITELABELING_ENABLED=true
101+
WHITELABELING_ENABLED=false
102+
NEXT_PUBLIC_WHITELABELING_ENABLED=false
101103
```
102104

103-
Once enabled, configure branding through **Settings → Organization → White-labeling** the same way.
104-
105105
---
106106

107107
## Instance-wide branding
@@ -117,8 +117,8 @@ NEXT_PUBLIC_BRAND_NAME=Acme
117117
NEXT_PUBLIC_BRAND_LOGO_URL=/branding/logo.png
118118
NEXT_PUBLIC_BRAND_WORDMARK_URL=/branding/wordmark.svg
119119
NEXT_PUBLIC_BRAND_FAVICON_URL=/branding/favicon.ico
120-
# Same-origin, or a host you have added to the CSP's style-src — a stylesheet
121-
# on another origin is blocked.
120+
# Must be same-originthe CSP's style-src allows only 'self' and Google
121+
# Fonts, so a stylesheet on another origin is blocked.
122122
NEXT_PUBLIC_CUSTOM_CSS_URL=/branding/custom.css
123123
```
124124

@@ -173,4 +173,4 @@ branding:
173173
favicon.ico: "AAABAAEAEBAAAAEAIABoBAAA..."
174174
```
175175
176-
With the default `mountPath`, a file named `logo.png` is served at `/branding/logo.png` — the value to give `NEXT_PUBLIC_BRAND_LOGO_URL`. Outside Helm, host the files anywhere the browser can reach and point the variables at absolute URLs.
176+
With the default `mountPath`, a file named `logo.png` is served at `/branding/logo.png` — the value to give `NEXT_PUBLIC_BRAND_LOGO_URL`. Outside Helm, host the logo, wordmark, and favicon anywhere the browser can reach and point those variables at absolute URLs. `NEXT_PUBLIC_CUSTOM_CSS_URL` is the exception — it must be same-origin, since the CSP's `style-src` takes no configured hosts.

apps/docs/content/docs/platform/self-hosting/authentication.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ See the [SSO guide](/platform/enterprise/sso) for identity-provider setup and th
8585
|---|---|
8686
| `DISABLE_REGISTRATION=true` | Blocks all new accounts — email/password, email OTP, and social sign-in. Only existing accounts can sign in, including to accept a workspace invitation. SSO is unaffected |
8787
| `DISABLE_EMAIL_SIGNUP=true` | Blocks new email/password registrations; existing email login keeps working |
88+
| `EMAIL_PASSWORD_SIGNUP_ENABLED=false` | Disables the whole email path — sign-in, signup, and email OTP — for existing users too. Use `DISABLE_EMAIL_SIGNUP` to block only new accounts |
8889
| `ALLOWED_LOGIN_DOMAINS` | Comma-separated domain allowlist, e.g. `acme.com,acme.co.uk`. Gates email sign-**in** as well as signup |
8990
| `ALLOWED_LOGIN_EMAILS` | Comma-separated address allowlist, applied the same way |
9091
| `BLOCKED_SIGNUP_DOMAINS` | Comma-separated domain blocklist |
@@ -93,7 +94,7 @@ See the [SSO guide](/platform/enterprise/sso) for identity-provider setup and th
9394
| `BLOCKED_EMAIL_MX_HOSTS` | MX-host substrings to block; used only with the above |
9495

9596
<Callout type="warn">
96-
`ALLOWED_LOGIN_DOMAINS`, `ALLOWED_LOGIN_EMAILS`, and `SIGNUP_MX_VALIDATION_ENABLED` gate the **email/password** path only. A first-time sign-in through Google, GitHub, or Microsoft creates an account through the social provider and is not filtered by them. To restrict who may sign in through a social provider, disable the ones you have not vetted (`DISABLE_GOOGLE_AUTH`, `DISABLE_GITHUB_AUTH`, `DISABLE_MICROSOFT_AUTH`) or restrict membership at the identity provider and use SSO.
97+
`ALLOWED_LOGIN_DOMAINS`, `ALLOWED_LOGIN_EMAILS`, and `SIGNUP_MX_VALIDATION_ENABLED` gate the **email/password** path only — and `SIGNUP_MX_VALIDATION_ENABLED` narrower still, running on email signup alone, not on email sign-in or email OTP. A first-time sign-in through Google, GitHub, or Microsoft creates an account through the social provider and is not filtered by them. To restrict who may sign in through a social provider, disable the ones you have not vetted (`DISABLE_GOOGLE_AUTH`, `DISABLE_GITHUB_AUTH`, `DISABLE_MICROSOFT_AUTH`) or restrict membership at the identity provider and use SSO.
9798

9899
`DISABLE_REGISTRATION` and `BLOCKED_SIGNUP_DOMAINS` apply to every path, social included.
99100
</Callout>

apps/docs/content/docs/platform/self-hosting/object-storage.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Set `STORAGE_PROVIDER` to `local`, `s3`, `azure`, or `gcs` to select a backend e
3131

3232
If `STORAGE_PROVIDER` is unset, Sim uses the first backend whose configuration is complete, in that order. An explicit `STORAGE_PROVIDER` takes precedence and must be valid and complete.
3333

34-
A partially configured backend is skipped, so a fully configured one later in the order still wins. What it never does is fall back to local disk: if no other backend is complete, startup fails with `File storage is partially or incorrectly configured`. `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` are checked as a pair — set both or neither.
34+
A partially configured backend is skipped, so a fully configured one later in the order still wins. A backend whose values are present but malformed is different: it stops startup immediately, and a later fully configured one does not take over. What it never does is fall back to local disk: if no other backend is complete, startup fails with `File storage is partially or incorrectly configured`. `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` are checked as a pair — set both or neither.
3535

3636
## Set up AWS S3
3737

apps/docs/content/docs/platform/self-hosting/reference-architectures.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Everything the chart can run itself, it runs by default. That is convenient for
2626
| Ingress | Off | You install the controller; the chart renders the Ingress |
2727
| TLS certificates | Off | You provision them |
2828
| Remote sandbox | Off | Required for Python, Shell, and imported JavaScript — a provider **and** an immutable Function image. See [Security](/platform/self-hosting/security) |
29-
| Pi execution | Off | A separate image from the Function one, set with `E2B_PI_TEMPLATE_ID` (the template **name**, not an immutable `<template>:<build-id>` ref) or `DAYTONA_PI_SNAPSHOT_ID`. Unlike the Function base these are not format-validated, but execution still fails closed when unset |
29+
| Pi execution | Off | A separate image from the Function one, set with `E2B_PI_TEMPLATE_ID` (a template name, an alias, or an immutable `<template>:<build-id>` ref) or `DAYTONA_PI_SNAPSHOT_ID`. Unlike the Function base these are not format-validated, but execution still fails closed when unset |
3030
| PII redaction, Ollama, telemetry collector | Off | Optional, off unless you enable them |
3131

3232
The bundled Postgres uses a 10 Gi `ReadWriteOnce` volume and is intended for evaluation. Moving to managed Postgres is the single most important production change.

apps/docs/content/docs/platform/self-hosting/upgrades.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ Behavior that is fixed in the migrator and not configurable, but that explains w
104104
|---|---|
105105
| Advisory-lock acquire deadline | 30 minutes, retried every 5s |
106106
| `lock_timeout` on the migration session | 5 seconds for ordinary DDL — a statement that waits longer fails with SQLSTATE `55P03`. An individual migration can set it to `0` for statements that must not be interrupted, such as `CREATE INDEX CONCURRENTLY`. `statement_timeout` is `0` on the same session by default, so a long migration is not cut off once it holds its locks — though a migration can narrow it for its own statements, as `0076_damp_vector.sql` does with a 180-second local setting |
107-
| SQL migration retry attempts | 8, with exponential backoff and jitter, and only for a lock timeout (`55P03`). Script (data) migrations run once — a failure there exits immediately |
107+
| SQL migration retry attempts | 8, with exponential backoff and jitter, and only for a lock timeout (`55P03`). Script (data) migrations run once — a failure there exits immediately. They also run with `lock_timeout = 0` and `statement_timeout = 0`, so one blocked on an app-held lock waits indefinitely: a stuck script migration looks like a hung migration container, not a `55P03` |
108108
| Connection attempts at startup | 10, for transient failures — `53300` (`too_many_connections`), `53400`, the `08xxx` connection-exception class, and socket-level errors such as `ECONNREFUSED`, `ECONNRESET`, `ETIMEDOUT`, `EHOSTUNREACH`, and `ENOTFOUND`. A database that is simply down is retried with backoff, not failed immediately |
109109

110110
The `lock_timeout` deliberately trades a table-wide stall for a failed migration: without it, DDL waiting on an `AccessExclusiveLock` queues every other query on that table behind it for the whole wait.

apps/docs/content/docs/platform/self-hosting/verify.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ All six should be present on Compose: `simstudio`, `realtime`, `db`, `redis`, `c
104104

105105
**Step 8 fails — knowledge base upload errors.** Knowledge bases need a hosted embedding provider — OpenAI, Azure OpenAI, or Gemini. There is no local embedding backend. If a key is set, check pgvector is installed on the database.
106106

107-
**Step 9 fails — no email arrives.** With no provider configured, emails are written to the app logs instead of sent — check there first to confirm the message was generated, then debug the provider.
107+
**Step 9 fails — no email arrives.** With no provider configured the mailer no-ops: it records the recipient, subject, and sender at `info` and reports success, never the message body. Raise `LOG_LEVEL` to `info` to see that line — at the production default of `ERROR` nothing is logged at all.
108108

109109
**Step 11 fails — schedule never fires.** Read the scheduler's logs (`docker compose -f docker-compose.prod.yml logs cron`, or `kubectl get cronjobs -n simstudio`). A `401` there means the app and the scheduler disagree on `CRON_SECRET`.
110110

0 commit comments

Comments
 (0)