Files
OwnCord/docs/tailscale.md
T
J3vb 70f3ed8f23 fix: resolve 20 code review bugs across Rust, TypeScript, and Go
Critical/High Rust (Tauri client):
- BUG-140: replace .run() with .build() + RunEvent::Exit handler; native error dialog on startup failure
- BUG-141: eliminate PTT thread TOCTOU race with Mutex critical section; add AtomicBool shutdown and catch_unwind
- BUG-144: fix TOFU cert store corruption — read-before-write rollback restores previous fingerprint on save failure (all 3 write sites)
- BUG-145: add VK code range guard (1..=254) in is_key_down; fix cast to (state as i16) < 0
- BUG-147: replace bare spawns with JoinSet; abort_all + drain on exit; unconditional closed event
- BUG-150: add CRLF guard in handle_connection before header rewriting
- BUG-151: wrap header read loop in tokio::time::timeout(10s)
- BUG-158: extract CERTS_STORE/SETTINGS_STORE to constants.rs (eliminate 3 duplicates)
- HIGH-2: PTT thread self-cleanup uses unwrap_or_else defensive pattern
- HIGH-4: ws_send distinguishes Full vs Closed errors; warn log on backpressure

Critical/High TypeScript (Tauri client):
- BUG-142: join-generation counter prevents stale connectAndSetup completions
- BUG-143: replace 8 mutable LiveKit session fields with discriminated union SessionState
- BUG-146: 60s token refresh deadline; cleared on reply or voice leave
- BUG-148: ResizeObserver hoisted to outer scope; disconnect() in destroy() before ac.abort()
- BUG-152: dismissSignal.aborted guard already present (no change needed)
- BUG-153: measureRendered split into two-pass read-then-write; eliminates per-message reflow
- BUG-154: WS dedup cache batch-evicts to 80% on overflow (amortised O(1))
- BUG-157: pendingUpdates replaced with coalesced function-composition slot (O(1) queue depth)

Go server:
- BUG-149: safe two-value type assertion in getOutboundIP with localhost fallback
- BUG-155: broadcast buffer 256→1024; broadcastDrops atomic counter exposed in /api/v1/metrics
- BUG-156: LiveKitHealthCheck and implementations accept ctx context.Context; all call sites pass r.Context() (12 files)
- BUG-159: MaxMessageBytes constant in config/constants.go; replaces 1<<20 literals in serve.go and updater.go
- HIGH-1: cert store rollback reads old value before write; restores previous cert on save failure

All validation passes: go build, go vet, cargo check, npm typecheck
2026-04-03 23:18:06 +02:00

1.2 KiB

Tailscale Guide (Zero-Config Remote Access)

Use Tailscale when you want remote access without port forwarding.

Why Tailscale

Tailscale creates an encrypted private network between your devices using WireGuard. It works behind CGNAT and strict home routers, so setup is usually faster than manual forwarding.

Setup

  1. Install Tailscale on the server machine and client machines: https://tailscale.com/download
  2. Sign in and confirm all devices are in the same tailnet (or shared access is granted).
  3. Get the server Tailscale IP (usually 100.x.y.z) from the Tailscale app.
  4. Keep OwnCord on port 8443.
  5. Connect clients to https://<tailscale-ip>:8443.

TLS Recommendation

  • Recommended: keep tls.mode: self_signed (default).
  • Optional advanced setup: set tls.mode: off only if every client is strictly inside trusted Tailscale access and you accept plaintext inside the tailnet.

Voice/Video with Tailscale

  • Tailscale handles device-to-device reachability, but LiveKit still needs correct runtime config.
  • Follow livekit-setup.md for LiveKit key/secret and port behavior.

Benefits

  • No router port forwarding.
  • Works behind CGNAT.
  • Stable private IPs.
  • Encrypted transport by default.