{"skill":{"slug":"webchat-https-proxy","displayName":"WebChat HTTPS Proxy","summary":"HTTPS/WSS reverse proxy for OpenClaw WebChat Control UI. Serves the Control UI over HTTPS with TLS cert management, proxies WebSocket connections to the gate...","description":"---\nname: webchat-https-proxy\ndescription: >\n  HTTPS/WSS reverse proxy for OpenClaw WebChat Control UI. Serves the Control UI\n  over HTTPS with TLS cert management, proxies WebSocket connections to the\n  gateway, and forwards /transcribe requests to the local faster-whisper endpoint.\n  Runs as a user systemd service. Pure infrastructure — no voice-specific UI logic.\n  Keywords: HTTPS proxy, WSS, TLS, reverse proxy, Control UI, systemd service,\n  self-signed certificate, WebSocket proxy.\nrequires:\n  config_paths:\n    - ~/.openclaw/openclaw.json (appends allowedOrigins entry)\n  modified_paths:\n    - ~/.config/systemd/user/openclaw-voice-https.service (creates unit)\n    - ~/.openclaw/workspace/voice-input/https-server.py (copies runtime file)\n    - ~/.openclaw/workspace/voice-input/certs/ (generates self-signed TLS cert)\n  env:\n    - VOICE_HTTPS_PORT (optional, default: 8443)\n    - VOICE_HOST (optional, default: 127.0.0.1 — set to a LAN IP to expose externally)\n    - VOICE_ALLOWED_ORIGIN (optional, default: https://<VOICE_HOST>:<VOICE_HTTPS_PORT>)\n  persistence:\n    - \"User systemd service: openclaw-voice-https.service (HTTPS/WSS proxy)\"\n  privileges: user-level only, no root/sudo required\n  dependencies:\n    - python3 with aiohttp >= 3.9.0 (pip)\n    - openssl (for self-signed cert generation)\n---\n\n# WebChat HTTPS Proxy\n\nStandalone HTTPS/WSS reverse proxy for OpenClaw WebChat Control UI:\n- Serves the Control UI over HTTPS (default port 8443)\n- WebSocket passthrough to gateway (`ws://127.0.0.1:18789`)\n- `/transcribe` proxy endpoint to local faster-whisper service (same-origin browser auth; optional Bearer fallback)\n- Self-signed TLS certificate management\n- SPA fallback for Control UI routing\n- Path traversal protection for static file serving\n\n## Deploy\n\n```bash\nbash scripts/deploy.sh\n```\n\nOr expose on LAN:\n```bash\nVOICE_HOST=10.0.0.42 VOICE_HTTPS_PORT=8443 bash scripts/deploy.sh\n```\n\nThis script is idempotent.\n\n## Quick verify\n\n```bash\nbash scripts/status.sh\n```\n\n## Security Notes\n\n### Network isolation\n- **Localhost by default**: Binds to `127.0.0.1` only. Not reachable from other devices unless `VOICE_HOST` is explicitly set.\n- **LAN access opt-in**: Setting `VOICE_HOST=<LAN-IP>` enables trusted LAN access. Re-deploys preserve the existing configured bind host unless you explicitly override `VOICE_HOST`.\n- **CORS**: Single allowed origin only (`VOICE_ALLOWED_ORIGIN`). Validated at startup — wildcards (`*`) and malformed origins are rejected.\n\n### TLS\n- **TLS 1.2+ enforced**: Minimum protocol version set to TLS 1.2. Legacy SSL/TLS 1.0/1.1 rejected.\n- **Self-signed TLS**: Auto-generated certificate. Browser certificate warning on first access.\n- **Private key permissions**: `chmod 600` on TLS key file.\n\n### Authentication\n- **Bearer token auth**: `/transcribe` endpoint validates Bearer token against gateway auth token using constant-time comparison (`hmac.compare_digest`).\n- When no gateway token is configured, auth is skipped (safe for localhost-only).\n\n### Input validation\n- **Upload size limit**: 50 MB hard limit on `/transcribe` proxy requests (HTTP 413).\n- **Empty body rejection**: HTTP 400 for empty requests.\n- **Response size limit**: 10 MB cap on upstream response to prevent memory exhaustion.\n- **Path traversal protection**: Static file serving resolves symlinks (`os.path.realpath`) and validates the resolved path stays within the Control UI directory.\n\n### Error handling\n- **No exception leaking**: Error responses return generic messages, not internal exception details.\n- **Upstream timeout**: 120s timeout on transcription backend requests.\n\n### SSRF protection\n- Upstream URLs (`VOICE_TRANSCRIBE_URL`, `VOICE_GATEWAY_WS`) are validated to point to localhost only. Non-localhost targets are rejected at startup.\n\n### No data exfiltration\n- No outbound network calls. Proxy only connects to localhost services.\n- No telemetry, analytics, or phone-home behavior.\n\n### Persistence\n- User systemd service starts on boot. Use `uninstall.sh` to fully revert.\n\n## What this skill modifies\n\n| What | Path | Action |\n|---|---|---|\n| Gateway config | `~/.openclaw/openclaw.json` | Adds HTTPS origin to `gateway.controlUi.allowedOrigins` |\n| Systemd service | `~/.config/systemd/user/openclaw-voice-https.service` | Creates + enables persistent HTTPS proxy |\n| Runtime file | `~/.openclaw/workspace/voice-input/https-server.py` | Copies proxy server |\n| TLS certs | `~/.openclaw/workspace/voice-input/certs/` | Auto-generated self-signed cert on first run |\n\n## Uninstall\n\n```bash\nbash scripts/uninstall.sh\n```\n\n## Common fixes\n\n- `404 /chat?...` → SPA fallback missing in HTTPS proxy.\n- `origin not allowed` → ensure deploy used correct `VOICE_HOST` and added matching HTTPS origin to `gateway.controlUi.allowedOrigins`.\n- `token missing` → open URL with `?token=...` once.\n- `pairing required` → approve pending device via `openclaw devices approve <requestId> --token <gateway-token>`.\n\nces approve <requestId> --token <gateway-token>`.\n\n","tags":{"latest":"0.1.1"},"stats":{"comments":0,"downloads":835,"installsAllTime":5,"installsCurrent":5,"stars":0,"versions":2},"createdAt":1772756807741,"updatedAt":1778491742347},"latestVersion":{"version":"0.1.1","createdAt":1773972051620,"changelog":"MIT license added; same-origin transcribe auth hardening; preserve configured voice host on redeploy.","license":"MIT-0"},"metadata":{"setup":[{"key":"[object Object]","required":true}],"os":null,"systems":null},"owner":{"handle":"neldar","userId":"s17fa26xrs6xbrreh4h0k2t521884byj","displayName":"neldar","image":"https://avatars.githubusercontent.com/u/387537?v=4"},"moderation":null}