Files
Webka/README.md
2026-09-06 16:47:05 +05:00

8.4 KiB
Raw Blame History

Webka

A private camera and screen streaming app for your local network. Nuxt 3 / Vue 3 / TypeScript, Pinia, English/Russian/Spanish, and an Axum/Rust service with SQLite and browser-to-browser WebRTC.

One-command start

Install Node 22.12+ (npm included) and stable Rust/Cargo once. Then, from the repository root:

npm run dev:all

This starts http://127.0.0.1:3000. To listen on all network interfaces at port 3002:

npm run dev:all -- --host 0.0.0.0 --port 3002

The -- after dev:all passes the options to the launcher. Use ordinary double hyphens. npm start -- --host 0.0.0.0 --port 3002 is an alias. --help shows usage.

The launcher installs frontend dependencies automatically on the first run, builds Nuxt, builds Rust, and runs one server serving both the frontend and API on the chosen port. First startup needs internet and can take several minutes. Subsequent runs reuse unchanged dependencies/frontend output; Cargo builds incrementally. Restart the command after code changes to rebuild. This convenience command does not provide hot reload.

The terminal prints the local URL, LAN URLs when available, and the setup-token file location. Open the local URL on the server computer for camera capture; use a printed LAN URL on other devices to watch. The QR code uses the detected LAN address when listening on all interfaces. Local and detected private IPv4 origins are explicitly allowed; arbitrary origins remain blocked. If the selected port is busy, startup stops with an actionable message.

Press Ctrl+C to stop the app and any build subprocesses. Accounts remain in data/. The first login page creates the administrator account using the token from data/setup-token. The administrator cannot be deleted; resetting its password ends its sessions.

For HTTPS behind a reverse proxy, set WEBKA_ORIGIN to the exact public origin before launching. This override disables automatic HTTP aliases; optional WEBKA_ALLOWED_ORIGINS is a comma-separated list of additional trusted exact origins. Browser capture on another LAN device still requires trusted HTTPS; plain LAN HTTP permits viewing only.

For frontend hot reload, the separate development workflow remains available: run cargo run --manifest-path backend/Cargo.toml and npm --prefix frontend run dev in separate terminals, then open http://localhost:3000.

Use on your LAN

A webpage cannot launch a Rust server on the device running its browser. Start the Rust service once on a computer on your LAN. A phone, tablet, or computer can then sign in as the administrator and act as the capturing host. This repository does not include a native iOS/Android service wrapper. Each service instance owns its account database.

Browser camera/screen APIs require a secure context: localhost on the service machine, or trusted HTTPS on a LAN device. LAN HTTP IP addresses cannot capture camera/screen. For LAN use, use the included Caddyfile.example with a trusted local certificate:

  1. Point webka.local at the service computer, through mDNS (WEBKA_MDNS=1), your router, or a hosts entry. .local resolution and multicast support vary by network/device; a local DNS name or IP with a matching trusted certificate also works.

  2. Configure Caddy with the example below, and install/trust Caddy’s local CA on every client device. Keep this CA private.

  3. Start Webka with its exact public origin:

    WEBKA_ORIGIN=https://webka.local WEBKA_MDNS=1 \
    WEBKA_PUBLIC_PORT=443 WEBKA_BIND=127.0.0.1:3001 \
    cargo run --release --manifest-path backend/Cargo.toml
    
  4. Open https://webka.local, create the admin account, add viewer accounts in Accounts, enable preview, and choose Go live. Share the QR code/local address. Each viewer signs in with an account created on this service.

Caddy terminates HTTPS and proxies to the loopback Rust server. Cookies gain Secure automatically when WEBKA_ORIGIN starts with https://. WebSocket handshakes and all mutations validate an explicitly configured Origin. No CORS wildcard or trusted forwarded-IP headers are used. The login throttle sees the reverse proxy as one IP, so its ten-attempts-per-minute limit is shared behind that proxy.

