Skip to content

feat(local): LAN/Tailscale access + secure-context UUID polyfill - #113

Open
betoneira26 wants to merge 1 commit into
CopilotKit:mainfrom
betoneira26:local-setup
Open

betoneira26 wants to merge 1 commit into
CopilotKit:mainfrom
betoneira26:local-setup

Conversation

@betoneira26

Copy link
Copy Markdown

Adds two small code changes plus a runbook for running OpenDots self-hosted (local CopilotKit Intelligence) and reaching it from other machines on a LAN or tailnet.

Changes

  • vite.config.ts: the dev server binds 0.0.0.0 with allowedHosts: true so the app is reachable beyond loopback (the API stays on loopback and is proxied by Vite).
  • src/client/polyfills.ts (+ one import in main.tsx): crypto.randomUUID fallback built from crypto.getRandomValues. On plain-HTTP access via an IP (not a secure context) crypto.randomUUID is undefined, the client throws, and the Dot stays stuck on "thinking". The fallback is a plain module (not an inline script) so it also survives a strict CSP.
  • docs/LOCAL-SETUP.md: a reproducible runbook (local Intelligence stack, LAN/Tailscale access, why the realtime gateway port must be forwarded to be browser-reachable, Slack managed channel, voice).
  • deployment/local/: socat systemd units to expose the realtime gateway port plus a commented .env template.

Notes

  • No secrets are included (.env, data/, .copilotkit/ remain git-ignored).
  • npm run typecheck and npm run lint pass.

- vite.config: bind 0.0.0.0 and allow LAN/tailnet hosts so the dev server is
  reachable beyond loopback (the API stays on 127.0.0.1 and is proxied).
- src/client/polyfills: fall back to a getRandomValues-derived v4 UUID when
  crypto.randomUUID is missing. On plain-HTTP access via an IP (not a secure
  context) the CopilotKit client threw and the Dot hung on "thinking".
- docs/LOCAL-SETUP: reproducible runbook (local Intelligence stack, LAN/tailnet
  gateway forwarding, Slack managed channel, voice).
- deployment/local: socat systemd units to expose the realtime gateway port and
  an .env template.

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>

@NathanTarbert NathanTarbert left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @betoneira26, this is a really useful writeup. The explanation of why crypto.randomUUID disappears on plain-HTTP LAN addresses is clear. The polyfill does it right: it only installs when randomUUID is missing, uses crypto.getRandomValues with the correct version and variant bits, and loads as a module so the CSP stays intact. The runbook covers the parts people usually get stuck on, like the gateway port the browser needs and local Slack and voice.

The part I'd change before merging is the Vite config. With host: '0.0.0.0' and allowedHosts: true set unconditionally, every npm run dev would listen on the network, not just setups that want LAN access, and Vite's host check that protects against DNS rebinding is turned off. The Vite dev server also serves project files directly, outside OpenDots' own auth, so it isn't a good thing to expose beyond localhost even with a token set.

A safer shape would be:

  • Keep 127.0.0.1 as the default and make LAN access opt-in, for example npm run dev -- --host or an env flag that sets the host.
  • Use an explicit allowedHosts list, like the LAN IP or tailnet name, rather than true.
  • For access from other machines, have the runbook use a production build served by the OpenDots server, with OWNER_TOKEN set and HTTPS in front (tailscale serve works well for that), rather than the Vite dev server.

Two smaller things in the runbook. deployment/local/opendots-gateway-lan.service has bind=192.168.1.38 hardcoded, which should be a placeholder. The Funnel example exposes the whole local Intelligence dashboard publicly. If Slack only needs the events path, funnelling just that would be safer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants