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.
Architecture
Section titled “Architecture”You need three pieces:
- 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. - 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/nodehandlers inbackend/api/. - 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.
1. Configure LiveKit
Section titled “1. Configure LiveKit”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-secretHere 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.comLIVEKIT_API_KEY=petal_keyLIVEKIT_API_SECRET=replace-with-a-long-random-secretLIVEKIT_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.
2. Deploy backend/
Section titled “2. Deploy backend/”Vercel
Section titled “Vercel”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:
cd backendnpm installvercel --prodThe 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.comNative 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_TOKENenables the protected/api/adminkick/close operations.SENTRY_DSNenables backend error reporting.BLOB_READ_WRITE_TOKENenables/api/updaterand/api/downloadfor 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.
3. Build the desktop client
Section titled “3. Build the desktop client”apps/desktop/src-tauri/build.rs reads PETAL_BACKEND_URL and embeds it in
the desktop binary. Set it when building from apps/desktop:
cd apps/desktopPETAL_BACKEND_URL=https://petal-backend.example.com npm run tauri buildUse 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:
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:
cd web-harnessVITE_PETAL_BACKEND_URL=https://petal-backend.example.com npm run buildFor 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.
Smoke check
Section titled “Smoke check”After deploying, verify that:
- A desktop build made with your
PETAL_BACKEND_URLcan create or join a room. - The backend’s
LIVEKIT_URL, API key, and secret match the LiveKit server; a mismatch produces token or room-service failures. - 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.