
Tela

Tela is a free and open-source (FOSS) remote-access system that lets you reach TCP services on remote machines through an encrypted WireGuard tunnel. It works through firewalls, NATs, and corporate proxies without requiring inbound ports, VPN software, kernel drivers, or administrator privileges on either end.
You run a small agent (telad) on the machine you want to reach. It connects outbound to a relay hub (telahubd). From any other machine, you run the client (tela) or the desktop app (TelaVisor) to connect through the hub. The hub pairs the two sides and relays encrypted traffic between them. It never sees the plaintext.
graph LR
Client["Native Client"]
Tela["tela"]
Hub["telahubd"]
Telad["telad"]
Services["Local Services"]
Client -->|TCP| Tela
Tela <-->|"wss (WireGuard inside)"| Hub
Hub <-->|ws| Telad
Telad --> Services
subgraph "WireGuard Tunnel (E2E encrypted)"
direction LR
Tela -.-|"gVisor netstack · Curve25519 + ChaCha20"| Telad
end
Why Tela
Most remote-access tools require at least one of the following: a VPN that needs administrator privileges to install, inbound firewall rules on the target machine, a cloud account with a specific vendor, or a TUN/TAP kernel driver. Tela requires none of these.
Tela uses WireGuard for encryption, but it runs WireGuard entirely in userspace through gVisor's network stack. There is no kernel module, no TUN device, and no need for root or Administrator. Both the agent and the client make outbound connections to the hub, so neither side needs to open inbound ports or configure port forwarding.
The hub acts as a blind relay. It forwards encrypted WireGuard packets between the agent and the client without being able to decrypt them. Even if the hub is compromised, session contents are not exposed.
Tela tunnels any TCP service. SSH, RDP, HTTP, PostgreSQL, SMB, VNC, or any other protocol that runs over TCP can be reached through a Tela tunnel. The hub does not need to understand the protocol being tunneled.
How it works
The agent (telad) and the client (tela) each create a userspace WireGuard tunnel using gVisor netstack. The hub (telahubd) relays encrypted WireGuard datagrams between them over WebSocket. After the initial connection, Tela automatically negotiates faster transports when available:
| Transport |
Path |
When it is used |
| WebSocket |
tela -> hub -> telad |
Always available, works through corporate proxies |
| UDP relay |
tela -> hub:41820 -> telad |
When outbound UDP to the hub is open |
| Direct P2P |
tela -> telad |
When STUN hole-punching succeeds |
Each transport tier falls back to the previous one automatically on failure. The hub always relays opaque WireGuard ciphertext regardless of which transport is active.
Components
Tela is built from three Go binaries and an optional desktop client:
| Component |
Description |
| tela |
Client CLI. Connects to a hub, establishes a WireGuard tunnel, and binds local TCP ports so native clients (ssh, mstsc, psql, etc.) can connect. |
| telad |
Agent daemon. Runs on the target machine, registers with the hub, and exposes local TCP services through the tunnel. |
| telahubd |
Hub server. Pairs agents with clients, relays encrypted traffic, and serves a built-in web console. |
| TelaVisor |
Desktop client. A graphical interface for managing connections, browsing remote files, and administering hubs. Built with Wails v2 (Go + JavaScript). |
All three binaries are single-file executables with no runtime dependencies. They run on Windows, Linux, and macOS.
TelaVisor
TelaVisor wraps the tela CLI in a graphical interface. It manages hub credentials, connection profiles, and real-time tunnel status without requiring terminal access. You select which services to connect to, click Connect, and monitor tunnel state as it updates live.

TelaVisor uses a three-mode layout that mirrors the three Tela binaries. Clients mode manages connections. Agents mode (coming soon) will manage telad instances. Hubs mode provides full hub administration including token management, ACL configuration, and machine monitoring.

The Files tab provides a built-in file browser for machines with file sharing enabled. You can upload, download, rename, move, and delete files on remote machines through the encrypted tunnel. The file list updates in real time as changes happen on the remote machine.

A persistent log panel at the bottom of the window shows application events, live tela output, and a filterable command log that displays every API call and CLI command with copy-to-clipboard support.

