Skip to content

Step 6: Start a tunnel

Why a tunnel at all

GitHub delivers webhook events to a public HTTPS URL. Without one, GitHub never reaches your machine, so a PR event is never delivered and the actual trigger — the thing that makes this a webhook-driven bot rather than a script you run by hand — is never exercised. A tunnel is what makes localhost:8000 reachable from GitHub's side.

Install it

cloudflared isn't in Step 1's shared prerequisites because it's only needed on this track. Install it, then confirm with cloudflared --version:

sudo apt install cloudflared   # or download the binary
brew install cloudflared
winget install Cloudflare.cloudflared

Official download page: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/. uv run python -m bot.scripts.doctor also checks for it and prints the same install hint if it's missing.

Start one

In a second terminal (the first will run the service in step 8):

cloudflared tunnel --url http://localhost:8000

cloudflared's quick tunnel (TryCloudflare) is the documented default here, not a hard dependency — it is the only option needing no account, no config, one binary, and one command. ngrok now requires a free account and an authtoken; Tailscale Funnel and VS Code port forwarding both need accounts too. Any tool that yields a public HTTPS URL works — all the app needs is that URL in PUBLIC_BASE_URL plus a registered webhook (next step).

Set it

cloudflared prints an https://<random>.trycloudflare.com URL to its terminal. Set that as PUBLIC_BASE_URL in .env.

The URL changes on every restart

A quick tunnel's URL is ephemeral — it changes every time you restart cloudflared, which means PUBLIC_BASE_URL changes too, and step 7 (register the webhook) has to be re-run each session to point GitHub at the new URL. A named Cloudflare tunnel gives a stable hostname instead, but it needs a Cloudflare account and DNS configuration — out of scope for this track.

Next

Continue to Step 7: register the webhook.