netbirdio/netbird · error

create SSH proxy: %w

Error message

create SSH proxy: %w

What it means

sshproxy.New builds a gRPC client to the NetBird daemon using daemonaddr.DialTarget(daemonAddr) and grpc.NewClient. Because NewClient is lazy (non-blocking), this error almost always means the daemon address itself is invalid or cannot be turned into a dial target, not that the daemon is unreachable — connectivity problems surface later in Connect(). The underlying error is wrapped by sshproxy.New as 'connect to daemon: ...' and again here as 'create SSH proxy: ...'.

Source

Thrown at client/cmd/ssh.go:836

	host := args[0]
	portStr := args[1]

	port, err := strconv.Atoi(portStr)
	if err != nil {
		return fmt.Errorf("invalid port: %s", portStr)
	}

	// Check env var for browser setting since this command is invoked via SSH ProxyCommand
	// where command-line flags cannot be passed. Default is to open browser.
	noBrowser := getBoolEnvOrDefault("NO_BROWSER", false)
	var browserOpener func(string) error
	if !noBrowser {
		browserOpener = util.OpenBrowser
	}

	proxy, err := sshproxy.New(daemonAddr, host, port, cmd.ErrOrStderr(), browserOpener)
	if err != nil {
		return fmt.Errorf("create SSH proxy: %w", err)
	}
	defer func() {
		if err := proxy.Close(); err != nil {
			log.Debugf("close SSH proxy: %v", err)
		}
	}()

	if err := proxy.Connect(cmd.Context()); err != nil {
		return fmt.Errorf("SSH proxy: %w", err)
	}

	return nil
}

var sshDetectCmd = &cobra.Command{
	Use:    "detect <host> <port>",
	Short:  "Detect if a host is running NetBird SSH",
	Long:   "Internal command used by SSH Match exec to detect NetBird SSH servers. Exit codes: 0=JWT, 1=no-JWT, 2=regular SSH",

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Check NB_DAEMON_ADDR / --daemon-addr and use the documented form, e.g. unix:///var/run/netbird.sock (Unix) or the named pipe form on Windows
  2. Unset NB_DAEMON_ADDR to use the default daemon address
  3. Run `netbird status` with the same env to confirm the address is dialable at all
  4. Print the resolved daemonAddr before invoking ssh-proxy to catch empty or mangled values

Example fix

# before
export NB_DAEMON_ADDR=/var/run/netbird.sock   # missing unix:// scheme may fail target parsing

# after
export NB_DAEMON_ADDR=unix:///var/run/netbird.sock
Defensive patterns

Strategy: validation

Validate before calling

// fail fast on a malformed daemon address before sshproxy.New
if daemonAddr == "" {
    return fmt.Errorf("daemon address is empty")
}
if _, _, err := daemonaddr.DialTarget(daemonAddr); err != nil { // or equivalent parse
    return fmt.Errorf("invalid daemon address %q: %w", daemonAddr, err)
}

Prevention

When it happens

Trigger: NB_DAEMON_ADDR env var or --daemon-addr flag set to a malformed target: missing scheme on a unix path, bad characters, empty string after shell expansion, or a URL that fails target parsing on this platform.

Common situations: Pointing the CLI at a custom daemon socket (NB_DAEMON_ADDR=unix:///var/run/netbird.sock) with a typo; environments where the env var leaks a Windows-style pipe name into a Linux session; version changes in the accepted address formats.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/f0aa777ca2f89c27. Report an issue: GitHub.