Abstract: Cloudflare Tunnel can reduce direct inbound exposure for OpenClaw on Hetzner, but only when you separate routes by trust level. Telegram webhook ingress (when intentionally enabled) should stay narrow, while gateway UI access should remain private-first and operator-gated. This article walks through a practical SetupClaw pattern, including route design, validation checks, and handoff documentation that keeps day-two operations predictable.
If you expose OpenClaw remotely, the most common mistake is also the easiest one to make: one hostname, one tunnel, one broad forwarding rule. It feels neat at first. Then it becomes hard to explain what is actually exposed, who should reach which path, and whether a change broke security boundaries or just routing.
For SetupClaw Basic Setup, route separation is not cosmetic. It is a control. Gateway UI and websocket access are high-privilege operator surfaces. /telegram webhook traffic, when used, is a narrow provider ingress path. Those two surfaces should not share identical exposure rules.
Start with OpenClaw defaults before opening routes
Before creating any public path, confirm whether webhook mode is needed at all. In standard OpenClaw setups, Telegram commonly runs with long polling by default, so /telegram exposure is optional in many deployments.
That decision has direct risk impact. If long polling already meets your requirements, do not add a webhook route. Fewer public paths means fewer controls to maintain, fewer failure modes, and simpler incident debugging.
If webhook mode is required, expose only the exact webhook path and keep everything else denied by default.
Define trust zones first, then write tunnel policy
A practical way to avoid drift is to define trust zones in plain terms before editing tunnel config.
Provider ingress zone: receives webhook delivery only. Narrow scope, minimal permissions, no extra endpoints.
Operator control zone: gateway UI and related control traffic. Higher privilege, private-first access preference, stronger operator authentication.
Once those zones are explicit, routing decisions become mechanical rather than subjective.
Practical route pattern for SetupClaw
A conservative baseline on Hetzner looks like this:
- Keep gateway authentication enabled regardless of tunnel usage.
- Keep operator UI private-first (SSH tunnel or Tailscale preferred).
- Publish
/telegramonly for intentional webhook deployments. - Avoid catch-all forwarding to gateway UI.
- End with explicit deny behaviour for unknown paths.
Illustrative only—adapt this to your exact Cloudflare Tunnel schema and OpenClaw port/bind settings:
ingress:
- hostname: bot.example.com
path: /telegram
service: http://127.0.0.1:3000
- hostname: ops.example.com
service: http://127.0.0.1:3000
- service: http_status:404
The point is policy intent, not exact syntax. Webhook ingress is narrow. Operator route is separate. Unknown routes fail closed.
Operator routes should also require strong access controls (for example Cloudflare Access plus OpenClaw gateway auth), not just separation by hostname.
Tunnel controls and app controls are different layers
Cloudflare Tunnel reduces direct network exposure. It does not replace OpenClaw application controls.
You still need channel policy and gateway policy: Telegram allowlists, DM policy, group mention gating, and gateway auth. These controls decide who can trigger behaviour after traffic reaches the service.
And network hardening does not replace change-control hardening. PR-only workflows and branch protection still determine whether repository changes can ship safely.
What route separation does not solve
This is important for realistic expectations.
Route hardening does not change where sensitive state lives. OpenClaw state remains on the host under ~/.openclaw and workspace files, so host permissions and backup discipline remain essential.
Route hardening also does not fix cron misses caused by gateway downtime or scheduler configuration. Cron reliability is tied to uptime, timezone, and job design, not ingress routing quality.
Practical implementation steps
Step one: decide if webhook mode is truly required
Test long polling first. If it works, skip /telegram exposure and keep the surface smaller.
Step two: create a route inventory table
Before deployment, document each route with path, upstream service, auth mode, intended audience, owner, and rollback step.
Step three: deploy separated ingress rules
Apply webhook routing only where needed, keep operator access separate, and ensure unmatched traffic is denied.
Step four: validate policy layering
After deployment, verify that route success does not bypass Telegram access policy or gateway auth controls.
Step five: run failure-path tests
Test unknown paths return deny/404, test route overlap does not leak UI access, and test behaviour after restart when gateway config changes.
Step six: hand off operational checks
Ship the route inventory plus a small verification checklist so future operators can validate boundaries quickly without reverse-engineering config intent.
Rollback baseline: disable the webhook route, revert to long polling, restart services, re-run trigger tests, and confirm unknown paths still fail closed.
Operational gotchas worth catching early
Most avoidable incidents come from a few patterns: publishing a temporary broad route and never removing it, assuming webhook is required when long polling is sufficient, relaxing gateway auth because tunnel access “feels private”, or forgetting that network model changes may require service restart.
If you treat route separation as a first-class boundary from the start, these are much easier to avoid.