Run OpenClaw securely without public inbound ports
If you want the safest practical setup, do this: keep OpenClaw private and access it through a secure overlay like Cloudflare Tunnel or Tailscale. No direct internet exposure, no open gateway port, much lower attack surface.
Recommended VPS specifications
- CPU: 2 vCPU minimum
- RAM: 4GB minimum
- Storage: 40GB+ SSD
- OS: Ubuntu 22.04/24.04 LTS
- Network: inbound locked down to SSH + HTTPS only (or less)
Architecture options
Option A: Cloudflare Tunnel (public hostname, private origin)
- OpenClaw listens on localhost/private interface
cloudflaredestablishes outbound tunnel to Cloudflare- Users authenticate through Cloudflare Access policies
- No direct public inbound to OpenClaw service ports
Option B: Tailscale (private mesh network)
- VPS joins private WireGuard mesh
- Only authorized tailnet devices can reach the service
- Great for operator-only/admin access with no public exposure
Baseline host hardening first
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
For detailed hardening, follow: OpenClaw Security Lockdown: Safe Internet Exposure Guide.
Cloudflare Tunnel setup (example)
# install cloudflared
curl -fsSL https://pkg.cloudflare.com/install.sh | sudo bash
sudo apt install -y cloudflared
# authenticate and create tunnel
cloudflared tunnel login
cloudflared tunnel create openclaw
# route a hostname
cloudflared tunnel route dns openclaw claw.example.com
Create config file /etc/cloudflared/config.yml:
tunnel: openclaw
credentials-file: /etc/cloudflared/<tunnel-id>.json
ingress:
- hostname: claw.example.com
service: http://127.0.0.1:18789
- service: http_status:404
sudo cloudflared service install
sudo systemctl enable --now cloudflared
sudo systemctl status cloudflared
Important: enforce Cloudflare Access policy (email/IdP/device posture) so the hostname is not anonymously reachable.
Tailscale setup (example)
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --ssh
tailscale status
Then bind access to tailnet IP/private DNS only, and avoid exposing public listener routes.
Nginx + localhost origin pattern
If you use a reverse proxy, keep upstream local-only:
location / {
proxy_pass http://127.0.0.1:18789;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Operational checklist
- Patch OS monthly (or faster for high severity CVEs)
- Rotate API keys and remove stale integrations
- Audit auth/access policies quarterly
- Backup configs and recovery secrets
- Monitor logs for abuse, bot scanning, and auth failures
Related guides
Need a stable home for this setup? Start with a Cloud VPS with full root access, then layer Cloudflare Access or Tailscale on top.


Be First to Comment