# openziti/zrok: zero-trust sharing without opening a port

> zrok is a Go CLI that publishes web services, folders and TCP/UDP ports through the OpenZiti overlay, so nothing inbound has to be exposed. Here is how the enable and share flow works, what self-hosting involves, and where it stops being the right tool.

**openziti/zrok** — Secure internet sharing made simple.

- Repository: https://github.com/openziti/zrok
- Website: https://zrok.io
- Stars: 4,726 · Forks: 225
- Language: Go
- License: Apache-2.0
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/openziti-zrok

## The problem zrok removes: inbound reachability

Most sharing tools assume you can accept a connection. A reverse proxy needs a port open. A tunnel service needs an outbound agent and a hosted relay. zrok's README frames the same problem differently: it says the tool works through firewalls, NAT and corporate networks with no port forwarding and no network configuration changes. That is the whole pitch, and it is narrower than it sounds.

The target user is someone who has a service running on localhost and no clean way to hand it to another person or machine. A developer demoing a build, someone passing a directory of files to a colleague, a team exposing an internal TCP service to a handful of known users. The README's own examples are exactly those three: a web service on port 8080, a folder shared as a network drive, and a private TCP or UDP service.

What separates it from a generic tunnel is the identity model. The README states that sharing is identity-based rather than address-based, and that traffic is encrypted end to end, including from zrok servers. If your requirement is "expose this to anyone on the internet with no account," that model is more machinery than you need.

## How the overlay carries a share

zrok does not implement its own transport. The README states it is built on OpenZiti, described there as a programmable zero-trust network overlay. The repository layout backs that up: go.mod depends on github.com/openziti/sdk-golang, github.com/openziti/channel/v4, github.com/openziti/identity and github.com/openziti/ziti itself.

The data flow implied by the README is: the CLI registers an identity with a controller, publishes a backend (an HTTP port, a TCP or UDP service, or a directory in drive mode), and other zrok users reach that backend through the overlay. The README says peer-to-peer connections are used when possible, with the overlay as the path when they are not. The practical consequence is that the listening side never needs an inbound route.

The repository is split into the pieces you would expect from that design: controller/ for the control plane, agent/ and endpoints/ for the connecting side, sdk/ for embedding, rest_server_zrok/ and rest_client_zrok/ generated from specs/, plus tui/ and ui/ for interfaces. The go.mod dependency on github.com/caddyserver/caddy/v2 and github.com/greenpau/caddy-security suggests HTTP handling and authentication are delegated rather than hand-rolled. That is a reasonable choice, and it also means a self-hosted deployment inherits Caddy's configuration surface.

## Install zrok and make a first share

The README does not inline the install commands. It points at the install guide at docs.zrok.io, so the exact package manager invocation depends on your platform and is not reproduced here. What the README does give is the account and enable sequence, and those three steps are the real gate.

After installing the binary, request an account and enable the environment:

```bash
zrok invite
zrok enable
```

The README says the invite step can use the free zrok.io service, and that enable activates sharing for that environment. Expect a token to be involved at this point; the README does not document the token format, and the related search terms for zrok token and zrok register suggest people hit this step first. Once enabled, the sharing commands are the interesting part:

```bash
zrok share public localhost:8080
zrok share public --backend-mode drive ~/Documents
zrok share private localhost:3000
```

The first exposes a local web service publicly. The second switches the backend to drive mode, which the README describes as turning a folder into a shareable network drive; the screenshot captions show it mounted in a file explorer. The third keeps the share private, so only other zrok users can reach it. If you want to build the CLI from source instead, the Makefile requires Node for the UI first:

```bash
make build
```

That target runs npm install and npm run build in both ui/ and agent/agentUi/ before go install ./cmd/zrok2. A Go toolchain alone is not enough to produce a working build.

## Where zrok is the wrong tool

The first limitation is the account. Every path in the README starts with invite and enable, which means an identity in a controller. If you want a colleague to open a URL with no client, no account and no enrollment, zrok's public share mode may still work, but the publisher side always has an identity, and the private mode explicitly requires the other party to be a zrok user.

The second is the dependency chain. A zrok share is only as available as the controller and the overlay behind it. The README does not describe what a client sees when the controller is unreachable, and there is no documented grace period or offline mode. For a short demo that is fine. For something you promise will be up, you are now operating two systems instead of one.

The third is build friction. The Makefile's build target installs npm dependencies for two separate frontends before compiling Go. If your environment cannot run Node during the build, you are limited to whatever prebuilt artifacts the release process publishes. The repository carries separate GoReleaser files for darwin, linux-amd64, linux-arm64, linux-armel, linux-armhf and windows, which indicates prebuilt binaries exist, but the README does not enumerate them.

Finally, drive mode is a file-sharing convenience, not a sync tool. The README describes it as a network drive, and nothing in it mentions conflict resolution, versioning or offline edits. Treat it as a mounted view, not as a replacement for a synced folder.

## Self-hosting versus the hosted service

The README states that a single binary contains everything needed to run your own zrok service, that it scales from a Raspberry Pi to large public instances, and that it is built on the same codebase as the public zrok.io service. It links a self-hosting guide rather than documenting the steps inline, so the operational detail lives outside the repository README.

