Most end-to-end testing advice assumes your app has a public URL. Plenty of the apps worth testing don't: an internal admin console, a staging environment behind a VPN, a preview build on your own laptop. TestVibe runs AI-generated Playwright tests inside isolated cloud sandboxes — this guide covers how those sandboxes reach an app the public internet can't, and the security trade-offs of each approach.
Three ways a run reaches your app
Every project runs on one of three execution targets. The choice comes down to two questions: is your app reachable from the public internet, and where do you want the test code to run?
| Situation | Execution target |
|---|---|
| Public site or a normal staging URL | Cloud — the default; works out of the box. |
| Private app, and you'd rather not host a runner | Tunneled — a small agent inside your network lets the sandbox reach your app. |
| Private app whose traffic must never leave your network | Private runner — you host the runner inside your firewall. |
The site is on localhost of your own machine | Tunneled — run the agent on that machine. |
If your site is public, there's nothing to decide. The rest of this guide is about the other rows.
How a tunnel works
A tunnel device is a machine inside your network running the tvtunnel agent. With one connected, a cloud sandbox can dial through it to reach an app that has no public address. Three properties make this practical:
- The app URL stays unchanged. You don't rewrite tests or stand up a reverse proxy with a public hostname. The sandbox opens the same internal URL your browser would.
- No inbound firewall changes. The agent makes an outbound connection to TestVibe and holds it open. You don't open a port or expose anything to the internet.
- Traffic is end-to-end encrypted between the run and your network.
The security posture is the reason to prefer a tunnel over a private runner when both would work. AI-generated test code is untrusted by definition — it's freshly written by a model. With a tunnel, that code stays inside TestVibe's sandbox. Only a small signed agent runs on your side, and all it does is relay connections. Nothing you host executes the generated tests.

Setting up a tunnel
The setup is two steps: get a token, then start the agent on a machine that can reach your app.
1. Get an API key. In the app, open Settings → CLI & API keys and create a key. The agent uses it to authenticate — the same key both connects the device and identifies it in your workspace.
2. Start the agent. On a machine inside your network with Node 20 or newer, run the command shown in Settings → Tunnels for your OS. It downloads the agent bundle from your TestVibe server, then runs it from that local file:
# macOS / Linux
curl -fsSL <agent-tarball-url> -o tvtunnel.tgz && \
npx --yes ./tvtunnel.tgz --token <your-api-key> --server <your-testvibe-url>
# Windows PowerShell
iwr <agent-tarball-url> -OutFile tvtunnel.tgz
npx --yes ./tvtunnel.tgz --token <your-api-key> --server <your-testvibe-url>
The Tunnels panel fills in the real tarball URL, token, and server, so copy the command from there rather than retyping it. Downloading the bundle first and running the local file avoids npx fetching a remote tarball directly, which recent npm versions block by default.
Once the agent connects, the device appears in the Tunnels list automatically, with its online status. Flip the project's tunneled execution on, and its runs route through the tunnel instead of egressing directly from the cloud.
Pinning devices per project
A workspace can have several tunnel devices — different networks, different offices, a developer's laptop for a localhost build. One is marked Default.
Runs resolve a device in a simple order: a project uses its pinned device, falling back to the Default. Pin a device when a project's app lives in a different network than the Default reaches. Everything else rides the Default.
Keep the agent alive
The most common failure mode is mundane: the tunnel went down mid-run. If no device is connected, runs against a private URL can't reach the target and fail there — while the public-URL path is unaffected.
Two habits prevent it:
- Run
tvtunnelas a service on a stable machine. A laptop that sleeps takes your tunnel down with it. A small always-on box or a container is a better home than someone's workstation. - When a private run stalls or times out, check the device first. If the run can't reach the site, an offline or asleep tunnel device is the usual cause before anything in the test itself.
When a tunnel isn't the right tool
A tunnel still relays your app's traffic through TestVibe's sandbox, encrypted end to end. For apps whose traffic must never leave your network, host a private runner inside your firewall instead: the test code and the app traffic both stay on your infrastructure, and only job metadata and uploaded results transit TestVibe. The trade-off is that the AI-generated code then runs on your machine — so review and approve generated tests before running them there. If keeping that untrusted code inside the sandbox matters more, use a tunnel.
For most private and staging apps, a tunnel is the lighter option: nothing to host, no inbound ports, the app URL unchanged. Get early access to try it, or read the tunnel devices guide for the full setup.