ngrok's Go SDK v2: simple, streamlined, more powerful

I’m excited to let you all know we’ve just published the v2 API of ngrok-go, our idiomatic open-source Go package for embedding ngrok directly into your Go applications. This v2 update modernizes the API, simplifies integration, and exposes new ngrok platform features for a leaner, more idiomatic interface that’s easier to learn, use, and maintain.

With just a few lines of code, ngrok-go adds a secure, environment-agnostic API gateway in front of your Go application—no matter where it runs. When you use ngrok-go, you will receive traffic the same way no matter where you run your app: any cloud, CI environment, on your laptop, … anywhere.

Over the last two years, ngrok-go has been adopted by thousands of developers and integrated into 80+ open source packages. Meanwhile, ngrok’s own platform has evolved—prompting a major upgrade to keep the SDK in step. Let’s take a closer look at what’s new in v2.

Here’s what’s new in v2:

  • Streamlined API surface: We reduced the SDK from 3 subpackages to 1 and trimmed over 150 exported identifiers down to just 50. You’ll find fewer concepts to learn, and more clarity in how to use them. See the new API reference docs.
  • Removed and consolidated features:
    • Removed labeled tunnels and unnecessary convenience methods.
    • Consolidated middleware and access control into a single Traffic Policy API.
  • Introduced fine-grained Dialer and TLS controls:
  • Simplified forwarding API: added a unified, simpler Forward API when you want to use ngrok-go to forward connections to another process like the ngrok agent
  • Simplified events API: There are fewer APIs needed to handle events and server RPCs and they are extensible so that additional ones can be added with minimal additions to the API surface
  • Unified logging with log/slog: Now uses Go’s new standard structured logging library, log/slog, so your ngrok logs integrate cleanly with modern observability stacks.
  • Unified terminology: We've aligned the SDK with ngrok's platform concepts—Endpoints, Agents, and Traffic Policies—eliminating confusion and making the experience consistent with other ngrok tools and SDKs.

Example: serve a “Hello World” Go app with ngrok-go v2

Let’s try ngrok-go v2! First, install the SDK with:

go get golang.ngrok.com/ngrok/v2

Then export your auth token by entering the following in your terminal:

export NGROK_AUTHTOKEN=<your_auth_token>

And go run the following code:

package main

import (
   "context"
   "fmt"
   "log"
   "net/http"
   "golang.ngrok.com/ngrok/v2"
)

func main() {
   l, err := ngrok.Listen(context.Background())
   if err != nil {
       log.Fatal(err)
   }
   fmt.Println("endpoint url: ", l.URL())
   http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
       fmt.Fprintln(w, "Hello from your ngrok-delivered Go app!")
   }))
}

Traffic Policy: declare traffic management in your Go code

Traffic Policy is ngrok’s configuration language that enables you to filter, match, manage, and orchestrate traffic with a simple CEL-based rules engine. Much of the v1 package API has been replaced with Traffic Policy. Let’s see how easy that is to use to add authentication to an endpoint:

package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"golang.ngrok.com/ngrok/v2"
)

func main() {
	if err := run(context.Background()); err != nil {
		log.Fatal(err)
	}
}

const trafficPolicy = `
on_http_request:
  - name: OAuth
    actions:
      - type: oauth
        config:
          auth_id: oauth
          provider: google
  - name: bad email
    expressions:
      - actions.ngrok.oauth.identity.email != 'alan@example.com'
    actions:
      - type: custom-response
        config:
          body: "Access denied: ${actions.ngrok.oauth.identity.name}!"
          status_code: 403
`

func run(ctx context.Context) error {
	// Create an HTTP listener with the traffic policy
	ln, err := ngrok.Listen(ctx,
		ngrok.WithTrafficPolicy(trafficPolicy),
		ngrok.WithDescription("traffic policy example"),
	)
	if err != nil {
		return err
	}
	// Serve HTTP traffic on the ngrok endpoint
	log.Println("Endpoint online", ln.URL())
	return http.Serve(ln, http.HandlerFunc(handler))
}

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %s\n", r.Header.Get("authenticated-user"))
}

Although it may seem unconventional at first to define traffic policy as YAML instead of typed Go code, we’ve found this approach greatly enhances the user experience. YAML-based traffic policies are easy to test, share, and reuse across Cloud Endpoints, Agent Endpoints, the Kubernetes Operator, and SDKs. You can copy and modify examples from documentation or the community with ease. Additionally, using Traffic Policy enables access to new traffic features without needing to upgrade your SDK.

Get started with ngrok-go v2

First, install the SDK: go get golang.ngrok.com/ngrok/v2

Then check out our other resources:

We distribute agent SDK libraries in Go, Rust, Python and Javascript. Go is the first agent SDK to get a 2.0 facelift, but you can expect us to roll out improved APIs for all languages over the remainder of the year.

If you have questions or feedback about ngrok-go v2 or any of our SDKs, why not pop into our Discord server? We'd be happy to help you over there and hear you to make things better.

Share this post
Go language
ngrok agent
API gateway
Features
Gateways
SDKs
Development
Production