|
| 1 | +# Copyright Built On Envoy |
| 2 | +# SPDX-License-Identifier: Apache-2.0 |
| 3 | +# The full text of the Apache license is available in the LICENSE file at |
| 4 | +# the root of the repo. |
| 5 | + |
| 6 | +name: web-terminal |
| 7 | +parent: composer |
| 8 | +categories: |
| 9 | + - Misc |
| 10 | +author: Anton Kanugalawattage |
| 11 | +description: Host an interactive terminal inside Envoy, streamed over SSE. |
| 12 | +longDescription: | |
| 13 | + Hosts an interactive shell (default `/bin/bash`) inside Envoy and exposes it to |
| 14 | + the browser without any backend server. The PTY runs in the Envoy process; its |
| 15 | + output is streamed to the client over a never-closing HTTP response as |
| 16 | + Server-Sent Events, and input and resize events come back as short POST |
| 17 | + requests correlated by a session id. Because it runs as a composer HTTP filter, |
| 18 | + no upstream cluster or extra port is required — Envoy hosts the session directly. |
| 19 | +
|
| 20 | + ## Protocol |
| 21 | +
|
| 22 | + The transport is plain HTTP and client-agnostic — any client can implement it: |
| 23 | +
|
| 24 | + - `GET /stream?sid=<id>&cols=<n>&rows=<n>[&token=<t>]` |
| 25 | + A `text/event-stream` where each `data:` event is a base64-encoded chunk of |
| 26 | + PTY output. Opening the stream spawns the PTY for `sid`; closing it (client |
| 27 | + disconnect) tears the PTY down. A final `event: exit` is sent on shell exit. |
| 28 | + - `POST /input?sid=<id>[&token=<t>]` |
| 29 | + The request body is written to the PTY. |
| 30 | + - `POST /resize?sid=<id>&cols=<n>&rows=<n>[&token=<t>]` |
| 31 | + Resizes the PTY. |
| 32 | +
|
| 33 | + ## Frontend |
| 34 | +
|
| 35 | + A small `xterm.js` client is bundled but is not served by default — the |
| 36 | + endpoints above are the primary interface, so bring your own client (e.g. an |
| 37 | + application's own terminal view). Set `serve_frontend: true` to serve the |
| 38 | + bundled client at `/`. |
| 39 | +
|
| 40 | + ## Security |
| 41 | +
|
| 42 | + A browser terminal is remote code execution by design. Set a `token` unless the |
| 43 | + listener is otherwise protected; clients then pass `?token=<token>` on each |
| 44 | + endpoint (the bundled frontend reads it from `/?token=<token>`). |
| 45 | +type: go |
| 46 | +tags: |
| 47 | + - go |
| 48 | + - http |
| 49 | + - terminal |
| 50 | + - pty |
| 51 | + - sse |
| 52 | +license: Apache-2.0 |
| 53 | +examples: |
| 54 | + - title: API only (default), bring your own client |
| 55 | + description: | |
| 56 | + Drive the /stream, /input and /resize endpoints from your own client. The |
| 57 | + bundled frontend is not served. |
| 58 | + code: | |
| 59 | + boe run --extension web-terminal --config '{ |
| 60 | + "command": "/bin/bash", |
| 61 | + "token": "change-me" |
| 62 | + }' |
| 63 | + - title: Serve the bundled xterm.js client |
| 64 | + description: | |
| 65 | + Enable the bundled frontend, then open it in the browser at |
| 66 | + http://localhost:10000/?token=change-me |
| 67 | + code: | |
| 68 | + boe run --extension web-terminal --config '{ |
| 69 | + "command": "/bin/bash", |
| 70 | + "token": "change-me", |
| 71 | + "serve_frontend": true |
| 72 | + }' |
0 commit comments