Expose your dashboard securely: Cloudflare Tunnel vs Tailscale Funnel vs ngrok for Claude Code, Codex, and OpenCode
A practical comparison of three ways to access a self-hosted dashboard from your phone, plus the trade-offs (trust boundaries, auth, HTTPS, and operational complexity).
- CLI
- 0.1.0
- Preview ref
- f36aa45
If you run Claude Code, Codex, or OpenCode on a machine you control, the next temptation is obvious:
“I want to check it from my phone.”
And then the dangerous follow-up thought:
“I’ll just expose a port.”
That’s how you end up with a half-authenticated dashboard on the public internet.
So this guide is about the safer version of the same desire:
give myself a phone-friendly HTTPS URL without opening inbound ports.
There are three common tools people reach for:
- Cloudflare Tunnel
- Tailscale Funnel
- ngrok
They all work.
They also have very different trust boundaries and failure modes.
TL;DR
- If you want “only inside my private network”, Tailscale Serve/Funnel is usually the simplest.
- If you want internet exposure with strong identity gating, Cloudflare Tunnel + Cloudflare Access is the most common pattern.
- If you want the fastest “get a URL now” workflow, ngrok is still the default.
- If the dashboard you’re exposing is a Happier web UI, remember the browser crypto constraint: remote phone access should be HTTPS (secure context).
The problem
You want three things at once:
- a URL you can open from a phone
- HTTPS (secure context)
- no inbound firewall holes
The hard part is that “secure” here is not just TLS.
It’s also:
- who can reach the URL
- how you authenticate
- what happens when your tunnel credentials leak
What I tried first (and where I bounced off)
- Open the port: fast, reckless.
- LAN-only access: safe, but doesn’t work on a phone off-network.
- A tunnel with no auth: slightly better than open port, still reckless.
So now I treat “phone access” as an identity + network design problem.
Option A: Cloudflare Tunnel
Cloudflare Tunnel is outbound-only: a connector dials out to Cloudflare.
Why people like it:
- no inbound ports
- Cloudflare Access gives you SSO, device posture, policies
Trade-offs:
- you’re trusting Cloudflare as the edge
- you now manage DNS + Access policy
Option B: Tailscale Funnel
Funnel publishes an HTTPS endpoint via Tailscale.
Why people like it:
- tailnet-native
- keeps origin IP hidden
Trade-offs:
- constraints and policy requirements
- it’s easy to confuse Funnel (public) with Serve (tailnet-only)
Option C: ngrok
ngrok is the fastest way to get a URL.
Trade-offs:
- limits and pricing become the constraint
- production-ish dashboards need strong auth
Where Happier fits (secure context + Tailscale Serve)
If you’re exposing a Happier web UI specifically, there’s an extra constraint:
Modern browsers only allow certain crypto features in a secure context.
http://localhost counts.
http://<lan-ip> and http://<tailscale-ip> do not.
So you want HTTPS.
Happier’s recommended remote access path is Tailscale Serve to get an https://*.ts.net URL.