Getting Started
import { Tabs, TabItem } from ‘@astrojs/starlight/components’;
Download
Section titled “Download”Grab the latest release from GitHub Releases. Builds are available for six platform/architecture combinations.
# Downloadcurl -LO https://github.com/mlorentedev/ts-bridge/releases/latest/download/ts-bridge-linux-amd64.tar.gz
# Extracttar -xzf ts-bridge-linux-amd64.tar.gzcd ts-bridge-linux-amd64
# (Optional) Install to PATHsudo mv ts-bridge /usr/local/bin/# Downloadcurl -LO https://github.com/mlorentedev/ts-bridge/releases/latest/download/ts-bridge-linux-arm64.tar.gz
# Extracttar -xzf ts-bridge-linux-arm64.tar.gzcd ts-bridge-linux-arm64
# (Optional) Install to PATHsudo mv ts-bridge /usr/local/bin/# Download and extract manually from GitHub Releases# OR use PowerShell:Invoke-WebRequest -Uri "https://github.com/mlorentedev/ts-bridge/releases/latest/download/ts-bridge-windows-amd64.zip" -OutFile "ts-bridge.zip"Expand-Archive -Path "ts-bridge.zip" -DestinationPath "ts-bridge"cd ts-bridge
# (Optional) Add to PATH$env:Path += ";$pwd"# Downloadcurl -LO https://github.com/mlorentedev/ts-bridge/releases/latest/download/ts-bridge-darwin-amd64.tar.gz
# Extracttar -xzf ts-bridge-darwin-amd64.tar.gzcd ts-bridge-darwin-amd64
# (Optional) Install to PATHsudo mv ts-bridge /usr/local/bin/# Downloadcurl -LO https://github.com/mlorentedev/ts-bridge/releases/latest/download/ts-bridge-darwin-arm64.tar.gz
# Extracttar -xzf ts-bridge-darwin-arm64.tar.gzcd ts-bridge-darwin-arm64
# (Optional) Install to PATHsudo mv ts-bridge /usr/local/bin/Configure
Section titled “Configure”Copy .env.example to .env and set the two required variables:
cp .env.example .envcopy .env.example .envEdit the .env file with your auth key and target:
TS_AUTHKEY=tskey-auth-kXXXXXXXXX # From Tailscale admin consoleTS_TARGET=100.82.151.104:3389 # Host Tailscale IP + portFor Headscale, use hskey-auth-* keys and set TS_CONTROL_URL:
# .env (Headscale)TS_AUTHKEY=hskey-auth-xxxxxTS_TARGET=100.64.0.5:3389TS_CONTROL_URL=https://vpn.example.comRequired variables
Section titled “Required variables”| Variable | Description | Example |
|---|---|---|
TS_AUTHKEY |
Auth key. Tailscale: generate here. Headscale: headscale preauthkeys create. Prefix: tskey- or hskey-. |
tskey-auth-kXXXXXX |
TS_TARGET |
Host address on the mesh network. Supports IP or MagicDNS hostname. | 100.82.151.104:3389 |
Optional variables
Section titled “Optional variables”| Variable | Default | Description |
|---|---|---|
TS_LOCAL_ADDR |
127.0.0.1:33389 |
Local bind address. Auto-derived in auto mode when unset. |
TS_CONTROL_URL |
(Tailscale default) | Custom control plane URL for self-hosted Headscale. Required for hskey- keys — they are rejected without it (a tskey- key routes to Tailscale SaaS by default). Must be an http(s):// URL. |
TS_HOSTNAME |
ts-bridge |
Node name in the admin console. Auto-generated per run in auto mode. |
TS_STATE_DIR |
(per-user) | Directory for node state (holds the private node identity). Default is a fixed per-user dir (e.g. ~/.local/state/ts-bridge/state on Linux, %LOCALAPPDATA%\ts-bridge\state on Windows). Created with 0700 permissions. Ephemeral temp dir in auto mode with an instance. A relative override is warned about. |
TS_AUTO_INSTANCE |
true |
Auto mode toggle. Set false to disable auto behavior. |
TS_MANUAL_MODE |
false |
Force legacy persistent mode. Takes precedence over TS_AUTO_INSTANCE. |
TS_INSTANCE_NAME |
(empty) | Stable instance alias for deterministic local port selection. |
TS_PORT_RANGE |
33389-34388 |
Port range for auto mode (START-END). |
TS_TIMEOUT |
30s |
Timeout for tsnet initialization (control-plane handshake). Go duration format. |
TS_DIAL_TIMEOUT |
5s |
Per-connection target dial timeout, distinct from TS_TIMEOUT. Keeps stuck dials from holding a slot across retries. Go duration format. (v1.8.0+) |
TS_DRAIN_TIMEOUT |
15s |
Timeout for graceful drain of active connections on shutdown. Go duration format. |
TS_MAX_CONNECTIONS |
1000 |
Maximum concurrent connections before rejecting new ones. |
TS_IDLE_TIMEOUT |
(disabled) | Close connections after this period of no traffic in either direction. Go duration format (e.g. 30m). Default 0 disables. Useful for reclaiming slots from abandoned RDP sessions. (v1.6.0+) |
TS_DIAL_RETRIES |
3 |
Maximum retries for transient target dial failures. 0 disables retry. (v1.7.0+) |
TS_DIAL_BACKOFF_BASE |
1s |
Base backoff for dial retries (multiplied by 2^attempt, plus jitter). Go duration format. (v1.7.0+) |
TS_DIAL_BACKOFF_MAX |
30s |
Cap on backoff per retry attempt. Must be ≥ TS_DIAL_BACKOFF_BASE. (v1.7.0+) |
TS_HEALTH_ADDR |
(disabled) | Address for health/metrics HTTP server. |
TS_VERBOSE |
false |
Enable debug logging. Also available as -v flag. |
TS_LOG_FORMAT |
text |
Log output format (text or json). |
# Run with .env config./ts-bridge connect
# Run with verbose logging./ts-bridge connect -v
# Run with all flags inline (overrides .env)./ts-bridge connect --target 100.82.151.104:3389 --auth-key tskey-auth-kXXXXXXXXX
# Interactive setup wizard./ts-bridge init# Run with .env config.\ts-bridge.exe connect
# Run with verbose logging.\ts-bridge.exe connect -v
# Run with all flags inline (overrides .env).\ts-bridge.exe connect --target 100.82.151.104:3389 --auth-key tskey-auth-kXXXXXXXXX
# Interactive setup wizard.\ts-bridge.exe initConfig precedence
Section titled “Config precedence”- CLI flags (highest)
- Environment variables (
TS_*) - YAML config file (
--config) - Built-in defaults (lowest)
Connect
Section titled “Connect”Once ts-bridge is running, it prints the local port. Connect your RDP client:
# FreeRDPxfreerdp /v:127.0.0.1:<LOCAL_PORT> /u:Username /cert:ignore
# Remminaremmina --new-protocol RDP --server 127.0.0.1:<LOCAL_PORT>
# SSHssh -p <LOCAL_PORT> user@127.0.0.1:: Built-in Remote Desktop Connectionmstsc /v:127.0.0.1:<LOCAL_PORT>
:: PowerShellStart-Process mstsc -ArgumentList "/v:127.0.0.1:<LOCAL_PORT>"# Microsoft Remote Desktop# Open app → Add PC → 127.0.0.1:<LOCAL_PORT>
# SSHssh -p <LOCAL_PORT> user@127.0.0.1For SSH targets, use any SSH client on any platform:
ssh -p <LOCAL_PORT> user@127.0.0.1Health endpoint
Section titled “Health endpoint”Set TS_HEALTH_ADDR to enable the HTTP health and metrics server:
TS_HEALTH_ADDR=127.0.0.1:9090curl http://127.0.0.1:9090/health/live # {"status":"ok"} -- process alivecurl http://127.0.0.1:9090/health/ready # {"status":"ok"} -- tsnet tunnel upcurl http://127.0.0.1:9090/metrics # Connection stats (JSON)Or use the status subcommand for a human-readable summary:
# One-shot summaryts-bridge status
# Continuous watchts-bridge status --watch --interval 2s
# Raw JSON metricsts-bridge status --jsonHost setup
Section titled “Host setup”The machine you connect to (the host) needs Tailscale installed natively with admin rights.
Requirements
Section titled “Requirements”- Windows Pro, Enterprise, Education, or Server (Home edition cannot host RDP)
- Remote Desktop enabled in Settings → System → Remote Desktop
- Administrator privileges
Automated setup
Section titled “Automated setup”# Run as Administratorts-bridge host setupThis configures:
- Tailscale unattended mode (
tailscale up --unattended) - Tailscale service to auto-start
- UPnP services (SSDP, UPnP Device Host)
- Tailscale network profile set to Private
- RDP enabled via registry
- Windows Firewall rule for RDP on TCP 3389
- (Optional) Power settings — sleep disabled
Verify
Section titled “Verify”# Read-only checkts-bridge host check
# JSON output for automationts-bridge host check --jsonCustom firewall rule
Section titled “Custom firewall rule”ts-bridge host setup --firewall-rule "MyCustomRDPRule"Requirements
Section titled “Requirements”xrdpinstalled (sudo apt install xrdp)ufworiptablesfor firewall- Root/sudo privileges
Automated setup
Section titled “Automated setup”sudo ts-bridge host setupThis configures:
- Detects
xrdpinstallation - Opens firewall for RDP port (3389) via
ufworiptables - Prints the Tailscale IP for client configuration
Verify
Section titled “Verify”# Read-only checkts-bridge host check
# JSON output for automationts-bridge host check --jsonHost setup is not applicable on macOS. macOS machines act as clients only — use ts-bridge connect to connect to a remote Windows or Linux host.
Manual host setup (Windows)
Section titled “Manual host setup (Windows)”For hosts that cannot run the binary, use the PowerShell setup script:
# Run as Administrator.\scripts\host\setup.ps1