Support embedding as a library in existing Go app #427

Open
opened 2025-11-20 05:11:11 -05:00 by saavagebueno · 4 comments
Owner

Originally created by @clarkmcc on GitHub (Aug 23, 2023).

Describe the solution you'd like
Something similar to tsnet which allows us to take advantage of existing netbird functionality without having to install it separately. There are probably some challenges with this, like the need to have #1054 implemented (which is what tsnet does), but figured I'd surface this as an issue now.

Originally created by @clarkmcc on GitHub (Aug 23, 2023). **Describe the solution you'd like** Something similar to [tsnet](https://pkg.go.dev/tailscale.com/tsnet) which allows us to take advantage of existing netbird functionality without having to install it separately. There are probably some challenges with this, like the need to have #1054 implemented (which is what tsnet does), but figured I'd surface this as an issue now.
saavagebueno added the client label 2025-11-20 05:11:11 -05:00
Author
Owner

@nickchomey commented on GitHub (Oct 5, 2024):

I'd also love to see this in Netbird. It might end up being the factor that makes me choose Tailscale over Netbird, even though I'd rather use Netbird. My constraints don't really make it all that feasible to install it as root on linux systems, so would need to embed it in my Go app that runs in user space.

@nickchomey commented on GitHub (Oct 5, 2024): I'd also love to see this in Netbird. It might end up being the factor that makes me choose Tailscale over Netbird, even though I'd rather use Netbird. My constraints don't really make it all that feasible to install it as root on linux systems, so would need to embed it in my Go app that runs in user space.
Author
Owner

@johnnypea commented on GitHub (Jan 24, 2025):

I would like to build Caddy plugin like this https://github.com/tailscale/caddy-tailscale , but this is a real blocker for me. Is it on the roadmap?

@johnnypea commented on GitHub (Jan 24, 2025): I would like to build Caddy plugin like this https://github.com/tailscale/caddy-tailscale , but this is a real blocker for me. Is it on the roadmap?
Author
Owner

@lixmal commented on GitHub (Jan 29, 2025):

Take a look at #3239.
Currently it's a bit rough and needs all the replace directives in go.mod, but this will be fixed at some point.

Example program:

package main

import (
	"context"
	"errors"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	netbird "github.com/netbirdio/netbird/client/embed"
)

func main() {
	// Create client with setup key and device name
	client, err := netbird.New(netbird.Options{
		DeviceName:    "http-server",
		SetupKey:      os.Getenv("NB_SETUP_KEY"),
		ManagementURL: os.Getenv("NB_MANAGEMENT_URL"),
		LogOutput:     io.Discard,
	})
	if err != nil {
		log.Fatal(err)
	}

	// Start with timeout
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	if err := client.Start(ctx); err != nil {
		log.Fatal(err)
	}

	// Create HTTP server
	mux := http.NewServeMux()
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Printf("Request from %s: %s %s\n", r.RemoteAddr, r.Method, r.URL.Path)
		fmt.Fprintf(w, "Hello from netbird!")
	})

	// Listen on netbird network
	l, err := client.ListenTCP(":8080")
	if err != nil {
		log.Fatal(err)
	}

	server := &http.Server{Handler: mux}
	go func() {
		if err := server.Serve(l); !errors.Is(err, http.ErrServerClosed) {
			log.Printf("HTTP server error: %v", err)
		}
	}()

	log.Printf("HTTP server listening on netbird network port 8080")

	// Handle shutdown
	stop := make(chan os.Signal, 1)
	signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
	<-stop

	shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := server.Shutdown(shutdownCtx); err != nil {
		log.Printf("HTTP shutdown error: %v", err)
	}

	if err := client.Stop(shutdownCtx); err != nil {
		log.Printf("Netbird shutdown error: %v", err)
	}
}

go.mod:

module nb

go 1.23.2

require github.com/netbirdio/netbird embed-netbird