What the repository does show is the shape of that deployment. There is a docker/ directory, an environment/ directory, a controller/ component and a set of GoReleaser configurations per platform. The go.mod pulls in github.com/lib/pq and github.com/mattn/go-sqlite3, so both PostgreSQL and SQLite appear as storage options, and github.com/rabbitmq/amqp091-go plus github.com/influxdata/influxdb-client-go suggest message queue and metrics integrations. None of that is described in the README; it is visible only by reading the dependency list and the directory names.

The honest framing is that self-hosting zrok means operating an OpenZiti-based service, not flipping a flag. If your reason for self-hosting is data residency, that is a legitimate reason, and the README supports it. If your reason is avoiding operational work, the hosted service is the lower-effort path and the README presents it as the default.

## Alternatives and the actual difference

The closest comparison in the search data is openziti versus zrok, and the answer is that they are not competitors. OpenZiti is the overlay; zrok is an application built on it. Choosing OpenZiti directly means you define services, identities and policies yourself and get no share command. Choosing zrok means you accept its opinionated share, drive and private modes in exchange for a much shorter path to a working link.

Against a general-purpose tunnel tool, the difference is the identity model. A typical tunnel assigns a public hostname to a local port and lets anyone with the URL in. zrok's private mode does the opposite: the README states sharing is with specific users, not IP addresses, and that traffic stays encrypted even from zrok servers. That is a real architectural difference, and it is also why private shares require the other side to be a zrok user.

Against a plain file-sync client, drive mode is not comparable. A sync client keeps two copies consistent; zrok exposes one directory over the overlay while the publisher is running. The README never claims otherwise, and anyone expecting sync semantics will be disappointed.

If you already run OpenZiti for other services, adding zrok is a small step because the overlay is already there. If you do not, zrok is the easier entry point into that model, and it is also a commitment to it.

## Maintenance, licensing and upgrade cost

The repository is not archived, and the last push was on 2026-06-22. Recent releases are v2.0.2 on 2026-04-21, v2.0.3 on 2026-05-07 and v2.0.4 on 2026-05-18, so the project is publishing tagged releases rather than only moving on main. That is the extent of what the README supports; it does not state a support window or a deprecation policy.

The licence is Apache-2.0, held in the LICENSE file at the repository root. That permits commercial use and modification with the usual notice and patent terms. It says nothing about the hosted zrok.io service, which is a separate offering with its own terms that the README does not reproduce. Self-hosting under Apache-2.0 and using the public service are two different legal situations, and the README does not spell out the second one.

Upgrade cost is where the Go module path matters. The module is declared as github.com/openziti/zrok/v2, and the release history sits in the v2 line. Anyone embedding the SDK should expect the v2 import path, and anyone on a v1-era integration should check the SDK guide linked from the README before assuming the calls are unchanged. The README's SDK example shows sdk.CreateShare with a ShareRequest carrying BackendMode and ShareMode, and sdk.NewListener taking a share token and a root. Those names are the contract you would be upgrading against.

The README does not document rollback, version pinning or a compatibility matrix, so verify those against the CHANGELOG and the release notes before upgrading a production instance.

## Conclusion

Adopt zrok when you need to expose a local service or folder to a specific audience without touching firewall rules, and you accept the dependency on either the zrok.io service or your own OpenZiti controller. Do not adopt it if you need a plain public reverse proxy with no overlay identity model, or if you cannot run the npm-based UI build that the Makefile requires. Before rolling it out, verify two things: that your target platform has a published binary or container image, and whether your deployment is pointed at the public zrok.io service or at a self-hosted instance, because that choice decides who holds the account data. The repository is Apache-2.0 and its most recent push was on 2026-06-22, so the code is moving, but the README does not document a rollback path for a share.

## FAQ

### How does zrok work?

zrok is built on OpenZiti, a zero-trust network overlay. The CLI enables an identity, publishes a backend such as an HTTP port, a TCP or UDP service, or a directory in drive mode, and other users reach it through the overlay, with peer-to-peer connections used when possible.

### Is zrok free?

The README says the invite step can use the free zrok.io service, and the source is Apache-2.0, so self-hosting is also an option. The README does not describe paid tiers or limits on the hosted service.

### Is zrok.io safe?

The README states that traffic is end-to-end encrypted and encrypted even from zrok servers, and that access is identity-based rather than address-based. It does not publish an independent audit or a security review, so that claim rests on the project's own documentation.

### How does OpenZiti work?

The README describes OpenZiti as a programmable zero-trust network overlay that zrok is built on, providing no inbound connectivity requirement, end-to-end encryption and identity-based access. The full architecture is documented at docs.openziti.io rather than in the zrok README.

## Sources

- [License: Apache-2.0](https://github.com/openziti/zrok/blob/main/LICENSE)
- [openziti/zrok on GitHub](https://github.com/openziti/zrok)
- [Project website](https://zrok.io)
- [README](https://github.com/openziti/zrok/blob/main/README.md)
- [Releases](https://github.com/openziti/zrok/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/openziti-zrok
