You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: correct the audit pass's own errors, and six it missed
Four of these are defects I introduced in the audit commits by applying
suggested replacement text without verifying the replacement the way I verified
the finding:
- `postgresql.enabled: false` alone renders an empty `DATABASE_URL`;
`externalDatabase.enabled: true` is required too. I dropped it.
- The external-database password check is skipped under `existingSecret` and
External Secrets, so "the chart refuses to render" was false. Under ESO the
mapping is what matters.
- `LOG_LEVEL` is an uppercase-only enum, so the `info` I told operators to set
would fail validation.
- `add cache` writes `REDIS_URL`, which `realtime` reads too, so recreating
only the app container leaves Socket.IO pointed at the old Redis.
Six the audits missed:
- `PII_URL` used `<release>-pii`, the same fullname bug already fixed for the
realtime Service. A manual value is also ignored when `pii.enabled`.
- External Redis does not need `redis.enabled: false` — a non-empty
`app.env.REDIS_URL` overrides the bundled URL and suppresses its Deployment.
- `sim-setup doctor` was recommended to Ollama-stack users, which it cannot
detect.
- The CA-bundle snippet said "in either case" directly after explaining that an
incomplete chain must be repaired server-side.
- `update` refuses only the `dev` mode; a source checkout on
`docker-compose.local.yml` is a Compose install and does update.
- Doctor cannot tell whether migrations are current on a standalone install —
the published package ships no migration journal.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015BwsJTEQRzWJaY4BRCkPZt
#Must be same-origin — the CSP's style-src allows only 'self' and Google
121
-
#Fonts, so a stylesheet on another origin is blocked.
120
+
#The CSP's style-src allows only 'self' and fonts.googleapis.com, and takes
121
+
#no configured hosts — in practice this means same-origin.
122
122
NEXT_PUBLIC_CUSTOM_CSS_URL=/branding/custom.css
123
123
```
124
124
@@ -173,4 +173,4 @@ branding:
173
173
favicon.ico: "AAABAAEAEBAAAAEAIABoBAAA..."
174
174
```
175
175
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.
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 — the CSP's `style-src` takes no configured hosts, so in practice it must be same-origin.
|`sim-setup reset`| After a confirmation prompt, archive the env files and wipe managed data. A Compose install archives the `.env` beside its Compose file; a source checkout, a Kubernetes install, and an invocation with no install detected all archive `apps/sim/.env`, `apps/realtime/.env`, `packages/db/.env`, and the root `.env`. On Kubernetes it runs `helm uninstall`, which leaves the Postgres volumes behind — they come from a StatefulSet's `volumeClaimTemplates`, which Kubernetes never deletes. Delete those PVCs yourself to reset the data |
183
183
|`sim-setup config`| Show configured capabilities and integrations |
184
184
|`sim-setup doctor`| Check the setup. `--fix` repairs what it can, `--json` prints machine-readable output |
185
-
|`sim-setup add <feature>`| Configure one capability: `email`, `storage`, `sandbox`, `jobs`, `cache`, `knowledge`, `knowledge-embeddings`, `chat`, `llm`, or `integration <slug>`. Writes to the `.env` beside your Compose file — recreate the app container to apply — or to `apps/sim/.env` on a source checkout. It refuses when no configuration is writable, when more than one is, and for Helm releases |
185
+
|`sim-setup add <feature>`| Configure one capability: `email`, `storage`, `sandbox`, `jobs`, `cache`, `knowledge`, `knowledge-embeddings`, `chat`, `llm`, or `integration <slug>`. Writes to the `.env` beside your Compose file — recreate the containers that read the value to apply it, which for `cache` means `realtime` as well as `simstudio`, since both take `REDIS_URL`— or to `apps/sim/.env` on a source checkout, where `apps/realtime/.env` needs the same value. It refuses when no configuration is writable, when more than one is, and for Helm releases |
186
186
|`sim-setup desktop`| Resolve the desktop installer for this deployment. `--url <url>` skips discovery, and is required when several detected configurations name different `NEXT_PUBLIC_APP_URL` origins. `--no-open` skips the "Download it now?" prompt — the link is printed either way |
187
187
188
188
`--dir <path>` is accepted by every command, not just the wizard. On a standalone install it also scopes the lifecycle commands to that directory's install, which is how you disambiguate when more than one exists.
Copy file name to clipboardExpand all lines: apps/docs/content/docs/platform/self-hosting/kubernetes.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -17,7 +17,7 @@ import { FAQ } from '@/components/ui/faq'
17
17
- PV provisioner support (a default StorageClass supporting `ReadWriteOnce`)
18
18
- An ingress controller, if `ingress.enabled=true`
19
19
-`metrics-server`, if you enable autoscaling
20
-
-**Redis** — bundled by the chart (`redis.enabled: true`). Only supply your own if you set `redis.enabled: false`; see[Redis](/platform/self-hosting/redis)
20
+
-**Redis** — bundled by the chart (`redis.enabled: true`). To use your own, set `app.env.REDIS_URL`: a non-empty value overrides the bundled URL and suppresses its Deployment on its own. `redis.enabled: false` is the explicit opt-out. See[Redis](/platform/self-hosting/redis)
Copy file name to clipboardExpand all lines: apps/docs/content/docs/platform/self-hosting/scaling.mdx
+5-3Lines changed: 5 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -78,7 +78,7 @@ Each app replica opens a pool. Total connections grow with replica count, and Po
78
78
79
79
Budget it: `replicas × pool size + realtime + cronjobs + migrations + headroom`must stay under `max_connections`.
80
80
81
-
For anything beyond a handful of replicas, put **PgBouncer** in transaction pooling mode in front of the database and point the chart at it with `externalDatabase.host` / `externalDatabase.port` and `postgresql.enabled: false`. Setting `app.env.DATABASE_URL` does nothing — the chart computes `DATABASE_URL` itself and inlines it on the container, where it overrides anything from the Secret. This is the single highest-leverage change for a large deployment — it decouples app replica count from database connection count.
81
+
For anything beyond a handful of replicas, put **PgBouncer** in transaction pooling mode in front of the database and point the chart at it with `externalDatabase.enabled: true`, `externalDatabase.host`, and `externalDatabase.port`, alongside `postgresql.enabled: false`. Both halves are required — with `postgresql.enabled: false` and `externalDatabase.enabled` still false the chart renders an empty `DATABASE_URL`. Setting `app.env.DATABASE_URL` does nothing — the chart computes `DATABASE_URL` itself and inlines it on the container, where it overrides anything from the Secret. This is the single highest-leverage change for a large deployment — it decouples app replica count from database connection count.
82
82
83
83
### Read replicas
84
84
@@ -147,8 +147,10 @@ externalDatabase:
147
147
port: 6432
148
148
database: simstudio
149
149
sslMode: require
150
-
# Required — supply it here, through externalDatabase.existingSecret, or
151
-
# through External Secrets, or the chart refuses to render.
150
+
# Required unless you use externalDatabase.existingSecret or External
151
+
# Secrets, either of which skips this check. Under External Secrets, map
152
+
# externalSecrets.remoteRefs.externalDatabase.password — an omitted mapping
Copy file name to clipboardExpand all lines: apps/docs/content/docs/platform/self-hosting/troubleshooting.mdx
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,7 +5,7 @@ description: Common issues and solutions
5
5
6
6
## Start here: `sim-setup doctor`
7
7
8
-
On a Docker Compose or source install, run the built-in checker first. It catches most failures without you having to guess which subsystem is broken. It reads env files, so it is not a Kubernetes tool — on Helm, skip to the checks below.
8
+
On a production or local-development Compose install, or a source checkout, run the built-in checker first. It does not detect the Ollama stack. It catches most failures without you having to guess which subsystem is broken. It reads env files, so it is not a Kubernetes tool — on Helm, skip to the checks below.
9
9
10
10
```bash
11
11
npx sim-setup doctor
@@ -127,7 +127,7 @@ Rule out expiry and clock drift first: the endpoint's certificate may genuinely
127
127
128
128
That leaves two cases a bundle does address: the endpoint is signed by a private CA — a corporate TLS-inspecting proxy, or an internal service — or it serves an incomplete chain, omitting an intermediate. Adding the private root to `NODE_EXTRA_CA_CERTS` resolves the first. An incomplete chain is different: Node still fails with `UNABLE_TO_GET_ISSUER_CERT` because the missing intermediate has to be served by the endpoint, so repair the server's chain rather than expecting a bundle to cover it.
129
129
130
-
In either case, the image already ships current CA certificates and runs as a non-root user, so installing packages inside it is not the fix. Mount your CA bundle and point Node at it:
130
+
For the private-CA case, the image already ships current CA certificates and runs as a non-root user, so installing packages inside it is not the fix. Mount your CA bundle and point Node at it — an incomplete chain is not fixed here, only on the server:
`sim-setup update` refuses two install kinds outright rather than doing something surprising:
215
215
216
216
-**Kubernetes** — it does not upgrade Helm releases. Use `helm upgrade` after reading the chart and release notes.
217
-
-**Source / dev** — update the checkout with git, run `bun install`, and restart `bun run dev:full`.
217
+
-**Source / dev** — the `dev` mode that manages only Postgres and Redis. Update the checkout with git, run `bun install`, and restart `bun run dev:full`. A source checkout running `docker-compose.local.yml` is a Compose install and does update, by rebuilding.
218
218
219
219
On a standalone `docker-compose.prod.yml` install it also refuses to overwrite its managed Compose file if you have edited it by hand, comparing the file against the hash it recorded in `.sim-setup.json`: preserve or remove your customizations first.
Copy file name to clipboardExpand all lines: apps/docs/content/docs/platform/self-hosting/verify.mdx
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -23,7 +23,7 @@ Run it from the directory holding your `.env` and Compose file, or from a source
23
23
|**Schema**|**Required** keys are present, are not still the example placeholder, are valid URLs where they should be, and have a usable shape — `ENCRYPTION_KEY` is checked as exactly 64 hex characters, the rest as a minimum length. Optional secrets are not shape-checked, so a malformed `API_ENCRYPTION_KEY` passes here and fails later at encrypt time. `--fix` generates missing or placeholder secrets |
24
24
|**Consistency**| The same key agrees across files — `BETTER_AUTH_SECRET` between the app and realtime, and `DATABASE_URL` between the app and `packages/db` (a mismatch there means migrations ran against a different database). `--fix` mirrors the `apps/sim/.env` value |
25
25
|**Coherence**| Configuration that is individually valid but jointly wrong: a feature flag whose dependency is unset, a storage provider that is half-configured, and a server flag whose `NEXT_PUBLIC_` twin disagrees with it |
26
-
|**Live**| Postgres is reachable, pgvector is available, migrations are applied and current, Redis answers, and the running services respond on their ports. Doctor reads env files, so on the production Compose layout — where those values live inside the containers rather than in `.env` — the Postgres, migration, and Redis probes are skipped and only the HTTP health checks run |
26
+
|**Live**| Postgres is reachable, pgvector is available, migrations are applied — on a standalone `npx sim-setup` install the published package carries no migration journal, so it can confirm what has been applied but not that it is current — Redis answers, and the running services respond on their ports. Doctor reads env files, so on the production Compose layout — where those values live inside the containers rather than in `.env` — the Postgres, migration, and Redis probes are skipped and only the HTTP health checks run |
27
27
28
28
<Callouttype="warn">
29
29
The check worth knowing about before you hit it: if `NEXT_PUBLIC_APP_URL` points at `sim.ai` or any subdomain of it, Sim treats the deployment as Sim's own hosted platform (`isHosted=true`) and disables self-host overrides. Doctor flags this. Use your own domain.
@@ -104,7 +104,7 @@ All six should be present on Compose: `simstudio`, `realtime`, `db`, `redis`, `c
104
104
105
105
**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.
106
106
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.
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 — the variable is uppercase-only, and at the production default of `ERROR` nothing is logged at all.
108
108
109
109
**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`.
0 commit comments