The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Rstream CLI MCP listing page.
rstream-go is the Go SDK for rstream, a secure connectivity platform built around a globally distributed edge network and lightweight agents. Agents maintain outbound-only tunnels from local and private environments, while the edge network authenticates traffic, enforces access policy, and routes requests to upstream services. rstream supports HTTP and non-HTTP workloads and provides end-to-end visibility through connection logs and metrics.
The Go SDK is the reference implementation. It covers the broadest rstream API surface and is the most complete SDK in terms of protocol support and tunnel lifecycle features. The rstream CLI is implemented in Go and lives in this repository, so the SDK and CLI share the same configuration model and operational behavior.
Looking for native integration? The C++ SDK is available at https://github.com/rstreamlabs/rstream-cpp.
A tunnel is a secure way to expose services without requiring inbound ports, public IPs, or NAT changes. In rstream, tunnels are established outbound to the edge network, reducing exposure while keeping access controllable and observable.
When you create a published tunnel with rstream, you get a forwarding address that routes inbound traffic to a local service. For example, a tunnel for localhost:8080 provides a forwarding address like https://abc123.rstream.io that forwards HTTP requests to local port 8080.
rstream establishes outbound tunnels between environments running services or devices and the rstream edge network. Clients connect to the edge using a forwarding address for published tunnels or a tunnel identifier for private tunnels. The edge authenticates the connection, applies policy, and forwards traffic through the existing tunnel path to the upstream service.
Tunnel transports are encrypted, and edge enforcement decisions are surfaced through logs and metrics.
rstream supports two fundamental tunnel types:
Bytestream tunnels (TCP-like) provide reliable, ordered transmission for protocols such as HTTP and TLS, as well as custom bytestream services.
Datagram tunnels (UDP-like) provide low-latency, message-oriented communication for protocols such as QUIC and DTLS, as well as custom datagram services.
Published tunnels are accessible via standard clients (browsers, curl, etc.) through forwarding addresses. Published tunnels can be configured with edge authentication and access policies depending on protocol and deployment.
Private tunnels require an rstream client to connect. Private tunnels are accessed by name (if specified) or by ID through the rstream dialer instead of a public forwarding address.
Local development: Expose a local service for testing, demos, and collaboration without changing network configuration.
Fleet operations: Provide controlled access to devices and machines across environments with consistent identity, policy, and observability.
Infrastructure and platforms: Use rstream as a connectivity layer for internal tools, CI workflows, and production access paths.
Generative AI workflows: Distribute work across fleets of runners or machines while keeping access scoped and auditable.
Real-time systems: Support low-latency traffic patterns for telemetry, streaming, and datagram workloads.
Core tunneling: Create tunnels for TCP-like and UDP-like workloads with outbound-only connectivity.
Multi-protocol support: HTTP (1.1, 2, 3), TLS, DTLS, QUIC, plus WebSocket and WebTransport in HTTP tunnels.
Access control: IP restrictions, GeoIP policies, mutual TLS, token-based access, and account-based access depending on tunnel configuration.
Operational visibility: Connection logs and metrics for traffic, enforcement decisions, and performance signals.
Transport configuration: IPv4/IPv6 selection, DNS override, interface binding, HTTP CONNECT proxy support, SOCKS5 proxy support, and MASQUE proxy support for QUIC transport.
Resilience: Long-lived agents, reconnect behavior, and transport-level multiplexing for stable connectivity.
Control-channel liveness and payload lifetime are intentionally separate. A
negotiated heartbeat grace absorbs short network interruptions. If that grace
expires, the listener stops admitting new streams and reconnects, while already
accepted byte streams and registered QUIC datagram channels remain usable until
the application closes them or the data path itself ends. Explicit tunnel,
control-channel, client or process shutdown still closes owned sessions. SDK
callers therefore retain normal ownership of every connection returned by
Accept; they must close it even if ControlChannel.Done reports a transport
failure.
HTTP protocols: HTTP/1.1, HTTP/2 (H2C), HTTP/3 with WebSocket and WebTransport support.
Secure transports: TLS- and QUIC-based transports for agent-to-edge connectivity, plus DTLS and QUIC as published tunnel protocols when enabled by the deployment.
Network options: IPv4/IPv6, MPTCP, HTTP CONNECT, SOCKS5, MASQUE CONNECT-UDP for QUIC transport, and custom DNS resolution.
rstream is compatible with Linux, macOS 13 or newer, and Windows. Additionally, rstream supports other UNIX systems such as FreeBSD, OpenBSD and NetBSD through manual installation.
rstream-go provides a restricted FIPS 140-3 build profile for reviewed Linux
client deployments. The FIPS SDK and CLI artifacts embed and use the
NIST CMVP-validated Go Cryptographic Module, certificate 5247,
which has Overall Security Level 1. They pin that module and the reviewed
quic-go and webtransport-go versions, run the module in its approved mode,
and fail closed when an excluded transport, protocol, or runtime configuration
is requested.
The applicable artifact claim is FIPS 140-3 Inside — Go Cryptographic Module, Certificate #5247 (Overall Security Level 1). The level and certificate apply to the embedded Go cryptographic module; the complete rstream product has not undergone a separate CMVP module validation. This is a distinct build from the standard multi-protocol distribution.
The profile supports TLS/mTLS, direct QUIC, ordinary HTTP/3, and authenticated E2E WebTTY over WebTransport. WebTTY uses a P-256/HKDF-SHA256/AES-256-GCM random-nonce protocol profile; the standard build can use either this profile or the legacy X25519 profile, while the FIPS build accepts only the former.
See docs/010-fips-140-3-profile.md for the supported boundary, exclusions, build procedure, runtime evidence, and module upgrade process.
The installation paths in this section install the rstream CLI binary and its runtime dependencies. They do not install the Go SDK as a library dependency.
To build the CLI locally from this repository on the current platform, run:
For Debian-based distributions, the installer deploys packaged CLI binaries and dependencies:
On macOS, the Homebrew tap provides the standard CLI installation path:
On Windows, install rstream from the official WinGet Community Repository:
If winget is not available, or a new stable release has not reached the
Community Repository yet, use the PowerShell installer:
For generic environments, use the manual installer script for the CLI binary:
If you run the CLI in containers, pull the public image:
The standard developer-machine path is browser-based login:
This uses OAuth 2.0 Device Authorization Grant by default. The legacy rstream login flow remains available for compatibility checks with rstream login --auth-flow legacy.
If this is a new rstream account, the browser step opened by rstream login is also where the user signs up or signs in and approves CLI access.
Codex can start the same flow through local MCP after rstream codex setup: rstream_auth_start returns the approval URL, and rstream_auth_poll stores the approved token locally without returning it to the prompt. The approval code is only returned separately when the provider cannot embed it in the URL. The default MCP login scope is limited; when the user explicitly asks Codex to create projects or change project settings, rstream_auth_start can request a broader permissions array and the hosted approval page shows that elevated grant.
For advanced authentication modes (token-based login, remote device flows, and project-scoped contexts), see docs/001-cli-workflow.md.
Before running SDK examples, ensure a project context is set up with the CLI (rstream project use <project-endpoint>). The SDK and CLI share the same configuration model and config file.
For agent and CI checks, run:
The diagnostic output covers config, context, token claims, Control plane API authentication, project resolution, DNS, TLS, and engine inventory without printing secrets.
These variables are shared across CLI and SDK configuration resolution. Prefer configuration contexts for regular usage, and use overrides for automation or constrained environments.
RSTREAM_CONFIG: Override the CLI config file path.RSTREAM_CONTEXT: Select the context by name.RSTREAM_ENGINE: Override the engine URL used for Engine API operations.RSTREAM_AUTHENTICATION_TOKEN: Override the authentication token.RSTREAM_MTLS_CERT_FILE: Client certificate file for mTLS agent authentication.RSTREAM_MTLS_KEY_FILE: Client private key file for mTLS agent authentication.RSTREAM_API_URL: Override the Control plane API URL.RSTREAM_REGION: Select an authorized region for a managed project.RSTREAM_CONTROL_PLANE_HEADERS: Add Control plane request headers as a JSON object.Resolution behavior follows the same model used by config.NewClientFromEnv(): explicit SDK options are evaluated first, then environment overrides, then context/environment values from the config file. RSTREAM_CONFIG selects the config file path before fallback to the default config location. Token authentication and mTLS agent authentication are mutually exclusive for the control-channel connection. When the mTLS certificate and key variables are set, config-derived tokens are not used for that connection; setting mTLS variables together with RSTREAM_AUTHENTICATION_TOKEN is an error. Engine HTTP API requests use token authentication.
Region selection requires a managed project endpoint and cannot be combined with an explicit engine override. Control plane headers are intended for an additional deployment access layer. Authentication, forwarding, and hop-by-hop headers are reserved; malformed values and case-insensitive duplicates are rejected before network I/O.
Use this command to publish a local HTTP service with default protocol and publication settings.
This command creates a public HTTP tunnel and displays the forwarding address (e.g., https://abc123.rstream.io). Any HTTP request sent to this URL will be redirected to localhost:8080. The tunnel remains active until you stop the command.
Use --tls when the exposed tunnel endpoint must terminate TLS.
Creates a secure TLS-encrypted tunnel accessible through the rstream network. Standard TLS clients can connect to the tunnel's forwarding address.
Use --no-publish to create private tunnels that are reachable only through rstream clients.
Private tunnels require rstream clients to connect and are identified by name or ID rather than public URLs.
Use rstream webtty server -v --rstream to expose a remote shell through rstream. In rstream mode, WebTTY defaults to a published HTTP/WebSocket tunnel with the standard WebTTY labels. Add --no-publish to create a private tunnel instead.
rstream codex setup --verify always validates a newly started MCP process.
An MCP process already attached to an open Codex task keeps running the CLI
version with which it was started; replacing the signed Homebrew binary cannot
replace code inside that process. After every rstream CLI upgrade, open a new
Codex task or reload Codex before relying on MCP, then run an actual tool call.
Code signing preserves binary identity and integrity, but does not restart
long-lived processes.
Inside rstream ui, press c to open the context and project picker. Configured
local contexts are available immediately, including unlinked contexts that have
no Control plane API. Projects for the active Control plane API are loaded in
the background when the selected credentials permit project discovery. Use 1
and 2 (or Tab) to move between the separate context and project views. Each
view shows explicit CURRENT and DEFAULT columns and a detail panel for the
selected row. Press Enter to switch only for the current UI process, or d to
switch and save the selection as the default context in the active rstream
config file. The picker also supports / to search and r to refresh remote
projects.
Project discovery failures never hide or disable local contexts. An explicit
--api-url or RSTREAM_API_URL scopes linked contexts and remote projects to
that API, while unlinked contexts remain selectable. RSTREAM_ENGINE remains a
hard override: the UI rejects a switch to a context that targets a different
engine. Close an active WebTTY session with Ctrl+g q before changing context.
Login execution mode is passwordless. --login-user <username> names the
existing operating-system account that will own every remote session; it is
not an rstream account or the user connecting from the WebTTY client. For
example, --login-user alice runs commands with the local alice home, shell,
and identity. Run id -un on Linux or macOS, or $env:USERNAME in
Windows PowerShell, to print the local username to pass to this option. rstream
does not create the account, and the server refuses to start when the configured
account cannot be resolved. On Unix-like systems, selecting a different OS user
applies the target uid, primary gid, and supplementary groups, so the WebTTY
server process needs the corresponding privileges. On Windows, set
--login-user to the same Windows account that runs the server; switching to a
different account or using a password is not supported.
Published WebTTY tunnels can be reached either through their forwarding wss:// address or through the native rstrm://<tunnel-id-or-name> form. Private WebTTY tunnels are reachable only through the native rstrm:// form. WebTTY servers advertise capabilities, execution mode, and endpoint paths through labels: command execution uses exec_path, currently / by default, and the optional filesystem sidecar uses fs_path, currently /fs when --fs-root is set. Filesystem paths are relative to that configured root: if the server starts with --fs-root "$HOME/project", read compose.yaml as /compose.yaml, not /home/user/project/compose.yaml. The sidecar rejects symlinks that resolve outside the configured root, but it is not a sandbox and still uses the WebTTY server process permissions. The filesystem sidecar is a separate WebDAV surface and is rejected when WebTTY E2E payload encryption is active.
Tunnel WebTTY servers created with rstream webtty server -v --rstream use the
HTTP/WebSocket tunnel path with standard WebTTY inventory labels. Registered
WebTTY servers are normally created and enrolled on the runtime host with
rstream webtty server create <name> --enroll. Split-machine setup creates the
record first, then runs rstream webtty server enroll <server-id> on the
runtime host. The generated local enrollment is stored under
~/.rstream/webtty/enrollments/<server-id>.yaml, and publish managed
protocol=webtty tunnels when started with --server-id. The enrollment stores
the control-plane server ID, project ID, server public key fingerprint, local
identity file path, and server encryption policy. Enrollment uses the local
authenticated rstream context and is not the operator runtime config.
Live managed attach is engine-coordinated: the participant and control request
resources use the HTTP control API, then the terminal stream upgrades to WebTTY
protobuf with an Attach handshake. Direct WebTTY servers accept only new
Open sessions and reject managed attach handshakes with a clear protocol
error. CLI live attach first checks the engine capability document and then
resolves E2E decrypt material from trusted workspace devices or local WebTTY
identity grants before opening the terminal stream.
Use --webtty-config or RSTREAM_WEBTTY_CONFIG when a daemon should be
configured from YAML instead of a long flag list. This runtime config is
operator-managed and may contain server.serverId; when it does, the CLI loads
the generated enrollment for that server ID before publishing managed WebTTY:
CLI flags override values from --webtty-config, and --server-id implies
rstream managed mode. server.serverEnrollment can be used in the runtime
config only when the generated enrollment lives outside the default
~/.rstream/webtty/enrollments/<server-id>.yaml path.
WebTTY E2E keeps the protobuf session envelope visible while encrypting
stdin/stdout/stderr payload bytes. Server identities are local host identities,
stored by default under ~/.rstream/webtty/identities/*.identity.json with file
mode 0600. Workspace keys are separate product keys and should live under the
workspace key hierarchy, not in the WebTTY identity directory. Explicit server
identity material, known server keys, or an enrolled server whose policy
requires encryption imply protected mode. For rstrm://... targets, the client
can resolve labels and local known-server entries before opening the session.
Direct ws://... targets need direct server trust material. Use
--known-server <name> to select a pinned server from the local trust store, or
pass --known-server-key when automation owns the trust material directly.
--e2e is only a fail-closed assertion when a command must refuse plaintext.
Local WebTTY files use this layout:
~/.rstream/webtty/identities/<name>.identity.json~/.rstream/webtty/enrollments/<server-id>.yaml~/.rstream/webtty/known_servers.json~/.rstream/workspaces/<workspace-id>/devices/<device-id>.json/etc/rstream/webtty/prod-shell.yamlIdentity, enrollment, known-server, and workspace-device files are created
with 0600 permissions on POSIX systems and rejected at runtime if group or
other users can read them.
Environment overrides are available for container and CI deployments:
RSTREAM_WEBTTY_CONFIG, RSTREAM_WEBTTY_AUTH_TOKEN,
RSTREAM_WEBTTY_IDENTITY, RSTREAM_WEBTTY_IDENTITY_FILE,
RSTREAM_WEBTTY_AUTHORIZED_CLIENT_KEYS, RSTREAM_WEBTTY_KNOWN_SERVER_KEY,
and RSTREAM_WEBTTY_KNOWN_SERVERS_FILE.
Server identity precedence is RSTREAM_WEBTTY_IDENTITY for an inline endpoint
identity JSON document, then --identity-file, then --identity, then
RSTREAM_WEBTTY_IDENTITY_FILE, then the registered server enrollment identity
file, then the default
~/.rstream/webtty/identities/default.identity.json for ad hoc servers started
with --e2e and no explicit identity. E2E servers require authorized client
signing keys from the default authorized-client store, --authorized-client-key,
RSTREAM_WEBTTY_AUTHORIZED_CLIENT_KEYS, or an explicit authorized-clients file.
Client identity precedence uses the same endpoint identity sources:
RSTREAM_WEBTTY_IDENTITY, then --identity-file, then --identity, then
RSTREAM_WEBTTY_IDENTITY_FILE, then the target-scoped client_identity
stored in ~/.rstream/webtty/known_servers.json. Authenticated E2E clients do
not silently use the default identity. Client known server material comes from
--known-server, repeated --known-server-key,
RSTREAM_WEBTTY_KNOWN_SERVER_KEY, --known-servers-file, or
RSTREAM_WEBTTY_KNOWN_SERVERS_FILE; the key value should normally be the
endpoint identity printed by rstream webtty identity show --endpoint-identity.
The default known-server store is target-scoped for resolved rstrm://...
connections. Direct ws://... connections should pass --known-server <name>
or explicit trust material when no resolved tunnel metadata is available.
The two-field encryption-only form remains accepted by lower-level helpers for
specialized encryption-only integrations, but it is not the recommended
operator workflow. The default
~/.rstream/webtty/known_servers.json is loaded when no explicit trusted
server keys were provided, so E2E can be inferred without an extra client flag.
Workspace-managed registered servers pin the public workspace keyset identity
automatically during server enrollment when the runtime host is already a
trusted workspace device. If local trust material changes later, refresh the
pin with rstream webtty server trust <server-id>. That repair command lets
the remote server verify workspace-managed client proofs without copying
workspace private keys to the host.
The implemented E2E helper suite is AES-256-GCM payload encryption with fresh
96-bit nonces and HPKE Base
DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, AES-256-GCM key envelopes.
Go WebTTY tls:// plain transport and local WebTransport use TLS 1.3 minimum.
See docs/006-webtty.md for the complete WebTTY CLI, local file, runtime config, and E2E workflow reference.
rstream mcp serve exposes the trusted, device-attached MCP surface over stdio. rstream codex setup installs that server for Codex, and rstream codex setup --verify performs a bounded MCP 2025-11-25 handshake and checks the essential local tools without login or network access.
The CLI surface owns workstation context, local tunnels, WebTTY E2E identities and grants, filesystem sidecars, remote service exposure, and remote MCP bridging. The hosted /api/mcp surface owns OAuth-scoped Control Plane automation and deliberately cannot use device-private E2E material. Their shared tools use the same names, titles, behavior annotations, semantic output keys, and object-shaped result contract.
rstream mcp publish exposes the device surface over Streamable HTTP at /mcp. Published clients require a short-lived, narrowly scoped rstream token; the current full-surface publication and secret-bearing result limitations are tracked explicitly before this can be treated as a least-privilege delegation boundary.
See docs/009-mcp.md for setup, the two-surface contract, security boundaries, validation, and deferred hardening work.
Use rstream netcat for bytestream sessions over plain TCP or native rstream tunnels. The command is also available as rstream ncat and rstream nc.
When --listen uses rstrm://[name], the CLI creates a private unpublished bytestream tunnel. If no name is provided, the generated tunnel identifier is printed on startup so another rstream client can dial it.
For SSH access to a private machine, rstream forward is usually the simpler server-side entrypoint. Start it on the remote machine that has access to the local SSH daemon:
On the client machine, validate the path with a one-off SSH command:
For regular use, move the client-side configuration into SSH ProxyCommand:
This keeps the tunnel private while SSH still performs its normal host key verification and user authentication.
In client mode, --exec/--sh-exec run a local command and bridge its stdin/stdout to the connection, which provides a bidirectional path without shell pipe plumbing:
rstream nc --datagram (-u) carries packets instead of a byte stream. Datagram mode requires rstrm:// endpoints on both sides: --listen rstrm://[name] creates a private unpublished datagram tunnel, and rstream nc -u rstrm://<id-or-name> dials one. --remote is not supported in datagram mode.
Since stdin/stdout are byte streams, packet boundaries on stdio are preserved with explicit framing, selected with --framing. The default and currently only supported framing is rfc4571, where each datagram is prefixed with a 2-byte big-endian length as defined by RFC 4571. One frame on stdio equals one datagram on the tunnel, so any program that reads and writes this framing exchanges packets through the tunnel without further adaptation.
Datagram tunnels can also bridge local UDP sockets instead of stdio, which connects UDP-native applications without any framing concern. One UDP packet equals one tunnel datagram, and --framing does not apply to udp endpoints.
The CLI defaults to automatic tunnel transport selection: it prefers QUIC and falls back to TLS when the UDP path is unavailable. When QUIC is selected, tunnel-side packets can ride QUIC datagrams (RFC 9221): they are congestion-controlled but never retransmitted, so delivery is not guaranteed and each datagram must fit the path MTU budget (roughly 1200 bytes is a safe payload target, for stdio frames and UDP packets alike). Oversized datagrams are dropped and logged without terminating the session. Use --datagram-guaranteed-delivery when packet boundaries must be preserved without loss; that mode carries packets over reliable streams even when the control channel uses QUIC.
Closing either side of a datagram channel closes the peer session as well. --idle-timeout handles a different case: it closes a session after no datagram has been received for the given duration. Use it only on a side that expects inbound packets. A send-only producer receives no traffic to refresh the deadline and must not set it. In datagram exec sessions the child's stderr goes to the local stderr rather than the connection, since raw stderr bytes would corrupt the framing.
For datagram transport, choose DTLS mode when you need encrypted UDP-style traffic.
DTLS tunnels automatically handle datagram traffic. The --datagram flag is implied with --dtls.
rstream run keeps tunnels in sync from a YAML file or Docker labels, with optional watch/reconcile.
forward: creates a single tunnel from CLI args and forwards immediately (single tunnel, interactive).run --apply: declarative list of tunnels from YAML, supports watch/reconcile.run --docker: discovers tunnels from Docker labels, supports watch/reconcile.See docs/008-cmd-run.md for the full YAML schema, Docker label reference, and reconciliation details.
rstream includes a comprehensive Makefile supporting multiple platforms and packaging formats.
For daily development loops, these targets build, test, and clean local artifacts.
When producing binaries for multiple targets, use:
Supports Linux, macOS, Windows, and BSD systems across multiple architectures including x86, ARM, MIPS, PowerPC, and RISC-V.
For release packaging workflows, these targets build archives and platform packages:
The Go SDK enables applications to create and manage tunnels programmatically. The examples below use config.NewClientFromEnv() to read the same config and environment settings as the CLI. Ensure a default context (or RSTREAM_ENGINE) is set, and provide either RSTREAM_AUTHENTICATION_TOKEN or the mTLS certificate/key environment variables if the selected agent control channel requires authentication. Engine HTTP API operations require token authentication.
The SDK also exposes helpers to generate managed TURN credentials.
config.CreateTURNCredentialsFromEnv(...) resolves the current config, context, and token automatically.token_endpoint and the context includes the TURN domain, realm, and listener
ports. It falls back to the Control plane API when that routing contract is
incomplete.PAT mode requires a PAT token. Explicit API mode can use either a project ID or a project endpoint.The TURN domain is the relay hostname placed in ICE URLs. The TURN realm is the authentication scope used for credential derivation. A regional relay attached to a global edge network can use different values. Context resolution keeps both fields explicit and never infers the realm from the engine address.
Use this only when bypassing config and environment resolution is required.
This example creates a published HTTP tunnel and serves requests through the tunnel listener. The forwarding address printed by ForwardingAddress() is the public URL that can be used from a browser or curl.
This example shows a private tunnel workflow. The server creates a non-published tunnel named echo and accepts inbound tunnel connections. The client dials the private tunnel by name and exchanges data over the resulting stream.
Server code:
Client code:
This example creates a published DTLS datagram tunnel. The forwarding address is where datagram clients connect. The server uses the packet listener API to accept datagram sessions and echo packets.
This example creates a published QUIC datagram tunnel. QUIC is a modern transport designed for low latency and resilience to network changes. The sample generates a local TLS configuration and serves QUIC streams over the tunnel packet listener.
Operational and advanced CLI/SDK workflows:
Pull requests are encouraged and appreciated. Whether you're fixing bugs, adding features, improving documentation, or suggesting enhancements, your contributions help make rstream better for everyone. Build locally, run checks, and submit focused pull requests with clear validation notes. See CONTRIBUTING.md for the repository-specific contribution guidelines.
Get help:
support@rstream.io
Report security concerns:
reports@rstream.io
See SECURITY.md for the security reporting guidance used by this repository.
This repository is licensed under the Apache License 2.0. See LICENSE.