Skip to content

x/tunnel v0.1.0

Choose a tag to compare

@slinkydeveloper slinkydeveloper released this 13 Jul 16:08

First release of github.com/restatedev/sdk-go/x/tunnel — a module that serves a Restate SDK deployment over an outbound connection to Restate Cloud's tunnel servers, so a deployment in a private network needs no inbound HTTP listener and no public ingress. It's the Go equivalent of TypeScript's @restatedev/restate-sdk-tunnel and interoperates with the restate-operator's in-process tunnel mode.

Install

go get github.com/restatedev/sdk-go/x/tunnel@v0.1.0

Requires github.com/restatedev/sdk-go v1.0.1+.

Usage

Instead of server.Restate.Start (which listens), you build a *server.Restate, wrap it with NewTunnel, and call Start:

package main

import (
	"context"
	"log/slog"
	"os"
	"os/signal"
	"syscall"

	restate "github.com/restatedev/sdk-go"
	"github.com/restatedev/sdk-go/server"
	"github.com/restatedev/sdk-go/x/tunnel"
)

type Greeter struct{}

func (Greeter) Greet(ctx restate.Context, name string) (string, error) {
	return "You said hi to " + name + "!", nil
}

func main() {
	ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
	defer stop()

	srv := server.NewRestate().
		Bind(restate.Reflect(Greeter{}))

	err := tunnel.NewTunnel(srv,
		// Config can either be in-code via options, or via env variables (see godoc for all details)
		tunnel.WithRegion("us"),
		tunnel.WithEnvironment("env_...", "publickeyv1_..."),
		tunnel.WithAuthToken(os.Getenv("RESTATE_AUTH_TOKEN")),
		tunnel.WithTunnelName("greeter-v1"),
	).Start(ctx) // blocks until ctx is cancelled, then drains + closes

	if err != nil {
		slog.Error("tunnel exited with error", "err", err.Error())
		os.Exit(1)
	}
}

Once started, the tunnel client connects to Restate cloud and allows to use this process as service deployment.

Start logs the deployment URL on connect; register it (the operator does this for you on Kubernetes):

restate deployments register <deployment-url>

Check https://pkg.go.dev/github.com/restatedev/sdk-go/x/tunnel for the full API documentation

Zero-config under the operator

With tunnelMode: in-process the operator injects the RESTATE_INPROC_* env vars, which setups all the necessary configuration entries. The code just needs:

err := tunnel.NewTunnel(srv).Start(ctx)

How it works

Dial out (TLS, ALPN h2) → role-flip: Restate Cloud drives the connection as the HTTP/2 client while the SDK serves as the HTTP/2 server (http2.Server.ServeConn) → GET /_/start-tunnel handshake completed via HTTP/2 trailers → each invocation is one stream whose /<scheme>/<host>/<port> prefix is stripped before the request is handed to the reused server.Restate handler (discovery, invoke, and request-identity verification against the signing key).