Architecture
How WebXTerm Works
Agent-based, zero-trust architecture. The agent connects on one port that is 8081 outbound/inbound traffic — no open ports, no VPN, no bastion hosts.
How WebXTerm Works
┌─────────────────────────────────────────────────────────────────────┐
│ CLIENT LAYER │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Browser │ │ VS Code │ │ VSAY CLI │ │
│ │ Web Terminal │ │ Extension │ │ Shell Tool │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ └─────────────────┬┘──────────────────┘ │
└────────────────────────────┼────────────────────────────────────────┘
│ HTTPS / WSS
▼
┌─────────────────────────────────────────────────────────────────────┐
│ WEBXTERM PORTAL │
│ (Control Hub :8080) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Auth │ │ Router │ │ Command │ │ Registry │ │
│ │ JWT │ │ Terminal │ │ History │ │ API Keys │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │
└────────────────────────────┬────────────────────────────────────────┘
│ gRPC + TLS (:8081)
│ Outbound/Inbound on one port only (8081) — agent initiates
▼
┌─────────────────────────────────────────────────────────────────────┐
│ MACHINE LAYER │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ vsay-agent │ │
│ │ (On your machine) │ │
│ │ │ │
│ │ Outbound only │ Systemd service │ Heartbeat 30s │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ prod-server │ │ dev-laptop │ │ bare-metal-02 │ │
│ │ Linux / x86 │ │ macOS / M1 │ │ Linux / ARM │ │
│ └───────────────┘ └───────────────┘ └───────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Legend:
- 🔵 Client connection (HTTPS/WSS)
- 🟢 Agent tunnel (gRPC/TLS) — Outbound/Inbound on one port only (8081)
- 🟠 Active session
Key Design Principles
1. Outbound-Only Agent Tunnel
The vsay-agent always initiates the connection outbound to the backend over gRPC. This means:
- No open inbound ports on your machines
- No firewall rule changes required
- Works behind NAT, behind corporate firewalls, on any network
- The agent auto-reconnects on network interruptions or backend restarts
2. TLS-Encrypted, API-Key Authenticated
The agent connection is encrypted with standard (server-verified) TLS — the agent verifies the backend's certificate, same as a browser verifying a website. On top of that, the agent authenticates itself with its API key on every connection:
Backend → presents TLS certificate → Agent verifies ✅
Agent → presents API key → Backend verifies ✅
- No SSH keys to rotate — just one API key per account, regenerable from the Profile page
- Mutual TLS (client-certificate authentication issued from a private CA) is an Enterprise Edition feature — see the Enterprise Architecture docs
3. Single-Account Model (Community)
Community Edition is single-account, not multi-user: whoever signs up owns the account and every machine registered under it. There are no roles, no per-machine access grants, and no separate admin/user distinction — that hierarchical RBAC model is an Enterprise feature (see the Enterprise docs' Architecture page).
4. Access Flow
Every terminal session goes through this verification chain:
User clicks Connect
│
▼
1. JWT validated → is this a real logged-in user?
│
▼
2. Agent located → is this machine online with active gRPC stream?
│
▼
3. Session bridged → WebSocket ↔ gRPC stream connected
│
▼
4. Command recorded → command text + timestamp saved to that machine's history
No step can be skipped — a session cannot open against a machine that is offline or without a valid token.
Component Overview
| Component | Role | Port |
|---|---|---|
| WebXTerm Backend | Control plane — auth (bcrypt+JWT), routing, command history | 8080 (HTTP) |
| vsay-agent | Lightweight daemon on each machine | outbound to 8081 |
| gRPC server | Agent tunnel endpoint over TLS | 8081 |
Agent Connection Lifecycle
1. vsay-agent configure --token <API_KEY>
│
▼
Agent saves the API key and backend host to /etc/vsay/agent.yaml
Agent installs itself as a systemd service
2. Every start / reconnect (restarts, network blips):
Agent opens TLS connection to backend
Agent presents its API key → Backend verifies ✅ → online
No certificate provisioning step — just the saved key
3. If the API key is regenerated:
Old key is rejected → agent goes offline
Re-run `vsay-agent configure` with the new key to reconnect
Enterprise Edition replaces this with a private-CA-issued client certificate per agent (true mTLS), so agents self-heal across CA rotations without re-entering a key. See the Enterprise Architecture docs.