Files
ultix/OPEN-TERMINAL.md
T
mrcharles c810942239 Open Terminal fleet for all accounts + OpenWebUI UAT pass (#610)
open-terminal 0.11.34 bare-metal (human-authorized host install) with a
systemd template unit: reachableceo on tailscale-only :30000 (cwd
~/projects) and all 8 other accounts on :30001-30008, each with its own
key kept out of ps in per-user TOMLs, all users added to the docker group.
Keys live in ~/.creds + /etc/ukrrs/open-terminal, never in this repo.

UAT: throwaway OpenWebUI v0.11.1 (matched to the human's Cloudron prod)
driven purely over its HTTP API against the beta gateway lane - connection
verify/config PASS, direct exec as uid 1001 PASS, and the chat round trip
PASS: the model emitted run_command, we executed it through OpenWebUI's
terminal proxy (server holds the key), and the final answer named 9/9 real
project directories; earlier negative runs prove the test catches
hallucinated output. Ops note OPEN-TERMINAL.md documents production wiring
(prod openwebui container v0.3.10 is too old and needs an upgrade first).

Also tonight: agent-stack relaunchers removed (6-, backups kept) so no
screen/crush sessions auto-start on reboot; 22:00 night-profile flip
observed live; docs synced for the earlier teardown.

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
[#610]
2026-08-31 22:50:53 -05:00

82 lines
4.1 KiB
Markdown

# Open Terminal fleet — ops note (#610, deployed 2026-08-31)
OpenWebUI "Open Terminal" for every account on ultix-streaming, in computer
mode (bare metal, real shell). Wired to start on reboot. UAT passed end to
end the same night (see 9-uat-openwebui.out).
## Layout
| account | port | bind | cwd | unit |
|---|---|---|---|---|
| reachableceo | 30000 | 100.101.187.119 (tailscale ONLY) | ~/projects | open-terminal@reachableceo |
| TSGCOO | 30001 | 〃 | ~/projects | open-terminal@TSGCOO |
| TSGCCO | 30002 | 〃 | ~ (no ~/projects yet) | open-terminal@TSGCCO |
| TSGCTO | 30003 | 〃 | ~/projects | open-terminal@TSGCTO |
| TSGBOD | 30004 | 〃 | ~ | open-terminal@TSGBOD |
| COS-RCEO | 30005 | 〃 | ~ | open-terminal@COS-RCEO |
| COS-WFO | 30006 | 〃 | ~ | open-terminal@COS-WFO |
| COS-TSG | 30007 | 〃 | ~ | open-terminal@COS-TSG |
| reachableceo-offstage | 30008 | 〃 | ~/projects | open-terminal@reachableceo-offstage |
- Binary: /usr/local/bin/open-terminal (open-terminal==0.11.34 via uv tool,
managed python at /opt/uv-python, venvs at /opt/uv-tools; world-readable
on purpose — non-root units exec it). Host-install exception authorized by
human 2026-08-31 ("pip/uv directly on my host... mandatory").
- Template unit: /etc/systemd/system/open-terminal@.service (After
tailscaled; Restart=always). Per-user TOML at
/etc/ukrrs/open-terminal/<user>.toml (key lives THERE, not on any command
line — nothing leaks via ps). Per-user cwd env alongside it.
- All 8 non-founder accounts were also added to the docker group (human
ruling 2026-08-31).
- Bind is 100.101.187.119 ONLY (tailscale interface; human ruling
2026-08-31 night: no LAN, no 0.0.0.0). Containers reach it fine (bridge →
host IP routing); so does anything over tailscale.
## API keys (NEVER in this repo)
~/.creds/open-terminal.env (reachableceo, 0600): URL + key per account in
`<ACCOUNT>_URL` / `<ACCOUNT>_API_KEY` form. Rotate a key with:
sudo sed -i "s/^api_key = .*/api_key = \"$(openssl rand -hex 32)\"/" \
/etc/ukrrs/open-terminal/<user>.toml && sudo systemctl restart open-terminal@<user>
then update ~/.creds/open-terminal.env to match.
## Wiring a production OpenWebUI (admin, server-side key)
Your Cloudron prod runs Open WebUI 0.11.1 — new enough. Admin UI:
Settings → Admin → Integrations → Open Terminal → "+":
URL: http://100.101.187.119:3000X (per-account port from the table)
API key: from ~/.creds/open-terminal.env
Auth: Bearer. Save → green "Connected".
API-only equivalent (what the UAT does):
POST /api/v1/configs/terminal_servers/verify {"url":…,"key":…}
POST /api/v1/configs/terminal_servers {"TERMINAL_SERVER_CONNECTIONS":[{"id":…,"url":…,"key":…,"auth_type":"bearer","enabled":true}]}
Scope per-user access via the connection's access control (each user gets
THEIR OWN port; do not share one terminal across accounts — one shell each).
In chat: pick the terminal (cloud icon) once per conversation; native
function calling is already the default in 0.11.x.
## UAT record (2026-08-31 22:48, all passed)
Throwaway openwebui:v0.11.1 (matched to Cloudron prod) on 127.0.0.1:8081,
LLM via the beta gateway lane:
- P3 connection verify+list OK; P4 direct exec runs as uid 1001 with real
~/projects output; P5 model emitted run_command, WE executed it through
OpenWebUI's terminal proxy (server holds the key), fed the result back,
and the model answered with 9/9 REAL directory names (no hallucination —
earlier runs without the tool attached fabricated names, proving the test
catches it). Full log: 9-uat-openwebui.out.
Gotcha learned: for raw API callers OpenWebUI returns tool_calls for the
CALLER to execute (the server-side loop needs a socket session — that's the
UI path). UI chats run the loop automatically.
## Hygiene notes
- open-terminal keeps per-process logs in
~/.local/state/open-terminal/logs/processes/ per user (unbounded; watch
when agents go wild).
- 0.0.0.0 was rejected by ruling; if tailscale is down at boot the units
retry (Restart=always) until the IP exists.
- Not in any ukrrs slice yet; fold into per-account slices when mkacct
lands (#607).