pyngrok – a Python wrapper for ngrok

pyngrok is a Python wrapper for ngrok that manages its own binary and puts it on our path, making ngrok readily available from anywhere on the command line and via a convenient Python API.

ngrok is a reverse proxy tool that opens secure tunnels from public URLs to localhost, perfect for exposing local web servers, building webhook integrations, enabling SSH access, testing chatbots, demoing from your own machine, and more, made even more powerful with native Python integration through pyngrok.

Installation

pyngrok is available on PyPI and can be installed using pip.

pip install pyngrok

That’s it! pyngrok is now available as a package to our Python projects, and ngrok is now available from the command line.

Open a Tunnel

To open a tunnel, use the connect() method, which returns the public URL generated by ngrok.

from pyngrok import ngrok

# Open a HTTP tunnel on the default port 80
public_url = ngrok.connect()
# Open a SSH tunnel
ssh_url = ngrok.connect(22, "tcp")

The connect() method takes an optional options parameter, which allows us to pass additional options that are supported by ngrokas shown below.

Get Active Tunnels

It can be useful to ask the ngrok client what tunnels are currently open. This can be accomplished with the get_tunnels() method, which returns a list of NgrokTunnel objects.

from pyngrok import ngrok

tunnels = ngrok.get_tunnels()
# A public ngrok URL that tunnels to port 80 (ex. http://<public_sub>.ngrok.io)
public_url = tunnels[0].public_url

Close a Tunnel

All open tunnels will automatically be closed when the Python process terminates, but we can also close them manually.

from pyngrok import ngrok

public_url = "http://<public_sub>.ngrok.io"

ngrok.disconnect(public_url)

The ngrok Process

Opening a tunnel will start the ngrok process. This process will remain alive, and the tunnels open, until ngrok.kill() is invoked, or until the Python process terminates.

If we are building a short-lived app, for instance a CLI, we may want to block on the ngrok process so tunnels stay open until the user intervenes. We can do that by accessing the NgrokProcess.

from pyngrok import ngrok

ngrok_process = ngrok.get_ngrok_process()

try:
    # Block until CTRL-C or some other terminating event
    ngrok_process.process.wait()
except KeyboardInterrupt:
    print(" Shutting down server.")

    ngrok.kill()

The NgrokProcess also contains an api_url variable, usually initialized to http://127.0.0.1:4040, from which we can access the ngrok client API.

If some feature we need is not available in this package, the client API is accessible to us via the api_request() method. Additionally, the NgrokTunnel objects expose a uri variable, which contains the relative path used to manipulate that resource against the client API. This package also gives us access to ngrok from the command line, as shown below.

Expose Other Service

Using ngrok we can expose any number of non-HTTP services, for instances databases, game servers, etc. This can be accomplished by using pyngrok to open a tcp tunnel to the desired service.

from pyngrok import ngrok

# Open a tunnel to MySQL with a Reserved TCP Address
ngrok.connect(3306, "tcp", options={"remoteaddr": "1.tcp.ngrok.io:12345")

Configuration

Setting the authtoken

Running ngrok with an auth token enables additional features available on our account (for instance, the ability to open multiple tunnels concurrently). We can obtain our auth token from the ngrok dashboard and install it like this:

from pyngrok import ngrok

ngrok.set_auth_token("<NGROK_AUTH_TOKEN>")

# Once an auth token is set, we are able to open multiple tunnels at the same time
ngrok.connect()
ngrok.connect(8000)

We can also override the auth token when necessary with:

from pyngrok import ngrok

ngrok.connect(auth_token="<NGROK_AUTH_TOKEN>")

The above will only work when ngrok is first starting, so if a tunnel has already been started in the session, we will need to kill() it first.

Setting the region

By default, ngrok will open a tunnel in the us region. To override this, use the region parameter:

from pyngrok import ngrok

url = ngrok.connect(region="au")

Passing options

It is also possible to configure the tunnel when it is created, for instance adding authentication, a subdomain, or other tunnel parameters supported by ngrok. These can be passed to the tunnel with the options parameter.

Here is an example starting ngrok in Australia, then opening a tunnel for with subdomain foo that requires basic authentication for requests.

from pyngrok import ngrok

url = ngrok.connect(region="au", options={"subdomain": "foo", "auth": "username:password"})

Config File

The default ngrok config file lives in the home directory’s .ngrok2 folder. We can change this in one of two ways. Either pass the config_path parameter to methods:

from pyngrok import ngrok

CONFIG_PATH = "/opt/ngrok/config.yml"

ngrok.connect(config_path=CONFIG_PATH)

or override the DEFAULT_CONFIG_PATH variable:

from pyngrok import ngrok

ngrok.DEFAULT_CONFIG_PATH = "/opt/ngrok/config.yml"

ngrok.set_auth_token("<NGROK_AUTH_TOKEN>")

Binary Path

The pyngrok package manages its own ngrok binary. However, we can use our ngrok binary if we want in one of two ways. Either pass the ngrok_path parameter to methods:

from pyngrok import ngrok

NGROK_PATH = "/usr/local/bin/ngrok"

ngrok.get_tunnels(ngrok_path=NGROK_PATH)

or override the DEFAULT_NGROK_PATH variable:

from pyngrok import ngrok

ngrok.DEFAULT_NGROK_PATH = "/usr/local/bin/ngrok"

ngrok.connect()

Command Line Usage

This package also puts the default ngrok binary on our path, so all features of ngrok are also available on the command line.

ngrok http 80

For details on how to fully leverage ngrok from the command line, see ngrok’s official documentation.

API Documentation

For more advanced usage, have a look at the API documentation for pyngrok to understand the public interfaces available to developers.

Contributing

  1. Become familiar with this package, pyngrok’s documentation, and ngrok’s documentation.
  2. Report issues on GitHub.
  3. Fork the repository on GitHub to start making changes.
  4. Write a test that plainly tests the changes made.
  5. Submit a pull requests to get the changes merged.