Skip to content

labring-sigs/sealos-tty-agent

Repository files navigation

sealos-tty-agent

Kubernetes exec terminal gateway over WebSocket.

Browser (xterm.js) <-> this server (WS) <-> Kubernetes API Server (exec) <-> Pod PTY

What’s in this repo

  • Server: sealos-tty-agent — a small HTTP + WebSocket gateway that turns Kubernetes pods/exec into a browser-friendly terminal stream.
  • Client: @labring/sealos-tty-client — a Web Streams API client (in packages/protocol-client) that handles ticket issuance + WebSocket wiring for you.

Server usage

Local (dev)

pnpm install
cp config.example.json config.json
pnpm run dev

Default: http://localhost:3000.

Production

# Using Docker Compose
docker compose up -d

# or use Docker CLI
# Build the image
docker build -t sealos-tty-agent:latest .
# Spin up the container
docker run -d -p 3000:3000 -v $(pwd)/config.json:/app/config.json:ro sealos-tty-agent:latest

Client usage

The recommended client is @labring/sealos-tty-client (Web Streams API), designed for browser terminals like xterm.js.

pnpm add @labring/sealos-tty-client

Minimal browser example (xterm-style wiring):

import { connectTerminalStreams } from '@labring/sealos-tty-client'

const { stdout, stdin, resize } = await connectTerminalStreams({
	client: { baseUrl: 'http://localhost:3000' },
	ticketRequest: { kubeconfig, namespace: 'default', pod: 'mypod', container: 'c1' },
	connect: { initialSize: { cols: term.cols, rows: term.rows } },
})

const enc = new TextEncoder()
const writer = stdin.getWriter()
term.onData(d => void writer.write(enc.encode(d)))
term.onResize(({ cols, rows }) => resize(cols, rows))

void stdout
	.pipeThrough(new TextDecoderStream())
	.pipeTo(new WritableStream({ write: s => term.write(s) }))

Notes:

  • The server starts Kubernetes exec only after receiving the first resize.
  • If you need lower-level access, call the HTTP API to get a ticket, then connect to GET /exec via WebSocket.

Run

pnpm install
pnpm run dev

API

POST /ws-ticket

Issues a short-lived, one-time ticket for browser clients.

Request body:

{
	"kubeconfig": "...",
	"namespace": "default",
	"pod": "mypod",
	"container": "c1",
	"command": ["bash", "-il"]
}

Response:

{ "ok": true, "ticket": "...", "expiresAt": 0 }

GET /exec (WebSocket)

  • If you cannot put the ticket in the URL, the first non-ping JSON message must be:
    • { "type": "auth", "ticket": "..." }
  • After auth, the client must send the first resize:
    • { "type": "resize", "cols": 120, "rows": 30 }
    • The server starts Kubernetes exec only after receiving the first resize.

Binary frames:

  • Client -> Server: stdin bytes
  • Server -> Client: stdout/stderr bytes (TTY usually merged)

Security

kubeconfig is sensitive. Use HTTPS/WSS and restrict RBAC for pods/exec.

About

Kubernetes `exec` terminal gateway over WebSocket.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors