Архітектура
Загальний потік
За замовчуванням (локальний tmux + тунель):
Код
Browser (phone)
|
| HTTPS
v
Cloudflare Quick Tunnel
|
| HTTP/WS
v
Local Termbridge server
|
| PTY
v
Tmux session
Прямий режим пісочниці (Daytona, без тунелю):
Код
Browser (phone)
|
| HTTPS
v
Daytona preview link
|
| HTTP/WS
v
Termbridge server (sandbox)
|
| PTY
v
Tmux session (sandbox)
Коли задано --no-tunnel, Termbridge пропускає Cloudflare і використовує наданий вами публічний URL.
Компоненти
Процес CLI
- Запускає сервер HTTP, який обслуговує ресурси UI.
- Запускає сервер WebSocket для вводу-виводу термінала.
- Створює один або кілька сеансів tmux (або псевдотерміналів Daytona).
- Видає одноразові токени для отримання доступу.
- Запускає тунель і стежить за ним, якщо його ввімкнено (нині Cloudflare).
- У прямому режимі пісочниці запускає Termbridge усередині пісочниці та очікує на посилання для доступу URL.
Бекенд термінала
- Бекенд tmux: використовує
node-ptyдля підключення до tmux і передавання натискань клавіш та виводу. - Бекенд Daytona: використовує псевдотермінали Daytona у пісочниці.
- Встановлює
TERM=xterm-256colorіCOLORTERM=truecolorдля повної підтримки кольорів. - Для tmux вимикає рядок стану tmux, щоб не захаращувати UI.
Реєстр терміналів
- Відстежує доступні сеанси термінала.
- Надає список для UI і перевіряє вибрані ідентифікатори терміналів.
Автентифікація та сеанс
- Одноразовий токен виводиться як URL і кодується у QR коді.
GET /__tb/s/:tokenотримує токен і встановлює сеансовий cookie.- Для з’єднань WebSocket потрібні дійсний сеансовий cookie та CSRF-токен.
- CSRF-токен отримується через
GET /__tb/api/csrfі передається як параметр запиту WebSocket.
Режим проксі
Коли передано --proxy <port>:
- Усі маршрути termbridge розміщуються за префіксом
/__tb/ - Запити, не пов’язані з
/__tb/, перенаправляються до цільового застосунку - UI надає подання «Термінал» і «Попередній перегляд» через перемикач «Подання»
- Подання «Попередній перегляд» завантажує iframe, що вказує на
/ - З’єднання WebSocket для HMR пересилаються до цільового застосунку
Безпека
- Захист від CSRF: для оновлення WebSocket потрібен CSRF-токен, що запобігає перехопленню між сайтами.
- Обмеження розміру вводу: тіло HTTP до 64KB, повідомлення WebSocket до 1MB, введення в термінал до 64KB на повідомлення.
- Обмеження частоти запитів: ліміти для отримання токена та з’єднань WebSocket на IP.
Кінцеві точки API
Усі маршрути розміщуються за префіксом /__tb/, щоб уникнути конфліктів із проксійованими застосунками:
GET /__tb/healthz— перевірка працездатностіGET /__tb/s/:token— отримання токена → cookie → перенаправленняGET /__tb/api/terminals— список терміналівGET /__tb/api/csrf— отримання CSRF-токена для WebSocketGET /__tb/api/config— отримання конфігурації (proxyPort, devProxyUrl)POST /__tb/api/terminals— створення нового сеансу tmuxGET /__tb/app/*— резервний маршрут SPAWS /__tb/ws/terminal/:terminalId?csrf=<token>— потокове передавання вводу-виводу термінала
Коли режим проксі ввімкнено:
GET /— перенаправляє до проксійованого застосунку (або/__tb/app, якщо вимкнено)* /*— проксіюється до цільового застосунку
Протокол WebSocket
Клієнт → сервер:
JSON
{ "type": "input", "data": "ls -la" }
{ "type": "resize", "cols": 120, "rows": 32 }
{ "type": "control", "key": "ctrl_c" }
Сервер → клієнт:
JSON
{ "type": "output", "data": "..." }
{ "type": "status", "state": "connected" }
Стек UI
- Vite + TanStack Router
- xterm.js + додаток Fit + рушій WebGL
- Макет насамперед для мобільних пристроїв із закріпленим рядком вводу
- Автоматичне повторне підключення з експоненційною затримкою (до 10 спроб)
- Індикатор стану з’єднання