# zrok: Zero-Trust localhost Tunneling for Public and Private Sharing


[zrok](https://zrok.io/) is an open-source sharing tool by NetFoundry that exposes local services to collaborators or the internet. **It supports two modes: public sharing, which generates an HTTPS URL anyone can access, and private sharing**, which creates a token-based connection that never produces a public endpoint. The security layer is [OpenZiti](https://openziti.io/), an open-source zero-trust networking platform, which means traffic is routed through an encrypted overlay network rather than directly through the public internet.

<iframe width="100%" height="315" src="https://www.youtube.com/embed/dLW0cT-iTjs" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


## Problems with traditional tunneling tools

Tools like ngrok make a local service publicly accessible by forwarding traffic from a public URL to a local port. This is fast for webhooks and quick demos, but comes with practical and security tradeoffs.

**Ephemeral URLs** are regenerated each session on free tiers, requiring webhook URLs, documentation links, and anything else referencing that endpoint to be updated every time.

**Session limits** close free tunnels after a period of inactivity, which is disruptive during long debugging sessions.

**Request rate limits** on free plans can be hit quickly when testing APIs or serving content.

**Browser warnings** appear for users visiting an ngrok tunnel for the first time, adding friction to client demos.

![Standard ngrok terminal session showing the generated public URL and connection status](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/aeb139d3-93e6-4353-978d-b4bc93ce3500/orig =1280x720)

![The ngrok warning page that users see before accessing a tunneled site](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/879d5468-36a6-4559-bad7-729939d5dd00/lg1x =1280x720)

Beyond usability, any public tunnel exposes a development machine to automated scanners and bots that continuously probe public URLs for vulnerabilities. For a service with database access or sensitive business logic, this is an unnecessary risk.

## How zrok's zero-trust model works

zrok is built on OpenZiti, which creates a private overlay network rather than forwarding a public port.

![Graphic indicating that zrok has "OpenZiti Baked In" highlighting the foundational technology](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/b1fd9bfb-0b01-406f-179c-524aaa3d5500/orig =1280x720)

When you share something privately with zrok, no public endpoint is created. The connection exists only between authenticated participants in the overlay network. Traffic does not touch the public internet unless you explicitly choose a public share. This reduces the attack surface to zero for private shares: there is no URL to scan, no public port to probe.

## Public and private sharing

![zrok homepage featuring its astronaut mascot and simple command-line examples](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/4eed28f0-685e-48da-9cd3-2d0c21be9d00/lg1x =1280x720)

**Public sharing** generates an HTTPS URL that forwards to your local service. This is appropriate for webhook testing with services like GitHub, Stripe, or Twilio, and for demos where the recipient does not have zrok installed.

**Private sharing** provides a share token instead of a URL. The recipient uses their own zrok client to create a local connection to your share. They access your service at a `localhost` address on their machine, which is proxied through the encrypted overlay to your service. No public endpoint is created at any point.

![Diagram illustrating the private sharing workflow with a secure tunnel through the OpenZiti cloud between two private networks](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/8b3d1ad0-f5fb-44b2-953c-32474b0f0b00/public =1280x720)

The private model works as follows: you share a service and receive a token, you send that token through a secure channel to a trusted collaborator, they run `zrok access private <token>` on their machine, and a local port on their machine proxies to your service through the overlay network. No one else can access the connection.

## Installation and setup

### Installing the binary

On macOS with Homebrew:

```command
brew install zrok
```

On Linux:

```command
bash -c "$(curl -sS https://zrok.io/install.sh)"
```

On Windows with Scoop:

```command
scoop bucket add zrok https://github.com/openziti/zrok-scoop.git
```

```command
scoop install zrok
```

Verify the installation:

```command
zrok version
```

### Creating an account

Register with the free `zrok.io` service:

```command
zrok invite
```

Enter an email address when prompted. A verification email arrives with a link to activate the account.

### Enabling the environment

The verification page displays an `enable` command containing a unique token. Copy and run it:

```command
zrok enable LgVx0ZAL99Kx
```

![The zrok enable command being executed in the terminal showing the successful confirmation message](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/f1c71024-22be-460f-75e4-224f56810800/public =1280x720)

This stores the environment identity on the local machine. It only needs to be done once per device.

## Sharing a local service

The following examples assume a service is running at `http://localhost:3000`.

### Public share

```command
zrok share public http://localhost:3000
```

zrok outputs a public HTTPS URL such as `https://sfnblbt17596.shares.zrok.io`. Anyone with that URL can access the service. Press `Ctrl+C` to stop the share.

### Private share

```command
zrok share private http://localhost:3000
```

Instead of a URL, zrok outputs a share token such as `d6zu50wi2cm8`. Send this token to the collaborator through a secure channel.

On the recipient's machine (with zrok installed and enabled):

```command
zrok access private d6zu50wi2cm8
```

![Recipient's terminal showing the zrok access private command with the unique share token](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/371c92ac-1859-4038-bdd5-b3bce398ee00/orig =1280x720)

Their terminal shows a local proxy address such as `http://127.0.0.1:9191 -> d6zu50wi2cm8`. Opening `http://127.0.0.1:9191` in their browser connects them to your local service through the encrypted overlay. No public URL exists at any point.

## Final thoughts

The **private sharing mode is the most significant differentiator from ngrok and similar tools. For collaboration on work-in-progress code**, API endpoints with sensitive logic, or anything that should not be publicly accessible, private shares eliminate the risk entirely rather than relying on obscurity.

zrok is also self-hostable. If you need full control over the infrastructure rather than using the `zrok.io` public service, the project's documentation covers deploying your own instance.

The project is available at [github.com/openziti/zrok](https://github.com/openziti/zrok) and documentation at [docs.zrok.io](https://docs.zrok.io/).