Cloud-VM workspaces connect to the browser webApp automatically. At create
time the control plane makes a named Cloudflare Tunnel for the workspace, a
proxied DNS record ws-<workspace-id>.<your-zone>, and hands the box a tunnel
token. The box dials out; it opens no inbound port. The webApp talks only to
the control plane, which proxies terminal, files, and previews through the
tunnel and authenticates every hop. Destroying the workspace removes the
tunnel and the DNS record.
This page is step 8 of the self-host guide.
- The Cloudflare account that runs your control-plane Worker.
- A domain you own, added as an active zone on that same account. Cross-account tunnel DNS does not work. Any spare domain is fine; users never see these hostnames.
- Access to the domain's registrar to change nameservers.
wranglerauthenticated against the account.- Default account limit: 1,000 tunnels, which caps concurrent cloud-VM workspaces. Enterprise can raise it.
- Two Worker secrets:
CLOUDFLARE_API_TOKEN(created in step 2) andWEBAPP_TOKEN_SECRET(a random 32-byte string). Step 5 sets both.WEBAPP_TOKEN_SECRETis required for every webApp surface on every provider, tunnel or not.
- In
dash.cloudflare.com, select the account, click Add a domain. - Enter your domain. Pick the Free plan. Accept the DNS defaults.
- Cloudflare shows two nameservers. Set exactly those at your registrar.
- Wait until the zone Overview shows Active.
-
Go to
dash.cloudflare.com/profile/api-tokens→ Create Token → Create Custom Token. -
Name it (for example
blitz-connectivity). -
Add exactly three permission rows:
Scope Group Level Account Cloudflare Tunnel (older UI: "Argo Tunnel") Edit Zone DNS Edit Zone Zone Read -
Account Resources: Include → your account.
-
Zone Resources: Include → All zones from an account → your account.
-
Leave IP filtering and TTL empty. Create the token.
-
Copy only the token value from the copy box. It is one unbroken string of letters, digits,
_,-. It never contains=, spaces, or quotes. Do not copy thecurlexample line.
Zone Overview page, right column, Zone ID. Or:
curl -s -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
"https://api.cloudflare.com/client/v4/zones?name=<your-domain>"In packages/control-plane/wrangler.toml:
CLOUDFLARE_ACCOUNT_ID = "<your account id>"
CLOUDFLARE_ZONE_ID = "<zone id from step 3>"
WORKSPACE_TUNNEL_ZONE = "<your-domain>"Leaving these three vars empty does not degrade gracefully for cloud VMs: a
cloud-VM workspace still boots and reports ready, but every browser
active surface — terminal, files, and previews — routes through this tunnel and
returns 503 workspace has no webapp tunnel without it.
npx wrangler secret put CLOUDFLARE_API_TOKEN --config packages/control-plane/wrangler.toml
# paste the token from step 2
npx wrangler secret put WEBAPP_TOKEN_SECRET --config packages/control-plane/wrangler.tomlWEBAPP_TOKEN_SECRET is in the deploy gate's required set, so it may already
be set. Its value and what it protects are in
step 3 of the self-host guide.
npm run deploy -w packages/control-planeThe deploy command applies migrations, re-checks the required secrets, builds the webApp, and deploys.
- Create a cloud-VM workspace in the webApp.
- A proxied DNS record
ws-<workspace-id>.<your-domain>appears in the zone, and the workspace terminal, files, and preview tabs work with no SSH forwards. - Destroy the workspace. The DNS record and tunnel disappear.
Invalid format for Authorization header(codes 6003/6111): the stored token is not the token value. Re-copy it; check the charset rule in step 2.7.- Zone queries return an empty list: the token was scoped to the wrong account, or the zone is not Active yet.
- Workspace creation fails with a tunnel error: confirm the token has Account → Cloudflare Tunnel → Edit, on the same account as the zone.
- WebApp endpoints return 503
workspace has no webApp tunnel: the workspace was created before this feature was configured. Recreate it.