Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Public Access

The daemon binds to 127.0.0.1:7890 by default. To accept GitHub webhooks or reach the daemon from another machine, expose it through a tunnel.

Cloudflare Quick TunnelTailscale Funnel
Account requiredNoYes (free)
URL stabilityRotates on restartPersistent (*.ts.net)
Best forOne-off testing, demosProduction webhooks, daily use
Prerequisitecloudflared on PATHTailscale enrolled on host

Cloudflare Tunnel

Bento can spin up a Cloudflare Quick Tunnel alongside the daemon, exposing the local 127.0.0.1:7890 port via an ephemeral *.trycloudflare.com URL with no Cloudflare account required. Useful for one-off webhook receivers, demos, and "show this to a teammate for an hour."

Prerequisites

  • cloudflared on the daemon host's PATH. On macOS: brew install cloudflared. On Linux see Cloudflare's install docs.
  • bento doctor validates this when the tunnel: block is present in bento.yaml.

Quick tunnel (no account)

Add a tunnel: block to bento.yaml:

tunnel:
  provider: cloudflare
  mode: quick

Then restart the daemon:

bento restart

The daemon spawns cloudflared, parses the public URL out of its startup log, and emits one info line:

[INFO] [tunnel] public URL ready: https://essentially-carrying-recorder-merely.trycloudflare.com

bento status surfaces the same URL:

local   : reachable (8ms) — @bento/daemon uptime=14s
tunnel  : reachable (83ms) — https://essentially-carrying-recorder-merely.trycloudflare.com
funnel  : not configured (tailscale funnel not active)

Use the public URL

GitHub webhooks — point the webhook delivery URL at:

https://<random>.trycloudflare.com/events

Make sure webhooks.secret in bento.yaml matches the GitHub webhook secret so signature verification passes. The daemon also accepts /webhooks/github and /webhooks/linear.

MCP clients — configure Claude Code / Codex / pi against the tunnel URL — see Authentication for the exact commands. Issue a bearer token first:

bento token issue --email you@example.com

Lifecycle

  • The tunnel is supervised as a child of the daemon. bento stop sends SIGTERM to cloudflared before stopping the HTTP server.
  • If cloudflared crashes while the daemon is up, the daemon logs the exit code at warn and keeps running. Restart to re-establish the tunnel.
  • The daemon does not block on tunnel readiness during startup.

Named tunnels (stable URL)

For a stable URL, pre-create a named tunnel in your Cloudflare account. The auto-generated <uuid>.cfargotunnel.com URL is only valid as a CNAME target — you need a real hostname.

Prerequisites

  • A free Cloudflare account.
  • cloudflared on the host.
  • A hostname you control with a CNAME pointing at the tunnel:
    • Cloudflare DNScloudflared tunnel route dns creates the CNAME automatically.
    • External DNS — create bento.example.com CNAME <tunnel-uuid>.cfargotunnel.com yourself.

One-time setup

  1. Authenticate cloudflared:

    cloudflared tunnel login
  2. Create the tunnel:

    cloudflared tunnel create bento-prod
  3. Route a hostname:

    # Cloudflare-managed DNS:
    cloudflared tunnel route dns bento-prod bento.example.com
     
    # External DNS: add a CNAME manually:
    # bento.example.com   CNAME   <uuid>.cfargotunnel.com

Point bento at the tunnel

tunnel:
  provider: cloudflare
  mode: named
  name: bento-prod

Then bento restart. The daemon runs cloudflared tunnel run, detects the registered hostname, and surfaces it in bento status.

Tear down

cloudflared tunnel delete bento-prod

Remove the DNS CNAME separately via your DNS provider.

Files

PathCreated byPurposeNeeded at runtime?
~/.cloudflared/cert.pemtunnel loginManage tunnels (create/delete/route DNS)No
~/.cloudflared/<uuid>.jsontunnel create <name>Authenticate the running tunnelYes
~/.cloudflared/config.ymlhand-written (optional)Ingress rulesOnly if not passing --url

Notes

  • Quick tunnels are public and unauthenticated at the tunnel layer. The daemon's bearer-token middleware and webhook signature verification are the only auth — never disable them.
  • Cloudflare may rate-limit Quick Tunnels under heavy traffic. For production webhook ingestion use a named tunnel.

Tailscale Funnel

Tailscale Funnel gives a persistent TLS-terminated *.ts.net URL routed back to your machine over the tailnet.

Two ways to wire it up:

  • Let bento manage ittunnel: block in bento.yaml; bento calls tailscale funnel --bg <port> at start and teardown.
  • Manage it yourself — run tailscale funnel --bg 7890 once; bento status still detects it.

Prerequisites

  • A Tailscale account with the daemon's host enrolled.
  • HTTPS certificates and Funnel enabled for your tailnet (admin console: DNS → HTTPS Certificates and Access Controls → Funnel).

Bento-managed mode

tunnel:
  provider: tailscale
  mode: funnel

bento restart execs tailscale funnel --bg 7890, polls tailscale funnel status for the public URL, and surfaces it via bento status.

On shutdown bento runs tailscale funnel --bg off — but only if it was the one that enabled the funnel. If a funnel was already active at startup, bento adopts the existing URL and skips both setup and teardown.

Manual mode

tailscale funnel --bg 7890

--bg persists across shell exits. You only need to run this once per machine.

Verify:

tailscale funnel status
# https://8640p.tail673878.ts.net (Funnel on)
# |-- / proxy http://127.0.0.1:7890

bento status picks it up automatically:

local   : reachable (4ms) — bento uptime=120s
funnel  : reachable (38ms) — https://8640p.tail673878.ts.net

Use the public URL

MCP clients — configure Claude Code, Codex, or pi — see Authentication. Issue a token first:

bento token issue --email you@example.com

GitHub webhooks — point the delivery URL at:

https://<node>.tail<id>.ts.net/events

Set the same secret as webhooks.secret in bento.yaml.

Stopping the funnel

tailscale funnel --bg off

Unbinds the public URL but leaves the daemon running locally.

Notes

  • Funnel only serves ports 443, 8443, and 10000 on the public side. Tailscale maps :443:7890 automatically.
  • Funnel traffic counts against tailnet bandwidth limits. For high-volume webhook traffic consider a server with a real DNS record.
  • The funnel URL is publicly reachable. Authentication is enforced by the daemon's bearer-token middleware — never disable it.