TUNNEL COMPARISON

Four ways to expose OpenCode. Pick by use case, not by habit.

Every option below can carry OpenCode traffic to KKCode. The right one depends on who needs access, how often the address changes, and what your dev machine already runs. There is no universally best choice — only the best choice for your situation.

Last updated: 2026-08-03English

Quick recommendation

If you need…PickWhy
Just your own iPhone, with zero setupQR tunnel (@kkcode-app/agent)One command on the dev machine, scan a QR, done. No account, no domain, no router config.
Your own iPhone plus your other devices, stable hostnameTailscalePrivate HTTPS inside your tailnet, no public exposure, free for personal use, works across cellular.
Access from any browser, plus your iPhone, under your own domainCloudflare TunnelPublic HTTPS with a stable hostname, no router port forwarding, integrates with Cloudflare Access if you need SSO.
Already run Caddy / Nginx / Traefik on the dev machineReverse proxyReuse your existing HTTPS infrastructure. Make sure SSE and WebSocket upgrades are preserved.

Option A — KKCode built-in QR tunnel

Shipped as the @kkcode-app/agent npm package. On the dev machine, run:

npx -y @kkcode-app/agent@latest

The agent starts opencode serve, opens an outbound tunnel through the KKCode relay, and prints a QR code on the terminal. Open KKCode, tap the QR scanner on the connection screen, and the URL plus auth header are filled in for you.

Strengths

  • Zero configuration. No account to create, no domain to own, no router to configure.
  • One QR, one scan. Works across cellular and Wi-Fi.
  • The dev machine only makes outbound connections, so it works behind strict NAT, carrier-grade NAT, and corporate firewalls.
  • Reconnection is handled by the agent — kill it and restart to re-establish.

Trade-offs

  • Traffic passes through the KKCode relay. Do not use it for code that must never leave your infrastructure.
  • Address is tied to the agent run. Stopping the agent means the next launch needs a new QR.
  • Single-tenant by design — sharing with other people means giving them the QR (and the password).

Option B — Tailscale

Tailscale is the default when only your own devices need access. It keeps the OpenCode process bound to loopback and provides a private HTTPS address inside your tailnet.

Setup

# Dev machine
opencode serve --hostname 127.0.0.1 --port 4096
tailscale serve --bg 4096
tailscale serve status

Install Tailscale on the iPhone, sign in to the same tailnet, and enter the resulting https://machine-name.tailnet-name.ts.net address in KKCode.

Strengths

  • Private by construction — the address only resolves inside your tailnet.
  • Stable hostname that survives reboots and address changes.
  • Free for personal use, with simple ACL management.
  • Works across cellular and Wi-Fi with no port forwarding.

Trade-offs

  • Requires a Tailscale account and the Tailscale app on every device that needs access.
  • Tailnet growth, key expiry, and ACL changes are operational concerns you own.
  • Not a fit if you need to share the same OpenCode with someone outside your tailnet.

Option C — Cloudflare Tunnel

Cloudflare Tunnel gives you a public HTTPS URL with a stable hostname and no router port forwarding. Because the URL is publicly reachable, OpenCode authentication is mandatory — the tunnel controls transport, not identity.

Setup

# Quick tunnel (temporary URL)
cloudflared tunnel --url http://127.0.0.1:4096

# Named tunnel (stable hostname)
cloudflared tunnel login
cloudflared tunnel create opencode-mobile
cloudflared tunnel route dns opencode-mobile opencode.example.com
cloudflared tunnel run opencode-mobile

Enter the resulting URL in KKCode. Confirm the /global/health endpoint with curl -u user:password before opening the app.

Strengths

  • Public HTTPS, no port forwarding, no public IP needed on the dev machine.
  • Stable hostname under a domain you already own.
  • Optional Cloudflare Access for SSO, device posture, and audit logs.
  • Free tier covers personal use.

Trade-offs

  • The URL is reachable by anyone on the public internet. Treat the OpenCode password as a public credential.
  • Quick-tunnel URLs are temporary and should be considered disposable.
  • Streaming and WebSocket traffic must be preserved by the tunnel config — verify SSE works before relying on it.

Option D — reverse proxy

If you already run Caddy, Nginx, or Traefik on the dev machine, mount OpenCode under a path prefix and reuse your existing HTTPS infrastructure.

Example Caddy config

opencode.example.com {
    reverse_proxy 127.0.0.1:4096
}

Example with path prefix

dev.example.com {
    @opencode path /api/*
    reverse_proxy @opencode 127.0.0.1:4096
}

Enter the full URL (with prefix) in KKCode. The reverse proxy section covers what to watch for with SSE and WebSocket upgrades.

Strengths

  • Reuses your existing TLS, certificates, and observability stack.
  • Mounts OpenCode under your own domain and path convention.
  • Integrates with corporate SSO, IP allowlists, and rate limits you already maintain.

Trade-offs

  • You own the configuration — wrong proxy settings silently break SSE and look like a connection error in the app.
  • Exposure depends entirely on your DNS and proxy config; not a good fit for quick experimentation.

What about plain LAN or SSH port forwarding?

Both are valid for specific situations and are covered in the remote-access guide. LAN is fine when the iPhone and the dev machine are on the same trusted Wi-Fi; SSH forwarding is fine when the iPhone is jailbroken or you want to keep the dev machine off every tunnel product. Neither is a remote-by-default option, so the four above are the ones to choose between for "use my OpenCode from anywhere" setups.