Files
ubuntu-bare-metal/coding-agent/SERVER-UI-CLI.md
T
tomasz-syn-grzegorza 359afb3a59 Initial import: bare-metal stacks, Server UI, GPU fan, tutorials.
Infrastructure configs for GMKtec K11 (Docker, vLLM, LocalAI, ComfyUI,
control-plane, gpu-fan agent, Server UI with CLI/file explorer/GPU fan curve).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-05 12:02:04 +00:00

3.2 KiB

Server UI — CLI (terminal PTY)

Data: 2026-07-05
Status: wdrożone (bugfix FitAddon: 2026-07-05 — patrz SERVER-UI-CLI-BUGFIX.md)

Zakładka CLI w panelu Server UI (:8091) — interaktywny shell bash w przeglądarce (PTY + xterm.js).

UI

  • Zakładka CLI (pierwsza, przed Pliki)
  • Hash URL: http://<host>:8091/#cli
  • Wymaga API Key w toolbarze (WebSocket nie obsługuje nagłówka X-API-Key)

Architektura

sequenceDiagram
    participant Browser
    participant xterm as xterm_js
    participant WS as WS_api_cli_ws
    participant PTY as cli_pty_py
    participant Shell as bash

    Browser->>xterm: klawiatura
    xterm->>WS: dane terminala
    WS->>PTY: zapis master_fd
    PTY->>Shell: stdin
    Shell->>PTY: stdout/stderr
    PTY->>WS: odczyt master_fd
    WS->>xterm: output

WebSocket

Parametr Wartość
Ścieżka /api/cli/ws
Auth ?api_key=<API_KEY> (query string)
Protokół I/O surowe bajty terminala (text/binary frames)
Resize JSON: {"type":"resize","cols":120,"rows":40}

Przykład (wscat)

API_KEY=$(sudo grep ^API_KEY= /opt/control-plane/.env | cut -d= -f2)

# wymaga: npm i -g wscat
wscat -c "ws://127.0.0.1:8091/api/cli/ws?api_key=${API_KEY}"

Bez klucza na bind LAN → połączenie zamknięte z kodem 1008.

Konfiguracja

W /opt/control-plane/.env (opcjonalnie):

Zmienna Domyślnie Opis
CLI_ENABLED 1 0 = WebSocket odrzucany
CLI_SHELL /bin/bash Shell PTY (np. /bin/bash -l)
CLI_DEFAULT_CWD $HOME usługi Katalog startowy
CLI_MAX_SESSIONS 5 Limit równoległych sesji WS

Uprawnienia POSIX

Server UI działa jako tomasz-syn-grzegorza (server-ui.service):

  • docker ps, edycja repo, /data/apps/ — OK
  • sudo — interaktywnie (hasło użytkownika w terminalu)
  • root-only pliki — odmowa jak w SSH

Kod

Plik Rola
stacks/server-ui/cli_pty.py PTY + asyncio bridge
stacks/server-ui/app.py WebSocket /api/cli/ws, mount /static
stacks/server-ui/static/index.html Zakładka CLI
stacks/server-ui/static/vendor/xterm/ xterm.js + FitAddon (vendored; UMD: new FitAddon.FitAddon())

Bezpieczeństwo

  • Pełny shell przez LAN = wysokie ryzyko — wymagany API_KEY przy SERVER_UI_HOST=0.0.0.0
  • CLI_ENABLED=0 jako kill switch
  • CLI_MAX_SESSIONS ogranicza liczbę równoległych bashów
  • Brak whitelisty komend (właściciel serwera)
  • Sesja kończy się przy zamknięciu zakładki / rozłączeniu WS (nowy bash przy reconnect)

Deploy

sudo rsync -a --exclude '.venv' --exclude '__pycache__' \
  stacks/server-ui/ /opt/server-ui/
sudo systemctl restart server-ui

Tutorial użytkownika: manual-tutorial/10-server-ui-cli.md

Znane problemy / bugfix

Pusty terminal przy działającym API Key: SERVER-UI-CLI-BUGFIX.md