
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:
- WithAgentTLSTermination: manage mTLS and TLS termination your application.
- WithUpstreamTLSClientConfig: customize TLS configuration when forwarding.
- WithUpstreamDialer: define your own dialing logic for upstreams.
- 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:
- Quickstart guide: A step-by-step guide on how to use ngrok-go with a sample app.
- Go package documentation: The package documentation includes functions, variables, and even more examples.
- Repo on GitHub: ngrok-go is open source on GitHub—star the repo to follow along!
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.