openclaw-cloudflare-secure
High-risk skill to expose an OpenClaw WebUI via Cloudflare Tunnel and DNS. It downloads and installs cloudflared, makes network calls to https://api.cloudflare.com/client/v4, and requires the CLOUDFLARE_API_TOKEN environment variable.
OpenClaw WebUI: Cloudflare Access + Tunnel (VPS)
Use this when you want an easy public URL (e.g. openclaw.example.com) that is NOT directly exposed, protected by Cloudflare Access allowlist, and delivered via Cloudflare Tunnel to a local service (commonly http://127.0.0.1:18789).
Assumptions
- OpenClaw WebUI is reachable locally on the VPS at
http://127.0.0.1:18789(or your chosen local port). - You control DNS for the zone in Cloudflare (e.g.
example.com). - You have a Cloudflare API token available to the agent/VPS as
CLOUDFLARE_API_TOKEN.- Recommended token perms (least privilege): Zone:DNS:Edit + Zone:Zone:Read for the target zone.
- This is the key reason this setup is “agent-friendly”: the agent can securely create subdomains / manage DNS records without giving it full Cloudflare account access.
- You can access Cloudflare Zero Trust UI to create:
- an Access Application for the hostname
- an Allow policy for specific emails
- a Block policy for Everyone
- a Tunnel and its token
Quick start (copy/paste)
0) Optional: disable Tailscale Serve
If you used Tailscale Serve earlier and want to remove it:
sudo tailscale serve reset
1) Install and start cloudflared tunnel service (token-based)
In Cloudflare Zero Trust:
- Networks → Connectors → Tunnels → Create tunnel → Cloudflared
- Copy the token from the command
cloudflared service install <TOKEN>
On the VPS:
./scripts/install_cloudflared.sh
sudo ./scripts/tunnel_service_install.sh '<TOKEN>'
Verify:
sudo systemctl is-active cloudflared
sudo systemctl status cloudflared --no-pager -l | sed -n '1,80p'
2) DNS cutover: point hostname to the tunnel
This uses the bundled DNS helper (./scripts/cf_dns.py). It will:
- find and delete any existing A/AAAA/CNAME for that hostname
- create a proxied CNAME to
<TUNNEL_UUID>.cfargotunnel.com
Prereq:
export CLOUDFLARE_API_TOKEN='...'
2b) (Optional) Create/update a subdomain / DNS record (agent-friendly)
Use this when you want the agent (with least-privilege DNS token) to create records programmatically:
./scripts/dns_create_record.sh --zone example.com --type A --name openclaw --content 1.2.3.4 --proxied true
./scripts/dns_create_record.sh --zone example.com --type CNAME --name openclaw --content target.example.net --proxied true
./scripts/dns_point_hostname_to_tunnel.sh \
--zone example.com \
--hostname openclaw.example.com \
--tunnel-uuid <TUNNEL_UUID>
3) In Cloudflare Zero Trust UI: bind hostname → service
In the tunnel:
- Add Public Hostname:
- Hostname:
openclaw.example.com - Service:
http://127.0.0.1:18789
- Hostname:
4) Cloudflare Access policy
In Zero Trust:
- Access → Applications → Add → Self-hosted
- Public hostname:
openclaw.example.com
- Public hostname:
- Policies:
- Allow: include specific emails (your allowlist)
- Block: include Everyone
Notes / gotchas
- If the Tunnel “route traffic” wizard errors with “record already exists”, it’s just DNS collision. Either:
- delete the existing DNS record and let the wizard recreate it, OR
- keep DNS as-is and set the Public Hostname mapping inside the Tunnel.
- Keep the hostname proxied (orange cloud). Access/Tunnel require proxy.
Rollback
- DNS: point the hostname back to an origin A record (or remove the record).
- VPS:
sudo systemctl disable --now cloudflared.