From a042dfb31c5ea65877a1497c7676408b5c8326f3 Mon Sep 17 00:00:00 2001 From: Olusegun Durojaye Date: Wed, 27 May 2026 00:22:51 +0100 Subject: [PATCH 1/7] Update OpenClaw template to new schema: secrets for sensitive vars, updated image ref, weight 10 --- .saturn/templates-enterprise.json | 4 +- .saturn/templates-hosted.json | 4 +- examples/openclaw/.saturn/saturn.json | 83 ++++++++++++++++++--------- 3 files changed, 61 insertions(+), 30 deletions(-) diff --git a/.saturn/templates-enterprise.json b/.saturn/templates-enterprise.json index 782e53fc..b949f925 100644 --- a/.saturn/templates-enterprise.json +++ b/.saturn/templates-enterprise.json @@ -109,9 +109,9 @@ "recipe_path": "examples/wandb/.saturn/saturn.json" }, { - "title": "OpenClaw (Deployment)", + "title": "OpenClaw Beta", "thumbnail_image_url": "https://saturn-public-assets.s3.us-east-2.amazonaws.com/example-thumbnails/openclaw.png", - "weight": 1950, + "weight": 10, "recipe_path": "examples/openclaw/.saturn/saturn.json" } ] diff --git a/.saturn/templates-hosted.json b/.saturn/templates-hosted.json index 782e53fc..b949f925 100644 --- a/.saturn/templates-hosted.json +++ b/.saturn/templates-hosted.json @@ -109,9 +109,9 @@ "recipe_path": "examples/wandb/.saturn/saturn.json" }, { - "title": "OpenClaw (Deployment)", + "title": "OpenClaw Beta", "thumbnail_image_url": "https://saturn-public-assets.s3.us-east-2.amazonaws.com/example-thumbnails/openclaw.png", - "weight": 1950, + "weight": 10, "recipe_path": "examples/openclaw/.saturn/saturn.json" } ] diff --git a/examples/openclaw/.saturn/saturn.json b/examples/openclaw/.saturn/saturn.json index 1b0d10fd..2091edbe 100644 --- a/examples/openclaw/.saturn/saturn.json +++ b/examples/openclaw/.saturn/saturn.json @@ -1,28 +1,59 @@ { - "name": "example-openclaw", - "image_uri": "public.ecr.aws/saturncloud/saturn-python:2025.05.01", - "description": "Deploy OpenClaw Beta on Saturn Cloud.", - "environment_variables": { - "ANTHROPIC_API_KEY": "", - "ENABLE_TELEGRAM": "false", - "ENABLE_WHATSAPP": "false", - "OPENCLAW_GATEWAY_TOKEN": "", - "OPENCLAW_MODEL": "anthropic/claude-sonnet-4-5", - "OPENCLAW_PUBLIC_ORIGIN": "https://your-subdomain.community.saturnenterprise.io", - "TELEGRAM_ALLOW_FROM": "[\"123456789\"]", - "TELEGRAM_BOT_TOKEN": "", - "WHATSAPP_ALLOW_FROM": "[\"+1234567890\"]" - }, - "working_directory": "/home/jovyan/examples/examples/openclaw", - "git_repositories": [ - { - "url": "https://github.com/saturncloud/examples", - "path": "/home/jovyan/examples" - } - ], - "deployment": { + "schema_version": "2024.04.01", + "type": "deployment", + "spec": { + "name": "example-openclaw", + "description": "Deploy OpenClaw Beta on Saturn Cloud.", + "tags": { + "type": "featured-tutorial" + }, + "image": "saturncloud/saturn-python:2025.05.01", "instance_type": "large", - "command": "bash .saturn/bootstrap-openclaw.sh" - }, - "version": "2022.01.06" -} \ No newline at end of file + "environment_variables": { + "ENABLE_TELEGRAM": "false", + "ENABLE_WHATSAPP": "false", + "OPENCLAW_MODEL": "anthropic/claude-sonnet-4-5", + "OPENCLAW_PUBLIC_ORIGIN": "https://your-subdomain.community.saturnenterprise.io", + "TELEGRAM_ALLOW_FROM": "[\"123456789\"]", + "WHATSAPP_ALLOW_FROM": "[\"+1234567890\"]" + }, + "secrets": [ + { + "description": "Gateway token for the OpenClaw deployment", + "location": "OPENCLAW_GATEWAY_TOKEN", + "attachment_type": "environment_variable" + }, + { + "description": "Anthropic API key for OpenClaw", + "location": "ANTHROPIC_API_KEY", + "attachment_type": "environment_variable" + }, + { + "description": "Telegram bot token (only required if ENABLE_TELEGRAM is true)", + "location": "TELEGRAM_BOT_TOKEN", + "attachment_type": "environment_variable" + } + ], + "working_directory": "/home/jovyan/examples/examples/openclaw", + "extra_packages": {}, + "start_script": "", + "token_scope": null, + "git_repositories": [ + { + "url": "https://github.com/saturncloud/examples", + "path": "/home/jovyan/examples", + "public": true, + "reference": "main", + "reference_type": "branch", + "on_restart": "preserve changes" + } + ], + "start_dind": false, + "command": "bash .saturn/bootstrap-openclaw.sh", + "scale": 1, + "start_ssh": false, + "use_spot_instance": false, + "routes": [], + "viewers": [] + } +} From 7e6892920a6b80b04fafd5fbaebdcca41bfdcde1 Mon Sep 17 00:00:00 2001 From: Olusegun Durojaye Date: Wed, 27 May 2026 04:26:41 +0100 Subject: [PATCH 2/7] Add name field to secrets entries for correct store linking --- examples/openclaw/.saturn/saturn.json | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/examples/openclaw/.saturn/saturn.json b/examples/openclaw/.saturn/saturn.json index 2091edbe..8595d6b8 100644 --- a/examples/openclaw/.saturn/saturn.json +++ b/examples/openclaw/.saturn/saturn.json @@ -19,19 +19,22 @@ }, "secrets": [ { - "description": "Gateway token for the OpenClaw deployment", + "name": "OPENCLAW_GATEWAY_TOKEN", "location": "OPENCLAW_GATEWAY_TOKEN", - "attachment_type": "environment_variable" + "attachment_type": "environment_variable", + "description": "Gateway token for the OpenClaw deployment" }, { - "description": "Anthropic API key for OpenClaw", + "name": "ANTHROPIC_API_KEY", "location": "ANTHROPIC_API_KEY", - "attachment_type": "environment_variable" + "attachment_type": "environment_variable", + "description": "Anthropic API key for OpenClaw" }, { - "description": "Telegram bot token (only required if ENABLE_TELEGRAM is true)", + "name": "TELEGRAM_BOT_TOKEN", "location": "TELEGRAM_BOT_TOKEN", - "attachment_type": "environment_variable" + "attachment_type": "environment_variable", + "description": "Telegram bot token (only required if ENABLE_TELEGRAM is true)" } ], "working_directory": "/home/jovyan/examples/examples/openclaw", From e32068f162c9a6037f6a548ae6fb0b8a97dcba6c Mon Sep 17 00:00:00 2001 From: Olusegun Durojaye Date: Wed, 27 May 2026 05:40:17 +0100 Subject: [PATCH 3/7] Auto-detect OPENCLAW_PUBLIC_ORIGIN from SATURN_JUPYTER_BASE_DOMAIN at startup --- .../openclaw/.saturn/bootstrap-openclaw.sh | 20 ++++++++++++++++++- examples/openclaw/.saturn/saturn.json | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/examples/openclaw/.saturn/bootstrap-openclaw.sh b/examples/openclaw/.saturn/bootstrap-openclaw.sh index b8e68b6f..38594e36 100755 --- a/examples/openclaw/.saturn/bootstrap-openclaw.sh +++ b/examples/openclaw/.saturn/bootstrap-openclaw.sh @@ -8,7 +8,25 @@ set -euo pipefail echo "[openclaw] starting setup..." : "${OPENCLAW_GATEWAY_TOKEN:?OPENCLAW_GATEWAY_TOKEN is required}" -: "${OPENCLAW_PUBLIC_ORIGIN:?OPENCLAW_PUBLIC_ORIGIN is required}" + +# Auto-detect the public origin from Saturn Cloud's injected env vars. +# SATURN_JUPYTER_BASE_DOMAIN is available in every Saturn Cloud container +# (workspace or deployment) and always matches the resource's public URL. +# If OPENCLAW_PUBLIC_ORIGIN is explicitly set to a real URL, that takes +# precedence — useful when a custom domain is in front of the deployment. +_PLACEHOLDER_ORIGIN="https://your-subdomain.community.saturnenterprise.io" +if [ -z "${OPENCLAW_PUBLIC_ORIGIN:-}" ] || [ "${OPENCLAW_PUBLIC_ORIGIN}" = "${_PLACEHOLDER_ORIGIN}" ]; then + if [ -n "${SATURN_JUPYTER_BASE_DOMAIN:-}" ]; then + OPENCLAW_PUBLIC_ORIGIN="https://${SATURN_JUPYTER_BASE_DOMAIN}" + echo "[openclaw] auto-detected public origin: $OPENCLAW_PUBLIC_ORIGIN" + else + echo "[openclaw] ERROR: OPENCLAW_PUBLIC_ORIGIN is not set and could not be auto-detected." + echo "[openclaw] Set OPENCLAW_PUBLIC_ORIGIN to your deployment URL and restart." + exit 1 + fi +else + echo "[openclaw] using configured public origin: $OPENCLAW_PUBLIC_ORIGIN" +fi ENABLE_WHATSAPP="${ENABLE_WHATSAPP:-false}" ENABLE_TELEGRAM="${ENABLE_TELEGRAM:-false}" diff --git a/examples/openclaw/.saturn/saturn.json b/examples/openclaw/.saturn/saturn.json index 8595d6b8..a1fe230b 100644 --- a/examples/openclaw/.saturn/saturn.json +++ b/examples/openclaw/.saturn/saturn.json @@ -13,7 +13,7 @@ "ENABLE_TELEGRAM": "false", "ENABLE_WHATSAPP": "false", "OPENCLAW_MODEL": "anthropic/claude-sonnet-4-5", - "OPENCLAW_PUBLIC_ORIGIN": "https://your-subdomain.community.saturnenterprise.io", + "OPENCLAW_PUBLIC_ORIGIN": "", "TELEGRAM_ALLOW_FROM": "[\"123456789\"]", "WHATSAPP_ALLOW_FROM": "[\"+1234567890\"]" }, From 453aa510d21510065624fdb81de8c4d835cfee6b Mon Sep 17 00:00:00 2001 From: Olusegun Durojaye Date: Wed, 27 May 2026 06:01:14 +0100 Subject: [PATCH 4/7] Add all AI provider secrets to recipe, rewrite README with full setup guide --- examples/openclaw/.saturn/saturn.json | 31 ++++-- examples/openclaw/README.md | 145 +++++++++++++++++++------- 2 files changed, 133 insertions(+), 43 deletions(-) diff --git a/examples/openclaw/.saturn/saturn.json b/examples/openclaw/.saturn/saturn.json index a1fe230b..606b8ea5 100644 --- a/examples/openclaw/.saturn/saturn.json +++ b/examples/openclaw/.saturn/saturn.json @@ -12,29 +12,46 @@ "environment_variables": { "ENABLE_TELEGRAM": "false", "ENABLE_WHATSAPP": "false", - "OPENCLAW_MODEL": "anthropic/claude-sonnet-4-5", + "OPENCLAW_MODEL": "", "OPENCLAW_PUBLIC_ORIGIN": "", "TELEGRAM_ALLOW_FROM": "[\"123456789\"]", "WHATSAPP_ALLOW_FROM": "[\"+1234567890\"]" }, "secrets": [ { - "name": "OPENCLAW_GATEWAY_TOKEN", "location": "OPENCLAW_GATEWAY_TOKEN", "attachment_type": "environment_variable", - "description": "Gateway token for the OpenClaw deployment" + "description": "Gateway authentication token — set this to a secure random string (e.g. openssl rand -hex 32). Required." }, { - "name": "ANTHROPIC_API_KEY", "location": "ANTHROPIC_API_KEY", "attachment_type": "environment_variable", - "description": "Anthropic API key for OpenClaw" + "description": "Anthropic API key. Link this OR one of the other provider keys below — only one is needed." + }, + { + "location": "OPENAI_API_KEY", + "attachment_type": "environment_variable", + "description": "OpenAI API key. Link this OR one of the other provider keys — only one is needed." + }, + { + "location": "GEMINI_API_KEY", + "attachment_type": "environment_variable", + "description": "Google Gemini API key. Link this OR one of the other provider keys — only one is needed." + }, + { + "location": "MISTRAL_API_KEY", + "attachment_type": "environment_variable", + "description": "Mistral API key. Link this OR one of the other provider keys — only one is needed." + }, + { + "location": "OPENROUTER_API_KEY", + "attachment_type": "environment_variable", + "description": "OpenRouter API key. Link this OR one of the other provider keys — only one is needed." }, { - "name": "TELEGRAM_BOT_TOKEN", "location": "TELEGRAM_BOT_TOKEN", "attachment_type": "environment_variable", - "description": "Telegram bot token (only required if ENABLE_TELEGRAM is true)" + "description": "Telegram bot token from BotFather. Only required if ENABLE_TELEGRAM is set to true." } ], "working_directory": "/home/jovyan/examples/examples/openclaw", diff --git a/examples/openclaw/README.md b/examples/openclaw/README.md index 44f7da05..68620524 100644 --- a/examples/openclaw/README.md +++ b/examples/openclaw/README.md @@ -1,54 +1,127 @@ -# OpenClaw on Saturn Cloud +# OpenClaw Beta on Saturn Cloud -This example runs [OpenClaw](https://docs.openclaw.ai/) as a **Deployment**: on start it installs OpenClaw (once), applies onboarding and configuration from environment variables, then runs `openclaw gateway` on port **8000**. The recipe uses **`saturn-python:2025.05.01`** and instance size **`large`** (AWS **r5.large**: 2 vCPU, 16 GB RAM). - -For the full guide (resource options, QR flows, troubleshooting), see: +[OpenClaw](https://docs.openclaw.ai/) is an AI agent gateway that connects any major AI model to a browser-based Control UI and optional messaging channels (Telegram, WhatsApp). This template deploys OpenClaw as a long-running **Deployment** on Saturn Cloud — install, onboard, and start the gateway automatically on every boot. +For the full guide, see: [https://saturncloud.io/blog/how-to-deploy-openclaw-on-saturncloud/](https://saturncloud.io/blog/how-to-deploy-openclaw-on-saturncloud/) -## Startup +--- + +## 🚀 Getting Started + +### Step 1 — Create your secrets + +Go to **Settings → Secrets** in Saturn Cloud and create the following secrets. Secret names must match exactly (case-sensitive). + +**Required:** + +| Secret name | What to put in it | +|---|---| +| `OPENCLAW_GATEWAY_TOKEN` | A secure random token — run `openssl rand -hex 32` to generate one. This is the password to access your OpenClaw Control UI. | + +**AI provider — create exactly one:** + +| Secret name | Provider | Default model (if `OPENCLAW_MODEL` is blank) | +|---|---|---| +| `ANTHROPIC_API_KEY` | Anthropic | `anthropic/claude-sonnet-4-5` | +| `OPENAI_API_KEY` | OpenAI | `openai/gpt-5.5` | +| `GEMINI_API_KEY` | Google Gemini | `google/gemini-3.1-pro-preview` | +| `MISTRAL_API_KEY` | Mistral | `mistral/mistral-large-latest` | +| `OPENROUTER_API_KEY` | OpenRouter | `openrouter/auto` | + +Only **one** provider key is needed. If you set more than one, OpenClaw uses the first it detects in the order listed above (Anthropic → OpenAI → Gemini → Mistral → OpenRouter). + +--- + +### Step 2 — Link your secrets to the deployment + +On the deployment detail page, scroll to the **Secrets** section. You'll see a slot for each provider. Link the secrets you created in Step 1 to their matching slots. Leave the other provider slots unlinked. + +--- + +### Step 3 — Configure optional settings + +In the **Environment Variables** section: + +| Variable | Default | When to change it | +|---|---|---| +| `OPENCLAW_MODEL` | *(auto, based on provider)* | Set a specific model ID to override the default, e.g. `anthropic/claude-opus-4-7` | +| `OPENCLAW_PUBLIC_ORIGIN` | *(auto-detected)* | Leave blank — the deployment auto-detects its own public URL at startup | +| `ENABLE_TELEGRAM` | `false` | Set to `true` to enable Telegram channel | +| `ENABLE_WHATSAPP` | `false` | Set to `true` to enable WhatsApp channel | + +--- + +### Step 4 — Start the deployment + +Hit **Start**. The bootstrap script will: +1. Install OpenClaw +2. Run non-interactive onboarding (configures gateway port, token auth, allowed origin) +3. Set the default model +4. Start the gateway on port 8000 + +Startup takes **3–5 minutes** on first boot. + +--- + +### Step 5 — Open the Control UI + +Once the status shows **Running**, click the deployment URL. You'll be prompted for your `OPENCLAW_GATEWAY_TOKEN`. Enter the token you generated in Step 1. + +--- + +## 🔌 Optional Channels + +### Telegram + +Set `ENABLE_TELEGRAM=true` and create + link a `TELEGRAM_BOT_TOKEN` secret (token from [@BotFather](https://t.me/BotFather)). -`deployment.command`: **`bash .saturn/bootstrap-openclaw.sh`** (runs from **`working_directory`**). +Update `TELEGRAM_ALLOW_FROM` with the Telegram user ID(s) allowed to message the bot: +``` +["your_telegram_user_id"] +``` +Get your Telegram user ID by messaging [@userinfobot](https://t.me/userinfobot). -## Environment variables +### WhatsApp -Set values in the deployment **Details** (never commit secrets). +Set `ENABLE_WHATSAPP=true`. -### Required +Update `WHATSAPP_ALLOW_FROM` with the phone number(s) in E.164 format: +``` +["+1234567890"] +``` +After the gateway starts, go to **Channels → WhatsApp** in the Control UI and scan the QR code. -| Variable | Description | -|----------|-------------| -| `OPENCLAW_GATEWAY_TOKEN` | Gateway authentication token (`--gateway-token-ref-env`). | -| `OPENCLAW_PUBLIC_ORIGIN` | Control UI allowed origin, e.g. `https://your-subdomain.community.saturnenterprise.io`. | +--- -### AI provider +## ⚙️ How It Works -Set **one** API key; that determines the provider. Optional model override: **`OPENCLAW_MODEL`**. +The deployment command runs `bash .saturn/bootstrap-openclaw.sh`, which: -| Variable | Description | -|----------|-------------| -| `OPENAI_API_KEY` | OpenAI (`openai-api-key`). | -| `ANTHROPIC_API_KEY` | Anthropic (`anthropic-api-key`). | -| `GEMINI_API_KEY` or `GOOGLE_API_KEY` | Gemini (`gemini-api-key`). | -| `MISTRAL_API_KEY` | Mistral (`mistral-api-key`). | -| `OPENROUTER_API_KEY` | OpenRouter (`openrouter-api-key`). | -| `OPENCLAW_MODEL` | Primary model id (defaults depend on provider if unset). | +1. **Validates** that `OPENCLAW_GATEWAY_TOKEN` is set — fails immediately with a clear error if not +2. **Auto-detects the public origin** from `SATURN_JUPYTER_BASE_DOMAIN` (injected by Saturn Cloud) — no manual URL needed +3. **Detects the AI provider** from whichever API key env var is set +4. **Installs OpenClaw** via the official installer +5. **Runs onboarding** non-interactively — configures port 8000, LAN binding, token auth +6. **Applies config** — sets model, allowed origins, disables device pairing for proxy environments +7. **Configures channels** if enabled (Telegram / WhatsApp) +8. **Starts the gateway** via `exec openclaw gateway` -### WhatsApp (optional) +--- -When **`ENABLE_WHATSAPP=true`**: +## 🛠️ Tech Stack -| Variable | Description | -|----------|-------------| -| `ENABLE_WHATSAPP` | `true` / `false`. | -| `WHATSAPP_ALLOW_FROM` | JSON array string, e.g. `["+1234567890"]`. | +| Component | Role | +|---|---| +| **OpenClaw** | AI agent gateway — Control UI, channels, tool use | +| **Saturn Cloud Deployment** | Hosts the gateway as a long-running service on port 8000 | +| **`saturn-python:2025.05.01`** | Base image (includes Node.js, required by OpenClaw) | +| **`large` instance** | AWS r5.large — 2 vCPU, 16 GB RAM | -### Telegram (optional) +--- -When **`ENABLE_TELEGRAM=true`**: +## 🔗 Resources -| Variable | Description | -|----------|-------------| -| `ENABLE_TELEGRAM` | `true` / `false`. | -| `TELEGRAM_BOT_TOKEN` | Bot token from BotFather. | -| `TELEGRAM_ALLOW_FROM` | JSON array string, e.g. `["123456789"]`. | +- [OpenClaw Documentation](https://docs.openclaw.ai/) +- [Saturn Cloud Deployment Guide](https://saturncloud.io/docs/) +- [Full Tutorial: OpenClaw on Saturn Cloud](https://saturncloud.io/blog/how-to-deploy-openclaw-on-saturncloud/) From 2dc614ddd64aeb47a07779628384d8f8d2349ec6 Mon Sep 17 00:00:00 2001 From: Olusegun Durojaye Date: Wed, 27 May 2026 06:12:50 +0100 Subject: [PATCH 5/7] Expand README with full user journey: secrets, linking, startup, Control UI, troubleshooting --- examples/openclaw/README.md | 177 +++++++++++++++++++++++++----------- 1 file changed, 124 insertions(+), 53 deletions(-) diff --git a/examples/openclaw/README.md b/examples/openclaw/README.md index 68620524..391c93aa 100644 --- a/examples/openclaw/README.md +++ b/examples/openclaw/README.md @@ -1,27 +1,53 @@ # OpenClaw Beta on Saturn Cloud -[OpenClaw](https://docs.openclaw.ai/) is an AI agent gateway that connects any major AI model to a browser-based Control UI and optional messaging channels (Telegram, WhatsApp). This template deploys OpenClaw as a long-running **Deployment** on Saturn Cloud — install, onboard, and start the gateway automatically on every boot. +[OpenClaw](https://docs.openclaw.ai/) is an AI agent gateway that connects any major AI model to a browser-based Control UI and optional messaging channels (Telegram, WhatsApp). This template deploys OpenClaw as a long-running **Deployment** on Saturn Cloud — it installs, configures, and starts the gateway automatically every time it boots. For the full guide, see: [https://saturncloud.io/blog/how-to-deploy-openclaw-on-saturncloud/](https://saturncloud.io/blog/how-to-deploy-openclaw-on-saturncloud/) --- -## 🚀 Getting Started +## What You'll End Up With -### Step 1 — Create your secrets +A live OpenClaw gateway running on Saturn Cloud, accessible at your deployment URL, protected by your own token, connected to the AI provider of your choice. Total setup time: **under 10 minutes** (plus 3–5 minutes for the deployment to boot). -Go to **Settings → Secrets** in Saturn Cloud and create the following secrets. Secret names must match exactly (case-sensitive). +--- -**Required:** +## Step 1 — Create the Deployment from the Template -| Secret name | What to put in it | -|---|---| -| `OPENCLAW_GATEWAY_TOKEN` | A secure random token — run `openssl rand -hex 32` to generate one. This is the password to access your OpenClaw Control UI. | +Click **Use Template** on the OpenClaw Beta card. Saturn Cloud pre-fills the deployment form with everything already configured: + +- Instance type, image, and command are set +- Environment variables are pre-filled with sensible defaults +- Secret slots for your gateway token and all supported AI providers are already defined with descriptions + +You can rename the deployment if you like. Click **Create** — the deployment is created but not started yet. You'll set up your secrets first. + +--- + +## Step 2 — Create Your Secrets + +Go to **Settings → Secrets** in the left sidebar. You need to create **two secrets**: one gateway token and one AI provider key. -**AI provider — create exactly one:** +### Gateway token (required) -| Secret name | Provider | Default model (if `OPENCLAW_MODEL` is blank) | +This is the password that protects access to your OpenClaw Control UI. Generate a secure random one: + +```bash +openssl rand -hex 32 +``` + +Copy the output. In **Settings → Secrets**, click **New Secret**: +- **Name**: `OPENCLAW_GATEWAY_TOKEN` +- **Value**: the output from the command above + +Save it somewhere safe — you'll need it every time you open the Control UI. + +### AI provider key (pick one) + +Create a secret for whichever AI provider you have an account with. Only one is needed. + +| Secret name | Provider | Default model used | |---|---|---| | `ANTHROPIC_API_KEY` | Anthropic | `anthropic/claude-sonnet-4-5` | | `OPENAI_API_KEY` | OpenAI | `openai/gpt-5.5` | @@ -29,83 +55,112 @@ Go to **Settings → Secrets** in Saturn Cloud and create the following secrets. | `MISTRAL_API_KEY` | Mistral | `mistral/mistral-large-latest` | | `OPENROUTER_API_KEY` | OpenRouter | `openrouter/auto` | -Only **one** provider key is needed. If you set more than one, OpenClaw uses the first it detects in the order listed above (Anthropic → OpenAI → Gemini → Mistral → OpenRouter). +If you set more than one, OpenClaw picks the first it detects in the order above (Anthropic → OpenAI → Gemini → Mistral → OpenRouter). --- -### Step 2 — Link your secrets to the deployment +## Step 3 — Link Your Secrets to the Deployment -On the deployment detail page, scroll to the **Secrets** section. You'll see a slot for each provider. Link the secrets you created in Step 1 to their matching slots. Leave the other provider slots unlinked. +Go back to your deployment and open the **Details** tab. Scroll to the **Secrets** section — you'll see a slot for each provider and for the gateway token. + +- Find the `OPENCLAW_GATEWAY_TOKEN` slot → click its dropdown → select the `OPENCLAW_GATEWAY_TOKEN` secret you just created +- Find the slot matching your AI provider (e.g. `ANTHROPIC_API_KEY`) → link your API key secret to it +- Leave all other provider slots **unlinked** — that's fine, the unused ones are just ignored --- -### Step 3 — Configure optional settings +## Step 4 — Optional Configuration + +Most users can skip this step entirely and go straight to Start. The defaults work out of the box. -In the **Environment Variables** section: +If you want to customise: -| Variable | Default | When to change it | +| Environment variable | Default | When to change | |---|---|---| -| `OPENCLAW_MODEL` | *(auto, based on provider)* | Set a specific model ID to override the default, e.g. `anthropic/claude-opus-4-7` | -| `OPENCLAW_PUBLIC_ORIGIN` | *(auto-detected)* | Leave blank — the deployment auto-detects its own public URL at startup | -| `ENABLE_TELEGRAM` | `false` | Set to `true` to enable Telegram channel | -| `ENABLE_WHATSAPP` | `false` | Set to `true` to enable WhatsApp channel | +| `OPENCLAW_MODEL` | *(auto, based on provider)* | Set a specific model ID, e.g. `anthropic/claude-opus-4-7` or `openai/gpt-4o` | +| `OPENCLAW_PUBLIC_ORIGIN` | *(auto-detected)* | Leave blank — the deployment detects its own public URL at startup. Only set this if you're using a custom domain in front of the deployment. | +| `ENABLE_TELEGRAM` | `false` | Set to `true` to connect a Telegram bot | +| `ENABLE_WHATSAPP` | `false` | Set to `true` to connect WhatsApp | +| `TELEGRAM_ALLOW_FROM` | `["123456789"]` | Replace with your actual Telegram user ID(s) | +| `WHATSAPP_ALLOW_FROM` | `["+1234567890"]` | Replace with your actual phone number(s) in E.164 format | --- -### Step 4 — Start the deployment +## Step 5 — Start the Deployment + +Click **Start**. The status changes from `stopped` → `pending` → `running`. + +During startup (3–5 minutes), the bootstrap script runs automatically. You can watch its progress in the **Logs** section of the deployment page: -Hit **Start**. The bootstrap script will: -1. Install OpenClaw -2. Run non-interactive onboarding (configures gateway port, token auth, allowed origin) -3. Set the default model -4. Start the gateway on port 8000 +``` +[openclaw] starting setup... +[openclaw] auto-detected public origin: https://your-deployment-url.community.saturnenterprise.io +[openclaw] selected auth provider: anthropic-api-key +[openclaw] selected model: anthropic/claude-sonnet-4-5 +[openclaw] installing OpenClaw... +[openclaw] running onboarding... +[openclaw] setting default model... +[openclaw] starting gateway on port 8000... +[gateway] ready +``` -Startup takes **3–5 minutes** on first boot. +If the status changes to `error`, check the logs — the most common cause is a missing or unlinked secret. --- -### Step 5 — Open the Control UI +## Step 6 — Open the Control UI + +Once the status shows **Running**, click the deployment URL (shown on the deployment detail page). The OpenClaw Control UI opens in your browser. -Once the status shows **Running**, click the deployment URL. You'll be prompted for your `OPENCLAW_GATEWAY_TOKEN`. Enter the token you generated in Step 1. +When prompted for a token, enter the value of `OPENCLAW_GATEWAY_TOKEN` — the one you generated with `openssl rand -hex 32` in Step 2. You're in. --- -## 🔌 Optional Channels +## Step 7 — Use OpenClaw -### Telegram +Inside the Control UI you can: -Set `ENABLE_TELEGRAM=true` and create + link a `TELEGRAM_BOT_TOKEN` secret (token from [@BotFather](https://t.me/BotFather)). +- **Chat** with your AI model directly from the browser +- **View conversation history** across sessions +- **Configure tools and plugins** (web search, memory, and more) +- **Connect Telegram** (if enabled) — message your bot from Telegram and it replies via your AI model +- **Connect WhatsApp** (if enabled) — go to Channels → WhatsApp and scan the QR code -Update `TELEGRAM_ALLOW_FROM` with the Telegram user ID(s) allowed to message the bot: -``` -["your_telegram_user_id"] -``` -Get your Telegram user ID by messaging [@userinfobot](https://t.me/userinfobot). +--- -### WhatsApp +## 🔌 Enabling Telegram -Set `ENABLE_WHATSAPP=true`. +1. Create a bot via [@BotFather](https://t.me/BotFather) on Telegram — it gives you a bot token +2. Create a secret named `TELEGRAM_BOT_TOKEN` in **Settings → Secrets** with that token +3. Link it to the `TELEGRAM_BOT_TOKEN` slot on your deployment +4. Get your Telegram user ID by messaging [@userinfobot](https://t.me/userinfobot) +5. Set `ENABLE_TELEGRAM=true` and update `TELEGRAM_ALLOW_FROM` with your user ID: `["your_id"]` +6. Restart the deployment -Update `WHATSAPP_ALLOW_FROM` with the phone number(s) in E.164 format: -``` -["+1234567890"] -``` -After the gateway starts, go to **Channels → WhatsApp** in the Control UI and scan the QR code. +--- + +## 🔌 Enabling WhatsApp + +1. Set `ENABLE_WHATSAPP=true` and update `WHATSAPP_ALLOW_FROM` with your phone number in E.164 format: `["+1234567890"]` +2. Restart the deployment +3. Once running, open the Control UI → go to **Channels → WhatsApp** → scan the QR code with your phone --- ## ⚙️ How It Works -The deployment command runs `bash .saturn/bootstrap-openclaw.sh`, which: +Every time the deployment starts, `bash .saturn/bootstrap-openclaw.sh` runs and does the following in order: -1. **Validates** that `OPENCLAW_GATEWAY_TOKEN` is set — fails immediately with a clear error if not -2. **Auto-detects the public origin** from `SATURN_JUPYTER_BASE_DOMAIN` (injected by Saturn Cloud) — no manual URL needed -3. **Detects the AI provider** from whichever API key env var is set -4. **Installs OpenClaw** via the official installer -5. **Runs onboarding** non-interactively — configures port 8000, LAN binding, token auth -6. **Applies config** — sets model, allowed origins, disables device pairing for proxy environments -7. **Configures channels** if enabled (Telegram / WhatsApp) -8. **Starts the gateway** via `exec openclaw gateway` +| Step | What happens | +|---|---| +| **Validate** | Fails immediately with a clear error if `OPENCLAW_GATEWAY_TOKEN` is not set | +| **Auto-detect origin** | Reads `SATURN_JUPYTER_BASE_DOMAIN` (injected by Saturn Cloud into every container) and sets the Control UI allowed origin automatically — no manual URL needed | +| **Detect provider** | Checks which API key env var is set and picks the matching provider and default model | +| **Install** | Downloads and installs OpenClaw via the official installer | +| **Onboard** | Runs `openclaw onboard --non-interactive` — configures port 8000, LAN binding, token auth | +| **Configure** | Sets the default model, allowed origins, and disables device pairing (required for Saturn's proxy environment) | +| **Channels** | Configures Telegram and/or WhatsApp if enabled | +| **Start** | Runs `exec openclaw gateway` — replaces the shell with the gateway process | --- @@ -120,6 +175,22 @@ The deployment command runs `bash .saturn/bootstrap-openclaw.sh`, which: --- +## ❓ Troubleshooting + +**Deployment goes to `error` on startup** +→ Open the **Logs** section. Look for `is required` in the output — this means a required secret is missing or unlinked. Check that `OPENCLAW_GATEWAY_TOKEN` and your AI provider key are both linked in the Secrets section. + +**Control UI loads but token is rejected** +→ Make sure you're entering the exact value you set for `OPENCLAW_GATEWAY_TOKEN`, not the secret name. Copy it directly from where you saved it. + +**`origin not allowed` error in logs** +→ `OPENCLAW_PUBLIC_ORIGIN` was set to an incorrect value. Clear it (set to blank) and restart — auto-detection will handle it correctly. + +**No AI provider found error in logs** +→ None of the AI provider keys are linked. Go to the deployment's Secrets section and link your API key to the correct slot. + +--- + ## 🔗 Resources - [OpenClaw Documentation](https://docs.openclaw.ai/) From 196aacb015cc440060e8217ffc2ca954d386b913 Mon Sep 17 00:00:00 2001 From: Olusegun Durojaye Date: Wed, 27 May 2026 06:25:20 +0100 Subject: [PATCH 6/7] Add debug env dump to identify Saturn vars available in deployments --- examples/openclaw/.saturn/bootstrap-openclaw.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/openclaw/.saturn/bootstrap-openclaw.sh b/examples/openclaw/.saturn/bootstrap-openclaw.sh index 38594e36..9f3eeea0 100755 --- a/examples/openclaw/.saturn/bootstrap-openclaw.sh +++ b/examples/openclaw/.saturn/bootstrap-openclaw.sh @@ -7,6 +7,12 @@ set -euo pipefail echo "[openclaw] starting setup..." +echo "[openclaw] debug — Saturn Cloud env vars:" +env | grep -i saturn || true +echo "[openclaw] debug — BOKEH vars:" +env | grep -i bokeh || true +echo "[openclaw] debug — end" + : "${OPENCLAW_GATEWAY_TOKEN:?OPENCLAW_GATEWAY_TOKEN is required}" # Auto-detect the public origin from Saturn Cloud's injected env vars. From 9457ccc4ea717431fee6d4e412e636b046d24ef0 Mon Sep 17 00:00:00 2001 From: Olusegun Durojaye Date: Wed, 27 May 2026 06:27:43 +0100 Subject: [PATCH 7/7] Fix auto-detect: use Saturn API + JWT decode instead of workspace-only env var --- .../openclaw/.saturn/bootstrap-openclaw.sh | 57 ++++++++++++++----- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/examples/openclaw/.saturn/bootstrap-openclaw.sh b/examples/openclaw/.saturn/bootstrap-openclaw.sh index 9f3eeea0..963cfcad 100755 --- a/examples/openclaw/.saturn/bootstrap-openclaw.sh +++ b/examples/openclaw/.saturn/bootstrap-openclaw.sh @@ -7,25 +7,56 @@ set -euo pipefail echo "[openclaw] starting setup..." -echo "[openclaw] debug — Saturn Cloud env vars:" -env | grep -i saturn || true -echo "[openclaw] debug — BOKEH vars:" -env | grep -i bokeh || true -echo "[openclaw] debug — end" - : "${OPENCLAW_GATEWAY_TOKEN:?OPENCLAW_GATEWAY_TOKEN is required}" -# Auto-detect the public origin from Saturn Cloud's injected env vars. -# SATURN_JUPYTER_BASE_DOMAIN is available in every Saturn Cloud container -# (workspace or deployment) and always matches the resource's public URL. +# Auto-detect the public origin from the Saturn Cloud API. +# SATURN_TOKEN (a JWT) contains the deployment ID in its payload. +# We decode it, call the Saturn API to get the deployment's public URL, +# and use that as the allowed origin for the OpenClaw Control UI. # If OPENCLAW_PUBLIC_ORIGIN is explicitly set to a real URL, that takes # precedence — useful when a custom domain is in front of the deployment. _PLACEHOLDER_ORIGIN="https://your-subdomain.community.saturnenterprise.io" if [ -z "${OPENCLAW_PUBLIC_ORIGIN:-}" ] || [ "${OPENCLAW_PUBLIC_ORIGIN}" = "${_PLACEHOLDER_ORIGIN}" ]; then - if [ -n "${SATURN_JUPYTER_BASE_DOMAIN:-}" ]; then - OPENCLAW_PUBLIC_ORIGIN="https://${SATURN_JUPYTER_BASE_DOMAIN}" - echo "[openclaw] auto-detected public origin: $OPENCLAW_PUBLIC_ORIGIN" - else + echo "[openclaw] auto-detecting public origin via Saturn API..." + + if [ -n "${SATURN_TOKEN:-}" ] && [ -n "${SATURN_BASE_URL:-}" ]; then + # Decode JWT payload to extract the deployment ID + _RESOURCE_ID=$(python3 -c " +import json, base64, sys +try: + token = '$SATURN_TOKEN' + payload = token.split('.')[1] + payload += '=' * (4 - len(payload) % 4) + data = json.loads(base64.urlsafe_b64decode(payload)) + resource = data.get('resource', '') + print(resource.split(':')[-1] if ':' in resource else '') +except: + print('') +" 2>/dev/null) + + if [ -n "$_RESOURCE_ID" ]; then + _PUBLIC_URL=$(curl -sf \ + -H "Authorization: token $SATURN_TOKEN" \ + "$SATURN_BASE_URL/api/deployments/$_RESOURCE_ID" \ + | python3 -c " +import json, sys +try: + data = json.load(sys.stdin) + url = (data.get('state', {}).get('url') or + data.get('url') or '') + print(url) +except: + print('') +" 2>/dev/null) + + if [ -n "$_PUBLIC_URL" ]; then + OPENCLAW_PUBLIC_ORIGIN="$_PUBLIC_URL" + echo "[openclaw] auto-detected public origin: $OPENCLAW_PUBLIC_ORIGIN" + fi + fi + fi + + if [ -z "${OPENCLAW_PUBLIC_ORIGIN:-}" ]; then echo "[openclaw] ERROR: OPENCLAW_PUBLIC_ORIGIN is not set and could not be auto-detected." echo "[openclaw] Set OPENCLAW_PUBLIC_ORIGIN to your deployment URL and restart." exit 1