1Prerequisites
Cloudflare account
- Workers Paid plan ($5/month), required for Sandbox containers. dash.cloudflare.com
Local tools
# Check Node.js version (need 18+)
node --version
# Install Wrangler (Cloudflare's deployment tool)
npm install -g wrangler
# Authenticate with Cloudflare
wrangler loginCreate R2 buckets
Go to R2 Object Storage > Create bucket in the Cloudflare Dashboard:
- 1.moltbot-data: Stores OpenClaw config, conversation history, device pairings, workspace files
- 2.obsidian-vault (optional): Stores your Obsidian vault for AI-accessible knowledge base
Create R2 API credentials
Go to R2 Object Storage > Manage R2 API Tokens > Create API Token:
- Token name:
moltbot-rclone - Permissions: Object Read & Write
- Scope: Apply to specific buckets (select
moltbot-dataandobsidian-vault)
Save the Access Key ID and Secret Access Key. You'll need them later.
Use R2 API Tokens (under R2 settings), not the general Cloudflare API tokens. They're different systems. Find them at: Dashboard > R2 Object Storage > Manage R2 API Tokens.
Note your account ID
Your Cloudflare Account ID is in the URL when viewing the dashboard: dash.cloudflare.com/{account-id}/... You'll also find it on the Workers & Pages overview page in the right sidebar.
2Project setup
Clone and install
Moltworker is Cloudflare's official wrapper for running OpenClaw in Sandbox containers.
git clone https://github.com/cloudflare/moltworker.git
cd moltworker
npm installProject structure
moltworker/
├── src/
│ ├── index.ts # Main Worker entry point
│ ├── types.ts # Environment variable types
│ ├── auth/ # Cloudflare Access JWT verification
│ ├── gateway/ # OpenClaw process lifecycle
│ ├── routes/ # Admin UI, API, vault, debug endpoints
│ └── client/ # React admin UI source
├── Dockerfile # Container image (Ubuntu + Node.js + OpenClaw)
├── start-openclaw.sh # Container startup script
├── skills/ # Custom skills (SKILL.md files)
├── wrangler.jsonc # Cloudflare Worker configuration
└── package.jsonKey config: wrangler.jsonc
This file defines your Worker's bindings. The important sections:
{
"name": "moltbot-sandbox",
"main": "src/index.ts",
"compatibility_date": "2025-05-06",
"compatibility_flags": ["nodejs_compat"],
// Sandbox container configuration
"containers": [{
"class_name": "Sandbox",
"image": "./Dockerfile",
"instance_type": "standard-1", // 1/2 vCPU, 4GB RAM, 8GB disk
"max_instances": 1
}],
// R2 storage buckets
"r2_buckets": [
{ "binding": "MOLTBOT_BUCKET", "bucket_name": "moltbot-data" },
{ "binding": "OBSIDIAN_VAULT", "bucket_name": "obsidian-vault" }
],
// Admin UI static assets
"assets": {
"directory": "./dist/client",
"binding": "ASSETS",
"html_handling": "single-page-application"
}
}3Configure secrets
Gateway token (required)
Protects the Control UI. Generate a random token and set it:
# Generate a random token
openssl rand -hex 32
# Set it as a secret
npx wrangler secret put MOLTBOT_GATEWAY_TOKENAI provider (pick one)
Option A: Cloudflare AI Gateway (recommended): Routes through Cloudflare with caching, rate limiting, and analytics. Supports Anthropic, OpenAI, and Workers AI backends.
npx wrangler secret put CLOUDFLARE_AI_GATEWAY_API_KEY # API key for your backend
npx wrangler secret put CF_AI_GATEWAY_ACCOUNT_ID # Your Cloudflare account ID
npx wrangler secret put CF_AI_GATEWAY_GATEWAY_ID # Gateway ID (create in Dashboard > AI > AI Gateway)
npx wrangler secret put CF_AI_GATEWAY_MODEL # e.g., "anthropic/claude-sonnet-4-5"| Model | Value |
|---|---|
| Claude Sonnet 4.5 | anthropic/claude-sonnet-4-5 |
| GPT-4o | openai/gpt-4o |
| Llama 3.3 70B (Workers AI) | workers-ai/@cf/meta/llama-3.3-70b-instruct-fp8-fast |
| Qwen3 30B (Workers AI) | workers-ai/@cf/qwen/qwen3-30b-a3b-fp8 |
Workers AI models are cheaper (some have free tiers) but lower quality than Claude or GPT-4o. Start cheap to verify everything works, then upgrade.
Option B: Direct Anthropic API key
npx wrangler secret put ANTHROPIC_API_KEYOption C: Direct OpenAI API key
npx wrangler secret put OPENAI_API_KEYR2 persistence (strongly recommended)
Without R2, all configuration, conversations, and device pairings are lost when the container restarts.
npx wrangler secret put R2_ACCESS_KEY_ID # From R2 API token creation
npx wrangler secret put R2_SECRET_ACCESS_KEY # From R2 API token creation
npx wrangler secret put CF_ACCOUNT_ID # Your Cloudflare account IDVerify your secrets
npx wrangler secret listYou should see your configured secrets listed (values are hidden).
4Deploy to Cloudflare
# Build the admin UI and deploy everything
npm run deployThis builds the React admin UI with Vite, builds the Docker container image (installs Node.js 22, OpenClaw, rclone, git, gh), pushes the image to Cloudflare's registry, and deploys the Worker.
First deploy takes 5-10 minutes because it builds the Docker image from scratch. Subsequent deploys are faster due to layer caching.
Verify deployment
curl https://your-worker.your-subdomain.workers.dev/api/statusYour Worker URL follows the pattern: https://{worker-name}.{subdomain}.workers.dev. Find it in the Wrangler output or in Dashboard > Workers & Pages.
5Set up Cloudflare Access (Zero Trust auth)
Cloudflare Access protects the admin UI and API endpoints with identity-provider login (Google, GitHub, email OTP, etc.).
Create an Access application
- 1.Go to Cloudflare Zero Trust Dashboard
- 2.Navigate to Access > Applications > Add an application
- 3.Choose Self-hosted
- 4.Set your Worker URL as the application domain, leave path empty
- 5.Add a policy: Allow > Emails > your email address
- 6.Save and note the Application Audience (AUD) tag from the overview page
Set Access secrets
# Your Zero Trust team domain (e.g., myteam.cloudflareaccess.com)
npx wrangler secret put CF_ACCESS_TEAM_DOMAIN
# Application Audience tag (the long hex string from step 6)
npx wrangler secret put CF_ACCESS_AUDHow auth works
Three layers of authentication:
Cloudflare Access
JWT verification via JWKS endpoint. Protects /_admin/*, /api/*, /debug/*
Gateway token
Injected server-side into WebSocket connections after CF Access validates the user
Device pairing
Each new client (browser, app) must be approved via the admin UI before it can chat
6First boot and device pairing
- 1.Open your Worker URL:
https://your-worker.workers.dev/_admin/ - 2.Authenticate through Cloudflare Access
- 3.The admin UI loads, showing the Control UI
- 4.Pair your device (you may need to add
?token=YOUR_GATEWAY_TOKENto the URL)
First boot takes ~80 seconds (cold start). The container needs to start, run the startup script, restore from R2, and launch the OpenClaw gateway.
Admin API endpoints
| Endpoint | Method | Purpose |
|---|---|---|
| /api/admin/devices | GET | List paired/pending devices |
| /api/admin/devices | POST | Approve device |
| /api/admin/storage | POST | Trigger manual R2 backup |
| /api/admin/gateway/restart | POST | Restart OpenClaw process |
7AI model configuration
Switching models
Change the CF_AI_GATEWAY_MODEL secret and restart the container (via admin UI or redeploy).
npx wrangler secret put CF_AI_GATEWAY_MODEL
# Enter: anthropic/claude-sonnet-4-5Model comparison
| Model | Cost | Quality | Best for |
|---|---|---|---|
| Claude Sonnet 4.5 | ~$3/1M input | Excellent | General assistant, coding |
| GPT-4o | ~$2.50/1M input | Excellent | Broad knowledge, creative |
| Qwen3 30B | Very cheap | Good | Budget-friendly, basic tasks |
| Llama 3.3 70B | Cheap (free tier) | Decent | Testing, simple queries |
Start with a Workers AI model to verify everything works, then upgrade to Claude or GPT-4o.
Monitoring costs
- AI Gateway: Dashboard > AI > AI Gateway > Analytics
- Workers AI: Dashboard > AI > Workers AI (shows usage and costs)
- Direct API keys: Check your provider's dashboard (Anthropic Console, OpenAI Usage)
8R2 persistent storage
How persistence works
The container is ephemeral. When it restarts, everything is lost. R2 persistence solves this:
On startup
start-openclaw.sh uses rclone to restore from R2: config, workspace files, and custom skills
Background sync
Every 30 seconds, changed files are synced back to R2 (excludes lock files, logs, .git, node_modules)
Manual backup
Available via admin API: POST /api/admin/storage
What's stored in R2
| R2 path | Container path | Contents |
|---|---|---|
| openclaw/ | /root/.openclaw/ | Config, device records |
| workspace/ | /root/clawd/ | SOUL.md, USER.md, AGENTS.md |
| skills/ | /root/clawd/skills/ | Custom SKILL.md files |
9Obsidian vault sync (Second Brain)
Optional step that syncs your Obsidian vault to R2 so the AI can search your notes.
Install Remotely Save plugin
- 1.In Obsidian: Settings > Community Plugins > Browse > search “Remotely Save”
- 2.Install and enable the plugin
Configure S3-compatible storage
In Remotely Save settings:
- Remote service: S3 or S3-compatible
- Endpoint:
https://{your-account-id}.r2.cloudflarestorage.com - Region:
auto - Access Key ID: Your R2 API token access key
- Secret Access Key: Your R2 API token secret key
- Bucket name:
obsidian-vault
Add exclusion patterns in Remotely Save for any private folders you don't want synced.
10Vault MCP server with semantic search
This deploys a separate Cloudflare Worker that provides MCP access to your Obsidian vault with AI-powered semantic search.
Create the project
# In a separate directory from moltworker
npm create cloudflare@latest vault-mcp -- --template cloudflare/ai-mcp-demo
cd vault-mcpCreate the Vectorize index
npx wrangler vectorize create vault-embeddings \
--dimensions 768 \
--metric cosine768 dimensions matches the BGE Base English embedding model (@cf/baai/bge-base-en-v1.5).
Set auth token
npx wrangler secret put VAULT_TOKENAvailable MCP tools
| Tool | Description |
|---|---|
| list_files | List vault files, optionally filtered by prefix |
| read_file | Read a single file's contents |
| search | Keyword search across all text files |
| semantic_search | AI-powered meaning-based search using embeddings |
| index_vault | Build/rebuild the semantic search index |
How semantic search works
Each markdown file is split into ~500-character chunks by paragraph boundaries
Chunks are converted to 768-dimensional vectors using @cf/baai/bge-base-en-v1.5
Vectors stored in Vectorize with metadata (file path, chunk index, preview)
Queries get embedded and matched via cosine similarity
Cron job re-indexes modified files every 15 minutes
Cost: Workers AI embeddings are ~$0.011 per 1M tokens. There's a free tier of 10,000 neurons/day. A typical vault of 500-1000 files costs fractions of a cent to index.
Deploy and connect
npx wrangler deployThen add the MCP server to your client's configuration:
{
"mcpServers": {
"second-brain": {
"url": "https://vault-mcp.your-subdomain.workers.dev/mcp",
"headers": {
"Authorization": "Bearer YOUR_VAULT_TOKEN"
}
}
}
}11GitHub integration (PR creation)
This lets the OpenClaw agent clone repos, make changes, and create pull requests.
Create a fine-grained GitHub PAT
- 1.Go to GitHub Fine-grained PAT settings
- 2.Repository access: “Only select repositories” > choose the repos you want
- 3.Permissions: Contents (Read & write), Pull requests (Read & write), Metadata (Read-only)
Set secrets
npx wrangler secret put GITHUB_TOKEN # Your fine-grained PAT
# Optional: override the default git identity
npx wrangler secret put GIT_USER_NAME # Default: "Gravemind"
npx wrangler secret put GIT_USER_EMAIL # Default: "gravemind@blueorchid.world"Then redeploy: npm run deploy
How it works inside the container
When the container starts with GITHUB_TOKEN set, the startup script configures git, authenticates gh CLI, and rewrites HTTPS URLs to use the token automatically.
A github-dev skill teaches the agent the workflow: clone to /tmp/REPO, create a feature branch, make changes, commit with conventional messages, push and create a PR via gh pr create.
12Chat channel setup
Telegram (easiest)
- 1.Message
@BotFatheron Telegram, send/newbot - 2.Copy the bot token
- 3.Set secrets and redeploy
npx wrangler secret put TELEGRAM_BOT_TOKEN # Bot token from BotFather
npx wrangler secret put TELEGRAM_DM_POLICY # "pairing" (secure) or "open"
npm run deployIf using “pairing” policy: approve the device in /_admin/ after messaging the bot.
Discord
npx wrangler secret put DISCORD_BOT_TOKEN
npx wrangler secret put DISCORD_DM_POLICY # "pairing" or "open"
npm run deployCreate a bot at the Discord Developer Portal.
Slack
npx wrangler secret put SLACK_BOT_TOKEN
npx wrangler secret put SLACK_APP_TOKEN
npm run deployCreate a Slack app at api.slack.com and enable Socket Mode.
13Workspace personality files
OpenClaw loads workspace files from /root/clawd/ into every conversation's system prompt (max 24k characters). These define your agent's personality, context, and behavior.
| File | Purpose |
|---|---|
| SOUL.md | Personality, tone, boundaries |
| USER.md | Who you are, your context |
| AGENTS.md | Operating rules, priorities |
| IDENTITY.md | Name, branding |
| HEARTBEAT.md | Periodic check-in behavior |
| TOOLS.md | Notes about available tools |
How to add workspace files
Option A: Edit via the OpenClaw Control UI (changes sync to R2 automatically)
Option B: Upload directly to R2:
echo "You are Gravemind, a proactive AI assistant..." > /tmp/SOUL.md
npx wrangler r2 object put moltbot-data/workspace/SOUL.md --file /tmp/SOUL.mdOption C: Add to the skills/ directory in the moltworker repo and redeploy
Files are restored from R2 on every container restart and synced back every 30 seconds when changed.
14Troubleshooting
| Issue | Solution |
|---|---|
| 502/503 after deploy | First cold start takes ~80 seconds. Wait and retry. Check logs: npx wrangler tail moltbot-sandbox |
| 401 or redirect loop on /_admin/ | Verify CF_ACCESS_TEAM_DOMAIN and CF_ACCESS_AUD secrets are set. Check your email is in the Access allow list. Clear cookies. |
| Low-quality AI responses | You're likely using a small model. Upgrade: npx wrangler secret put CF_AI_GATEWAY_MODEL > anthropic/claude-sonnet-4-5 |
| Config lost on restart | Verify R2 secrets: R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, CF_ACCOUNT_ID. Trigger manual backup via POST /api/admin/storage. |
| Remotely Save errors in Obsidian | Press Cmd+P > “Reload app without saving”. This rebuilds the file index. |
| Device pairing stuck | Try approving via API: POST /api/admin/devices with { "action": "approve-all" }. Check gateway is running via GET /api/status. |
15Architecture reference
Environment variables
| Variable | Required | Description |
|---|---|---|
| MOLTBOT_GATEWAY_TOKEN | Yes | Protects Control UI access |
| CLOUDFLARE_AI_GATEWAY_API_KEY | One AI provider | AI Gateway API key |
| CF_AI_GATEWAY_ACCOUNT_ID | With AI Gateway | Cloudflare account ID |
| CF_AI_GATEWAY_GATEWAY_ID | With AI Gateway | AI Gateway instance ID |
| CF_AI_GATEWAY_MODEL | With AI Gateway | provider/model-id |
| ANTHROPIC_API_KEY | Alt provider | Direct Anthropic key |
| CF_ACCESS_TEAM_DOMAIN | For admin auth | Zero Trust team domain |
| CF_ACCESS_AUD | For admin auth | Application audience tag |
| R2_ACCESS_KEY_ID | For persistence | R2 API token access key |
| R2_SECRET_ACCESS_KEY | For persistence | R2 API token secret key |
| CF_ACCOUNT_ID | For persistence | Cloudflare account ID |
| TELEGRAM_BOT_TOKEN | For Telegram | Bot token from BotFather |
| DISCORD_BOT_TOKEN | For Discord | Discord bot token |
| GITHUB_TOKEN | For GitHub | Fine-grained PAT |
| SANDBOX_SLEEP_AFTER | No (default: never) | never, 10m, 1h: sleep to save costs |
| DEV_MODE | No | true to skip all auth (dev only) |
Request flow
Incoming Request
│
├─ Public routes (no auth): /api/status, /sandbox-health, static assets
│
├─ CDP routes (secret auth): /cdp/* - browser automation
│
└─ Protected routes (CF Access JWT required):
│
├─ /_admin/* → Admin SPA (React)
├─ /api/admin/* → Device, storage, gateway, vault APIs
├─ /debug/* → Diagnostics (if DEBUG_ROUTES=true)
│
└─ /* (catch-all) → Proxy to OpenClaw Gateway in container
├─ HTTP requests → Direct proxy
└─ WebSocket → Bidirectional relay with token injectionContainer startup sequence
1. Git/GitHub setup (if GITHUB_TOKEN set)
2. Rclone configuration (if R2 credentials set)
3. Restore from R2 (config, workspace, skills)
4. OpenClaw onboard (if no config exists)
5. Config patching (channels, gateway auth, AI model, trusted proxies)
6. Background sync loop (every 30 seconds)
7. Start OpenClaw Gateway (port 18789)Want more AI systems?
Join the newsletter for weekly guides on building personal AI systems.
Get it in your inbox
Free weekly newsletter. AI workflows, technical deep-dives, and lessons from building in public.
No spam. Unsubscribe anytime.
Frequently asked questions
Get more
Main guide: Back to the full personal AI assistant guide
Questions? DM me on Instagram or Twitter
Weekly insights: Be Superpowered Newsletter
Guide created from a working deployment. Last updated: February 2026.