require (
	cunicu.li/go-rosenpass v0.4.0 // indirect
	github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
	github.com/aws/aws-sdk-go-v2 v1.30.3 // indirect
	github.com/aws/aws-sdk-go-v2/config v1.27.27 // indirect
	github.com/aws/aws-sdk-go-v2/credentials v1.17.27 // indirect
	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect
	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect
	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 // indirect
	github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
	github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect
	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect
	github.com/aws/aws-sdk-go-v2/service/route53 v1.42.3 // indirect
	github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 // indirect
	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect
	github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect
	github.com/aws/smithy-go v1.20.3 // indirect
	github.com/caddyserver/certmagic v0.21.3 // indirect
	github.com/caddyserver/zerossl v0.1.3 // indirect
	github.com/cenkalti/backoff/v4 v4.3.0 // indirect
	github.com/cilium/ebpf v0.15.0 // indirect
	github.com/cloudflare/circl v1.5.0 // indirect
	github.com/coreos/go-iptables v0.7.0 // indirect
	github.com/creack/pty v1.1.18 // indirect
	github.com/davecgh/go-spew v1.1.1 // indirect
	github.com/fsnotify/fsnotify v1.7.0 // indirect
	github.com/gliderlabs/ssh v0.3.8 // indirect
	github.com/go-ole/go-ole v1.3.0 // indirect
	github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
	github.com/godbus/dbus/v5 v5.1.0 // indirect
	github.com/golang/protobuf v1.5.4 // indirect
	github.com/google/btree v1.1.2 // indirect
	github.com/google/go-cmp v0.6.0 // indirect
	github.com/google/gopacket v1.1.19 // indirect
	github.com/google/nftables v0.2.0 // indirect
	github.com/google/pprof v0.0.0-20211214055906-6f57359322fd // indirect
	github.com/google/uuid v1.6.0 // indirect
	github.com/gopacket/gopacket v1.1.1 // indirect
	github.com/hashicorp/errwrap v1.1.0 // indirect
	github.com/hashicorp/go-multierror v1.1.1 // indirect
	github.com/hashicorp/go-version v1.6.0 // indirect
	github.com/jmespath/go-jmespath v0.4.0 // indirect
	github.com/josharian/native v1.1.0 // indirect
	github.com/klauspost/cpuid/v2 v2.2.7 // indirect
	github.com/libdns/libdns v0.2.2 // indirect
	github.com/libdns/route53 v1.5.0 // indirect
	github.com/libp2p/go-netroute v0.2.1 // indirect
	github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae // indirect
	github.com/mdlayher/genetlink v1.3.2 // indirect
	github.com/mdlayher/netlink v1.7.2 // indirect
	github.com/mdlayher/socket v0.5.1 // indirect
	github.com/mholt/acmez/v2 v2.0.1 // indirect
	github.com/miekg/dns v1.1.59 // indirect
	github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
	github.com/nadoo/ipset v0.5.0 // indirect
	github.com/onsi/ginkgo/v2 v2.9.5 // indirect
	github.com/pion/dtls/v2 v2.2.10 // indirect
	github.com/pion/ice/v3 v3.0.2 // indirect
	github.com/pion/logging v0.2.2 // indirect
	github.com/pion/mdns v0.0.12 // indirect
	github.com/pion/randutil v0.1.0 // indirect
	github.com/pion/stun/v2 v2.0.0 // indirect
	github.com/pion/transport/v2 v2.2.4 // indirect
	github.com/pion/transport/v3 v3.0.1 // indirect
	github.com/pion/turn/v3 v3.0.1 // indirect
	github.com/pmezard/go-difflib v1.0.0 // indirect
	github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
	github.com/quic-go/quic-go v0.48.2 // indirect
	github.com/shirou/gopsutil/v3 v3.24.4 // indirect
	github.com/shoenig/go-m1cpu v0.1.6 // indirect
	github.com/sirupsen/logrus v1.9.3 // indirect
	github.com/stretchr/testify v1.9.0 // indirect
	github.com/things-go/go-socks5 v0.0.4 // indirect
	github.com/tklauser/go-sysconf v0.3.14 // indirect
	github.com/tklauser/numcpus v0.8.0 // indirect
	github.com/vishvananda/netlink v1.2.1-beta.2 // indirect
	github.com/vishvananda/netns v0.0.4 // indirect
	github.com/yusufpapurcu/wmi v1.2.4 // indirect
	github.com/zcalusic/sysinfo v1.1.3 // indirect
	github.com/zeebo/blake3 v0.2.3 // indirect
	go.uber.org/mock v0.4.0 // indirect
	go.uber.org/multierr v1.11.0 // indirect
	go.uber.org/zap v1.27.0 // indirect
	golang.org/x/crypto v0.32.0 // indirect
	golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
	golang.org/x/mod v0.17.0 // indirect
	golang.org/x/net v0.30.0 // indirect
	golang.org/x/sync v0.10.0 // indirect
	golang.org/x/sys v0.29.0 // indirect
	golang.org/x/term v0.28.0 // indirect
	golang.org/x/text v0.21.0 // indirect
	golang.org/x/time v0.5.0 // indirect
	golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
	golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
	golang.zx2c4.com/wireguard v0.0.0-20230704135630-469159ecf7d1 // indirect
	golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 // indirect
	golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
	google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
	google.golang.org/grpc v1.64.1 // indirect
	google.golang.org/protobuf v1.34.2 // indirect
	gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
	gopkg.in/yaml.v3 v3.0.1 // indirect
	gvisor.dev/gvisor v0.0.0-20231020174304-db3d49b921f9 // indirect
	nhooyr.io/websocket v1.8.11 // indirect
)

