December 6, 2023
|
5
min read

Introducing the ngrok Python SDK

Bob Hagemann

We are delighted to announce the release of ngrok-python, a native and idiomatic ngrok agent SDK designed to integrate secure ingress directly into your Python applications. If you have prior experience with ngrok, think of ngrok-python as the ngrok agent conveniently packaged as a Python library. ngrok-python is open source on GitHub, with docs available here, and a getting started guide available here.

With ngrok-python, developers can effortlessly serve Python apps through ngrok’s global network using just a single line of code. It eliminates the need to navigate complex network configurations such as reverse proxies, certificates, and load balancers. 

An excellent example of ngrok-python's capabilities is its seamless integration into Stable Diffusion Web UI, a widely popular UI for Stable Diffusion, developed by AUTOMATIC1111. Thousands of users rely on ngrok-python daily to ensure the security and global accessibility of their machines across the globe.

Try out our ngrok Python SDK

Check out how easy it is to run a Hello World web app with ngrok-python:


from http.server import HTTPServer, BaseHTTPRequestHandler
import logging, ngrok, os
import asyncio

class HelloHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        body = bytes("Hello", "utf-8")
        self.protocol_version = "HTTP/1.1"
        self.send_response(200)
        self.send_header("Content-Length", len(body))
        self.end_headers()
        self.wfile.write(body)

logging.basicConfig(level=logging.INFO)
server = HTTPServer(("localhost", 8080), HelloHandler)
listener = ngrok.forward("localhost:8080", authtoken_from_env=True)
server.serve_forever()

How it works

Similar to how the other ngrok SDKs work, such as ngrok-go, in the example above, when calling <code>ngrok.forward()</code> ngrok-python creates a secure and persistent outbound TLS connection to ngrok’s ingress-as-a-service platform.

After a connection has been established, ngrok transmits that configuration information through the nearest Point of Presence (POP) and applies the modules defined by your application. Any unauthorized requests are blocked at the edge, ensuring only authorized requests reach your application.

As many experienced Python developers may recognize, passing sockets around is not a universally accepted interface, and instead, many frameworks opt to establish local connections themselves. To solve for this use case, ngrok-python exposes multiple ways to forward traffic to a pre-existing socket or connection:


ngrok.forward("8080")
ngrok.forward("192.168.1.100:8080")
ngrok.forward("https://192.168.1.100")
ngrok.forward("unix:///path/to/unix.sock")

For those familiar with how the ngrok agent works, <code>ngrok.forward()</code> works in a similar fashion, establishing a secure connection to the ngrok platform and forwarding traffic to the given destination.

We’ve also added some helper methods for establishing connectivity with popular frameworks. You can learn more about them on the ngrok-python GitHub repo.

Why we built ngrok-python

Ingress should be a high-level abstraction

Creating ingress today can be a frustrating task that involves managing various low-level networking components. Developers have to grapple with multiple technologies at different layers of the network stack, such as DNS, TLS certificates, CIDR policies, IP and subnet routing, load balancing, VPNs, and NATs, among others. In essence, developers are forced to work with the intricate details of networking, similar to working with assembly language. In addition, developers also bear the responsibility of ensuring high performance, security, and resilience for their applications and APIs. Slowdowns or downtime can significantly impact user experience. Instead of focusing on core business logic, developers often invest substantial time and effort in adding non-functional capabilities such as authentication, authorization, observability, and high availability that are outside their area of expertise. 

To address this issue, we have developed ngrok-python, which empowers application developers to define ingress policies at a higher level of abstraction without compromising security and control. With ngrok-python, developers can easily specify ingress using declarative options, eliminating the burden of dealing with low-level intricacies. We do the heavy lifting of ensuring high performance, security, and resilience for your apps so you don’t have to spend time and effort building it yourself.


ngrok.forward(
	addr="localhost:8080",
	authtoken_from_env=True,
	circuit_breaker=0.5,
	compression=True,
	deny_user_agent="bar/(d)+",
	domain="my-app.ngrok.dev",
	deny_cidrs="200.2.0.0/16",
	oauth_provider="google",
	oauth_allow_domains=["example.com"],
	oauth_allow_emails=["bob@example.com"],
	request_header_add="X-Requester:app",
)

Ingress should be environment-independent

In traditional scenarios, ingress is closely tied to where and how you deploy your app. For instance, deploying your app to a data center, an EC2 instance, or a Kubernetes cluster entails varying networking configurations, and you must maintain a separate ingress configuration for each of these environments.

When your application uses ngrok-python, you can run it anywhere and it will receive traffic the same way. From an ingress standpoint, your application becomes portable: it does not matter whether it runs on bare metal, VMs, AWS, Azure, Kubernetes, serverless platforms like Heroku or Render, a racked data center server, a Raspberry Pi, or  your laptop.

Ingress shouldn’t require sidecars

Developers often distribute the ngrok agent alongside their own applications to create ingress for their IoT devices, SaaS offerings, and CI/CD pipelines. It can be challenging to bundle and manage the ngrok agent as a sidecar process. ngrok-python eliminates the agent, simplifying distribution and management and enabling developers to easily deliver private-label experiences.

How we designed ngrok-python

We designed ngrok-python to integrate seamlessly into the Python ecosystem. Here are just some of the features and functionality we built out:

  • Easy installation: Installed from PyPI via pip
  • Easy integration: Implements python <code>socket listen()</code> and <code>fd()</code> for easy integration into systems like AIOHTTP, flask, and uvicorn
  • Works in one-line: Provides ingress with a single <code>ngrok.forward(port)</code> call
  • Idiomatic functional options:Enables developers to declare behaviors like authentication simply using <code>kwargs</code>, e.g. <code>ngrok.forward(oauth_provider=”google”)</code>
  • Built-in forwarding: Forwards to any framework that can listen to a tcp or unix socket
  • Out-of-the-box logging support: Supports python standard logging, which you can enable using  <code>`logging.basicConfig(level=logging.INFO)`</code>

We validated the design of our library by collecting feedback from the following open-source Python communities:

Our GitHub repo includes examples for using ngrok-python with these Python frameworks:

Get started with ngrok-python

Check out these other resources to learn more about the ngrok-python agent SDK::

Share this post