Use a private LAN and firewall; do not expose the service through public port forwarding. The app uses no cloud accounts, public STUN/TURN, telemetry, CDNs, or external fonts. WebRTC connects peers directly with local ICE candidates. Client isolation, VLANs, and firewalls that block peer UDP can prevent streams; no cloud relay fallback is provided. The one active host sends a separate peer stream to each viewer (32 signaling connections total, including the host). Capacity depends on the host device and Wi-Fi.

Configuration

Variable Default Purpose
WEBKA_BIND 127.0.0.1:3001 Rust listener
WEBKA_ORIGIN http://localhost:3000 Exact public origin; used for CSRF checks, QR and secure cookies
WEBKA_ALLOWED_ORIGINS none Additional trusted exact origins; launcher configures local/LAN aliases
WEBKA_DATA data Local database and persistent secrets
WEBKA_ASSETS frontend/.output/public Generated frontend; paths are relative to the current directory
WEBKA_MDNS off Set 1 to advertise _webka._tcp.local. and webka.local
WEBKA_PUBLIC_PORT 443 for HTTPS, otherwise 3000 Advertised public port

Back up WEBKA_DATA securely. On Unix the data directory is owner-only and secret files are created with mode 0600. On Windows configure equivalent directory ACLs. Session tokens are random, HMAC-signed, stored only as SHA-256 digests in SQLite, and sent in HttpOnly/SameSite=Strict cookies. Argon2id stores salted passwords. Sessions expire after 30 minutes without activity and always after 12 hours. Visible authenticated pages send a heartbeat; hidden pages do not. Revocation closes signaling and tells the host to close the affected peer. A recipient may still retain media already received.

Features and implementation

  • /login: protected first-run setup and local sign-in.
  • /host: camera preview, front/back/screen selection, start/stop, uptime, bitrate presets, QR link and viewer disconnection.
  • /watch: live video, connection/resolution indicator, fullscreen, logout and automatic reconnect with backoff.
  • /settings/accounts: viewer creation/deletion, password reset, last login and active session revocation.
  • /settings/general: light/dark glass, accent, locale and security information.
  • Shared GlassCard, GlassButton, GlassNavBar, GlassModal and LanguageSwitcher with layered rim highlights, pointer-responsive specular light, rounded geometry, reduced-motion support, native keyboard focus and dialog focus containment.
  • Content panels stay opaque. Glass is used for navigation, source/share controls and dialogs. CSS edge layers approximate refraction; they do not implement physically accurate optical lensing.

Quality presets control the host’s per-peer send bitrate; the viewer shows actual received resolution. Capture is video-only. Closing/navigating away from the host tab stops capture; a browser may also suspend hosting when the device locks or the tab is backgrounded. Screen share support varies, particularly on mobile. Back-camera discovery becomes reliable after granting camera permission. Physical-device tests are documented in docs/MANUAL_TEST_PLAN.md.

Nuxt 3 is retained to match the requested stack. Its upstream documentation now marks it end-of-life; plan a Nuxt 4 upgrade before broader distribution. Reference: https://nuxt.com/docs/3.x/getting-started/installation.

Validation

npm run test:launcher
cargo fmt --manifest-path backend/Cargo.toml --check
cargo test --manifest-path backend/Cargo.toml
cargo clippy --manifest-path backend/Cargo.toml --all-targets -- -D warnings
npm --prefix frontend run typecheck
npm --prefix frontend run build
node frontend/scripts/check-locales.mjs
cargo build --manifest-path backend/Cargo.toml
python3 scripts/smoke.py
# Optional POSIX integration test: reserves port 3002, tests startup/restart/stop.
python3 scripts/test-launcher.py

See docs/API.md for REST/signaling contracts and docs/MANUAL_TEST_PLAN.md for real-device checks. Design references: Apple’s introduction and Meet Liquid Glass. No Apple assets are included. Nothing is published by the build commands.