Most VPS boxes ship with a public IP, open ports, and a big attack surface. You can run OpenClaw safely on a $5 VPS without exposing any ports by fronting it with Cloudflare Tunnel. This guide walks you through provisioning, securing, and updating—end-to-end.
What you'll set up
- A minimal Ubuntu VPS (or any Debian-based host)
- OpenClaw running behind Cloudflare Tunnel (no inbound ports open)
- TLS handled by Cloudflare, origin locked down with a firewall
- Systemd service for reliability + zero-downtime updates
Prerequisites
- A domain managed in Cloudflare
- Cloudflare account with tunnel access (free is fine)
- VPS running Ubuntu 22.04+ (other distros work with minor tweaks)
- Node.js 20+ (OpenClaw target) and pnpm 9.x installed
1) Prep the VPS
Update base packages and install essentials:
❯ sudo apt update && sudo apt upgrade -y
❯ sudo apt install -y curl git ufw
Install Node.js 20 and pnpm:
❯ curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
❯ sudo apt install -y nodejs
❯ corepack enable
❯ corepack prepare pnpm@9 --activate
Add a non-root deploy user (recommended):
❯ sudo adduser --disabled-password --gecos "" openclaw
❯ sudo usermod -aG sudo openclaw
❯ sudo su - openclaw
2) Install Cloudflare Tunnel (cloudflared)
❯ curl -fsSL https://developers.cloudflare.com/cloudflare-one/static/documentation/connections/connect-apps/install-and-setup/tunnel-run.sh | sudo bash
❯ cloudflared tunnel login # opens browser to authenticate
❯ cloudflared tunnel create openclaw-vps
Grab the tunnel UUID from the output; you'll need it in the config file.
3) Clone and configure OpenClawVPS
❯ cd ~
❯ git clone https://github.com/openclaw/openclawvps.git
❯ cd openclawvps
❯ pnpm install
Create your environment file with required secrets (example):
❯ cp .env.example .env
# Edit with your values
Key values to set:
ANTHROPICAPIKEY(or OpenAI key if configured)NEXTPUBLICAPP_URL=https://yourdomain.comGATEWAY_TOKENand any provider tokens you use
4) Lock down the firewall
Allow only outbound + SSH, block inbound HTTP/HTTPS (tunnel will handle edge TLS):
❯ sudo ufw default deny incoming
❯ sudo ufw default allow outgoing
❯ sudo ufw allow OpenSSH
❯ sudo ufw enable
❯ sudo ufw status
5) Wire the Cloudflare Tunnel to your local port
Create /etc/cloudflared/config.yml:
tunnel: <YOUR_TUNNEL_UUID>
credentials-file: /home/<user>/.cloudflared/<YOUR_TUNNEL_UUID>.json
ingress:
- hostname: yourdomain.com
service: http://localhost:3000
- hostname: www.yourdomain.com
service: http://localhost:3000
- service: http_status:404
Start the tunnel as a service:
❯ sudo cloudflared service install
❯ sudo systemctl enable cloudflared
❯ sudo systemctl start cloudflared
❯ sudo systemctl status cloudflared
6) Add a systemd service for OpenClaw
Create /etc/systemd/system/openclaw.service:
[Unit]
Description=OpenClaw VPS
After=network.target cloudflared.service
[Service]
Type=simple
User=openclaw
WorkingDirectory=/home/openclaw/openclawvps
Environment=NODE_ENV=production
EnvironmentFile=/home/openclaw/openclawvps/.env
ExecStart=/usr/bin/pnpm start
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Reload and start:
❯ sudo systemctl daemon-reload
❯ sudo systemctl enable openclaw
❯ sudo systemctl start openclaw
❯ sudo systemctl status openclaw
7) Zero-downtime updates
Pull and restart with no rebuild surprises:
❯ cd /home/openclaw/openclawvps
❯ git pull
❯ pnpm install --frozen-lockfile
❯ pnpm run build
❯ sudo systemctl restart openclaw
For safer rollouts, keep a cached build and swap only after success:
❯ pnpm run build && sudo systemctl restart openclaw
8) Observability quick wins
- Health check: Add an uptime monitor to
https://yourdomain.com/health(or a simple/api/ping). - Logs:
journalctl -u openclaw -ffor live app logs;journalctl -u cloudflared -ffor tunnel issues. - Rate limiting: Use Cloudflare WAF rules to throttle abusive IPs before they hit the tunnel.
9) Security hardening checklist
- Keep SSH on key auth, disable password login in
/etc/ssh/sshd_config:
❯ PasswordAuthentication no
❯ PermitRootLogin prohibit-password
Then sudo systemctl reload sshd.
- Restrict sudo to your deploy user.
- Rotate API keys periodically; store secrets in
.envwith least privilege. - Turn on Cloudflare bot fight mode and WAF managed rules.
10) Validation steps
curl -I https://yourdomain.comshould return200and showcloudflareserver header.sudo ufw statusshould show only SSH allowed.systemctl status openclawshould beactive (running).- Visit your blog at
https://yourdomain.com/blogand confirm dynamic OG/Twitter cards render from/api/og?title=....
Troubleshooting
- Tunnel 502/522: Check
cloudflaredlogs; ensure app is listening on 3000. - Mixed content warnings: Make sure
NEXTPUBLICAPP_URLishttps://.... - Unexpected 404: Verify your
ingresshostnames match the domain you visit. - Memory spikes: Use a small swap file on low-RAM VPS (
sudo fallocate -l 1G /swapfile && sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfile).
---
With a Cloudflare Tunnel in front of your $5 VPS, you avoid open inbound ports, get automatic TLS, and can ship OpenClaw fast without waiting on firewall rules. Keep pnpm run build && systemctl restart as your update habit and you’ll have a stable, low-maintenance setup.