Best way to try openziti


now I’m starting to understand the concept and workings of the Openziti application. i have followed 2 documentations and 2 youtube links, they are very helpful

but somehow I still can’t connect between edge client (macos, ios) and edge client host (docker), is there a good way to troubleshoot?


  • docker-compose
version: "2.4"
    image: "openziti/ziti-edge-tunnel"
    container_name: ziti-edge-tunnel
      NF_REG_NAME: "purple-ziti-edge-tunnel"
      - ./data:/ziti-edge-tunnel
    command: "run-host"

    image: traefik/whoami
    container_name: whoami
      - --name=berrabe
  • here’s my applied config
ziti edge create identity user macbook
ziti edge create identity device docker -o docker.jwt
ziti edge create config host.v1 '{"protocol":"tcp", "address":"whoami", "port":80}'
ziti edge create config whoami.intercept.v1 intercept.v1 '{"protocols":["tcp"],"addresses":["whoami.ziti"], "portRanges":[{"low":80, "high":80}]}'
ziti edge create service whoami.service --configs whoami.intercept.v1,
ziti edge create service-policy whoami.policy.bind Bind --service-roles '@whoami.service' --identity-roles "@PURPLE-openziti-edge-router"
ziti edge create service-policy whoami.policy.dial Dial --service-roles "@whoami.service" --identity-roles '@macbook'
  • always stuck in here, whether setup using “local - docker-compose” / “host anywhere”


Hi @berrabe, welcome to the forum and to OpenZiti!

You’re off to a good start! Thanks for providing the ziti cli commands you ran too. Looking at the host.v1. I see you used “whoami” as the address. That means when the traffic lands at the ‘bind’ side, there should be an underlay endpoint available at “tcp:whoami:80”. I see you have used what seems to be a router for the bind point of your service: “@PURPLE-openziti-edge-router”.

The docker compose file sets up a network named ziti but I don’t see your whoami/ziti-edge-tunnel containers on that network. Is that intentional? That might be the problem.

As for “the best way to debug” here’s the flow I usually follow:

Step Result
does the client have the proper service? Yes. We can see your client resolved “whoami.ziti” properly. good
did the client intercept the traffic? Yes. We don’t see a timeout in your example, so it defintely looks like seems like it intercepted the traffic
Any errors in the client side logs unknown yet, check the client logs for suspicious errors like “NO_EDGE_ROUTERS” etc
are there any errors in the ‘bind’ identity? unknown at this time. in your case it looks like you used the edge router, so you need to look at the edge router’s logs here.

My hunch right now is you have two different docker networks, one for ziti and one for traefik/ziti-edge-tunnel. I dunno if that’ intentional or not, but I would start off with them all on the same docker network to take that out of the equation and move them to separate docker networks if you want later. That will come with another challenge of routing between the two networks which we can figure out later if you want?

Oh my bad - I forgot it uses networks named “zitired” and “zitiblue” by default.

thank you for your reply, i really appreciate it

UPDATE: I was able to connect from macbook to traefik/whoami docker, apparently I was wrong when configuring bind identity roles, which should be from purple ziti to docker


# docker edge tunnel run as host only
ziti edge create identity device docker -o docker.jwt
# wrong binding
ziti edge create service-policy whoami.policy.bind Bind --service-roles '@whoami.service' --identity-roles "@PURPLE-openziti-edge-router"
# correct binding
ziti edge create service-policy whoami.policy.bind Bind --service-roles '@whoami.service' --identity-roles "@docker"


at least I already understand how openziti and zero trust framework work. Now I want to apply this setup to replace my traditional network using OpenVPN.

I have 100 servers all connected to 1 central server using OpenVPN, what is the best way to put it all into openziti which will be accessed by several people/team based on their own policies?

Your 100 servers, are they all in docker like you did here or are they all just regular servers you can install software into?

For situations like this I always look to install the ziti-edge-tunnel, often in host mode like you did depending on if you want the servers to be able to intercommunicate or not.

I would use attributes for the policies and make policies like “developer”, “kubernetes”, “ci”, etc. Whatever policies make sense to your overlay. Then each new person that needs access, I would provision them an identity, and assign the appropriate attributes to the identity. Then in their local client they’ll see the services they have access to shown.

That make enough sense? Hopefully, but if it doesn’t just let us know.

the server I mean is a VM (regular server) not a container

