1.8 KiB
1.8 KiB
ADR-0006 · Router serves console shell, Cell provides APIs
Status: accepted Date: 2026-05
Context
The operator console is a SPA that needs:
- A stable, well-known URL (
http://blocao-router.local/). - Access to APIs from both the router (network config) and the Cell (Frigate, forensic engine).
- TLS termination.
- Auth.
Options:
- SPA hosted on the Cell, router redirects.
- SPA hosted on the router, Cell exposes APIs cross-origin.
- SPA hosted on the router, router reverse-proxies to Cell APIs.
Decision
Option 3. The router always serves the SPA shell at http://blocao-router.local/ (or HTTPS once cert is set up). The Cell provides APIs only — never a UI directly.
The router reverse-proxies API calls based on path:
/api/router/*→ localubusover/ubus/api/cell/*→ discovered Cell IP/port/api/cell/<cell-id>/*→ specific Cell when multi-Cell
The browser only ever talks to the router. CORS never appears.
Consequences
Good:
- Single origin, no CORS complications.
- Cell can be unreachable temporarily without breaking the router-side parts of the UI.
- Router is the natural single point of auth.
- Cell discovery is a router responsibility, transparent to the UI.
Bad / trade-offs:
- Router has to do reverse-proxy work; small CPU cost on a low-power device.
- If the router is down, no UI access at all. Mitigated by Tailscale fallback to direct Cell SSH (ops only).
- The mental model "router = thin, Cell = fat" is partially violated — router does carry the SPA bytes.
Alternatives considered
- Cell hosts the SPA: requires Cell to be discoverable from operator's machine, makes URLs unstable when Cell IPs change.
- Hub hosts the SPA, both router and Cell expose APIs: requires WAN connectivity for the operator UI, breaks air-gapped deployments.