Skip to content

Commit 99253be

Browse files
waleedlatif1claude
andcommitted
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
1 parent 96310d4 commit 99253be

8 files changed

Lines changed: 20 additions & 16 deletions

File tree

apps/docs/content/docs/platform/enterprise/data-retention.mdx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,11 @@ PII redaction runs against a standalone [Presidio](https://microsoft.github.io/p
213213

214214
```bash
215215
# The Presidio service exposing /analyze and /anonymize
216-
# Helm — setting pii.enabled wires this for you. Set it by hand only for an
217-
# external Presidio, substituting your release name and namespace.
218-
PII_URL=http://<release>-pii.<namespace>.svc.cluster.local:5001
216+
# Helm — setting pii.enabled wires this for you, and a manual value is then
217+
# ignored. Set it by hand only for an external Presidio with pii.enabled:
218+
# false. The bundled Service is <release>-sim-pii, or <release>-pii when the
219+
# release name already contains "sim".
220+
PII_URL=http://<service>.<namespace>.svc.cluster.local:5001
219221
# Docker Compose — no shipped file defines a PII service. Add one to the
220222
# same project, then use its service name.
221223
# PII_URL=http://pii:5001

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
# 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.
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 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.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ docker compose -f "$COMPOSE_FILE" up -d --force-recreate simstudio
182182
| `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 |
183183
| `sim-setup config` | Show configured capabilities and integrations |
184184
| `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 |
186186
| `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 |
187187

188188
`--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.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { FAQ } from '@/components/ui/faq'
1717
- PV provisioner support (a default StorageClass supporting `ReadWriteOnce`)
1818
- An ingress controller, if `ingress.enabled=true`
1919
- `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)
2121

2222
## Installation
2323

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Each app replica opens a pool. Total connections grow with replica count, and Po
7878

7979
Budget it: `replicas × pool size + realtime + cronjobs + migrations + headroom` must stay under `max_connections`.
8080

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.
8282

8383
### Read replicas
8484

@@ -147,8 +147,10 @@ externalDatabase:
147147
port: 6432
148148
database: simstudio
149149
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
153+
# renders no Secret and the pod cannot start.
152154
password: "<password>"
153155
154156
autoscaling:

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: Common issues and solutions
55

66
## Start here: `sim-setup doctor`
77

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.
99

1010
```bash
1111
npx sim-setup doctor
@@ -127,7 +127,7 @@ Rule out expiry and clock drift first: the endpoint's certificate may genuinely
127127
128128
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.
129129

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:
131131

132132
```yaml
133133
# docker-compose.prod.yml

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ docker compose -f docker-compose.ollama.yml --profile "$PROFILE" up -d
214214
`sim-setup update` refuses two install kinds outright rather than doing something surprising:
215215

216216
- **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.
218218

219219
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.
220220
</Callout>

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Run it from the directory holding your `.env` and Compose file, or from a source
2323
| **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 |
2424
| **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 |
2525
| **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 |
2727

2828
<Callout type="warn">
2929
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
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 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.
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)