Skip to content

Self-hosting Petal

Petal can run against infrastructure you operate yourself. The supported path is a self-hosted LiveKit server plus a deployment of this repository’s stateless backend/ service. The backend mints short-lived, room-scoped LiveKit tokens; the LiveKit API secret stays on the backend and is never baked into the desktop app or sent to a browser.

There are no application-code changes needed for this setup. Configure the backend, then build the desktop client with its backend URL embedded at build time.

You need three pieces:

  1. A reachable LiveKit server, with a DNS name and trusted TLS certificate for production clients. Clients connect to its WebSocket URL, usually wss://livekit.example.com.
  2. The backend/ directory deployed as serverless functions. Vercel is the supported deployment target, but another platform can be used if it can run the Vercel-style @vercel/node handlers in backend/api/.
  3. A desktop build configured with the public base URL of that backend.

The backend uses LiveKit itself as its only room store. It does not require a database, Redis, or a separate Petal service for the core token and room discovery APIs.

Create one API key and secret in the LiveKit server configuration. For a production self-hosted server, use the LiveKit deployment’s normal config file or LIVEKIT_CONFIG mechanism; the exact surrounding settings depend on whether LiveKit is running in Docker, Kubernetes, or directly on a host. The important part is that the key and secret match the values supplied to the Petal backend.

For example, a LiveKit config can contain:

keys:
petal_key: replace-with-a-long-random-secret

Here petal_key is the API key and its value is the API secret. Keep both private on the server. Expose the LiveKit signaling endpoint over wss:// and configure the network, firewall, UDP/TCP media ports, and TURN as required by the LiveKit self-hosting deployment guide. ws://localhost:7880 with livekit-server --dev is suitable only for local development.

The backend needs these environment variables, using the same credentials:

LIVEKIT_URL=wss://livekit.example.com
LIVEKIT_API_KEY=petal_key
LIVEKIT_API_SECRET=replace-with-a-long-random-secret

LIVEKIT_URL is the public LiveKit signaling URL. The backend also derives the HTTPS API host from it for room administration, so use the public ws:// or wss:// URL without a path or query string.

Create a Vercel project whose root directory is backend/, then set the three LIVEKIT_* variables above as server-side Project Environment Variables. Do not expose LIVEKIT_API_SECRET as a client or VITE_* variable.

From a checkout of this repository, the project can also be deployed with the Vercel CLI from the backend directory:

Terminal window
cd backend
npm install
vercel --prod

The deployment’s base URL is the value to use for PETAL_BACKEND_URL below. The backend exposes /api/token, /api/rooms, and the other handlers listed in Backend API reference. Browser callers must also be allowed by CORS. Set PETAL_ALLOWED_ORIGINS to a comma-separated list such as the origin of your web harness:

PETAL_ALLOWED_ORIGINS=https://meet.example.com

Native desktop requests do not need this setting because they normally have no Origin header.

The core meeting service needs only the three LIVEKIT_* variables. The following are optional integrations, not prerequisites for self-hosted meetings:

  • PETAL_ADMIN_TOKEN enables the protected /api/admin kick/close operations.
  • SENTRY_DSN enables backend error reporting.
  • BLOB_READ_WRITE_TOKEN enables /api/updater and /api/download for the repository’s Vercel Blob-based release distribution. If you do not operate those distribution endpoints, they are not needed for token or room APIs.

For a non-Vercel host, deploy the same backend/api/*.ts handlers with a compatible serverless adapter and provide the same environment variables. backend/vercel.json supplies the root and updater rewrites used by Vercel; recreate any routes you need on the alternative platform.

apps/desktop/src-tauri/build.rs reads PETAL_BACKEND_URL and embeds it in the desktop binary. Set it when building from apps/desktop:

Terminal window
cd apps/desktop
PETAL_BACKEND_URL=https://petal-backend.example.com npm run tauri build

Use the repository’s normal release command and signing variables when making a distributable release; the important self-hosting setting is still the same PETAL_BACKEND_URL environment variable at build time. The value should be the backend origin only, without /api/token; the app appends endpoint paths itself.

There is no hosted default. A build that leaves PETAL_BACKEND_URL unset bakes no backend at all: cargo prints a warning for release builds, and at runtime every join fails with a message telling the user the build has no token backend. This is deliberate — a default would mean every third-party build silently minting tokens against the maintainers’ LiveKit and Vercel accounts.

In a debug build, leaving it unset (or setting it explicitly empty) instead activates the local dev token mint, which reads LIVEKIT_URL, LIVEKIT_API_KEY, and LIVEKIT_API_SECRET and talks to a local livekit-server --dev. That path is compiled out of release builds.

Changing the environment variable causes Cargo to rebuild the relevant crate, so do not rely on a previously built app bundle.

Auto-update and release signing for a fork

Section titled “Auto-update and release signing for a fork”

If you distribute your own builds, you must repoint the updater. Otherwise your users’ apps poll Petal’s update feed and will replace your build with Petal’s official binary.

apps/desktop/src-tauri/tauri.conf.json ships Petal’s official endpoint and minisign public key as the default. Override them at build time with Tauri’s TAURI_CONFIG merge:

Terminal window
export TAURI_CONFIG='{"bundle":{"createUpdaterArtifacts":true},"plugins":{"updater":{"endpoints":["https://updates.example.com/api/updater"],"pubkey":"<your-minisign-public-key>"}}}'

Generate your own key with npx tauri signer generate; never reuse Petal’s, since you will not hold the matching private key and your updates will fail verification.

Two related build-time values let a fork’s own signed build be recognized as a release of itself rather than an unsigned build. Unset, they fall back to Petal’s values:

Variable Purpose
PETAL_RELEASE_BUNDLE_ID Bundle identifier the release-signing check expects
PETAL_RELEASE_TEAM_ID Apple Developer Team ID in your signing certificate

scripts/verify-universal-app.sh enforces that the built app carries the expected updater anchors. Point it at yours with PETAL_EXPECTED_UPDATER_ENDPOINT and PETAL_EXPECTED_UPDATER_PUBKEY so the gate validates your trust anchors instead of Petal’s.

Renaming and rebranding a redistributed build is also a trademark requirement — see TRADEMARKS.md.

The desktop app does not need LIVEKIT_URL, LIVEKIT_API_KEY, or LIVEKIT_API_SECRET for the normal join/rooms path. Those credentials belong on the LiveKit server and backend. Keep them out of release build commands and out of client-distributed .env files.

4. Point web-harness at the backend (optional)

Section titled “4. Point web-harness at the backend (optional)”

If you also deploy web-harness/, set VITE_PETAL_BACKEND_URL at its build time to the same backend origin:

Terminal window
cd web-harness
VITE_PETAL_BACKEND_URL=https://petal-backend.example.com npm run build

For Vercel, set the value in the project’s build command or environment and deploy from the web-harness/ root. The checked-in vercel.json currently contains the hosted Petal default, so replace that value for a self-hosted deployment rather than deploying it unchanged. The harness calls <backend-origin>/api/token and uses the LiveKit URL returned by that response.

For local development against a local LiveKit server, leave VITE_PETAL_BACKEND_URL unset and use the harness’s local token middleware; see Joining from a browser.

After deploying, verify that:

  1. A desktop build made with your PETAL_BACKEND_URL can create or join a room.
  2. The backend’s LIVEKIT_URL, API key, and secret match the LiveKit server; a mismatch produces token or room-service failures.
  3. A web-harness build, if deployed, has the same backend origin and is listed in PETAL_ALLOWED_ORIGINS.

For backend-specific endpoint and local test details, see Backend API reference.