See TelaVisor.md for full documentation.
Quick start
Build
go build -o tela ./cmd/tela
go build -o telad ./cmd/telad
go build -o telahubd ./cmd/telahubd
Run locally (three terminals)
Start the hub:
./telahubd
Start the agent on the machine you want to reach. This example exposes SSH and RDP:
./telad -hub ws://localhost -machine mybox -ports "22:SSH,3389:RDP"
From a third terminal, list the available machines and connect:
./tela machines -hub ws://localhost
./tela connect -hub ws://localhost -machine mybox
You can also connect by service name:
./tela connect -hub ws://localhost -machine mybox -services ssh
Once connected, use your usual tools against localhost:
ssh localhost
mstsc /v:localhost
To avoid repeating flags, set environment variables:
export TELA_HUB=ws://localhost TELA_MACHINE=mybox
tela connect
tela machines
tela services
Hub remotes (name resolution)
If your hubs are listed on a directory service, you can add it as a remote and use short hub names:
tela remote add awansaya https://awansaya.net # configure once
tela machines -hub myhub # short name resolved via remote
tela connect -hub myhub -machine mybox
Short hub names are resolved by querying configured remotes first, then falling back to the local hubs.yaml file.
Connection profiles
You can define all your tunnels in a single YAML file and open them in parallel with one command:
# ~/.tela/profiles/work.yaml
connections:
- hub: corp-hub
machine: prod-web01
token: ${CORP_TOKEN}
services:
- remote: 22
local: 2201
- remote: 8080
local: 9001
- hub: corp-hub
machine: staging-db
token: ${CORP_TOKEN}
services:
- name: postgres
tela connect -profile work
# Opens parallel tunnels to both machines. Each auto-reconnects independently.
# SSH: localhost:2201, Admin panel: localhost:9001, PostgreSQL: localhost:5432
Profiles support environment variable expansion (${VAR}), service name resolution, local port remapping, and connections across multiple hubs. See REFERENCE.md section 7 for the full profile schema.
Run with Docker (production)
docker compose up --build -d
./tela connect -hub wss://your-hostname -machine barn
See IMPLEMENTATION.md for the full Docker Compose setup.
Enable authentication (recommended)
On first startup, the hub auto-generates an owner token (secure by default). For Docker deployments, you can bootstrap authentication with an environment variable:
# 1. Generate an owner token
openssl rand -hex 32
# 2. Add to docker-compose.yml environment:
# - TELA_OWNER_TOKEN=<your-token>
# 3. Redeploy
docker compose up --build -d
# 4. Manage remotely from any workstation:
tela admin list-tokens -hub wss://your-hub -token <owner-token>
tela admin add-token bob -hub wss://your-hub -token <owner-token>
tela admin grant bob barn -hub wss://your-hub -token <owner-token>
See CONFIGURATION.md for the full auth schema and tela admin reference.
Authentication and security
Tela is designed to be secure by default. The hub auto-generates an owner token on first startup, and all administrative operations require authentication.
End-to-end encryption. All traffic between the client and agent is encrypted with WireGuard using Curve25519 for key exchange and ChaCha20-Poly1305 for data encryption. The hub relays opaque ciphertext and cannot read tunnel contents.
Token-based access control. The hub uses named token identities with four roles: owner, admin, user, and viewer. Per-machine ACLs control which tokens can register and connect to each machine. A wildcard ACL applies to all machines.
Remote management. Owners and admins can manage tokens, ACLs, and portal registrations remotely using tela admin. No shell access to the hub is required.
Credential storage. The tela login and telad login commands store hub tokens in a local credential file (0600 permissions) so you do not need to pass tokens on every command.
One-time pairing codes. Administrators can generate short-lived pairing codes (e.g., ABCD-1234) for users and agents. Codes are single-use, time-limited (10 minutes to 7 days), and replace the need to copy 64-character hex tokens manually. Users paste a code in TelaVisor or run tela pair to exchange it for a permanent token.
File sharing. The agent can expose a sandboxed directory for file transfer through the tunnel. Upload, download, rename, move, and delete operations are available via the CLI (tela files) or the TelaVisor Files tab. File sharing is off by default and must be explicitly enabled per machine. Extension filtering, size limits, and read-only mode are configurable.
No admin required. All three binaries run in userspace. gVisor netstack provides a full WireGuard implementation without kernel modules, TUN devices, or elevated privileges.
Outbound-only. Both tela and telad initiate outbound connections to the hub. No inbound ports are needed on either end.
See CONFIGURATION.md for the full auth schema and admin API reference. See howto/telad.md for agent onboarding examples.
Networking and port requirements
Tela is outbound-only for agents and clients. Only the hub needs to be reachable from the internet.
At a minimum, the hub must accept inbound HTTPS/WebSocket traffic from both tela (client) and telad (agent). The agent must be able to reach the services it exposes, either on localhost or via a target host in gateway mode.
| Component |
Inbound |
Outbound |
Notes |
Hub (telahubd) |
TCP 443 for HTTPS + WebSocket |
None |
Optional: UDP 41820 for the UDP relay. |
Agent (telad) |
None |
TCP 443 to the hub |
Optional: outbound UDP to hub:41820 and STUN. |
Client (tela) |
None |
TCP 443 to the hub |
Optional: outbound UDP to hub:41820 and STUN. Binds localhost ports for apps. |
| Portal |
TCP 80/443 for the portal UI and API |
HTTPS to each hub's /api/status and /api/history |
Proxies hub requests server-side. Browsers do not contact hubs directly. |
See also: howto/networking.md, howto/hub.md, howto/telad.md.
Running as an OS service
All three binaries support native OS service management on Windows (SCM), Linux (systemd), and macOS (launchd). Configuration is stored in a YAML file in a system-wide directory. To reconfigure, edit the file and restart the service.
# Install telad as a service
telad service install -config telad.yaml
telad service start
# Install telahubd as a service
telahubd service install -name myhub -port 80
telahubd service start
# Install tela client as a service (always-on tunnel)
tela service install -config myprofile.yaml
tela service start
# Reconfigure: edit the config, then restart
telad service restart
telahubd service restart
tela service restart
See howto/services.md for full details.
Registering with a portal
Hub operators can register their hub with a Tela portal (such as Awan Saya) so that users who query the portal can discover the hub by name:
telahubd portal add awansaya https://awansaya.net
telahubd portal list
telahubd portal remove awansaya
The portal add command discovers the portal's hub directory endpoint via /.well-known/tela (RFC 8615), registers the hub via its API, and stores the association in the hub config. See DESIGN.md section 8.5 for details.
Project structure
cmd/tela/ Client CLI (connect, machines, services, status, remote, admin, files, profile, pair, service)
cmd/telad/ Agent daemon
cmd/telahubd/ Hub server
cmd/telagui/ Desktop client (Wails v2 app)
internal/service/ Cross-platform OS service management (Windows SCM, systemd, launchd)
internal/wsbind/ WireGuard conn.Bind over WebSocket/UDP/direct
howto/ Guides (hub setup, services, networking, use cases)
www/ Hub console (web UI)
docker/ Dockerfile, docker-compose, Caddyfile
Glossary
| Term |
Meaning |
| Hub |
The central relay server (telahubd). Pairs agents with clients and relays encrypted traffic. Also serves the hub console. |
| Hub Console |
The web interface served by a hub (e.g., https://hub.example.com/). Shows registered machines, services, and session history. |
| Agent / telad |
A long-lived daemon on a managed machine. Registers with the hub and exposes local services through the tunnel. |
| Client / tela |
The CLI tool on the user's machine. Connects through the hub to an agent and binds local TCP ports for native clients. |
| TelaVisor |
The desktop client. Provides a graphical interface for connections, file browsing, and hub administration. |
| Machine |
A named resource registered by an agent (e.g., barn). One agent can register one or more machines. |
| Service |
A TCP endpoint exposed through a machine (e.g., SSH on port 22, RDP on port 3389). |
| Session |
An active encrypted tunnel between a client and an agent. Each session gets its own WireGuard keypair and virtual IP address. |
| Portal |
A multi-hub dashboard and directory service. Implements the hub directory API (/api/hubs). Can be added as a remote with tela remote add. |
| File Share |
A sandboxed directory on an agent machine that can be browsed, uploaded to, and downloaded from through the tunnel. |
Documentation
License
Apache 2.0. See LICENSE.