Can I achieve something similar using Zrok instead of Ngrok? Possible?

is it possible to do something like this but using Zrok?

code for ngrok:
import os
from pyngrok import ngrok
from IPython.display import clear_output, Javascript
ngrok.kill()
%cd /kaggle/working/program_ml
os.system(f"filebrowser -r /kaggle -p 9876 > /dev/null 2>&1 &")
clear_output()
%load_ext tensorboard
%tensorboard --logdir logs --port 8077
p_tunnel = ngrok.connect(6969)
t_tunnel = ngrok.connect(8077)
f_tunnel = ngrok.connect(9876)
clear_output()
print("Applio Url:", p_tunnel.public_url)
print("Tensorboard Url:", t_tunnel.public_url)
print("File Url:", f_tunnel.public_url)
print("Save the link for later, this will take a while...")

!source /kaggle/tmp/.venv/bin/activate; python app.py

currently I am using this to run zrok:
command = 'source /kaggle/tmp/.venv/bin/activate; python app.py'
port = '6969'
port_t = '8077'
port_f = '9876'

------------------------

os.system(f"filebrowser -r /kaggle -p 9876 > /dev/null 2>&1 &")
%load_ext tensorboard
%tensorboard --logdir logs --port 8077
cmd = f'/kaggle/working/zrok/zrok share public http://localhost:{port} --headless & /kaggle/working/zrok/zrok share public http://localhost:{port_t} --headless & {command}'
get_ipython().system(cmd)

My question is:

  • Is there a better or more streamlined way to replicate what I'm doing with Ngrok but using Zrok instead?
  • Are there any improvements I can make to this code to achieve similar functionality more efficiently?
1 Like

The ngrok.connect function is replicating (in code) what the zrok share public command is doing. Unfortunately the zrok SDK does not (currently) have a single function you can call like that (from Python) to instantiate the reverse proxy in code.

To do the equivalent of ngrok.connect for zrok, you would need to call zrok.share.CreateShare and also open a network connection to the local resource. With those 2 network connections created (one to the zrok network, and another to the local resource), you would need to use 2 threads to read from one and write to the other, and then also the inverse (read from the other and write to the first).

There's an example in the Python SDK that shows how CreateShare and zrok.listener works:

At some point in the future we can probably provide a single function call that can instantiate a full reverse proxy in Python code.

1 Like

There's a new proxy package for the Py SDK coming in the next zrok release. It enables a Jupyter notebook to proxy a public or private share to a local target like this:

# %%
! pip install zrok

# %%

import zrok
from zrok.proxy import ProxyShare


# %%

target_url = "http://127.0.0.1:8000/"
unique_name = "myuniquename"  # a name to reuse each run or 'None' for random
share_mode = "public"         # "public" or "private"
frontend = "public"           # custom domain frontend or "public"

if unique_name.lower() == "none":
    unique_name = None


# %%

zrok_env = zrok.environment.root.Load()  # Load the environment from ~/.zrok

proxy_share = ProxyShare.create(
    root=zrok_env,
    target=target_url,
    frontends=[frontend],
    share_mode=share_mode,
    unique_name=unique_name,
    verify_ssl=True                     # Set 'False' to skip SSL verification
)


# %%

if share_mode == "public":
    print(f"Access proxy at: {', '.join(proxy_share.endpoints)}")
elif share_mode == "private":
    print(f"Run a private access frontend: 'zrok access private {proxy_share.token}'")

proxy_share.run()

Link to proxy notebook example: zrok/sdk/python/examples/proxy/proxy.ipynb at main · openziti/zrok · GitHub

Basic usage excerpt from the proxy README:

from zrok.proxy import ProxyShare
import zrok

# Load the environment
root = zrok.environment.root.Load()

# Create a temporary proxy share (will be cleaned up on exit)
proxy = ProxyShare.create(root=root, target="http://my-target-service")

# print the public URL
print(f"Access proxy at: {proxy.endpoints}")
proxy.run()

wow, this seems amazing! Is there any way to use it now?

1 Like

It just dropped. Will you let me know how it works for you?

pip install zrok==0.4.47

tried the code but got this:

---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-19-d49b02e43cb2> in <cell line: 2>()
      1 #
----> 2 zrok_env = zrok.environment.root.Load()  # Load the environment from ~/.zrok
      3 
      4 proxy_share = ProxyShare.create(
      5     root=zrok_env,

/usr/local/lib/python3.10/dist-packages/zrok/environment/root.py in Load()
    112     if __rootExists():
    113         r.meta = __loadMetadata()
--> 114         r.cfg = __loadConfig()
    115         r.env = __loadEnvironment()
    116     else:

/usr/local/lib/python3.10/dist-packages/zrok/environment/root.py in __loadConfig()
    137 def __loadConfig() -> Config:
    138     cf = configFile()
--> 139     with open(cf) as f:
    140         data = json.load(f)
    141         return Config(

FileNotFoundError: [Errno 2] No such file or directory: '/root/.zrok/config.json'

I am using it on a kaggle notebook

The Load() function loads your existing zrok user environment from ~/.zrok (or Windows equivalent) that you enabled on this device: Getting Started | Zrok

The error indicates it was unable to find the config.json file in your environment, so it's possible you need to enable a zrok user environment or perhaps there is a bug requiring a config.json file when it might not exist.

EDIT: I found the issue. The SDK requires a config.json file to exist, but it should not require it, only loading it if it exists. Workaround is to create the file by setting at least one configuration directive.

This will set the same value as the default, so it will not change behavior if you are missing a config.json file inside your enabled zrok user environment dir, e.g., ~/.zrok.

zrok config set apiEndpoint https://api.zrok.io

after trying a lot I am not able to run it using the way you mentioned if possible may you write a code that can work in kaggle/colab notebook so share ports like 8188 and sometimes able to share multiple ports. that would be so helpful

Sure thing, glad to help. Please help me understand the problem you encountered.

For example, if you are running a local webserver on 8188/TCP you can do this after you set at least one configuration with zrok config set.

from zrok.proxy import ProxyShare
import zrok

# Load the environment
root = zrok.environment.root.Load()

# Create a temporary proxy share (will be cleaned up on exit)
proxy = ProxyShare.create(root=root, target="http://127.0.0.1:8188")

# print the public URL
print(f"Access proxy at: {proxy.endpoints}")
proxy.run()