summaryrefslogtreecommitdiff
path: root/stacks/web/README.md
blob: 18cc2915983a1599485dddac8c20d9541cd4f6e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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 <text>` | `SEND` |
| `/monitor` | `MONITOR on\|off` |
| `/connect` `/disconnect` | `CONNECT` / `DISCONNECT` |
| `/devices` | `GET DEVICES` |
| `/device <id>` | `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
git clone -b <branch> https://cgit.mode42.com/<repo>.git
git clone -b <branch> git://cgit.mode42.com/<repo>.git

info@mode42.com