> For the complete documentation index, see [llms.txt](https://docs.testvibe.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.testvibe.com/runners/self-hosted-runners.md).

# Private Runners

A private runner is the same runner image TestVibe uses in the cloud, run by you on a machine inside your firewall. It exists for applications that are fully private and whose traffic must never leave your network: the tests execute on your own infrastructure and reach the app directly.

The connection is **outbound-only**: the runner dials out to TestVibe, picks up the next job, runs it locally, and uploads the results. Nothing inbound is opened.

## Private Runner vs Tunneled

Both targets let you test an app the public internet can't reach. They differ in *where the test code runs*:

|                                       | Private runner            | [Tunneled](/account-settings/tunnel-devices.md) |
| ------------------------------------- | ------------------------- | ----------------------------------------------- |
| Where the AI-generated test code runs | Your infrastructure       | TestVibe's isolated sandbox                     |
| What you host                         | The runner image          | The small `tvtunnel` agent                      |
| App traffic                           | Never leaves your network | Relayed to the sandbox (encrypted end-to-end)   |

{% hint style="warning" %}
On a private runner, the AI-generated test code runs on **your** infrastructure rather than in a TestVibe sandbox. **Review and approve generated tests before running them on a private runner.** Scope the runner machine's network access to the application under test, and keep its runner token rotated. If you'd rather keep the untrusted code inside TestVibe's sandbox, use a [tunnel](/account-settings/tunnel-devices.md) instead.
{% endhint %}

## When To Use A Private Runner

| Need                              | Why a private runner fits                                                            |
| --------------------------------- | ------------------------------------------------------------------------------------ |
| Fully private or on-prem app      | The runner sits inside the network that hosts your app and reaches it directly.      |
| Traffic must stay in your network | Nothing about the run transits TestVibe — only job metadata and uploaded results do. |
| Strict outbound-only posture      | The runner dials out; no inbound firewall changes are needed.                        |

## How A Private Runner Works

A private runner is **pull-based** — it asks TestVibe for work rather than receiving it:

1. The runner registers with TestVibe and sends a periodic heartbeat (all outbound).
2. It long-polls for the next job assigned to your project.
3. When a job arrives, it runs the Playwright tests locally against your app.
4. It uploads screenshots, videos, traces, and logs to TestVibe's cloud, then posts the result.

Results, live status, and evidence appear in the Runs section exactly as they do for cloud runs.

## Set A Project To Use A Private Runner

Switch a project to the private-runner target, then point a runner at your project. While no runner is online, a run waits in **preparing** (TestVibe is waiting for an online runner) and times out with an error if none connects.

For choosing between targets, see [Choose an execution target](/runners/choose-a-runner.md). To pick a project's default target, see [Set a project's execution target](/runners/set-default-runner.md).

## Keep It Reliable

| Area           | Recommendation                                                                                                            |
| -------------- | ------------------------------------------------------------------------------------------------------------------------- |
| Uptime         | Run the runner as a service on a stable machine — a laptop that sleeps stops picking up jobs.                             |
| Network access | The runner only needs outbound access to TestVibe plus reach to the apps your tests target.                               |
| Tokens         | Treat the runner token like any credential; rotate or revoke it from Settings → CLI & API keys if the machine is retired. |

## Related Help

* [Choose an execution target](/runners/choose-a-runner.md)
* [Tunnel devices](/account-settings/tunnel-devices.md)
* [Set a project's execution target](/runners/set-default-runner.md)
* [Troubleshoot execution](/runners/troubleshooting-runners.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.testvibe.com/runners/self-hosted-runners.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
