Realtime (Reverb + AJAX polling)
Most buyers can skip Reverb. Hirevia already works on shared hosting. Building reports and the notification bell update via short AJAX polling when Reverb is off. Only set up Reverb if you have a VPS/dedicated server and want instant push.
What this is (and is not)β
| This guide | App UI: βreport is readyβ, notification badge |
| Not this guide | Interview audio/video β that still goes browser β AI provider (OpenAI, Tavus, β¦) |
Two ways the UI can update:
| Method | You need | What the user sees |
|---|---|---|
| AJAX polling (default) | Nothing extra β works with `BROADCAST_CONNECTION=null` | Report βbuildingβ page and notification bell refresh every few seconds |
| Laravel Reverb (optional) | VPS + Reverb process + (usually) Nginx/Apache proxy | Same screens update the moment scoring finishes |
Polling pauses when the browser tab is hidden, and stops if Reverb connects successfully (so the app does not double-load).
Reverb is optional. Interviews, scoring, email, cron, and reports work without it. On shared hosting, leave broadcasting as null β polling still updates building reports and the inbox badge without a WebSocket process. Check Admin β Health β Realtime broadcasting.
Shared hosting (cPanel, etc.) β recommended defaultβ
Do not try to run Reverb on typical shared hosting. Hosts usually block long-running processes and WebSocket ports.
-
Open your Hirevia
`.env`file (in the app root β same folder as`artisan`) -
Find
`BROADCAST_CONNECTION`and set:BROADCAST_CONNECTION=null -
Save the file.
-
Open Admin β Health β Clear Cache (so Laravel reloads
`.env`). Realtime broadcasting can show as off β that is expected. -
Open Admin β Health. Realtime broadcasting can show as off β that is expected.
-
Confirm CRON is running so reports still finish building.
You are done. Users still get updates via polling.
Do I need Reverb?β
| Your hosting | Recommendation |
|---|---|
| Shared / cPanel | Leave Reverb off (polling) |
| VPS, dedicated, Docker, Cloudways βVPS-likeβ | Optional β follow the setup below for instant push |
| Local laptop for development | Optional β see βLocal developmentβ at the end |
Production setup on a VPS (full walkthrough)β
You will:
- Decide your public website domain (example:
`hirevia.example.com`). - Edit
`.env`so browsers know where to connect. - Keep Reverb running in the background (Supervisor or systemd).
- Tell Nginx (or Apache) to forward WebSocket traffic to Reverb.
- Check Health and do a test interview.
Replace every example path and domain with your values.
SSH into the serverβ
Use your hostβs SSH (Terminal / Putty). Go to the Hirevia app folder (the folder that contains artisan):
cd /var/www/hirevia
Your path might look like /home/username/hirevia or /var/www/html β use the real path.
Understand REVERB_HOST (important)β
Reverb is a small program that listens on the server (often port 8080).
Visitorsβ browsers cannot safely talk to 127.0.0.1 on your server β that address means βthis computerβ on their laptop.
So in production you normally:
- Keep Reverb listening on the server at
127.0.0.1:8080. - Put Nginx/Apache in front on your real domain with HTTPS.
- Set
REVERB_HOSTto that public domain (what people type in the browser).
Visitor browser
β wss://hirevia.example.com (port 443, HTTPS)
βΌ
Nginx / Apache on your VPS
β forwards WebSocket to 127.0.0.1:8080
βΌ
php artisan reverb:start (Reverb)
SettingLocal laptopProduction behind NginxREVERB_HOST````localhost````hirevia.example.com (your domain)REVERB_PORT````8080````443````REVERB_SCHEME````http````https
Edit .envβ
Open .env in the app root. Enable broadcasting and set Reverb values.
Generate random keys (do this once). In SSH, from the app folder:
php -r "echo bin2hex(random_bytes(16)), PHP_EOL;"
php -r "echo bin2hex(random_bytes(16)), PHP_EOL;"
Use the first line as REVERB_APP_KEY and the second as REVERB_APP_SECRET (or any long random strings).
Example production block (change the domain to yours):
BROADCAST_CONNECTION=reverb
REVERB_APP_ID=100000
REVERB_APP_KEY=paste-first-random-string-here
REVERB_APP_SECRET=paste-second-random-string-here
# Public hostname browsers use (your site domain β NOT 127.0.0.1)
REVERB_HOST=hirevia.example.com
REVERB_PORT=443
REVERB_SCHEME=https
# Keep these equal to the REVERB_* values above (for local asset builds)
VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="${REVERB_HOST}"
VITE_REVERB_PORT="${REVERB_PORT}"
VITE_REVERB_SCHEME="${REVERB_SCHEME}"
Save the file.
Clear cache (Admin)β
- Sign in to Hirevia as an admin.
- Open Admin β Health.
- Click Clear Cache.
That clears config, routes, views, and application cache so the new
.envvalues load. You do not need SSH orphp artisan config:clearfor this.
Keep Reverb running in the backgroundβ
php artisan reverb:start dies when you close SSH if you run it in the foreground. Use Supervisor or systemd.
Option A β Supervisorβ
- Paste (change paths and
userto match your server): - Install Supervisor if needed (
sudo apt install supervisoron Ubuntu). - Create a config file, e.g.
/etc/supervisor/conf.d/hirevia-reverb.conf.
[program:hirevia-reverb]
process_name=%(program_name)s
command=php /var/www/hirevia/artisan reverb:start
directory=/var/www/hirevia
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/hirevia/storage/logs/reverb.log
stopwaitsecs=3600
PlaceholderWhat to put/var/www/hireviaFull path to your Hirevia folderuser=www-dataThe Linux user that owns the site (sometimes ubuntu, nginx, or your cPanel-style user on a VPS)command=php ...Use the same PHP binary as the site if php alone is wrong (e.g. /usr/bin/php8.3)
Load and start:β
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start hirevia-reverb
sudo supervisorctl status hirevia-reverb
You want status RUNNING.
Option B β systemdβ
Create /etc/systemd/system/hirevia-reverb.service:
[Unit]
Description=Hirevia Laravel Reverb
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/hirevia
ExecStart=/usr/bin/php /var/www/hirevia/artisan reverb:start
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Enable and start:β
sudo systemctl daemon-reload
sudo systemctl enable --now hirevia-reverb
sudo systemctl status hirevia-reverb
You want active (running).
Quick test only (not for production)β
cd /var/www/hirevia
nohup php artisan reverb:start > storage/logs/reverb.log 2>&1 &
This can stop after reboot. Prefer Supervisor or systemd.
Reverse-proxy WebSockets (Nginx)β
Visitors connect to HTTPS on your domain. Nginx forwards that traffic to Reverb on 127.0.0.1:8080.
- Open your siteβs Nginx config (often
/etc/nginx/sites-available/hireviaor similar). - Inside the
server { ... }block that already serves Hirevia on443, add a location for Reverbβs app key path or proxy all Laravel WebSocket upgrades. A common pattern:# Inside your existing HTTPS server block for hirevia.example.com``location /app {proxy_http_version 1.1;proxy_set_header Host $http_host;proxy_set_header Scheme $scheme;proxy_set_header SERVER_PORT $server_port;proxy_set_header REMOTE_ADDR $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "Upgrade";proxy_pass http://127.0.0.1:8080;``}Laravel Echo / Reverb typically connects under a path like/app/.... If your panel uses a different Reverb path, keep the sameproxy_passto127.0.0.1:8080and preserve theUpgrade` / `Connectionheaders β those are what make WebSockets work. - Test and reload Nginx:
sudo nginx -t``sudo systemctl reload nginxApache (if you use Apache instead of Nginx), enable proxy modules and something like:ProxyPreserveHost On``RequestHeader set X-Forwarded-Proto "https"``ProxyPass /app ws://127.0.0.1:8080/app``ProxyPassReverse /app ws://127.0.0.1:8080/app``ProxyPass /app http://127.0.0.1:8080/app``ProxyPassReverse /app http://127.0.0.1:8080/app(Exact Apache module names:proxy,proxy_http, ``proxy_wstunnel.)
Firewallβ
Reverb itself can stay bound to localhost (127.0.0.1:8080). You usually do not open port 8080 to the public internet. Visitors use 443 (HTTPS) only; Nginx talks to 8080 privately.
Verify it worksβ
- On the report page while it says Building, it should flip to ready without a manual refresh (instant with Reverb; within a few seconds with polling if Reverb is down).
- Admin β Health β Realtime broadcasting should look OK when
BROADCAST_CONNECTION=reverband the app key is set. - Open the site in a normal browser (not only SSH).
- Start a short practice interview / question run and wait for scoring.
- Trigger a notification (e.g. support reply if enabled) and watch the bell. If push fails but polling still updates within ~5 seconds, Reverb/proxy/env is wrong β the app is still usable.
Turn Reverb off againβ
In `.env`:
BROADCAST_CONNECTION=null
Then open Admin β Health β Clear Cache.
Stop the background process if you started one:
sudo supervisorctl stop hirevia-reverb
# or
sudo systemctl stop hirevia-reverb
Polling keeps working for reports and notifications.
Local development (optional)β
On your laptop:
BROADCAST_CONNECTION=reverb
REVERB_HOST=localhost
REVERB_PORT=8080
REVERB_SCHEME=http
Start Reverb in a second terminal:
php artisan reverb:start
Or use `composer run dev` / `php artisan dev` if your project already starts Reverb with the app.
Leave that terminal open while you test. Closing it stops Reverb (fine for local).
Troubleshootingβ
| Problem | What to check |
|---|---|
| Health says realtime off | `.env` has `BROADCAST_CONNECTION=reverb`, keys filled, then Admin β Health β Clear Cache |
| Browser cannot connect / console WebSocket errors | `REVERB_HOST` is your public domain, `REVERB_PORT=443`, `REVERB_SCHEME=https`; Nginx has `Upgrade` headers; Reverb process is running |
| Works on laptop, fails on server | You left REVERB_HOST=localhost on production β change to the real domain |
| Process dies after SSH logout | Use Supervisor or systemd (Step 5), not a bare reverb:start |
| Shared host kills Reverb | Expected β set BROADCAST_CONNECTION=null and rely on polling |
| Report stuck on Building forever | That is usually cron/queue, not Reverb β see CRON job |
Relatedβ
{% content-ref url="../reference/cron-job" %} cron-job.md {% endcontent-ref %}
{% content-ref url="reports-and-sharing" %} reports-and-sharing.md {% endcontent-ref %}
{% content-ref url="/hirevia/reference/troubleshooting" %} Broken link {% endcontent-ref %}
{% content-ref url="access-and-health" %} access-and-health.md {% endcontent-ref %}