xpos

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 3, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package xpos provides a Go SDK for XPOS — instant public URLs via SSH tunnels.

XPOS exposes local services to the internet through SSH tunnels. This SDK wraps the SSH CLI into a clean, idiomatic Go library and CLI tool. Zero external dependencies — uses only the Go standard library.

Quick Start

Create and start a tunnel with a single call:

tunnel, err := xpos.Connect(ctx, xpos.WithPort(3000))
if err != nil {
    log.Fatal(err)
}
fmt.Println(tunnel.URL) // https://abc.xpos.to
defer tunnel.Close()
<-tunnel.Done()

Authentication

Pass a token to unlock features like reserved subdomains and longer expiry:

tunnel, err := xpos.Connect(ctx,
    xpos.WithPort(3000),
    xpos.WithToken("tk_xxx"),
    xpos.WithSubdomain("myapp"),
)

Alternatively, set the XPOS_TOKEN environment variable and omit WithToken.

TCP Tunnels

Expose TCP services (databases, etc.) by setting the mode to "tcp":

tunnel, err := xpos.Connect(ctx,
    xpos.WithPort(5432),
    xpos.WithToken("tk_xxx"),
    xpos.WithMode("tcp"),
)
fmt.Println(tunnel.URL) // 1.2.3.4:54321

Requirements

An SSH client must be installed and available in your PATH. SSH is pre-installed on macOS, Linux, and Windows 10+.

See https://xpos.dev for more information.

Index

Constants

View Source
const (
	ModeHTTP = "http"
	ModeTCP  = "tcp"
)

Mode constants for tunnel type.

View Source
const (
	DefaultHost    = "127.0.0.1"
	DefaultServer  = "go.xpos.dev"
	DefaultSSHPort = 443
	DefaultMode    = ModeHTTP
)

Default configuration values matching all XPOS SDKs.

View Source
const (
	DefaultConnectTimeout = 15 * time.Second
	DefaultKillTimeout    = 3 * time.Second
)

Default timeouts.

Variables

This section is empty.

Functions

func BuildRemoteForward

func BuildRemoteForward(port int, host, subdomain, domain string) string

BuildRemoteForward constructs the -R argument for SSH. For custom domains: "domain:80:host:port" For subdomains: "subdomain:80:host:port" For random: "0:host:port"

func BuildSSHUser

func BuildSSHUser(token, mode string) string

BuildSSHUser constructs the SSH username from a resolved token and mode. Anonymous connections use "x". TCP mode appends "+tcp" to the token.

func FormatExpiry

func FormatExpiry(rfc3339 string) string

FormatExpiry converts an RFC3339 expiry timestamp into a human-readable countdown string like "Expires in 3h 0m (12:00 UTC)".

func ResolveToken

func ResolveToken(token string) string

ResolveToken resolves an auth token from the given value or the XPOS_TOKEN environment variable. Auto-prepends "tk_" if missing. Returns empty string if no token is available.

func ShouldFilterLine

func ShouldFilterLine(line string) bool

ShouldFilterLine reports whether a line should be suppressed from CLI pass-through display. These lines are parsed and displayed by the CLI itself in a formatted manner.

Types

type Option

type Option func(*options)

Option configures a Tunnel. Use the With* functions to create Options.

func WithConnectTimeout

func WithConnectTimeout(d time.Duration) Option

WithConnectTimeout sets the maximum time to wait for tunnel establishment. Default: 15 seconds.

func WithDomain

func WithDomain(domain string) Option

WithDomain sets a custom domain (Business plans). Mutually exclusive with WithSubdomain. Requires a token.

func WithHost

func WithHost(host string) Option

WithHost sets the local host to forward traffic to. Default: "127.0.0.1".

func WithMode

func WithMode(mode string) Option

WithMode sets the tunnel mode: "http" (default) or "tcp".

func WithOnClose

func WithOnClose(fn func(exitCode int)) Option

