Example 3: Other Environments (VPS / Docker)
Example 3: Other Environments (Custom VPS / Docker / Self-Hosted)
If you deploy your Laravel application to a self-managed Linux VPS, Kubernetes, or Docker setup without Laravel Cloud or Forge, you need to configure Supervisor (for the background processes) and Nginx (to proxy WebSocket traffic to Laravel Reverb).
Step 1: Configure Supervisor for Queue Workers & Reverb
Install Supervisor (apt install supervisor) and create two process configurations in /etc/supervisor/conf.d/:
1. Chat Queue Worker (/etc/supervisor/conf.d/laravel-chat-worker.conf)
[program:laravel-chat-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/app/artisan queue:work redis --queue=chat,default --sleep=3 --tries=1 --timeout=120 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=3
redirect_stderr=true
stdout_logfile=/var/www/app/storage/logs/chat-worker.log
stopwaitsecs=130
(If you use Laravel Horizon, run a single command=php /var/www/app/artisan horizon daemon instead.)
2. Laravel Reverb Server (/etc/supervisor/conf.d/laravel-reverb.conf)
[program:laravel-reverb]
process_name=%(program_name)s
command=php /var/www/app/artisan reverb:start --host=127.0.0.1 --port=8080 --no-interaction
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/app/storage/logs/reverb.log
stopwaitsecs=60
Reload Supervisor to start both services:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start all
Step 2: Configure Nginx Reverse Proxy for WebSockets (/app & /apps)
Browsers connect to Laravel Reverb over wss://yourdomain.com/app/{REVERB_APP_KEY} on port 443, while your Laravel queue worker publishes events to https://yourdomain.com/apps/{REVERB_APP_ID}/events.
Add the following location blocks inside your HTTPS (listen 443 ssl) Nginx server block so WebSocket upgrade requests are forwarded to 127.0.0.1:8080:
# Proxy WebSocket connections (/app) and Reverb HTTP API calls (/apps)
location ~ ^/(app|apps) {
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_read_timeout 60s;
proxy_send_timeout 60s;
proxy_pass http://127.0.0.1:8080;
}
Reload Nginx after updating the configuration:
sudo nginx -t && sudo systemctl reload nginx
Step 3: Self-Hosted / CI Deployment Checklist
In your CI/CD pipeline (GitHub Actions, GitLab CI, Envoyer, or custom deploy script), run the following steps on each release:
# 1. Install PHP & JS dependencies and compile Vite assets (requires VITE_REVERB_* in .env)
composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader
npm ci && npm run build
# 2. Link public storage (for chat attachments) and run database migrations
php artisan storage:link
php artisan migrate --force
# 3. Cache Laravel configuration, routes, views, and events
php artisan optimize
# 4. Signal queue workers and Reverb to reload code on next cycle
php artisan queue:restart
php artisan reverb:restart