replace golang.zx2c4.com/wireguard => github.com/netbirdio/wireguard-go v0.0.0-20241125150134-f9cdce5e32e9

replace github.com/cloudflare/circl => github.com/cunicu/circl v0.0.0-20230801113412-fec58fc7b5f6

replace github.com/pion/ice/v3 => github.com/netbirdio/ice/v3 v3.0.0-20240315174635-e72a50fcb64e

Let me know what you think of the API

@lixmal commented on GitHub (Jan 29, 2025): Take a look at #3239. Currently it's a bit rough and needs all the `replace` directives in [go.mod](https://github.com/netbirdio/netbird/blob/main/go.mod), but this will be fixed at some point. Example program: ```go package main import ( "context" "errors" "fmt" "io" "log" "net/http" "os" "os/signal" "syscall" "time" netbird "github.com/netbirdio/netbird/client/embed" ) func main() { // Create client with setup key and device name client, err := netbird.New(netbird.Options{ DeviceName: "http-server", SetupKey: os.Getenv("NB_SETUP_KEY"), ManagementURL: os.Getenv("NB_MANAGEMENT_URL"), LogOutput: io.Discard, }) if err != nil { log.Fatal(err) } // Start with timeout ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := client.Start(ctx); err != nil { log.Fatal(err) } // Create HTTP server mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Printf("Request from %s: %s %s\n", r.RemoteAddr, r.Method, r.URL.Path) fmt.Fprintf(w, "Hello from netbird!") }) // Listen on netbird network l, err := client.ListenTCP(":8080") if err != nil { log.Fatal(err) } server := &http.Server{Handler: mux} go func() { if err := server.Serve(l); !errors.Is(err, http.ErrServerClosed) { log.Printf("HTTP server error: %v", err) } }() log.Printf("HTTP server listening on netbird network port 8080") // Handle shutdown stop := make(chan os.Signal, 1) signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM) <-stop shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := server.Shutdown(shutdownCtx); err != nil { log.Printf("HTTP shutdown error: %v", err) } if err := client.Stop(shutdownCtx); err != nil { log.Printf("Netbird shutdown error: %v", err) } } ``` go.mod: ``` module nb go 1.23.2 require github.com/netbirdio/netbird embed-netbird require ( cunicu.li/go-rosenpass v0.4.0 // indirect github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect github.com/aws/aws-sdk-go-v2 v1.30.3 // indirect github.com/aws/aws-sdk-go-v2/config v1.27.27 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.17.27 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect github.com/aws/aws-sdk-go-v2/service/route53 v1.42.3 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect github.com/aws/smithy-go v1.20.3 // indirect github.com/caddyserver/certmagic v0.21.3 // indirect github.com/caddyserver/zerossl v0.1.3 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cilium/ebpf v0.15.0 // indirect github.com/cloudflare/circl v1.5.0 // indirect github.com/coreos/go-iptables v0.7.0 // indirect github.com/creack/pty v1.1.18 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gliderlabs/ssh v0.3.8 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gopacket v1.1.19 // indirect github.com/google/nftables v0.2.0 // indirect github.com/google/pprof v0.0.0-20211214055906-6f57359322fd // indirect github.com/google/uuid v1.6.0 // indirect github.com/gopacket/gopacket v1.1.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-version v1.6.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/native v1.1.0 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/libdns/libdns v0.2.2 // indirect github.com/libdns/route53 v1.5.0 // indirect github.com/libp2p/go-netroute v0.2.1 // indirect github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae // indirect github.com/mdlayher/genetlink v1.3.2 // indirect github.com/mdlayher/netlink v1.7.2 // indirect github.com/mdlayher/socket v0.5.1 // indirect github.com/mholt/acmez/v2 v2.0.1 // indirect github.com/miekg/dns v1.1.59 // indirect github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect github.com/nadoo/ipset v0.5.0 // indirect github.com/onsi/ginkgo/v2 v2.9.5 // indirect github.com/pion/dtls/v2 v2.2.10 // indirect github.com/pion/ice/v3 v3.0.2 // indirect github.com/pion/logging v0.2.2 // indirect github.com/pion/mdns v0.0.12 // indirect github.com/pion/randutil v0.1.0 // indirect github.com/pion/stun/v2 v2.0.0 // indirect github.com/pion/transport/v2 v2.2.4 // indirect github.com/pion/transport/v3 v3.0.1 // indirect github.com/pion/turn/v3 v3.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/quic-go/quic-go v0.48.2 // indirect github.com/shirou/gopsutil/v3 v3.24.4 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/stretchr/testify v1.9.0 // indirect github.com/things-go/go-socks5 v0.0.4 // indirect github.com/tklauser/go-sysconf v0.3.14 // indirect github.com/tklauser/numcpus v0.8.0 // indirect github.com/vishvananda/netlink v1.2.1-beta.2 // indirect github.com/vishvananda/netns v0.0.4 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/zcalusic/sysinfo v1.1.3 // indirect github.com/zeebo/blake3 v0.2.3 // indirect go.uber.org/mock v0.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.32.0 // indirect golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.30.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.29.0 // indirect golang.org/x/term v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect golang.zx2c4.com/wireguard v0.0.0-20230704135630-469159ecf7d1 // indirect golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 // indirect golang.zx2c4.com/wireguard/windows v0.5.3 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect google.golang.org/grpc v1.64.1 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gvisor.dev/gvisor v0.0.0-20231020174304-db3d49b921f9 // indirect nhooyr.io/websocket v1.8.11 // indirect ) replace golang.zx2c4.com/wireguard => github.com/netbirdio/wireguard-go v0.0.0-20241125150134-f9cdce5e32e9 replace github.com/cloudflare/circl => github.com/cunicu/circl v0.0.0-20230801113412-fec58fc7b5f6 replace github.com/pion/ice/v3 => github.com/netbirdio/ice/v3 v3.0.0-20240315174635-e72a50fcb64e ``` Let me know what you think of the API
Author
Owner

@mlsmaycon commented on GitHub (Apr 8, 2025):

Hello @johnnypea , have you got the chance to look into the embedded version and caddy?

@mlsmaycon commented on GitHub (Apr 8, 2025): Hello @johnnypea , have you got the chance to look into the embedded version and caddy?
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: SVI/netbird#427