diff --git a/README.md b/README.md
index 5b3c90b..be5f83b 100644
--- a/README.md
+++ b/README.md
@@ -75,13 +75,13 @@ An honest comparison on the axes that matter most to teams evaluating voice AI p
##### Download and setup Dograh on your Local Machine
> **Note**
-> We collect anonymous usage data to improve the product. You can opt out by setting the `ENABLE_TELEMETRY` to `false` in the below command.
+> We collect anonymous usage data to improve the product. You can opt out by setting `ENABLE_TELEMETRY=false` before running the startup script.
> **Note**
> If you wish to run the platform on a remote server instead, checkout our [Documentation](https://docs.dograh.com/deployment/docker#option-2:-remote-server-deployment)
```bash
-curl -o docker-compose.yaml https://raw.githubusercontent.com/dograh-hq/dograh/main/docker-compose.yaml && REGISTRY=ghcr.io/dograh-hq ENABLE_TELEMETRY=true docker compose up --pull always
+curl -o docker-compose.yaml https://raw.githubusercontent.com/dograh-hq/dograh/main/docker-compose.yaml && curl -o start_docker.sh https://raw.githubusercontent.com/dograh-hq/dograh/main/scripts/start_docker.sh && chmod +x start_docker.sh && ./start_docker.sh
```
> **Note**
diff --git a/docs/deployment/docker.mdx b/docs/deployment/docker.mdx
index d0f2959..28a6a8b 100644
--- a/docs/deployment/docker.mdx
+++ b/docs/deployment/docker.mdx
@@ -20,18 +20,27 @@ Watch the video tutorial below for a step-by-step walkthrough of setting up Dogr
allowFullScreen
>
-For local development and testing, you can run Dograh AI directly on your machine using Docker with a single command.
+For local development and testing, you can run Dograh AI directly on your machine using Docker with a small startup script.
### Quick Start
-Run this single command to download and start Dograh AI:
+Download the compose file and starter script, then confirm the prompt to start Dograh AI:
-```bash
-curl -o docker-compose.yaml https://raw.githubusercontent.com/dograh-hq/dograh/main/docker-compose.yaml && REGISTRY=ghcr.io/dograh-hq ENABLE_TELEMETRY=true docker compose up --pull always
+
+```bash macOS/Linux
+curl -o docker-compose.yaml https://raw.githubusercontent.com/dograh-hq/dograh/main/docker-compose.yaml && curl -o start_docker.sh https://raw.githubusercontent.com/dograh-hq/dograh/main/scripts/start_docker.sh && chmod +x start_docker.sh && ./start_docker.sh
```
+```powershell Windows
+Invoke-WebRequest -OutFile docker-compose.yaml https://raw.githubusercontent.com/dograh-hq/dograh/main/docker-compose.yaml
+Invoke-WebRequest -OutFile start_docker.ps1 https://raw.githubusercontent.com/dograh-hq/dograh/main/scripts/start_docker.ps1
+.\start_docker.ps1
+```
+
-This command:
+This setup:
- Downloads the latest docker-compose.yaml
+- Creates `OSS_JWT_SECRET` in `.env` if one does not already exist
+- Prompts before running Docker Compose
- Starts all required services including PostgreSQL, Redis, MinIO, API, and UI
- Pulls the latest images automatically
@@ -43,7 +52,7 @@ http://localhost:3010
```
-You can disable telemetry by setting `ENABLE_TELEMETRY=false` in the command above.
+You can disable telemetry by setting `ENABLE_TELEMETRY=false` before running `./start_docker.sh` or `.\start_docker.ps1`.
### Troubleshooting WebRTC Connectivity
@@ -72,7 +81,7 @@ The script will prompt you for:
- The host browsers should use to reach TURN (press Enter for `127.0.0.1`; use your LAN IP if testing from another device on the same network)
- A shared secret for the TURN server (press Enter to generate a random one)
-It creates `docker-compose.yaml`, a `.env` file with TURN credentials, and the small helper bundle that `dograh-init` uses to render coturn config at startup. Start the stack with the `local-turn` profile so coturn comes up alongside the other services:
+It creates `docker-compose.yaml`, a `.env` file with JWT and TURN credentials, and the small helper bundle that `dograh-init` uses to render coturn config at startup. Start the stack with the `local-turn` profile so coturn comes up alongside the other services:
```bash
docker compose --profile local-turn up --pull always
diff --git a/docs/deployment/update.mdx b/docs/deployment/update.mdx
index c307b89..b289778 100644
--- a/docs/deployment/update.mdx
+++ b/docs/deployment/update.mdx
@@ -67,12 +67,20 @@ The script overwrites `docker-compose.yaml` and the remote helper bundle (`remot
## Local deployment
-For local Docker installs (the [Quick Start](/deployment/docker#quick-start) flow or `setup_local.sh` / `setup_local.ps1`), there are no host-side config files to refresh — pull new images and restart:
+For local Docker installs (the [Quick Start](/deployment/docker#quick-start) flow or `setup_local.sh` / `setup_local.ps1`), there are no host-side config files to refresh — stop the stack, then use the startup script to preserve `OSS_JWT_SECRET` and pull new images:
-```bash
+
+```bash macOS/Linux
+curl -o start_docker.sh https://raw.githubusercontent.com/dograh-hq/dograh/main/scripts/start_docker.sh && chmod +x start_docker.sh
docker compose down
-docker compose up --pull always
+./start_docker.sh
```
+```powershell Windows
+Invoke-WebRequest -OutFile start_docker.ps1 https://raw.githubusercontent.com/dograh-hq/dograh/main/scripts/start_docker.ps1
+docker compose down
+.\start_docker.ps1
+```
+
To pin a specific version instead of `latest`, edit `docker-compose.yaml` and change both `image:` lines for `api` and `ui` to the same tag (e.g. `:1.28.0` — Docker image tags use bare semver, no `v` prefix), then run the commands above.
diff --git a/docs/getting-started/index.mdx b/docs/getting-started/index.mdx
index 7dfebff..0925208 100644
--- a/docs/getting-started/index.mdx
+++ b/docs/getting-started/index.mdx
@@ -24,16 +24,23 @@ Watch the following video to learn about Dograh’s capabilities.
## Setting up
-Get the platform up and running using Docker with a single command on your local computer. If you are looking to deploy the platform on a server different than your local machine, please check the [Deployment](deployment/introduction) section.
+Get the platform up and running using Docker with a small startup script on your local computer. If you are looking to deploy the platform on a server different than your local machine, please check the [Deployment](deployment/introduction) section.
-We collect anonymous usage data to improve the product. You can opt out by setting the `ENABLE_TELEMETRY` to `false` in the below command.
+We collect anonymous usage data to improve the product. You can opt out by setting `ENABLE_TELEMETRY=false` before running the startup script.
-```bash
-curl -o docker-compose.yaml https://raw.githubusercontent.com/dograh-hq/dograh/main/docker-compose.yaml && REGISTRY=ghcr.io/dograh-hq ENABLE_TELEMETRY=true docker compose up --pull always
+
+```bash macOS/Linux
+curl -o docker-compose.yaml https://raw.githubusercontent.com/dograh-hq/dograh/main/docker-compose.yaml && curl -o start_docker.sh https://raw.githubusercontent.com/dograh-hq/dograh/main/scripts/start_docker.sh && chmod +x start_docker.sh && ./start_docker.sh
```
+```powershell Windows
+Invoke-WebRequest -OutFile docker-compose.yaml https://raw.githubusercontent.com/dograh-hq/dograh/main/docker-compose.yaml
+Invoke-WebRequest -OutFile start_docker.ps1 https://raw.githubusercontent.com/dograh-hq/dograh/main/scripts/start_docker.ps1
+.\start_docker.ps1
+```
+
Please check [Prerequisites](getting-started/prerequisites) for the system requirements and [Troubleshooting](getting-started/troubleshooting) for common issues.
## Next Steps
-You can see how to configure the inference provider in [Inference Provider](/configurations/inference-providers).
\ No newline at end of file
+You can see how to configure the inference provider in [Inference Provider](/configurations/inference-providers).
diff --git a/docs/getting-started/prerequisites.mdx b/docs/getting-started/prerequisites.mdx
index 48e60cd..aebd6aa 100644
--- a/docs/getting-started/prerequisites.mdx
+++ b/docs/getting-started/prerequisites.mdx
@@ -74,12 +74,23 @@ Dograh images are available from two registries:
- **GitHub Container Registry (Default)**: `ghcr.io/dograh-hq` - Recommended for most users
- **Docker Hub**: `dograhai` - Alternative registry
-To use a specific registry, set the `REGISTRY` environment variable:
+To use a specific registry, set the `REGISTRY` environment variable when running the startup script:
+
```bash
# Using GitHub Container Registry (recommended)
-REGISTRY=ghcr.io/dograh-hq docker compose up --pull always
+REGISTRY=ghcr.io/dograh-hq ./start_docker.sh
# Using Docker Hub
-REGISTRY=dograhai docker compose up --pull always
+REGISTRY=dograhai ./start_docker.sh
```
+```powershell Windows
+# Using GitHub Container Registry (recommended)
+$env:REGISTRY = 'ghcr.io/dograh-hq'
+.\start_docker.ps1
+
+# Using Docker Hub
+$env:REGISTRY = 'dograhai'
+.\start_docker.ps1
+```
+
diff --git a/scripts/start_docker.ps1 b/scripts/start_docker.ps1
new file mode 100644
index 0000000..e039bb9
--- /dev/null
+++ b/scripts/start_docker.ps1
@@ -0,0 +1,95 @@
+$ErrorActionPreference = 'Stop'
+
+$EnvFile = '.env'
+$Registry = if ([string]::IsNullOrEmpty($env:REGISTRY)) { 'ghcr.io/dograh-hq' } else { $env:REGISTRY }
+$EnableTelemetry = if ([string]::IsNullOrEmpty($env:ENABLE_TELEMETRY)) { 'true' } else { $env:ENABLE_TELEMETRY }
+$Utf8NoBom = [System.Text.UTF8Encoding]::new($false)
+
+function New-HexSecret {
+ $bytes = [byte[]]::new(32)
+ [System.Security.Cryptography.RandomNumberGenerator]::Fill($bytes)
+ return -join ($bytes | ForEach-Object { $_.ToString('x2') })
+}
+
+function Get-DotEnvValue {
+ param(
+ [string]$Path,
+ [string]$Key
+ )
+
+ if (-not (Test-Path $Path)) {
+ return $null
+ }
+
+ $resolvedPath = (Resolve-Path $Path).Path
+ foreach ($line in [System.IO.File]::ReadLines($resolvedPath)) {
+ if ($line.StartsWith("$Key=")) {
+ return $line.Substring($Key.Length + 1)
+ }
+ }
+
+ return $null
+}
+
+function Set-DotEnvValue {
+ param(
+ [string]$Path,
+ [string]$Key,
+ [string]$Value
+ )
+
+ $lines = New-Object System.Collections.Generic.List[string]
+ $updated = $false
+
+ if (Test-Path $Path) {
+ $resolvedPath = (Resolve-Path $Path).Path
+ foreach ($line in [System.IO.File]::ReadLines($resolvedPath)) {
+ if ($line.StartsWith("$Key=")) {
+ $lines.Add("$Key=$Value")
+ $updated = $true
+ } else {
+ $lines.Add($line)
+ }
+ }
+ }
+
+ if (-not $updated) {
+ $lines.Add("$Key=$Value")
+ }
+
+ [System.IO.File]::WriteAllLines((Join-Path (Get-Location) $Path), $lines, $Utf8NoBom)
+}
+
+if (-not (Test-Path 'docker-compose.yaml')) {
+ Write-Error 'docker-compose.yaml not found. Download it first, then re-run this script.'
+ exit 1
+}
+
+$existingSecret = Get-DotEnvValue -Path $EnvFile -Key 'OSS_JWT_SECRET'
+if ([string]::IsNullOrEmpty($existingSecret)) {
+ Set-DotEnvValue -Path $EnvFile -Key 'OSS_JWT_SECRET' -Value (New-HexSecret)
+ Write-Host "Created OSS_JWT_SECRET in $EnvFile."
+} else {
+ Write-Host "OSS_JWT_SECRET is already set in $EnvFile."
+}
+
+Write-Host ''
+Write-Host "Docker registry: $Registry"
+Write-Host "Telemetry enabled: $EnableTelemetry"
+Write-Host ''
+Write-Host 'This will run:'
+Write-Host " `$env:REGISTRY = '$Registry'; `$env:ENABLE_TELEMETRY = '$EnableTelemetry'; docker compose up --pull always"
+Write-Host ''
+
+$answer = Read-Host 'Start Dograh now? [Y/n]'
+if ($answer -match '^[Nn]') {
+ Write-Host 'Dograh was not started.'
+ exit 0
+}
+
+$env:REGISTRY = $Registry
+$env:ENABLE_TELEMETRY = $EnableTelemetry
+docker compose up --pull always
+if ($LASTEXITCODE -ne 0) {
+ exit $LASTEXITCODE
+}
diff --git a/scripts/start_docker.sh b/scripts/start_docker.sh
new file mode 100755
index 0000000..9cb9675
--- /dev/null
+++ b/scripts/start_docker.sh
@@ -0,0 +1,108 @@
+#!/usr/bin/env bash
+set -e
+
+ENV_FILE=".env"
+REGISTRY="${REGISTRY:-ghcr.io/dograh-hq}"
+ENABLE_TELEMETRY="${ENABLE_TELEMETRY:-true}"
+
+fail() {
+ echo "Error: $*" >&2
+ exit 1
+}
+
+generate_secret() {
+ if command -v python3 >/dev/null 2>&1 && python3 -c 'import secrets; print(secrets.token_hex(32))'; then
+ return
+ fi
+
+ if command -v openssl >/dev/null 2>&1 && openssl rand -hex 32; then
+ return
+ fi
+
+ if [[ -r /dev/urandom ]] && command -v od >/dev/null 2>&1 && command -v tr >/dev/null 2>&1 && od -An -N32 -tx1 /dev/urandom | tr -d ' \n'; then
+ return
+ fi
+
+ fail "Could not generate OSS_JWT_SECRET. Install python3 or openssl, or set OSS_JWT_SECRET manually in .env."
+}
+
+dotenv_value() {
+ local key=$1
+ local line
+
+ [[ -f "$ENV_FILE" ]] || return 1
+
+ while IFS= read -r line || [[ -n "$line" ]]; do
+ case "$line" in
+ "$key"=*)
+ printf '%s\n' "${line#*=}"
+ return 0
+ ;;
+ esac
+ done < "$ENV_FILE"
+
+ return 1
+}
+
+set_dotenv_value() {
+ local key=$1
+ local value=$2
+ local tmp_file="${ENV_FILE}.tmp.$$"
+ local line
+ local updated=false
+
+ if [[ -f "$ENV_FILE" ]]; then
+ while IFS= read -r line || [[ -n "$line" ]]; do
+ case "$line" in
+ "$key"=*)
+ printf '%s=%s\n' "$key" "$value"
+ updated=true
+ ;;
+ *)
+ printf '%s\n' "$line"
+ ;;
+ esac
+ done < "$ENV_FILE" > "$tmp_file"
+
+ if [[ "$updated" != "true" ]]; then
+ printf '%s=%s\n' "$key" "$value" >> "$tmp_file"
+ fi
+
+ mv "$tmp_file" "$ENV_FILE"
+ else
+ printf '%s=%s\n' "$key" "$value" > "$ENV_FILE"
+ fi
+}
+
+[[ -f docker-compose.yaml ]] || fail "docker-compose.yaml not found. Download it first, then re-run this script."
+
+existing_secret="$(dotenv_value OSS_JWT_SECRET || true)"
+if [[ -z "$existing_secret" ]]; then
+ set_dotenv_value OSS_JWT_SECRET "$(generate_secret)"
+ echo "Created OSS_JWT_SECRET in $ENV_FILE."
+else
+ echo "OSS_JWT_SECRET is already set in $ENV_FILE."
+fi
+
+echo ""
+echo "Docker registry: $REGISTRY"
+echo "Telemetry enabled: $ENABLE_TELEMETRY"
+echo ""
+echo "This will run:"
+echo " REGISTRY=$REGISTRY ENABLE_TELEMETRY=$ENABLE_TELEMETRY docker compose up --pull always"
+echo ""
+
+if [[ ! -t 0 ]]; then
+ echo "Run the command above from an interactive shell to start Dograh."
+ exit 0
+fi
+
+read -r -p "Start Dograh now? [Y/n]: " answer
+case "$answer" in
+ [Nn]*)
+ echo "Dograh was not started."
+ exit 0
+ ;;
+esac
+
+REGISTRY="$REGISTRY" ENABLE_TELEMETRY="$ENABLE_TELEMETRY" docker compose up --pull always