From 7c24159218f9aa75023f66152e57a93706cb6ca0 Mon Sep 17 00:00:00 2001 From: brainx <12695242+brainx@users.noreply.github.com> Date: Tue, 21 Jul 2026 19:48:33 +0200 Subject: [PATCH 1/3] fix(docker): require persistent auth secrets --- .github/CONTRIBUTING.md | 24 +++++++++ README.md | 25 ++++++++++ .../content/docs/de/self-hosting/docker.mdx | 49 +++++++++++++++---- .../docs/en/platform/self-hosting/docker.mdx | 48 ++++++++++++++---- .../content/docs/es/self-hosting/docker.mdx | 49 +++++++++++++++---- .../content/docs/fr/self-hosting/docker.mdx | 49 +++++++++++++++---- .../content/docs/ja/self-hosting/docker.mdx | 46 +++++++++++++---- .../content/docs/zh/self-hosting/docker.mdx | 44 +++++++++++++---- .../config/docker-compose-secrets.test.ts | 35 +++++++++++++ docker-compose.prod.yml | 10 ++-- 10 files changed, 319 insertions(+), 60 deletions(-) create mode 100644 apps/sim/lib/core/config/docker-compose-secrets.test.ts diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index a41a49e628b..cb5b7fe88b4 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -165,12 +165,36 @@ After running this command, open [http://localhost:3000/](http://localhost:3000/ git clone https://github.com//sim.git cd sim +# Generate persistent secrets once (the file is ignored by Git) +( + set -euC + if [ -e .env ]; then + echo 'Refusing to overwrite existing .env' >&2 + exit 1 + fi + umask 077 + better_auth_secret=$(openssl rand -hex 32) + encryption_key=$(openssl rand -hex 32) + api_encryption_key=$(openssl rand -hex 32) + internal_api_secret=$(openssl rand -hex 32) + cat > .env << EOF +BETTER_AUTH_SECRET=$better_auth_secret +ENCRYPTION_KEY=$encryption_key +API_ENCRYPTION_KEY=$api_encryption_key +INTERNAL_API_SECRET=$internal_api_secret +EOF +) + # Start Sim docker compose -f docker-compose.prod.yml up -d ``` Access the application at [http://localhost:3000/](http://localhost:3000/) +Back up this `.env` file separately in a secured secret store; do not bundle it with database +backups. Do not regenerate the values when restarting an existing installation: changing encryption +keys can make stored secrets unreadable, and changing `BETTER_AUTH_SECRET` invalidates sessions. + #### Using Local Models To use local models with Sim: diff --git a/README.md b/README.md index 40dec306468..261becbc780 100644 --- a/README.md +++ b/README.md @@ -79,11 +79,36 @@ Docker must be installed and running. Use `-p, --port ` to run Sim on a di ```bash git clone https://github.com/simstudioai/sim.git && cd sim + +# Generate persistent secrets once (the file is ignored by Git) +( + set -euC + if [ -e .env ]; then + echo 'Refusing to overwrite existing .env' >&2 + exit 1 + fi + umask 077 + better_auth_secret=$(openssl rand -hex 32) + encryption_key=$(openssl rand -hex 32) + api_encryption_key=$(openssl rand -hex 32) + internal_api_secret=$(openssl rand -hex 32) + cat > .env << EOF +BETTER_AUTH_SECRET=$better_auth_secret +ENCRYPTION_KEY=$encryption_key +API_ENCRYPTION_KEY=$api_encryption_key +INTERNAL_API_SECRET=$internal_api_secret +EOF +) + docker compose -f docker-compose.prod.yml up -d ``` Open [http://localhost:3000](http://localhost:3000) +Back up the generated `.env` file separately in a secured secret store; do not bundle it with +database backups. Replacing its encryption keys can make stored secrets unreadable, while replacing +`BETTER_AUTH_SECRET` invalidates existing sessions. + Sim also supports local models via [Ollama](https://ollama.ai) and [vLLM](https://docs.vllm.ai/). See the [Docker self-hosting docs](https://docs.sim.ai/self-hosting/docker) for setup details. ### Manual Setup diff --git a/apps/docs/content/docs/de/self-hosting/docker.mdx b/apps/docs/content/docs/de/self-hosting/docker.mdx index 52fb5f19cb1..2d2117cf47f 100644 --- a/apps/docs/content/docs/de/self-hosting/docker.mdx +++ b/apps/docs/content/docs/de/self-hosting/docker.mdx @@ -9,29 +9,57 @@ import { Callout } from 'fumadocs-ui/components/callout' ## Schnellstart ```bash -# Clone and start +# Clone the repository git clone https://github.com/simstudioai/sim.git && cd sim + +# Generate persistent secrets once (.env is ignored by Git) +( + set -euC + if [ -e .env ]; then + echo 'Refusing to overwrite existing .env' >&2 + exit 1 + fi + umask 077 + better_auth_secret=$(openssl rand -hex 32) + encryption_key=$(openssl rand -hex 32) + api_encryption_key=$(openssl rand -hex 32) + internal_api_secret=$(openssl rand -hex 32) + cat > .env << EOF +BETTER_AUTH_SECRET=$better_auth_secret +ENCRYPTION_KEY=$encryption_key +API_ENCRYPTION_KEY=$api_encryption_key +INTERNAL_API_SECRET=$internal_api_secret +EOF +) + +# Start Sim docker compose -f docker-compose.prod.yml up -d ``` Öffnen Sie [http://localhost:3000](http://localhost:3000) + + Sichern Sie die erzeugte `.env` separat in einem geschützten Secret-Speicher und nicht zusammen + mit Datenbanksicherungen. Erzeugen Sie diese Werte bei einem Neustart nicht neu. Geänderte + Verschlüsselungsschlüssel können gespeicherte Secrets unlesbar machen; ein geändertes + `BETTER_AUTH_SECRET` macht bestehende Sitzungen ungültig. + + ## Produktionseinrichtung ### 1. Umgebung konfigurieren -```bash -# Generate secrets -cat > .env << EOF -DATABASE_URL=postgresql://postgres:postgres@db:5432/simstudio -BETTER_AUTH_SECRET=$(openssl rand -hex 32) -ENCRYPTION_KEY=$(openssl rand -hex 32) -INTERNAL_API_SECRET=$(openssl rand -hex 32) +Behalten Sie die beim Schnellstart erzeugten Secrets und ergänzen Sie die öffentliche URL in +derselben `.env`-Datei: + +```dotenv NEXT_PUBLIC_APP_URL=https://sim.yourdomain.com BETTER_AUTH_URL=https://sim.yourdomain.com -EOF ``` +Wenn Sie den Schnellstart übersprungen haben, führen Sie zuerst dessen Secret-Erzeugung aus. +Ersetzen Sie niemals Verschlüsselungsschlüssel einer Installation, die bereits Daten enthält. + ### 2. Dienste starten ```bash @@ -125,6 +153,9 @@ docker compose -f docker-compose.ollama.yml exec ollama ollama pull llama3.2 Wenn Ollama auf Ihrem Host-Rechner läuft (nicht in Docker): +Führen Sie zuerst den Schnellstart aus, damit die persistente `.env` vorhanden ist. Verwenden Sie +dann die passende Host-URL: + ```bash # macOS/Windows OLLAMA_URL=http://host.docker.internal:11434 docker compose -f docker-compose.prod.yml up -d diff --git a/apps/docs/content/docs/en/platform/self-hosting/docker.mdx b/apps/docs/content/docs/en/platform/self-hosting/docker.mdx index 2ec82d0ccd9..0d47748dfc0 100644 --- a/apps/docs/content/docs/en/platform/self-hosting/docker.mdx +++ b/apps/docs/content/docs/en/platform/self-hosting/docker.mdx @@ -10,29 +10,56 @@ import { FAQ } from '@/components/ui/faq' ## Quick Start ```bash -# Clone and start +# Clone the repository git clone https://github.com/simstudioai/sim.git && cd sim + +# Generate persistent secrets once (the file is ignored by Git) +( + set -euC + if [ -e .env ]; then + echo 'Refusing to overwrite existing .env' >&2 + exit 1 + fi + umask 077 + better_auth_secret=$(openssl rand -hex 32) + encryption_key=$(openssl rand -hex 32) + api_encryption_key=$(openssl rand -hex 32) + internal_api_secret=$(openssl rand -hex 32) + cat > .env << EOF +BETTER_AUTH_SECRET=$better_auth_secret +ENCRYPTION_KEY=$encryption_key +API_ENCRYPTION_KEY=$api_encryption_key +INTERNAL_API_SECRET=$internal_api_secret +EOF +) + +# Start Sim docker compose -f docker-compose.prod.yml up -d ``` Open [http://localhost:3000](http://localhost:3000) + + Back up the generated `.env` file separately in a secured secret store; do not bundle it with + database backups. Do not regenerate these values when restarting an existing installation. + Changing encryption keys can make stored secrets unreadable, while changing `BETTER_AUTH_SECRET` + invalidates existing sessions. + + ## Production Setup ### 1. Configure Environment -```bash -# Generate secrets -cat > .env << EOF -DATABASE_URL=postgresql://postgres:postgres@db:5432/simstudio -BETTER_AUTH_SECRET=$(openssl rand -hex 32) -ENCRYPTION_KEY=$(openssl rand -hex 32) -INTERNAL_API_SECRET=$(openssl rand -hex 32) +Keep the secrets generated during Quick Start and add your public URL to the same `.env` file: + +```dotenv NEXT_PUBLIC_APP_URL=https://sim.yourdomain.com BETTER_AUTH_URL=https://sim.yourdomain.com -EOF ``` +If you skipped Quick Start, run its secret-generation step first. Never replace encryption keys for +an installation that already has database data. + ### 2. Start Services ```bash @@ -121,6 +148,8 @@ docker compose -f docker-compose.ollama.yml exec ollama ollama pull llama3.2 If Ollama runs on your host machine (not in Docker): +Complete Quick Start first so the persistent `.env` exists, then use the appropriate host URL: + ```bash # macOS/Windows OLLAMA_URL=http://host.docker.internal:11434 docker compose -f docker-compose.prod.yml up -d @@ -158,4 +187,3 @@ docker compose -f docker-compose.prod.yml exec db pg_dump -U postgres simstudio { question: "How do I back up and restore the database?", answer: "Back up with: docker compose -f docker-compose.prod.yml exec db pg_dump -U postgres simstudio > backup.sql. Restore with: docker compose -f docker-compose.prod.yml exec -T db psql -U postgres simstudio < backup.sql. The database data is persisted in a Docker volume named postgres_data." }, { question: "Can I customize the PostgreSQL credentials?", answer: "Yes. The docker-compose.prod.yml uses environment variable defaults: POSTGRES_USER (default: postgres), POSTGRES_PASSWORD (default: postgres), POSTGRES_DB (default: simstudio), and POSTGRES_PORT (default: 5432). Set these in your .env file to override them." }, ]} /> - diff --git a/apps/docs/content/docs/es/self-hosting/docker.mdx b/apps/docs/content/docs/es/self-hosting/docker.mdx index 8f38d77da31..14c5bb63d65 100644 --- a/apps/docs/content/docs/es/self-hosting/docker.mdx +++ b/apps/docs/content/docs/es/self-hosting/docker.mdx @@ -9,29 +9,57 @@ import { Callout } from 'fumadocs-ui/components/callout' ## Inicio rápido ```bash -# Clone and start +# Clone the repository git clone https://github.com/simstudioai/sim.git && cd sim + +# Generate persistent secrets once (.env is ignored by Git) +( + set -euC + if [ -e .env ]; then + echo 'Refusing to overwrite existing .env' >&2 + exit 1 + fi + umask 077 + better_auth_secret=$(openssl rand -hex 32) + encryption_key=$(openssl rand -hex 32) + api_encryption_key=$(openssl rand -hex 32) + internal_api_secret=$(openssl rand -hex 32) + cat > .env << EOF +BETTER_AUTH_SECRET=$better_auth_secret +ENCRYPTION_KEY=$encryption_key +API_ENCRYPTION_KEY=$api_encryption_key +INTERNAL_API_SECRET=$internal_api_secret +EOF +) + +# Start Sim docker compose -f docker-compose.prod.yml up -d ``` Abre [http://localhost:3000](http://localhost:3000) + + Guarda el archivo `.env` generado por separado en un almacén seguro de secretos; no lo incluyas + con las copias de seguridad de la base de datos. No vuelvas a generar estos valores al reiniciar + una instalación existente. Cambiar las claves de cifrado puede hacer ilegibles los secretos + guardados, y cambiar `BETTER_AUTH_SECRET` invalida las sesiones existentes. + + ## Configuración de producción ### 1. Configurar entorno -```bash -# Generate secrets -cat > .env << EOF -DATABASE_URL=postgresql://postgres:postgres@db:5432/simstudio -BETTER_AUTH_SECRET=$(openssl rand -hex 32) -ENCRYPTION_KEY=$(openssl rand -hex 32) -INTERNAL_API_SECRET=$(openssl rand -hex 32) +Conserva los secretos generados durante el Inicio rápido y añade la URL pública al mismo archivo +`.env`: + +```dotenv NEXT_PUBLIC_APP_URL=https://sim.yourdomain.com BETTER_AUTH_URL=https://sim.yourdomain.com -EOF ``` +Si omitiste el Inicio rápido, ejecuta primero su paso de generación de secretos. No reemplaces las +claves de cifrado de una instalación que ya tenga datos. + ### 2. Iniciar servicios ```bash @@ -125,6 +153,9 @@ docker compose -f docker-compose.ollama.yml exec ollama ollama pull llama3.2 Si Ollama se ejecuta en tu máquina host (no en Docker): +Completa primero el Inicio rápido para crear el `.env` persistente y después usa la URL de host +adecuada: + ```bash # macOS/Windows OLLAMA_URL=http://host.docker.internal:11434 docker compose -f docker-compose.prod.yml up -d diff --git a/apps/docs/content/docs/fr/self-hosting/docker.mdx b/apps/docs/content/docs/fr/self-hosting/docker.mdx index 9ec36378684..67b5842e44b 100644 --- a/apps/docs/content/docs/fr/self-hosting/docker.mdx +++ b/apps/docs/content/docs/fr/self-hosting/docker.mdx @@ -9,29 +9,57 @@ import { Callout } from 'fumadocs-ui/components/callout' ## Démarrage rapide ```bash -# Clone and start +# Clone the repository git clone https://github.com/simstudioai/sim.git && cd sim + +# Generate persistent secrets once (.env is ignored by Git) +( + set -euC + if [ -e .env ]; then + echo 'Refusing to overwrite existing .env' >&2 + exit 1 + fi + umask 077 + better_auth_secret=$(openssl rand -hex 32) + encryption_key=$(openssl rand -hex 32) + api_encryption_key=$(openssl rand -hex 32) + internal_api_secret=$(openssl rand -hex 32) + cat > .env << EOF +BETTER_AUTH_SECRET=$better_auth_secret +ENCRYPTION_KEY=$encryption_key +API_ENCRYPTION_KEY=$api_encryption_key +INTERNAL_API_SECRET=$internal_api_secret +EOF +) + +# Start Sim docker compose -f docker-compose.prod.yml up -d ``` Ouvrez [http://localhost:3000](http://localhost:3000) + + Sauvegardez le fichier `.env` généré séparément dans un gestionnaire de secrets sécurisé ; ne + l'incluez pas avec les sauvegardes de la base de données. Ne régénérez pas ces valeurs au + redémarrage d'une installation existante. Modifier les clés de chiffrement peut rendre les + secrets stockés illisibles, et modifier `BETTER_AUTH_SECRET` invalide les sessions existantes. + + ## Configuration de production ### 1. Configurer l'environnement -```bash -# Generate secrets -cat > .env << EOF -DATABASE_URL=postgresql://postgres:postgres@db:5432/simstudio -BETTER_AUTH_SECRET=$(openssl rand -hex 32) -ENCRYPTION_KEY=$(openssl rand -hex 32) -INTERNAL_API_SECRET=$(openssl rand -hex 32) +Conservez les secrets générés lors du Démarrage rapide et ajoutez l'URL publique au même fichier +`.env` : + +```dotenv NEXT_PUBLIC_APP_URL=https://sim.yourdomain.com BETTER_AUTH_URL=https://sim.yourdomain.com -EOF ``` +Si vous avez ignoré le Démarrage rapide, exécutez d'abord son étape de génération des secrets. Ne +remplacez jamais les clés de chiffrement d'une installation qui contient déjà des données. + ### 2. Démarrer les services ```bash @@ -125,6 +153,9 @@ docker compose -f docker-compose.ollama.yml exec ollama ollama pull llama3.2 Si Ollama s'exécute sur votre machine hôte (pas dans Docker) : +Effectuez d'abord le Démarrage rapide afin de créer le fichier `.env` persistant, puis utilisez +l'URL d'hôte appropriée : + ```bash # macOS/Windows OLLAMA_URL=http://host.docker.internal:11434 docker compose -f docker-compose.prod.yml up -d diff --git a/apps/docs/content/docs/ja/self-hosting/docker.mdx b/apps/docs/content/docs/ja/self-hosting/docker.mdx index 3bd19092dd2..d16d5294385 100644 --- a/apps/docs/content/docs/ja/self-hosting/docker.mdx +++ b/apps/docs/content/docs/ja/self-hosting/docker.mdx @@ -9,29 +9,55 @@ import { Callout } from 'fumadocs-ui/components/callout' ## クイックスタート ```bash -# Clone and start +# Clone the repository git clone https://github.com/simstudioai/sim.git && cd sim + +# Generate persistent secrets once (.env is ignored by Git) +( + set -euC + if [ -e .env ]; then + echo 'Refusing to overwrite existing .env' >&2 + exit 1 + fi + umask 077 + better_auth_secret=$(openssl rand -hex 32) + encryption_key=$(openssl rand -hex 32) + api_encryption_key=$(openssl rand -hex 32) + internal_api_secret=$(openssl rand -hex 32) + cat > .env << EOF +BETTER_AUTH_SECRET=$better_auth_secret +ENCRYPTION_KEY=$encryption_key +API_ENCRYPTION_KEY=$api_encryption_key +INTERNAL_API_SECRET=$internal_api_secret +EOF +) + +# Start Sim docker compose -f docker-compose.prod.yml up -d ``` [http://localhost:3000](http://localhost:3000)を開く + + 生成した `.env` はデータベースのバックアップに含めず、安全なシークレットストアに別途保管してください。 + 既存のインストールを再起動するときにこれらの値を再生成しないでください。暗号化キーを変更すると保存済みの + シークレットを読み取れなくなる可能性があり、`BETTER_AUTH_SECRET` を変更すると既存のセッションが無効になります。 + + ## 本番環境のセットアップ ### 1. 環境の設定 -```bash -# Generate secrets -cat > .env << EOF -DATABASE_URL=postgresql://postgres:postgres@db:5432/simstudio -BETTER_AUTH_SECRET=$(openssl rand -hex 32) -ENCRYPTION_KEY=$(openssl rand -hex 32) -INTERNAL_API_SECRET=$(openssl rand -hex 32) +クイックスタートで生成したシークレットを維持し、同じ `.env` ファイルに公開 URL を追加します: + +```dotenv NEXT_PUBLIC_APP_URL=https://sim.yourdomain.com BETTER_AUTH_URL=https://sim.yourdomain.com -EOF ``` +クイックスタートを省略した場合は、先にシークレット生成手順を実行してください。すでにデータがあるインストールの +暗号化キーは決して置き換えないでください。 + ### 2. サービスの起動 ```bash @@ -125,6 +151,8 @@ docker compose -f docker-compose.ollama.yml exec ollama ollama pull llama3.2 Ollamaがホストマシン上で実行されている場合(Dockerではない): +最初にクイックスタートを完了して永続的な `.env` を作成し、その後で適切なホスト URL を使用してください: + ```bash # macOS/Windows OLLAMA_URL=http://host.docker.internal:11434 docker compose -f docker-compose.prod.yml up -d diff --git a/apps/docs/content/docs/zh/self-hosting/docker.mdx b/apps/docs/content/docs/zh/self-hosting/docker.mdx index 46897f5ea11..ba4980fc39f 100644 --- a/apps/docs/content/docs/zh/self-hosting/docker.mdx +++ b/apps/docs/content/docs/zh/self-hosting/docker.mdx @@ -9,29 +9,53 @@ import { Callout } from 'fumadocs-ui/components/callout' ## 快速开始 ```bash -# Clone and start +# Clone the repository git clone https://github.com/simstudioai/sim.git && cd sim + +# Generate persistent secrets once (.env is ignored by Git) +( + set -euC + if [ -e .env ]; then + echo 'Refusing to overwrite existing .env' >&2 + exit 1 + fi + umask 077 + better_auth_secret=$(openssl rand -hex 32) + encryption_key=$(openssl rand -hex 32) + api_encryption_key=$(openssl rand -hex 32) + internal_api_secret=$(openssl rand -hex 32) + cat > .env << EOF +BETTER_AUTH_SECRET=$better_auth_secret +ENCRYPTION_KEY=$encryption_key +API_ENCRYPTION_KEY=$api_encryption_key +INTERNAL_API_SECRET=$internal_api_secret +EOF +) + +# Start Sim docker compose -f docker-compose.prod.yml up -d ``` 打开 [http://localhost:3000](http://localhost:3000) + + 请将生成的 `.env` 单独备份到安全的密钥存储中,不要与数据库备份放在一起。重启现有安装时不要重新生成这些值。 + 更改加密密钥可能会导致已存储的密钥无法读取,而更改 `BETTER_AUTH_SECRET` 会使现有会话失效。 + + ## 生产环境设置 ### 1. 配置环境 -```bash -# Generate secrets -cat > .env << EOF -DATABASE_URL=postgresql://postgres:postgres@db:5432/simstudio -BETTER_AUTH_SECRET=$(openssl rand -hex 32) -ENCRYPTION_KEY=$(openssl rand -hex 32) -INTERNAL_API_SECRET=$(openssl rand -hex 32) +保留快速开始期间生成的密钥,并将公共 URL 添加到同一个 `.env` 文件中: + +```dotenv NEXT_PUBLIC_APP_URL=https://sim.yourdomain.com BETTER_AUTH_URL=https://sim.yourdomain.com -EOF ``` +如果跳过了快速开始,请先运行其中的密钥生成步骤。切勿替换已经包含数据的安装所使用的加密密钥。 + ### 2. 启动服务 ```bash @@ -125,6 +149,8 @@ docker compose -f docker-compose.ollama.yml exec ollama ollama pull llama3.2 如果 Ollama 在您的主机上运行(而不是在 Docker 中): +请先完成快速开始以创建持久化的 `.env`,然后使用相应的主机 URL: + ```bash # macOS/Windows OLLAMA_URL=http://host.docker.internal:11434 docker compose -f docker-compose.prod.yml up -d diff --git a/apps/sim/lib/core/config/docker-compose-secrets.test.ts b/apps/sim/lib/core/config/docker-compose-secrets.test.ts new file mode 100644 index 00000000000..5b0fab7f82f --- /dev/null +++ b/apps/sim/lib/core/config/docker-compose-secrets.test.ts @@ -0,0 +1,35 @@ +import { readFileSync } from 'node:fs' +import { load } from 'js-yaml' +import { describe, expect, it } from 'vitest' + +type ComposeService = { + environment?: string[] +} + +type ComposeFile = { + services?: Record +} + +const composePath = new URL('../../../../../docker-compose.prod.yml', import.meta.url) +const compose = load(readFileSync(composePath, 'utf8')) as ComposeFile + +function environmentValue(serviceName: string, variableName: string): string | undefined { + const prefix = `${variableName}=` + return compose.services?.[serviceName]?.environment + ?.find((entry) => entry.startsWith(prefix)) + ?.slice(prefix.length) +} + +describe('production Docker Compose secrets', () => { + it.each([ + ['simstudio', 'BETTER_AUTH_SECRET'], + ['simstudio', 'ENCRYPTION_KEY'], + ['simstudio', 'INTERNAL_API_SECRET'], + ['realtime', 'BETTER_AUTH_SECRET'], + ['realtime', 'INTERNAL_API_SECRET'], + ])('requires %s to receive %s', (serviceName, variableName) => { + expect(environmentValue(serviceName, variableName)).toMatch( + new RegExp(`^\\$\\{${variableName}:\\?.+\\}$`) + ) + }) +}) diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 67266fbc780..96ff5920260 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -17,10 +17,10 @@ services: # addition to NEXT_PUBLIC_APP_URL. Use when serving from multiple domains # (apex + www, alias hostnames, reverse-proxy IPs). Empty by default. - TRUSTED_ORIGINS=${TRUSTED_ORIGINS:-} - - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET} - - ENCRYPTION_KEY=${ENCRYPTION_KEY} + - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:?Set BETTER_AUTH_SECRET in .env using openssl rand -hex 32} + - ENCRYPTION_KEY=${ENCRYPTION_KEY:?Set ENCRYPTION_KEY in .env using openssl rand -hex 32} - API_ENCRYPTION_KEY=${API_ENCRYPTION_KEY:-} - - INTERNAL_API_SECRET=${INTERNAL_API_SECRET} + - INTERNAL_API_SECRET=${INTERNAL_API_SECRET:?Set INTERNAL_API_SECRET in .env using openssl rand -hex 32} - REDIS_URL=${REDIS_URL:-} - COPILOT_API_KEY=${COPILOT_API_KEY} - SIM_AGENT_API_URL=${SIM_AGENT_API_URL} @@ -60,8 +60,8 @@ services: - DATABASE_URL=postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@db:5432/${POSTGRES_DB:-simstudio} - NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL:-http://localhost:3000} - BETTER_AUTH_URL=${BETTER_AUTH_URL:-http://localhost:3000} - - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET} - - INTERNAL_API_SECRET=${INTERNAL_API_SECRET} + - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:?Set BETTER_AUTH_SECRET in .env using openssl rand -hex 32} + - INTERNAL_API_SECRET=${INTERNAL_API_SECRET:?Set INTERNAL_API_SECRET in .env using openssl rand -hex 32} - REDIS_URL=${REDIS_URL:-} depends_on: db: From 3d6cb877f157c426e13bdd98c011a1e612e7ebe9 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 21 Jul 2026 11:28:11 -0700 Subject: [PATCH 2/3] fix(docker): require the same auth secrets in the Ollama Compose file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Ollama Compose file fell back to broken defaults: docker compose does not perform $(...) command substitution, so BETTER_AUTH_SECRET and ENCRYPTION_KEY resolved to literal, shared, weak values (and the ENCRYPTION_KEY literal was under the 32-char minimum the app enforces). INTERNAL_API_SECRET — required (min 32) by both the app and realtime — was not passed at all, so first-user signup failed the same way prod did. Mirror the prod hardening: require BETTER_AUTH_SECRET, ENCRYPTION_KEY, and INTERNAL_API_SECRET via mandatory ${VAR:?...} interpolation, add INTERNAL_API_SECRET to both services, extend the regression test to cover the Ollama Compose file, and note the .env prerequisite in the docs. --- .github/CONTRIBUTING.md | 2 +- .../content/docs/de/self-hosting/docker.mdx | 2 + .../docs/en/platform/self-hosting/docker.mdx | 2 + .../content/docs/es/self-hosting/docker.mdx | 2 + .../content/docs/fr/self-hosting/docker.mdx | 2 + .../content/docs/ja/self-hosting/docker.mdx | 2 + .../content/docs/zh/self-hosting/docker.mdx | 2 + .../config/docker-compose-secrets.test.ts | 47 +++++++++++++------ docker-compose.ollama.yml | 8 ++-- 9 files changed, 50 insertions(+), 19 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index cb5b7fe88b4..cfb3f1cc245 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -209,7 +209,7 @@ To use local models with Sim: ollama pull gemma3:4b ``` -2. Start Sim with local model support: +2. Start Sim with local model support (generate the persistent `.env` from the Quick Start above first — the Ollama Compose file requires the same secrets and refuses to start without them): ```bash # With NVIDIA GPU support diff --git a/apps/docs/content/docs/de/self-hosting/docker.mdx b/apps/docs/content/docs/de/self-hosting/docker.mdx index 2d2117cf47f..c50a40396af 100644 --- a/apps/docs/content/docs/de/self-hosting/docker.mdx +++ b/apps/docs/content/docs/de/self-hosting/docker.mdx @@ -135,6 +135,8 @@ sudo certbot --nginx -d sim.yourdomain.com ## Ollama +Führen Sie zuerst den Schnellstart aus, damit die persistente `.env` mit Ihren Secrets vorhanden ist – die Ollama-Compose-Datei benötigt dieselben Secrets und startet ohne sie nicht. + ```bash # With GPU docker compose -f docker-compose.ollama.yml --profile gpu --profile setup up -d diff --git a/apps/docs/content/docs/en/platform/self-hosting/docker.mdx b/apps/docs/content/docs/en/platform/self-hosting/docker.mdx index 0d47748dfc0..e0e9d53e134 100644 --- a/apps/docs/content/docs/en/platform/self-hosting/docker.mdx +++ b/apps/docs/content/docs/en/platform/self-hosting/docker.mdx @@ -131,6 +131,8 @@ sudo certbot --nginx -d sim.yourdomain.com ## Ollama +Complete Quick Start first so the persistent `.env` with your secrets exists — the Ollama Compose file requires the same secrets and refuses to start without them. + ```bash # With GPU docker compose -f docker-compose.ollama.yml --profile gpu --profile setup up -d diff --git a/apps/docs/content/docs/es/self-hosting/docker.mdx b/apps/docs/content/docs/es/self-hosting/docker.mdx index 14c5bb63d65..9cde3086e9c 100644 --- a/apps/docs/content/docs/es/self-hosting/docker.mdx +++ b/apps/docs/content/docs/es/self-hosting/docker.mdx @@ -135,6 +135,8 @@ sudo certbot --nginx -d sim.yourdomain.com ## Ollama +Completa primero el Inicio rápido para crear el `.env` persistente con tus secretos: el archivo Compose de Ollama requiere los mismos secretos y no se inicia sin ellos. + ```bash # With GPU docker compose -f docker-compose.ollama.yml --profile gpu --profile setup up -d diff --git a/apps/docs/content/docs/fr/self-hosting/docker.mdx b/apps/docs/content/docs/fr/self-hosting/docker.mdx index 67b5842e44b..4f78f5c7a2c 100644 --- a/apps/docs/content/docs/fr/self-hosting/docker.mdx +++ b/apps/docs/content/docs/fr/self-hosting/docker.mdx @@ -135,6 +135,8 @@ sudo certbot --nginx -d sim.yourdomain.com ## Ollama +Effectuez d'abord le Démarrage rapide pour créer le `.env` persistant avec vos secrets : le fichier Compose d'Ollama requiert les mêmes secrets et ne démarre pas sans eux. + ```bash # With GPU docker compose -f docker-compose.ollama.yml --profile gpu --profile setup up -d diff --git a/apps/docs/content/docs/ja/self-hosting/docker.mdx b/apps/docs/content/docs/ja/self-hosting/docker.mdx index d16d5294385..4b26cf2f3e7 100644 --- a/apps/docs/content/docs/ja/self-hosting/docker.mdx +++ b/apps/docs/content/docs/ja/self-hosting/docker.mdx @@ -133,6 +133,8 @@ sudo certbot --nginx -d sim.yourdomain.com ## Ollama +先にクイックスタートを実行して、シークレットを含む永続的な `.env` を用意してください。Ollama の Compose ファイルは同じシークレットを必要とし、それらがないと起動しません。 + ```bash # With GPU docker compose -f docker-compose.ollama.yml --profile gpu --profile setup up -d diff --git a/apps/docs/content/docs/zh/self-hosting/docker.mdx b/apps/docs/content/docs/zh/self-hosting/docker.mdx index ba4980fc39f..87f6e8674cf 100644 --- a/apps/docs/content/docs/zh/self-hosting/docker.mdx +++ b/apps/docs/content/docs/zh/self-hosting/docker.mdx @@ -131,6 +131,8 @@ sudo certbot --nginx -d sim.yourdomain.com ## Ollama +请先完成快速开始,以生成包含密钥的持久 `.env` 文件——Ollama 的 Compose 文件需要相同的密钥,缺少时将无法启动。 + ```bash # With GPU docker compose -f docker-compose.ollama.yml --profile gpu --profile setup up -d diff --git a/apps/sim/lib/core/config/docker-compose-secrets.test.ts b/apps/sim/lib/core/config/docker-compose-secrets.test.ts index 5b0fab7f82f..473120bb0f3 100644 --- a/apps/sim/lib/core/config/docker-compose-secrets.test.ts +++ b/apps/sim/lib/core/config/docker-compose-secrets.test.ts @@ -10,26 +10,43 @@ type ComposeFile = { services?: Record } -const composePath = new URL('../../../../../docker-compose.prod.yml', import.meta.url) -const compose = load(readFileSync(composePath, 'utf8')) as ComposeFile +function loadCompose(fileName: string): ComposeFile { + const composePath = new URL(`../../../../../${fileName}`, import.meta.url) + return load(readFileSync(composePath, 'utf8')) as ComposeFile +} -function environmentValue(serviceName: string, variableName: string): string | undefined { +function environmentValue( + compose: ComposeFile, + serviceName: string, + variableName: string +): string | undefined { const prefix = `${variableName}=` return compose.services?.[serviceName]?.environment ?.find((entry) => entry.startsWith(prefix)) ?.slice(prefix.length) } -describe('production Docker Compose secrets', () => { - it.each([ - ['simstudio', 'BETTER_AUTH_SECRET'], - ['simstudio', 'ENCRYPTION_KEY'], - ['simstudio', 'INTERNAL_API_SECRET'], - ['realtime', 'BETTER_AUTH_SECRET'], - ['realtime', 'INTERNAL_API_SECRET'], - ])('requires %s to receive %s', (serviceName, variableName) => { - expect(environmentValue(serviceName, variableName)).toMatch( - new RegExp(`^\\$\\{${variableName}:\\?.+\\}$`) - ) - }) +const requiredSecrets: Array<[string, string, string]> = [ + ['docker-compose.prod.yml', 'simstudio', 'BETTER_AUTH_SECRET'], + ['docker-compose.prod.yml', 'simstudio', 'ENCRYPTION_KEY'], + ['docker-compose.prod.yml', 'simstudio', 'INTERNAL_API_SECRET'], + ['docker-compose.prod.yml', 'realtime', 'BETTER_AUTH_SECRET'], + ['docker-compose.prod.yml', 'realtime', 'INTERNAL_API_SECRET'], + ['docker-compose.ollama.yml', 'simstudio', 'BETTER_AUTH_SECRET'], + ['docker-compose.ollama.yml', 'simstudio', 'ENCRYPTION_KEY'], + ['docker-compose.ollama.yml', 'simstudio', 'INTERNAL_API_SECRET'], + ['docker-compose.ollama.yml', 'realtime', 'BETTER_AUTH_SECRET'], + ['docker-compose.ollama.yml', 'realtime', 'INTERNAL_API_SECRET'], +] + +describe('Docker Compose secrets', () => { + it.each(requiredSecrets)( + '%s requires %s to receive %s via mandatory interpolation', + (fileName, serviceName, variableName) => { + const compose = loadCompose(fileName) + expect(environmentValue(compose, serviceName, variableName)).toMatch( + new RegExp(`^\\$\\{${variableName}:\\?.+\\}$`) + ) + } + ) }) diff --git a/docker-compose.ollama.yml b/docker-compose.ollama.yml index 43f5cdcbff8..0fc5b938d6a 100644 --- a/docker-compose.ollama.yml +++ b/docker-compose.ollama.yml @@ -16,8 +16,9 @@ services: - DATABASE_URL=postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@db:5432/${POSTGRES_DB:-simstudio} - BETTER_AUTH_URL=${NEXT_PUBLIC_APP_URL:-http://localhost:3000} - NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL:-http://localhost:3000} - - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:-sim_auth_secret_$(openssl rand -hex 16)} - - ENCRYPTION_KEY=${ENCRYPTION_KEY:-$(openssl rand -hex 32)} + - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:?Set BETTER_AUTH_SECRET in .env using openssl rand -hex 32} + - ENCRYPTION_KEY=${ENCRYPTION_KEY:?Set ENCRYPTION_KEY in .env using openssl rand -hex 32} + - INTERNAL_API_SECRET=${INTERNAL_API_SECRET:?Set INTERNAL_API_SECRET in .env using openssl rand -hex 32} - COPILOT_API_KEY=${COPILOT_API_KEY} - SIM_AGENT_API_URL=${SIM_AGENT_API_URL} - OLLAMA_URL=http://ollama:11434 @@ -46,7 +47,8 @@ services: - DATABASE_URL=postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@db:5432/${POSTGRES_DB:-simstudio} - NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL:-http://localhost:3000} - BETTER_AUTH_URL=${BETTER_AUTH_URL:-http://localhost:3000} - - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:-sim_auth_secret_$(openssl rand -hex 16)} + - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:?Set BETTER_AUTH_SECRET in .env using openssl rand -hex 32} + - INTERNAL_API_SECRET=${INTERNAL_API_SECRET:?Set INTERNAL_API_SECRET in .env using openssl rand -hex 32} depends_on: db: condition: service_healthy From 41f1fef742ce5b5b1ce1c5eb1d0dff733071a903 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Tue, 21 Jul 2026 11:41:54 -0700 Subject: [PATCH 3/3] docs(docker): add upgrade path for installs with an existing .env The generation block refuses to overwrite an existing .env, so an installation that predates the newly required secrets had no documented way to add them before the hardened Compose files fail-fast on startup. Add an idempotent snippet that appends only the missing secrets while preserving existing values, across the README, contributor guide, and all localized Docker guides. --- .github/CONTRIBUTING.md | 8 ++++++++ README.md | 8 ++++++++ apps/docs/content/docs/de/self-hosting/docker.mdx | 8 ++++++++ .../docs/content/docs/en/platform/self-hosting/docker.mdx | 8 ++++++++ apps/docs/content/docs/es/self-hosting/docker.mdx | 8 ++++++++ apps/docs/content/docs/fr/self-hosting/docker.mdx | 8 ++++++++ apps/docs/content/docs/ja/self-hosting/docker.mdx | 8 ++++++++ apps/docs/content/docs/zh/self-hosting/docker.mdx | 8 ++++++++ 8 files changed, 64 insertions(+) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index cfb3f1cc245..e023c74fbd4 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -195,6 +195,14 @@ Back up this `.env` file separately in a secured secret store; do not bundle it backups. Do not regenerate the values when restarting an existing installation: changing encryption keys can make stored secrets unreadable, and changing `BETTER_AUTH_SECRET` invalidates sessions. +Already have a `.env` (for example from an install that predates these required secrets)? The block above refuses to overwrite it. Add only the missing secrets instead — this preserves every existing value: + +```bash +for key in BETTER_AUTH_SECRET ENCRYPTION_KEY API_ENCRYPTION_KEY INTERNAL_API_SECRET; do + grep -q "^${key}=" .env || printf '%s=%s\n' "$key" "$(openssl rand -hex 32)" >> .env +done +``` + #### Using Local Models To use local models with Sim: diff --git a/README.md b/README.md index 261becbc780..9121c25cc2c 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,14 @@ Back up the generated `.env` file separately in a secured secret store; do not b database backups. Replacing its encryption keys can make stored secrets unreadable, while replacing `BETTER_AUTH_SECRET` invalidates existing sessions. +Already have a `.env` (for example from an earlier install that predates these required secrets)? The block above refuses to overwrite it. Add only the missing secrets instead — this preserves every existing value: + +```bash +for key in BETTER_AUTH_SECRET ENCRYPTION_KEY API_ENCRYPTION_KEY INTERNAL_API_SECRET; do + grep -q "^${key}=" .env || printf '%s=%s\n' "$key" "$(openssl rand -hex 32)" >> .env +done +``` + Sim also supports local models via [Ollama](https://ollama.ai) and [vLLM](https://docs.vllm.ai/). See the [Docker self-hosting docs](https://docs.sim.ai/self-hosting/docker) for setup details. ### Manual Setup diff --git a/apps/docs/content/docs/de/self-hosting/docker.mdx b/apps/docs/content/docs/de/self-hosting/docker.mdx index c50a40396af..1dc6c663b0c 100644 --- a/apps/docs/content/docs/de/self-hosting/docker.mdx +++ b/apps/docs/content/docs/de/self-hosting/docker.mdx @@ -45,6 +45,14 @@ docker compose -f docker-compose.prod.yml up -d `BETTER_AUTH_SECRET` macht bestehende Sitzungen ungültig. +Sie haben bereits eine `.env` (z. B. aus einer Installation vor diesen erforderlichen Secrets)? Der obige Block überschreibt sie nicht. Ergänzen Sie stattdessen nur die fehlenden Secrets – vorhandene Werte bleiben erhalten: + +```bash +for key in BETTER_AUTH_SECRET ENCRYPTION_KEY API_ENCRYPTION_KEY INTERNAL_API_SECRET; do + grep -q "^${key}=" .env || printf '%s=%s\n' "$key" "$(openssl rand -hex 32)" >> .env +done +``` + ## Produktionseinrichtung ### 1. Umgebung konfigurieren diff --git a/apps/docs/content/docs/en/platform/self-hosting/docker.mdx b/apps/docs/content/docs/en/platform/self-hosting/docker.mdx index e0e9d53e134..7258ef3caab 100644 --- a/apps/docs/content/docs/en/platform/self-hosting/docker.mdx +++ b/apps/docs/content/docs/en/platform/self-hosting/docker.mdx @@ -46,6 +46,14 @@ Open [http://localhost:3000](http://localhost:3000) invalidates existing sessions. +Already have a `.env` (for example from an install that predates these required secrets)? The block above refuses to overwrite it. Add only the missing secrets instead — this preserves every existing value: + +```bash +for key in BETTER_AUTH_SECRET ENCRYPTION_KEY API_ENCRYPTION_KEY INTERNAL_API_SECRET; do + grep -q "^${key}=" .env || printf '%s=%s\n' "$key" "$(openssl rand -hex 32)" >> .env +done +``` + ## Production Setup ### 1. Configure Environment diff --git a/apps/docs/content/docs/es/self-hosting/docker.mdx b/apps/docs/content/docs/es/self-hosting/docker.mdx index 9cde3086e9c..a4d2492ba18 100644 --- a/apps/docs/content/docs/es/self-hosting/docker.mdx +++ b/apps/docs/content/docs/es/self-hosting/docker.mdx @@ -45,6 +45,14 @@ Abre [http://localhost:3000](http://localhost:3000) guardados, y cambiar `BETTER_AUTH_SECRET` invalida las sesiones existentes. +¿Ya tienes un `.env` (por ejemplo, de una instalación anterior a estos secretos obligatorios)? El bloque anterior no lo sobrescribe. Añade solo los secretos que falten; así se conservan todos los valores existentes: + +```bash +for key in BETTER_AUTH_SECRET ENCRYPTION_KEY API_ENCRYPTION_KEY INTERNAL_API_SECRET; do + grep -q "^${key}=" .env || printf '%s=%s\n' "$key" "$(openssl rand -hex 32)" >> .env +done +``` + ## Configuración de producción ### 1. Configurar entorno diff --git a/apps/docs/content/docs/fr/self-hosting/docker.mdx b/apps/docs/content/docs/fr/self-hosting/docker.mdx index 4f78f5c7a2c..cf0d0fcf2df 100644 --- a/apps/docs/content/docs/fr/self-hosting/docker.mdx +++ b/apps/docs/content/docs/fr/self-hosting/docker.mdx @@ -45,6 +45,14 @@ Ouvrez [http://localhost:3000](http://localhost:3000) secrets stockés illisibles, et modifier `BETTER_AUTH_SECRET` invalide les sessions existantes. +Vous avez déjà un `.env` (par exemple d'une installation antérieure à ces secrets requis) ? Le bloc ci-dessus ne l'écrase pas. Ajoutez seulement les secrets manquants — les valeurs existantes sont préservées : + +```bash +for key in BETTER_AUTH_SECRET ENCRYPTION_KEY API_ENCRYPTION_KEY INTERNAL_API_SECRET; do + grep -q "^${key}=" .env || printf '%s=%s\n' "$key" "$(openssl rand -hex 32)" >> .env +done +``` + ## Configuration de production ### 1. Configurer l'environnement diff --git a/apps/docs/content/docs/ja/self-hosting/docker.mdx b/apps/docs/content/docs/ja/self-hosting/docker.mdx index 4b26cf2f3e7..95330f305a2 100644 --- a/apps/docs/content/docs/ja/self-hosting/docker.mdx +++ b/apps/docs/content/docs/ja/self-hosting/docker.mdx @@ -44,6 +44,14 @@ docker compose -f docker-compose.prod.yml up -d シークレットを読み取れなくなる可能性があり、`BETTER_AUTH_SECRET` を変更すると既存のセッションが無効になります。 +すでに `.env` がある場合(これらの必須シークレット導入前のインストールなど)、上記のブロックは上書きしません。代わりに不足しているシークレットのみを追加してください。既存の値はすべて保持されます。 + +```bash +for key in BETTER_AUTH_SECRET ENCRYPTION_KEY API_ENCRYPTION_KEY INTERNAL_API_SECRET; do + grep -q "^${key}=" .env || printf '%s=%s\n' "$key" "$(openssl rand -hex 32)" >> .env +done +``` + ## 本番環境のセットアップ ### 1. 環境の設定 diff --git a/apps/docs/content/docs/zh/self-hosting/docker.mdx b/apps/docs/content/docs/zh/self-hosting/docker.mdx index 87f6e8674cf..27434abfab0 100644 --- a/apps/docs/content/docs/zh/self-hosting/docker.mdx +++ b/apps/docs/content/docs/zh/self-hosting/docker.mdx @@ -43,6 +43,14 @@ docker compose -f docker-compose.prod.yml up -d 更改加密密钥可能会导致已存储的密钥无法读取,而更改 `BETTER_AUTH_SECRET` 会使现有会话失效。 +已经有 `.env` 了吗(例如来自引入这些必需密钥之前的安装)?上面的代码块不会覆盖它。请改为仅添加缺失的密钥——这会保留所有现有值: + +```bash +for key in BETTER_AUTH_SECRET ENCRYPTION_KEY API_ENCRYPTION_KEY INTERNAL_API_SECRET; do + grep -q "^${key}=" .env || printf '%s=%s\n' "$key" "$(openssl rand -hex 32)" >> .env +done +``` + ## 生产环境设置 ### 1. 配置环境