if I had to deploy edge-tunnel on every server and create an identity for each server and setup them one by one I would be in a bit of trouble (yes I’m using ansible, but I’m not sure about the maintenance efforts going forward

what about ZTNA mode instead of ZTHA? maybe i can deploy edge-tunnel in front of my OpenVPN tunnel.

And can each attribute in each policy such as “developer”,“ops”,“sec-team” access the specific IP under ZTNA edge tunnel?

Oh, ok, sure. I understand what you’re looking for better now. I didn’t have quite a clear picture of your setup. I thought those servers were not colocated for some reason and were all on separate networks.

Yes that’s a perfectly viable option too and commonly deployed. For that, generally we recommend you deploy one or two edge routers in your private network space. Then you’d configure the edge routers to bind your services and use ZTNA. that’d work, indeed.

the network diagram will be like this

I have some questions (makes me ambiguous):

  1. different when using edge-router and edge-client, can i use edge-client instead of edge-router on OVPN server like on docker apps above (proxied application mode)
  2. do i need fabric router? can edge-router create mesh network without fabric?
  3. let’s say i’ve deployed edge-router on OVPN server and my OVPN subnet is, but how to make it useful? do i need to create host and intercept config for every IP under my OVPN network (OVPN edge-router)?

Thanks for the diagram. “Public Network” is actually public?

So this is more like what I was thinking originally but I was thinking you were looking to replace the deployment of the OpenVPN server and clients, and were planning to replace that with OpenZiti overlay/clients.

What you show in the diagram, feels like would work yes but I can’t say I’m sure since I’m not all that familiar with OpenVPN. It makes sense though, particularly if you’re not running in “intercept mode” and only use “host mode” of a tunneler.

  1. Yes, with this diagram you can definitely choose to use ziti-edge-tunnel instead of the edge router, sure. With the diagram as you’re showing it though, I don’t think you would need it. You would/could use that OpenZiti edge router to offload back towards the OpenVPN server. But – you could use a ziti-edge-tunnel if you want, it just seems like it’s one extra piece you wouldn’t need?
  2. Nope, you don’t need any more than one single edge-router. I run all my home stuff through a single public edge router. Additional routers can provide greater availability/resiliency and can add capacity. More routers (like ‘fabric routers’) are more nodes that the overlay can use to find the best/fastest path to offload data but they are entirely optional. One single edge-router is all you need.
  3. Assuming for this, you’re going to replace the OpenVPN clients entirely with OpenZiti tunnelers, you would just make a new service that is basically exactly like the old OpenVPN client. You make a single “intercept.v1” config that intercepts tcp/udp, intercepts, and ports 1-65535. Then you choose to “forward protocol”, “forward ip”, “forward port”.

Hopefully that all makes sense? :slight_smile:

yes, “public network” is a public network using public ip / WAN

I have tried, but I still haven’t succeeded until now, this is my current situation

  1. I’ve deployed ziti-edge-tunnel (using systemd) on my public OpenVPN Server, everything is good (enrolled)
  2. Creating Intercept.v1 (without host.v1) configuration using TCP and UDP as procotol, as address (my OVPN network), and 1 - 65535 as port ranges
  3. Activating edge-tunnel on my macbook, i’ve got ip, which is the same like edge-tunnel on my OpenVPN-server, is it ok?
  4. Try to ping my OVPN gateway (, connected, but with very low latency (around 1 ms), which is strage, pinging ip public got 20-30 ms
  5. Try to access my SSH on OVPN gateway using verbose mode, refused

Here’s my command history

ziti edge create identity device OVPN-server -o OVPN-server.jwt
ziti edge create config ovpn-server.intercept.v1 intercept.v1 '{"protocols":["tcp", "udp"],"addresses":[""], "portRanges":[{"low":1, "high":65535}]}'
ziti edge create service ovpn-server.service --configs ovpn-server.intercept.v1
ziti edge create service-policy ovpn-server.policy.bind Bind --service-roles '@ovpn-server.service' --identity-roles "@OVPN-server"
ziti edge create service-policy ovpn-server.policy.dial Dial --service-roles "@ovpn-server.service" --identity-roles '@macbook'

Did you create a ‘bind’ config? I only see the ‘intercept’ config in your command list? Also note that ICMP (ping) is not a supported protocol. We only support TCP/UDP.

You’ll also have to update your service and reference both configs once you make that bind config.

A great tool here is policy advisor. A service using tunnelers like this must have an intercept and a bind config:

ziti edge policy-advisor services ovpn-server.service -q

Here’s an example of one that is correct, you see both Dial: Y and Bind: Y

ziti edge policy-advisor services zsshSvc -q
OKAY : zsshSvcClient (1) -> zsshSvc (1) Common Routers: (1/1) Dial: Y Bind: N

OKAY : zsshSvcServer (1) -> zsshSvc (1) Common Routers: (1/1) Dial: N Bind: Y

I still don’t get it, I’m just following what you said, what I understand from your sentence is that it’s enough to make an intercept.v1 config (without bind) that intercepts TCP / UDP with ports 1 - 65535. But inside ZAC (Ziti Admin Console), there is no check mark that activate “forward protocol”, “forward ip”, “forward port” in intercept.v1

Assuming for this, you’re going to replace the OpenVPN clients entirely with OpenZiti tunnelers, you would just make a new service that is basically exactly like the old OpenVPN client. You make a single “intercept.v1” config that intercepts tcp/udp, intercepts, and ports 1-65535. Then you choose to “forward protocol”, “forward ip”, “forward port”.

and if I use bind (v1 / v2), what kind of settings should I apply? because when i apply for protocol address, it will show error message address is invalid: address: Must validate one and only one schema (oneOf)

this is my policy-advisor output

> ziti edge policy-advisor services -q ovpn-server.service

OKAY : OVPN-server (1) -> ovpn-server.service (1) Common Routers: (1/1) Dial: N Bind: Y
OKAY : macbook (1) -> ovpn-server.service (1) Common Routers: (1/1) Dial: Y Bind: N

No worries! Let’s see if I can be more clear and help you out. :slight_smile:

The forward* booleans are in the “host.v1” config. I went to my ZAC and picked a config I had. Notice the checkboxes there? you probably want to toggle all three of these. It sounds like you want to just forward “whatever” you intercepted on the client side, and send that through on the “far/server” side:

When you click those toggles, you’ll then see you need to set the “allowed” fields (if you look at this in ZAC). I think you probably want something like this. Make sure you click ‘add’ or hit enter to make the pills show up like this:

You can do that via the ziti CLI like this:

ziti edge create config "" host.v1 '{"forwardProtocol":true,"allowedProtocols":["tcp","udp"],"forwardAddress": true,"allowedAddresses":[""],"forwardPort":true,"allowedPortRanges":[{"high":65535,"low":1}]}'

That help?

amazing! it’s worked! thanks for your help, i really appreciate it

let me clear up my perception

  1. in ZTNA mode, you don’t need to fill in the protocol address? unless you are using ZTHA mode, is that correct?
  2. and what i understand is this bind mode does SRCNAT? all incoming traffic from my macbook to server ( will be translated to ip because when I do SSH, the variable SSH_CLIENT shows me that my connection is from ip
  3. usually I connect using the hostname instead of IP for SSH connection (i’ve external nameserver), but when using openziti, it doesn’t work, SSH connection stuck at “Connecting to xxx-server port X.” but when using IP (172.16.100.x), it works

Awesome! Great to hear. You’re welcome.

As for your questions:

ZTNA is more about whether the traffic enters or leaves the overlay via a network more than just the host network. So if your data enters the first piece of the OpenZiti overlay over the LAN/WAN, or if it leaves the final piece of the OpenZiti overlay and traverses a network (WAN/LAN) more than just the host network, we would consider that ZTNA. So either side can be ZTNA and you can mix/match modes. Often, like you’re thinking here, it’s the exit node that has a greater chance to be ZTNA. The traffic enters the overlay via a tunneler from the machine’s local network we would consider that ZTHA because it only traverses the local network. Hopefully, that makes sense? You still need to fill out the protocol and addresses though.

It’s kinda complex, and I’m not a network engineer, I’m a developer, so my terminology might be muddled here. I hope I get it right! :slight_smile: All traffic originating at the source, destined to, will be intercepted by OpenZiti, transported to the destination, and then a connection will be established from the remote, terminating side towards whatever IP was intercepted. Maybe an example will help. If you’re sending traffic to, because of your intercept config using a CIDR range, your traffic will be routed to our TUN locally. You’ll see a route sending all traffic to whatever our TUN ip is ( probably). The traffic will be ‘magically’ proxied by OpenZiti, sent to the final destination of the circuit where the remote machine will open a socket to and the traffic will be sent to the actual terminating side of the circuit. These packets will not look to be coming from the soruce IP from the initiating machine, they’ll be coming from the far end of the tunnel, whatever the IP is of the remote machine. I think OpenZiti has support for spoofing the source IP of those packets, but I’m not the expert here… @scareything or @dariuszSki could probably correct my words, if they are not accurate though. Maybe this is ‘good enough for now’ though? :slight_smile:

OpenZiti doesn’t support hostnames, but it does support fully qualified domain names. If you want to reduce the scope of your intercept, you can choose to intercept domain names. Personally, I will often add “.ziti” to the end of my intercept so that I can ssh to “pihole.ziti” or “m1mini.ziti” etc. You just need a single period in the intercept configuration, and then OpenZiti can intercept any domain name you want. Including names that don’t exist like “pihole.ziti” but you can also intercept legitimate domain names. This is incredibly powerful.

Take a look at one of my personal identities. You’ll see I only use FQDN for my services:

Then I don’t need to remember IP addresses. It’s quite nice :slight_smile:

Hope that all helps, happy OpenZiti-ing!!! :slight_smile: