FlexPoint Docs
Engineering

Realtime (Laravel Reverb) Deployment

How to deploy and configure the Laravel Reverb WebSocket server on Forge and wire the Vercel-hosted Next.js frontend to it.

The admin "LOS Debug Logs" live stream is powered by Laravel Reverb, a WebSocket server that runs as a persistent daemon on the API host (Forge). The Next.js frontend (Vercel) connects to it with Laravel Echo over the pusher protocol; the private-channel auth handshake is proxied through the BFF (/api/broadcasting/auth) so the Sanctum token never reaches the browser.

Reverb cannot run on Vercel

Reverb is a long-lived daemon and must live on the API host (Forge). Vercel only serves the Next.js client that connects to it. The "Public hostname" you configure for Reverb is the Reverb server's own host on Forge — not the Vercel frontend URL.

The two halves

Reverb is configured in two places that must agree:

  • API (apps/flex-hub-api, Forge) — runs the Reverb daemon and the broadcast config.
  • Web (apps/flex-hub, Vercel) — the browser-side Echo client. Its NEXT_PUBLIC_REVERB_* values mirror the public-facing API values.

Two ports, two roles (do not confuse them)

VariableRoleProduction value
REVERB_SERVER_PORTThe local port the daemon binds to (behind Nginx).8080
REVERB_SERVER_HOSTThe interface it binds to.0.0.0.0
REVERB_PORTThe public port the browser connects to.443
REVERB_HOSTThe public hostname the browser connects to.your custom host
REVERB_SCHEMEThe public scheme (drives forceTLS).https

Nginx terminates TLS on 443 and reverse-proxies the WebSocket traffic to 127.0.0.1:8080. The browser never talks to 8080 directly.

Enabling Reverb on Forge

Use Forge's native "Enable Laravel Reverb" integration on the API site. It installs Reverb, creates the daemon (reverb:start), and extends the site's Nginx config with the WebSocket proxy (including the Upgrade/Connection headers) on the host you provide.

The modal asks for:

  • Public hostname — the address the browser opens the socket against. It must resolve (DNS) to this Forge server.
  • Port — the internal proxy target. Leave it 8080.
  • Max concurrent connections1000 is a reasonable default.

Forge domains are rejected

Forge will not accept a Forge-owned domain (*.on-forge.com) as the Reverb public hostname — it shows "You cannot use a Forge domain as the hostname for a Reverb instance." You must use a custom domain or subdomain you control (e.g. ws.example.com) with a DNS record pointing at the Forge server and a Let's Encrypt certificate issued for it.

API environment variables

apps/flex-hub-api/.env (on Forge). The APP_ID / APP_KEY / APP_SECRET are a self-generated shared secret between the app and its reverb:start process — not vendor credentials. Generate a set with php artisan reverb:install.

BROADCAST_CONNECTION=reverb

REVERB_APP_ID=          # digits
REVERB_APP_KEY=         # random string
REVERB_APP_SECRET=      # random string

# Public-facing — what the browser connects to.
REVERB_HOST=ws.example.com   # custom domain (NOT *.on-forge.com)
REVERB_PORT=443
REVERB_SCHEME=https

# Where the daemon binds (server-side, behind Nginx).
REVERB_SERVER_HOST=0.0.0.0
REVERB_SERVER_PORT=8080

# Leave blank when using Forge's native integration (it proxies the standard
# /app endpoints on the host). Only set this for a manual path-prefix proxy.
REVERB_SERVER_PATH=

# The browser origin allowed to open a socket — the Vercel frontend URL.
REVERB_ALLOWED_ORIGINS=https://app.example.com

REVERB_ALLOWED_ORIGINS is the one place Vercel appears

The Next.js app is cross-origin to the Reverb host, so its public URL must be listed here or the handshake is rejected. Do not leave it as * in production.

Web (Vercel) environment variables

apps/flex-hub reads these in src/lib/client/echo.ts. Each NEXT_PUBLIC_REVERB_* value mirrors the matching public API value.

Vercel variableMust equal (API)Production value
NEXT_PUBLIC_REVERB_KEYREVERB_APP_KEYbyte-identical to the API key
NEXT_PUBLIC_REVERB_HOSTREVERB_HOSTws.example.com
NEXT_PUBLIC_REVERB_PORTREVERB_PORT443
NEXT_PUBLIC_REVERB_SCHEMEREVERB_SCHEMEhttps
NEXT_PUBLIC_REVERB_PATHREVERB_SERVER_PATHblank (Forge integration)
API_BASE_URLyour Laravel API URL (powers /api/broadcasting/auth)

NEXT_PUBLIC_* are build-time

These are inlined at build time. After changing them you must trigger a fresh deploy (not a redeploy of an old build), and set them for the Production environment (and Preview if you test there). The APP_ID / APP_SECRET are server-side only — never add them to Vercel.

Verification checklist

  1. The Reverb daemon shows running in Forge's Daemons list.
  2. REVERB_HOST is a custom domain with a valid TLS cert, resolving to the Forge server.
  3. NEXT_PUBLIC_REVERB_KEY is byte-identical to REVERB_APP_KEY.
  4. REVERB_ALLOWED_ORIGINS includes the Vercel app URL.
  5. Both *_PATH vars are blank (Forge native integration).
  6. Loading the admin LOS Debug Logs page opens a wss:// connection to REVERB_HOST instead of degrading to the offline state.

When NEXT_PUBLIC_REVERB_KEY or NEXT_PUBLIC_REVERB_HOST is blank, the client returns null from reverbConfig() and realtime is disabled — the page degrades to an "offline" state rather than erroring.

On this page