YOffice AI uses LiveKit for real-time video, audio, and voice-assistant sessions. You can run LiveKit locally with Docker (recommended for development) or connect to LiveKit Cloud for a fully managed setup.
The full YOffice feature set — including voice assistant, video calls, and screen sharing — works with a local LiveKit instance running in Docker. LiveKit Cloud is an optional convenience, not a requirement.
| Option | Best for | Cost | Setup time |
|---|---|---|---|
| Local Docker | Development, self-hosted production, air-gapped environments | Free (you host it) | ~5 minutes |
| LiveKit Cloud | Teams that want managed infrastructure and global media routing without running their own servers | Pay-as-you-go (free tier available) | ~10 minutes |
From command_center_tenant_server, run: docker compose up -d livekit. This uses livekit/livekit-server:latest with the config in livekit.yaml. Default ports: 7880 (WebSocket), 7881 (TCP), plus UDP for RTC. Default key: devkey / devkey-secret-32-chars-minimum!!
In command_center_tenant_server/config/passwords.yaml (development section), set: livekitUrl: ws://localhost:7880, livekitKey: devkey, livekitSecret: devkey-secret-32-chars-minimum!! If the tenant server runs inside Docker on the same compose, use ws://livekit:7880.
Run Postgres, Redis, and both the Auth and Tenant servers as described in the Quick Start guide. The Flutter app receives the LiveKit URL automatically from the tenant server when it requests a room token — no LiveKit URL needs to be configured in the Flutter app itself.
The tenant server needs three values in :config/passwords.yaml:
| Key | Description | Default (local) |
|---|---|---|
livekitUrl | WebSocket URL clients use to connect to LiveKit | ws://localhost:7880 |
livekitKey | API key (must match livekit.yaml) | devkey |
livekitSecret | API secret (must match livekit.yaml) | devkey-secret-32-chars-minimum!! |
If both the tenant server and LiveKit run inside the same Docker Compose network, use ws://livekit:7880 (service name) instead of ws://localhost:7880. The Flutter app receives the URL from the tenant server at token-issue time, so clients outside Docker still get the correct public URL.
Go to cloud.livekit.io and sign up or sign in. LiveKit Cloud offers a generous free tier suitable for development and small production workloads.
In the LiveKit Cloud dashboard, create a new project. Note down three values: WebSocket URL (e.g. wss://your-project.livekit.cloud), API Key, and API Secret (shown once — copy it immediately and store it securely).
In config/passwords.yaml (or environment variables for production), set: livekitUrl, livekitKey, and livekitSecret to the values from step 2.
Open Organization Settings → LiveKit Server. Toggle "Use LiveKit Cloud", paste the WebSocket URL, API key, and API secret, then press Save. This stores the credentials in Postgres and is the recommended approach for per-org overrides in multi-tenant deployments.
With LiveKit Cloud configured, you do not need to run a local LiveKit container. Start the Auth and Tenant servers and the Flutter app as usual. The tenant server will issue tokens pointing at LiveKit Cloud.
Organization admins can configure LiveKit Cloud credentials directly from the YOffice settings screen without touching server config files. This is the recommended approach for per-org overrides in multi-tenant deployments.
Navigate to Settings → Organization → LiveKit Server section.
Toggle "Use LiveKit Cloud" to on. Three input fields appear: WebSocket URL, API Key, and API Secret.
Enter the WebSocket URL (wss://…), API Key, and API Secret from your LiveKit Cloud project. API keys and secrets are stored encrypted — they are never returned in plain text after the initial save.
Tap Save. All members of this organization will use the configured LiveKit project for video calls and voice sessions.
When running multiple tenant-server replicas behind a load balancer, LiveKit Cloud requires no special configuration. JWTs are signed with credentials stored in Postgres — every replica reads from the same source, so any pod can mint a token for any user.
The customization-agent (voice/avatar worker) connects to LiveKit Cloud and calls back to your tenant server via TENANT_BASE_URL. Point this at your load balancer; any replica can handle the callbacks.
Sticky sessions are not required for voice. LiveKit Cloud connects clients directly to its own media plane after JWT minting. See the Multi-instance Deployment guide for the full checklist.
| Symptom | Likely cause | Fix |
|---|---|---|
| Video call connects but no audio | UDP ports blocked by firewall | Open UDP 50000–60000 (local) or check LiveKit Cloud region firewall rules |
| Token request returns 401 | Mismatched API key or secret | Double-check livekitKey / livekitSecret in passwords.yaml match the LiveKit project |
| Voice assistant connects but never speaks | Worker cannot reach tenant server | Set TENANT_BASE_URL to the public load-balancer URL, not a pod IP |
| Flutter app cannot reach LiveKit (local) | livekitUrl set to Docker-internal hostname | Use a hostname reachable from the Flutter device (e.g. your machine's LAN IP) |