WithOnClose sets a callback invoked when the tunnel closes. Receives the SSH process exit code.

func WithOnConnect

func WithOnConnect(fn func(url, expiresAt string)) Option

WithOnConnect sets a callback invoked when the tunnel connects successfully. Receives the public URL and optional expiry timestamp.

func WithOnOutput

func WithOnOutput(fn func(text string)) Option

WithOnOutput sets a callback invoked with raw SSH output text. Called for every chunk of data received from the SSH process.

func WithPort

func WithPort(port int) Option

WithPort sets the local port to expose. Required.

func WithSSHPort

func WithSSHPort(port int) Option

WithSSHPort sets the SSH server port. Default: 443.

func WithServer

func WithServer(server string) Option

WithServer sets the SSH server hostname. Default: "go.xpos.dev".

func WithSubdomain

func WithSubdomain(name string) Option

WithSubdomain sets a reserved subdomain (Pro+ plans). Mutually exclusive with WithDomain. Requires a token.

func WithToken

func WithToken(token string) Option

WithToken sets the authentication token. Auto-prepends "tk_" if missing. If not set, falls back to the XPOS_TOKEN environment variable.

type Tunnel

type Tunnel struct {
	// URL is the public tunnel URL.
	// For HTTP tunnels: "https://abc.xpos.to"
	// For TCP tunnels:  "1.2.3.4:54321"
	// Populated after Start returns successfully.
	URL string

	// ExpiresAt is the RFC3339 expiry timestamp, if any.
	// Empty string for paid plans with no expiry.
	ExpiresAt string

	// Connected indicates whether the tunnel is currently active.
	Connected bool
	// contains filtered or unexported fields
}

Tunnel manages an SSH subprocess that creates an XPOS tunnel. Create one with NewTunnel and call Start, or use the Connect convenience function.

func Connect

func Connect(ctx context.Context, opts ...Option) (*Tunnel, error)

Connect creates a new Tunnel with the given options and starts it. This is a convenience function combining NewTunnel and Start.

Example:

tunnel, err := xpos.Connect(ctx, xpos.WithPort(3000))
if err != nil {
    log.Fatal(err)
}
fmt.Println(tunnel.URL)
defer tunnel.Close()

func NewTunnel

func NewTunnel(opts ...Option) (*Tunnel, error)

NewTunnel creates a new Tunnel with the given options. The tunnel is not started until Start is called.

Returns an error if the options are invalid (missing port, bad mode, conflicting subdomain/domain, etc.).

func (*Tunnel) Close

func (t *Tunnel) Close()

Close gracefully shuts down the tunnel. Sends an interrupt signal first, then force-kills after the kill timeout (default 3 seconds) if the process hasn't exited.

Close is safe to call multiple times and from multiple goroutines.

func (*Tunnel) Done

func (t *Tunnel) Done() <-chan struct{}

Done returns a channel that is closed when the tunnel's SSH process exits. Use this to detect tunnel closure without blocking:

select {
case <-tunnel.Done():
    fmt.Println("Tunnel closed")
case <-ctx.Done():
    tunnel.Close()
}

func (*Tunnel) Start

func (t *Tunnel) Start(ctx context.Context) error

Start spawns the SSH process and blocks until the tunnel URL is available, an error occurs, or the context is cancelled.

The context controls cancellation but does not override the connect timeout (default 15s, configurable via WithConnectTimeout). Both the context and the timeout can terminate the connection attempt.

After Start returns successfully, the tunnel is active. Use Close to stop it, Wait or Done to block until it closes naturally.

Start may only be called once per Tunnel. To create a new tunnel, call NewTunnel again.

func (*Tunnel) Wait

func (t *Tunnel) Wait() error

Wait blocks until the tunnel's SSH process exits. Returns nil when the tunnel closes.

Example:

tunnel.Start(ctx)
go func() { tunnel.Wait() }()

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL