From 04d965d67a7264a1c7c211494aebda1953df7603 Mon Sep 17 00:00:00 2001 From: "info@mode42.com" Date: Fri, 7 Aug 2026 18:25:13 +0000 Subject: Initial push --- stacks/web/README.md | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 stacks/web/README.md (limited to 'stacks/web/README.md') diff --git a/stacks/web/README.md b/stacks/web/README.md new file mode 100644 index 0000000..18cc291 --- /dev/null +++ b/stacks/web/README.md @@ -0,0 +1,112 @@ +# MAX25 Web UI — browser remote terminal + +> **Status: available** — full remote terminal (M25/1 via WebSocket proxy). Same session model as `max25-terminal`. Not a replacement for the CLI client. + +**Operator guide:** [docs/WEBSOCKET.md](../../docs/WEBSOCKET.md) · **Roadmap:** [docs/V2.0.0-SCOPE.md](../../docs/V2.0.0-SCOPE.md#dev-levels-roadmap-stack-wide) + +Browser terminal for **max25d** M25/1 — hyBBX-style httpd + reverse-proxy pattern, MAX25-correct separate loopback proxy. + +| Layer | Component | Role | +|-------|-----------|------| +| Browser UI | PHP + JS (`docroot/max25-websocket/`) | Remote terminal; `/` commands + menu | +| Session defaults | `web-terminal.ini` | CALLERID, CALLID, device, ax25_ui per session | +| HTTP reverse-proxy | nginx / Apache / lighttpd examples | `WS /max25-websocket/ws` → loopback proxy | +| WebSocket proxy | `max25-ws-proxy.py` | RFC6455 ↔ M25/1 TCP forward (no translation) | +| Daemon | `max25d` | M25/1 on TCP `7325` | + +CLI operator client remains **max25-terminal** — see [docs/MAX25-TERMINAL.md](../../docs/MAX25-TERMINAL.md). + +## Implementation status + +| Item | State | +|------|--------| +| PHP + JS UI (`docroot/max25-websocket/`) | **Available** — header, dropdown menu, device select | +| `max25-terminal.js` | **Available** — F10-equivalent `/` commands, bootstrap from INI | +| `web-terminal.ini.example` | **Available** — session defaults from max25d logic | +| `max25-ws-proxy.py` | **Available** — CI smoke test passes | +| httpd examples | Draft configs (nginx, Apache, lighttpd) | +| systemd unit example | Shipped — `share/max25/max25-ws-proxy.service.example` | +| Admin dashboard | Later | + +## Browser commands (F10 equivalent) + +| `/command` | M25/1 | +|------------|-------| +| `/callerid` `/callid` | `SET CALLERID` / `SET CALLID` | +| `/status` | `GET STATUS` | +| `/send ` | `SEND` | +| `/monitor` | `MONITOR on\|off` | +| `/connect` `/disconnect` | `CONNECT` / `DISCONNECT` | +| `/devices` | `GET DEVICES` | +| `/device ` | `SET DEVICE` (max25d ids only) | +| `/ax25_ui on\|off` | `SET AX25_UI` | +| `/help` | Command list | + +Plain text without `/` → `SEND` (same as max25-terminal Enter). **Menu ▾** dropdown mirrors these actions. + +One **device per session**; change via dropdown or `/device`. Device list always from **GET DEVICES** — unknown ids rejected. + +## Quick start (local dev) + +```bash +# Terminal 1: max25d +python3 stacks/daemon/max25d.py --tcp-port 7325 + +# Terminal 2: dev stack (proxy + PHP) +./stacks/web/scripts/dev-server.sh +``` + +Browser: `http://127.0.0.1:8080/` + +Copy `share/web-terminal.ini.example` → `/etc/max25/web-terminal.ini` for session defaults (CALLERID, CALLID, device from max25d.ini logic). + +## Configuration + +### WebSocket proxy (`web-proxy.ini`) + +Copy `share/web-proxy.ini.example` to `/etc/max25/web-proxy.ini` (or `MAX25_WEB_PROXY_INI`). + +| Section | Key | Default | Meaning | +|---------|-----|---------|---------| +| `[proxy]` | `bind` | `127.0.0.1` | Loopback only | +| `[proxy]` | `port` | `7326` | WebSocket listen port | +| `[proxy]` | `path` | `/max25` | Upgrade path | +| `[upstream]` | `host` / `port` | `127.0.0.1` / `7325` | max25d M25/1 | +| `[upstream]` | `tcp_password` | *(empty)* | Proxy-side AUTH | + +### Browser session (`web-terminal.ini`) + +Copy `share/web-terminal.ini.example` to `/etc/max25/web-terminal.ini` (or `MAX25_WEB_TERMINAL_INI`). + +Merges with max25d `[modem]` and `[devices] default` when keys omitted — see [docs/WEBSOCKET.md](../../docs/WEBSOCKET.md). + +## Production deploy + +```bash +cmake --install $BUILD --prefix $PREFIX +``` + +Installs: `max25-ws-proxy`, `web-proxy.ini.example`, `web-terminal.ini.example`, `reverse-proxy/` tree. + +1. Copy `docroot/max25-websocket/` to httpd docroot +2. Add httpd WS snippet → `127.0.0.1:7326/max25` +3. Configure `web-proxy.ini` + `web-terminal.ini` +4. Run `max25-ws-proxy` (systemd example shipped) + +## Architecture + +``` +Browser → httpd (wss) → max25-ws-proxy :7326 → max25d M25/1 :7325 +``` + +M25/1 uses `\n` line endings. Proxy forwards bytes after connect handshake (`OK` + `STATUS`). + +## CI + +Target `max25_web_smoke` — PING through max25d + proxy + WebSocket (offline, no UART). + +## Related + +- [docs/WEBSOCKET.md](../../docs/WEBSOCKET.md) — operator guide +- [include/max25/protocol.md](../../include/max25/protocol.md) — M25/1 spec +- [docs/MAX25-CLIENT.md](../../docs/MAX25-CLIENT.md) — client contract -- cgit v1.3.1