STATUS: THIS PROJECT IS NOT YET PRODUCTION READY
It's what I'm running for my personal setup - with some config changes.
It's fantastic for hacking on OpenClaw in a secure environment.
It's packed full of useful tools.
But the openclaw.json config is in rapid development. Star the project to follow along. It will be more fully baked by Feb 28.
About this project:
This repo enables claude code to securely deploy & maintain OpenClaw on your own VPS.
What's included:
- CLAUDE.md & playbooks
- Carefully designed instructions for claude to follow
- Tools & scripts
- OpenClaw plugins & build scripts
- Cloudflare Workers
- for logging & LLM proxy (no API keys stored on the VPS)
OpenClaw gets wrapped with production-grade infrastructure: SSH hardening, firewall rules, Docker-in-Docker sandboxing via Sysbox, Cloudflare Tunnel for zero-exposed-port networking, and a Cloudflare Worker proxy that keeps your real API keys off the server entirely.
Quick install:
# Interactive claude setup:
curl -fsSL https://raw.githubusercontent.com/simple10/openclaude/main/docs/CLAUDE_INSTALL.md -o CLAUDE.md && claude "start"Or clone this repo and run
claude "start".
If you already use claude, care about security, or like to tinker, this project is worth your time.
There are a lot of power-ups stashed in this repo. It's a batteries included OpenClaw & devops framework.
One-click VPS installs are a great way to get up and running quickly. But then you're left running a fairly insecure or an overly locked-down OpenClaw setup. This project strikes a nice balance between the two.
Check out this guide on OpenClaw hosting for more details.
- Claude subscription - Pro/Max for Claude Code
- Cloudflare Account (free)
About 30 min for the first deploy. Claude does a LOT of work on your VPS to get OpenClaw securely deployed.
A secure OpenClaw instance that doesn't limit OpenClaw's ability to function.
Infrastructure
- Zero exposed ports — Cloudflare Tunnel + Access for secure connectivity, SSH is the only open port
- Hardened VPS — non-standard SSH port, key-only auth, fail2ban, UFW firewall, kernel tuning
- Docker-in-Docker sandboxing — gateway & agent tools run in their own isolated container via Sysbox
- API key isolation — LLM keys stored as Cloudflare Worker secrets, never in OpenClaw or on the VPS
Multi-Agent
- Coordinator plugin — auto-discovers agent skills and routes tasks to the right agent
- Per-agent sandboxes — custom images, network rules, memory limits, and tool permissions per agent
- Remote browser viewing — watch and control agent browser sessions via noVNC
Observability
- AI Gateway Worker — proxies all LLM requests through Cloudflare for analytics and key management
- Log shipping — Vector ships container logs to a Cloudflare Log Receiver Worker
- Host monitoring — cron-based health checks with Telegram alerts, shared with your OpenClaw so it can self-diagnose
- Debugging hooks — Claude Code can read command logs, session transcripts, and LLM traces to troubleshoot issues
Use claude to set up your env & clone this repo (recommended)
curl -fsSL https://raw.githubusercontent.com/simple10/openclaude/main/docs/CLAUDE_INSTALL.md -o CLAUDE.md
claude "start"That's it.
The CLAUDE_INSTALL.md file instructs claude on how to walk you through the required config setup, git clone this repo, and automate the deploy.
-
Create a new VPS and Cloudflare Tunnel
-
Clone this repo
-
Run
claudein this repo dir, just saystartgit clone git@github.com:simple10/openclaude.git openclaw-vps cd openclaw-vps # Copy the config template cp openclaw-config.env.example openclaw-config.env # Edit required config vars or just start claude, it will help you gather requirements # Run claude with skip permissions if you want a more automated deploy claude --dangerously-skip-permissions "start" # Claude will deploy OpenClaw and test the VPS (20+ minutes)
After successfully deploying OpenClaw, claude assists you in device pairing & accessing the webchat.
After deployment, claude can be used to make any changes or manage your VPS with the same prompt.
claude "start"Then just chat with claude...
Please verify the setup and run the end to end tests
I updated openclaw.json configs, please deploy it to the VPS
I can't access OpenClaw through the web, please help.
Please update OpenClaw to the latest version on the VPS
The agent routing doesn't seem to be working properly. Please check the debug logs and help me fix it.
The playbooks instruct claude on how to detect if you already deployed your VPS. There are also explicit claude instructions for verifying & maintaining deployments.
If you want more control, see scripts/ dir for CLI helper scripts without using claude.
- VPS Setup Guide - guidance on VPS setup
- Cloudflare Tunnel - details on Cloudflare Access & Tunnel setup
- Telegram - guide for setting up Telegram bots to use with OpenClaw
- Claude Subscription - info on using OpenClaw with a claude subscription
- Security - in depth details on the security layers
- See docs/ for more guides
Claude reads the playbooks and executes them step-by-step over SSH:
- Cloudflare Workers — deploys the AI Gateway proxy and Log Receiver (~2 min)
- VPS hardening — creates users, hardens SSH, configures firewall and fail2ban (~3 min)
- Docker + Sysbox — installs the container runtime with security hardening (~3 min)
- OpenClaw deployment — builds the Docker image, starts the gateway and Vector log shipper, builds sandbox images (base, packages, toolkit with 25+ tools, browser with noVNC) (~15 min on first boot)
- Backups — configures automated backup scripts (~1 min)
- Reboot + verification — reboots to confirm everything auto-starts, runs security audit (~3 min)
- Post-deploy — helps you configure Cloudflare Tunnel routes and pair your first device
Total time: ~30 minutes for a fresh deployment. Subsequent restarts are much faster since sandbox images are cached.
OpenClaw uses a multi-agent architecture where a main "coordinator" agent delegates tasks to specialized sub-agents:
User message
-> Gateway (single process, makes all LLM API calls)
-> Main agent (coordinator, routes tasks)
-> Code agent (development tools, Claude Code CLI)
-> Skills agent (gifgrep, weather, web tools, etc.)
Agents are not separate processes. An "agent" is a configuration profile — a sandbox image, network rules, memory limits, and tool permissions. The gateway process makes all LLM API calls itself and runs tool calls inside the agent's sandbox container via docker exec.
Each agent runs tools inside an isolated Docker container (via Sysbox for secure Docker-in-Docker). LLM provider API keys are stored as Cloudflare Worker secrets — they never touch the VPS. For details on how requests flow through the system, see docs/REQUEST-FLOW.md.
Cloudflare
|
+---------------+---------------+
| | |
Tunnel AI Gateway Log Receiver
(HTTPS) Worker Worker
| (LLM proxy) (log capture)
| ^ ^
v | |
+-------------------------------------+-------+
| VPS |
| |
| +-- openclaw-gateway (Sysbox) ----------+ |
| | Gateway process (Node.js) | |
| | Nested Docker daemon | |
| | -> sandbox containers (per agent) | |
| | -> browser container (noVNC) | |
| +---------------------------------------+ |
| |
| Vector (log shipper) |
| cloudflared (tunnel connector) |
| host-alert.sh (cron monitoring) |
| |
| Port 443: CLOSED |
| Port 80: CLOSED |
| All gateway ports: 127.0.0.1 only |
+----------------------------------------------+
| Component | Location | Purpose |
|---|---|---|
| Gateway | VPS (Sysbox container) | OpenClaw runtime — manages agents, makes LLM calls, runs tools in sandboxes |
| Vector | VPS (separate compose project) | Ships container logs to Cloudflare Log Receiver Worker (optional) |
| AI Gateway Worker | Cloudflare | Proxies LLM requests, injects API keys, provides analytics |
| Log Receiver Worker | Cloudflare | Captures and stores container logs |
| Cloudflare Tunnel | VPS -> Cloudflare | Outbound-only connection — no exposed ports, hidden origin IP |
| host-alert.sh | VPS (cron) | Monitors disk, memory, CPU; sends Telegram alerts |
No ports are exposed to the public internet. The Cloudflare Tunnel uses outbound-only connections. SSH is the only port open on the firewall.
- Claude Code — the CLI tool that runs the deployment
- VPS
- Minimum: 4 GB RAM, 2 vCPUs
- Recommended: 8 GB+ RAM, 4+ vCPUs (the gateway, nested Docker, and sandbox images need room)
- Linux with kernel 5.12+ (needed for Sysbox). Ubuntu 24.04+ or Debian 13+ recommended
- SSH access with a key (Claude needs to SSH into the server as root initially)
- Cloudflare Account (free tier works) — for the tunnel and workers
- Domain — any domain or subdomain managed in Cloudflare DNS
All deployment settings live in openclaw-config.env. The example file documents every field:
cp openclaw-config.env.example openclaw-config.envYou can prepopulate the config file or claude will ask for any missing required settings.
After deployment, add your LLM provider API keys to the Cloudflare Worker (not the VPS):
cd workers/ai-gateway
npx wrangler secret put ANTHROPIC_API_KEY
npx wrangler secret put OPENAI_API_KEY # if using OpenAI modelsThese keys are stored only in Cloudflare and never touch the VPS. See docs/POST-DEPLOY.md for details.
There are two main UIs provided by this setup:
- OpenClaw Control UI:
https://openclaw.YOURDOMAIN.com/chat- chat or change OpenClaw configs - Dashboard UI:
https://openclaw.YOURDOMAIN.com/dashboard- to access the agent browsers or downloaded media files
If you get a disconnected error when viewing the Control UI, that means your browser
is not properly paired with OpenClaw. It's a security feature.
Claude guides you through pairing your device during initial deployment.
If you need to re-pair your browser, just ask claude for the URL:
> I need to re-pair my device with OpenClaw. Please give me the link.
You'll get something like: https://openclaw.YOURDOMAIN.com/chat?token=GATEWAY_TOKEN
This opens the OpenClaw web UI where you can start chatting with your agents.
Agents with browser access run a real Chrome instance (not just headless) in a separate container.
You can watch and control their browser sessions remotely via noVNC:
https://openclaw.YOURDOMAIN.com/dashboard
See docs/DASHBOARD.md for details.
Optionally run end-to-end tests with claude:
claude "Run the tests in docs/TESTING.md using devtools mcp"Requires DevTools MCP installed in Claude Code.
Just use OpenClaw as normal. It will alert you if there's a problem with the VPS.
Then if there's a problem, use claude to fix it.
> Show me the gateway status
> Restart the gateway
> Show me the last 50 lines of gateway logs
# SSH into the VPS (port changes during hardening — check your config)
ssh -i ~/.ssh/your_key -p 222 adminclaw@YOUR_VPS_IP
# Gateway commands (run as openclaw user)
sudo -u openclaw bash -c 'cd /home/openclaw/openclaw && docker compose ps' # Status
sudo -u openclaw bash -c 'cd /home/openclaw/openclaw && docker compose logs -f' # Logs
sudo -u openclaw bash -c 'cd /home/openclaw/openclaw && docker compose restart openclaw-gateway' # RestartOr use the helper scripts:
# Most of the helper scripts have optional params like `--all` or `--dry-run`
# See comments at the top of each script for details
# Run OpenClaw CLI commands
# SSHs into gateway container to run `openclaw ...`
# Supports all of the openclaw CLI commands
./scripts/openclaw.sh
./scripts/openclaw.sh doctor --deep
# If any OpenClaw CLI commands don't work as expected,
# SSH into the gateway first then run `openclaw`
# Interactive commands sometimes have trouble with SSH -> Docker exec TTY -> openclaw
./scripts/gateway.sh
openclaw doctor --deep
# Health Checks
./scripts/health-check.sh # Show OpenClaw and docker containers health
# SSH
./scripts/ssh-vps.sh # SSH into VPS host
./scripts/ssh-gateway.sh # SSH into VPS -> exec bash into gateway container
./scripts/ssh-agent.sh # SSH into an agent sandbox - auto starts if not currently running
# Restart
./scripts/restart-gateway.sh
./scripts/restart-sandboxes.sh
# Logs
./scripts/logs-openclaw.sh # Logs from OpenClaw command logger (built-in plugin)
./scripts/logs-docker.sh # Docker container logs, including gateway
./scripts/logs-debug.sh # Logs from custom debug-logger OpenClaw plugin, similar to logs-openclaw but all messages
./scripts/logs-llm.sh # All LLM request & response messages (from llm-logger plugin)
./scripts/logs-session.sh # OpenClaw chat session logs - one of the most useful debugging logs
# Browser
./scripts/start-browser.sh # Start a browser container for an agent, print dashboard URL for pre-auth
# Sync browser downloaded media to local host
# Screenshots, PDFs etc. - whatever the agents or browser have downloaded
# Same files visible at /dashboard/media endpoint in web dashboard UI
./scripts/sync-media.sh
#
# Update Containers
#
# Update OpenClaw gateway container
# Pulls latest openclaw source & rebuilds & restarts gateway container
# Expect 5-10 seconds of downtime for the gateway and agent sandboxes
./scripts/update-openclaw.sh
# Update sandbox toolkit — sync config, rebuild images
# Default: detects new/changed tools and quick-layers them (seconds)
# Use --full for a complete rebuild with proper layer ordering
# See deploy/sandbox-toolkit.yaml for tool config
./scripts/update-sandbox-toolkit.sh # quick (default)
./scripts/update-sandbox-toolkit.sh --full # full rebuild
# Update and rebuild sandbox containers
./scripts/update-sandboxes.shUpdates are done via git pull and rebuilding the gateway container on the VPS.
OpenClaw's openclaw update command does not work (by design) because the .git
directory is not inside the container. It's safer to rebuild on host.
Just tell claude:
> Update openclaw to the latest version
Claude will pull the latest code, rebuild the Docker image with auto-patching, and restart the gateway.
# OR use the update script
./scripts/update-openclaw.shThe tools available inside agent sandboxes are defined in deploy/sandbox-toolkit.yaml.
Adding a tool is a one-line YAML edit + scripts/update-sandbox-toolkit.sh — the default quick mode layers the new tool in seconds. See docs/SANDBOX-TOOLKIT.md for details.
This deployment implements defense-in-depth with multiple independent security layers:
- No Exposed Ports - only SSH on non-standard port is reachable
- Cloudflare Tunnel uses outbound-only connections
- UFW firewall denies all incoming traffic except the SSH port
- Docker daemon binds all container ports to
127.0.0.1only, preventing Docker's iptables rules from bypassing UFW - Gateway ports (18789, 18790, 6090) are only reachable from localhost — external access goes through the Cloudflare Tunnel
- Two-user model:
adminclawfor SSH/admin with passwordless sudo,openclawfor app runtime with no SSH and no sudo - SSH hardened: custom port, key-only auth (passwords disabled), restricted to
adminclawonly, modern ciphers (curve25519, chacha20-poly1305), 3 max auth tries, all forwarding disabled - Fail2ban: bans IPs after 3 failed SSH attempts for 24 hours
- Cloudflare Access: optional identity-based authentication layer in front of the tunnel
- Sysbox runtime: provides secure Docker-in-Docker without
--privilegedmode — user namespace isolation maps container root to an unprivileged host user - Read-only root filesystems with targeted tmpfs mounts for writable paths
- All capabilities dropped (
capDrop: ALL) - PID limits (512 per sandbox, 1024 for gateway) prevent fork bombs
- Memory and CPU limits prevent resource exhaustion
- Internal sandbox network (
172.31.0.0/24) is markedinternal— no external connectivity
- Keys stored at the edge: LLM provider API keys are stored as Cloudflare Worker secrets, never on the VPS
- Injection at the edge: the AI Gateway Worker injects keys before forwarding to providers
- VPS has no direct access: the VPS only holds an auth token for the Worker, not the actual API keys
- Built-in security audit:
openclaw security auditchecks for misconfigurations - Host alerter: cron job monitors disk, memory, CPU, and container health — sends Telegram alerts
- Automatic security updates via unattended-upgrades
- Kernel hardening: sysctl tuning for IP spoofing protection, SYN flood mitigation, ASLR, restricted dmesg/kptr access
- Containerized gateway — runs inside its own Sysbox container with no root access to the host
- Sandboxed agents — all agent tools are
docker exec'd into isolated containers with dropped capabilities - Isolated browsers — each agent's browser runs in a separate container
- No stored API keys — the gateway only has an auth token for the LLM proxy, never the real provider keys
- Unprivileged processes — no root user in the gateway or any agent sandbox
- Device pairing - OpenClaw UI requires one-time per device pairing
- Double auth layer - Cloudflare Access + OpenClaw device pairing
In general, just chat with claude to troubleshoot. Claude is fully context-aware thanks to the CLAUDE.md and playbooks/
See also scripts/ for bash utils for SSHing, showing logs, etc.
If you're running into OpenClaw specific bugs, clone the openclaw repo into ./openclaw.
Then tell claude to scan through the local openclaw code to help you debug.
openclaw-vps/
├── README.md # This file
├── CLAUDE.md # Deployment orchestration instructions (for Claude)
├── REQUIREMENTS.md # Architecture reference and design decisions
├── openclaw-config.env # Your deployment config (secrets, gitignored)
├── openclaw-config.env.example # Template with all fields documented
│
├── deploy/ # Files deployed to the VPS
│ ├── docker-compose.override.yml # Container config (Sysbox, resource limits, ports)
│ ├── openclaw.json # Gateway config (agents, plugins, security)
│ ├── models.json # AI provider routing (baseUrl overrides)
│ ├── sandbox-toolkit.yaml # Sandbox tool definitions
│ ├── vector/ # Vector log shipper (standalone compose project)
│ │ ├── docker-compose.yml # Independent of gateway — start/stop separately
│ │ └── vector.yaml # Log shipper config
│ ├── build-openclaw.sh # Docker image builder with auto-patching
│ ├── entrypoint-gateway.sh # Container init (dockerd, sandboxes, privilege drop)
│ ├── rebuild-sandboxes.sh # Layered sandbox image builder with split config detection
│ ├── host-alert.sh # Host monitoring + Telegram alerts
│ ├── dashboard.mjs # Dashboard server — browser sessions, media, logs
│ └── logrotate-openclaw # Log rotation config
│
├── workers/ # Cloudflare Workers (deployed via wrangler)
│ ├── ai-gateway/ # LLM proxy — injects API keys, provides analytics
│ └── log-receiver/ # Log aggregation from Vector
│
├── scripts/ # Local management scripts
│ ├── update-sandbox-toolkit.sh # Sync toolkit config and rebuild sandbox images
│ ├── update-sandboxes.sh # Force-rebuild sandbox images
│ └── restart-sandboxes.sh # Restart sandbox containers
│
├── docs/
│ ├── VPS-SETUP-GUIDE.md # VPS provisioning instructions
│ ├── CLOUDFLARE-TUNNEL.md # Tunnel and Access setup
│ ├── DASHBOARD.md # Details on web server sidecar (noVNC browser, etc.)
│ ├── SANDBOX-TOOLKIT.md # How to add/manage sandbox tools
│ ├── TELEGRAM.md # Telegram integration guide
│ └── TESTING.md # End-to-end testing instructions
│
└── playbooks/ # Deployment playbooks (read by Claude)
├── 00-fresh-deploy-setup.md # Fresh deploy validation and overview
├── 00-analysis-mode.md # Analyze existing deployment
├── 01-workers.md # Cloudflare Workers deployment
├── 02-base-setup.md # Users, SSH, firewall, kernel hardening
├── 03-docker.md # Docker + Sysbox installation
├── 04-vps1-openclaw.md # Gateway deployment and configuration
├── 06-backup.md # Automated backup setup
├── 07-verification.md # Security audit and service verification
├── 08-post-deploy.md # Domain, tunnel routes, device pairing
└── maintenance.md # Token rotation and maintenance procedures
- OpenClaw Documentation: https://docs.openclaw.ai
- OpenClaw GitHub: https://github.com/openclaw/openclaw