# Socket Functionality Setup Guide

## 📋 Overview

This guide covers the **production deployment steps** needed to enable real-time WebSocket functionality using Laravel Reverb. This assumes your Laravel backend and Next.js frontend projects are already set up locally and you're deploying to production.

**What this guide covers:**

-   Setting up Redis (if not already installed)
-   Pulling latest code from repository
-   Installing Composer dependencies (including laravel/reverb from composer.json)
-   Configuring and encrypting environment variables
-   Setting up PM2 and starting Reverb WebSocket server
-   Optional Apache proxy configuration (update `000-default.conf` and `000-default-le-ssl.conf` in `/etc/apache2/sites-available/`)
-   Testing and troubleshooting

**Note:** This is a production deployment guide. The `laravel/reverb` package should already be in your `composer.json` file from local development.

---

## ✅ Prerequisites

Before starting, ensure:

-   ✅ Laravel backend is already running in production
-   ✅ Next.js frontend (Driver portal) is already deployed
-   ✅ SSH access to production server
-   ✅ Composer and PHP 8.1+ installed
-   ✅ Node.js and npm installed (required for PM2)
-   ✅ Domain name and SSL certificate configured

---

## 🔴 Step 1: Install and Configure Redis

### Check if Redis is Already Installed

```bash
redis-cli ping
```

If it returns `PONG`, Redis is already installed. Skip to **Step 2**.

### Install Redis (if not installed)

```bash
sudo apt-get update
sudo apt-get install redis-server -y
sudo systemctl start redis-server
sudo systemctl enable redis-server
```

### Configure Redis

Edit `/etc/redis/redis.conf`:

```bash
sudo nano /etc/redis/redis.conf
```

**Update these settings:**

```conf
# Bind to localhost only (security)
bind 127.0.0.1

# Set password (recommended)
requirepass your-strong-redis-password-here

# Memory management
maxmemory 256mb
maxmemory-policy allkeys-lru
```

**Restart Redis:**

```bash
sudo systemctl restart redis-server
```

**Test connection:**

```bash
redis-cli -a your-strong-redis-password-here ping
# Should return: PONG
```

---

## 📥 Step 2: Pull Latest Code

Pull the latest code from your repository:

```bash
cd /var/www/html/PremiereWarehousing
git pull origin master  # or your master branch name
```

**Note:** Make sure `laravel/reverb` is already in your `composer.json` file. If not, add it locally and commit before pulling.

---

## 📦 Step 3: Install Composer Dependencies

Install all dependencies including `laravel/reverb` (which should already be in `composer.json`):

```bash
cd /var/www/html/PremiereWarehousing/PremiereWarehousingBackend
composer install
```

**Note:** This will install all dependencies from `composer.json`, including `laravel/reverb` if it's listed there.

---

## ⚙️ Step 4: Publish Reverb Configuration (First Time Only)

If this is the first time setting up Reverb on this server, publish the configuration:

```bash
cd /var/www/html/PremiereWarehousing/PremiereWarehousingBackend
php artisan reverb:install
```

This command will:

-   Create `config/reverb.php` configuration file (if it doesn't exist)
-   Generate Reverb application keys (APP_ID, APP_KEY, APP_SECRET)
-   Update `config/broadcasting.php` if needed

**Important:** Copy the generated keys to your `.env` file (see Step 5).

**Note:** If `config/reverb.php` already exists, you can skip this step.

---

## ⚙️ Step 5: Configure Environment Variables

### Backend `.env` Configuration

**File**: `/var/www/html/PremiereWarehousing/PremiereWarehousingBackend/.env`

**Add/Update these variables:**

```env
# Broadcasting Configuration
# IMPORTANT: Set to 'null' during setup to avoid errors
# Change to 'reverb' after all configuration is complete
BROADCAST_CONNECTION=null

# Reverb Configuration
# Generate keys using: php artisan reverb:install
REVERB_APP_ID=your-production-app-id
REVERB_APP_KEY=your-production-app-key
REVERB_APP_SECRET=your-production-app-secret

# Reverb Host Configuration
# REVERB_HOST is used by WebSocket clients (frontend) - use your public domain
REVERB_HOST=api.premierwarehousingservices.com
REVERB_PORT=8080
REVERB_SCHEME=https

# Reverb Server Configuration (internal - for the Reverb server process)
REVERB_SERVER_HOST=0.0.0.0
REVERB_SERVER_PORT=8080

# Reverb HTTP Broadcasting Configuration (optional - for production)
# These are used by Laravel to send HTTP requests to Reverb server
# In production, Laravel uses localhost to connect to Reverb (same machine)
# Only set these if you need to override the defaults
# REVERB_HTTP_HOST=127.0.0.1
# REVERB_HTTP_PORT=8080

# Redis Configuration
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=your-strong-redis-password-here
REDIS_PORT=6379
REDIS_DB=0
```

**Important Notes:**

-   **During setup, set `BROADCAST_CONNECTION=null`** to prevent errors while configuring
-   Change `BROADCAST_CONNECTION=reverb` only after all configuration is complete
-   `REVERB_HOST` is the **public domain** used by WebSocket clients (frontend) to connect
-   In production, Laravel automatically uses `localhost:8080` for HTTP broadcasting (configured in `config/broadcasting.php`)
-   `REVERB_SERVER_HOST` and `REVERB_SERVER_PORT` are for the Reverb server process itself

**Encrypt Environment Values:**

This project uses encrypted environment values. After setting the values in `.env`, encrypt them.

**Environment keys that need to be encrypted:**

-   `REVERB_APP_ID`
-   `REVERB_APP_KEY`
-   `REVERB_APP_SECRET`
-   `REDIS_PASSWORD`

**Final Step - Enable Broadcasting:**

After all values are encrypted and configuration is complete, update `.env`:

```env
BROADCAST_CONNECTION=reverb
```

Then clear and cache the configuration:

```bash
php artisan config:clear
```

---

### Frontend Environment Variables

**File**: `/var/www/html/PremiereWarehousing/PremiereWarehousingDriver/.env.production`

**Add these variables:**

```env
# Reverb WebSocket Configuration
NEXT_PUBLIC_REVERB_HOST=your-production-domain.com
NEXT_PUBLIC_REVERB_PORT=8080
NEXT_PUBLIC_REVERB_APP_KEY=your-production-reverb-app-key
```

**Important:**

-   `NEXT_PUBLIC_REVERB_HOST` must be **ONLY the hostname** (no `https://` or `http://` prefix)
    -   ✅ Correct: `api.premierwarehousingservices.com`
    -   ❌ Wrong: `https://api.premierwarehousingservices.com`
-   `NEXT_PUBLIC_REVERB_APP_KEY` must match `REVERB_APP_KEY` in backend `.env`
-   If using Apache proxy, set `NEXT_PUBLIC_REVERB_PORT=443` (see Step 7)
-   If connecting directly, set `NEXT_PUBLIC_REVERB_PORT=8080`
-   Rebuild frontend after updating: `npm run build`

---

## 🚀 Step 6: Setup PM2 and Start Reverb

### Install PM2 (if not already installed)

**Check if PM2 is installed:**

```bash
pm2 --version
```

If it shows a version number, PM2 is installed. Skip to **Create PM2 Ecosystem File**.

**Install PM2 globally:**

```bash
sudo npm install -g pm2

# Verify installation
pm2 --version  # Should show version number
```

**Setup PM2 to start on system boot:**

```bash
# Generate startup script (follow the instructions it provides)
pm2 startup

# This will output a command like:
# sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u your-username --hp /home/your-username
# Copy and run that command
```

**Verify PM2 is working:**

```bash
pm2 list  # Should show empty list or existing processes
pm2 --version
```

### Create PM2 Ecosystem File

**Important:** The file must be named `ecosystem.config.cjs` (not `.js`) because your project uses ES modules (`"type": "module"` in `package.json`).

Create `ecosystem.config.cjs` in backend directory:

```bash
cd /var/www/html/PremiereWarehousing/PremiereWarehousingBackend
nano ecosystem.config.cjs
```

**Content:**

```javascript
module.exports = {
    apps: [
        {
            name: "reverb",
            script: "php",
            args: "artisan reverb:start",
            cwd: "/var/www/html/PremiereWarehousing/PremiereWarehousingBackend",
            interpreter: "none",
            instances: 1,
            autorestart: true,
            watch: false,
            max_memory_restart: "1G",
            error_file: "./storage/logs/reverb-error.log",
            out_file: "./storage/logs/reverb-out.log",
            log_date_format: "YYYY-MM-DD HH:mm:ss Z",
            merge_logs: true,
            env: {
                APP_ENV: "production",
            },
        },
    ],
};
```

**Important Notes:**

-   File must be `ecosystem.config.cjs` (CommonJS extension) because `package.json` has `"type": "module"`
-   `cwd` must point to the **backend directory**, not the parent directory
-   Log files will be created in `storage/logs/` directory

### Start Reverb with PM2

```bash
cd /var/www/html/PremiereWarehousing/PremiereWarehousingBackend
pm2 start ecosystem.config.cjs --only reverb
pm2 save
```

**Note:** If you haven't run `pm2 startup` yet, do it now:

```bash
pm2 startup
# Follow the instructions it provides to enable PM2 on system boot
```

### Verify Reverb is Running

```bash
pm2 status reverb
# Should show: online

pm2 logs reverb
# Check for any errors
```

---

## 🌐 Step 7: Configure Apache Proxy (Optional)

**Note:** This step is optional. You can connect directly to port 8080, but using Apache proxy provides SSL termination and a single port.

### Enable Apache Modules

```bash
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
sudo a2enmod rewrite
sudo systemctl restart apache2
```

### Update Apache Virtual Host

**Location**: `/etc/apache2/sites-available/`

**Files to update:**

-   `000-default.conf` (HTTP)
-   `000-default-le-ssl.conf` (HTTPS / SSL)

Add the following WebSocket proxy configuration inside each `<VirtualHost>` block:

```apache
ProxyPreserveHost On
ProxyRequests Off

# WebSocket upgrade
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^/app/(.*)$ ws://127.0.0.1:8080/app/$1 [P,L]

# Fallback for HTTP polling
ProxyPass /app http://127.0.0.1:8080/app
ProxyPassReverse /app http://127.0.0.1:8080/app
```

**Notes:**

-   The `/app/` path is the WebSocket endpoint (not a physical folder) - Laravel Reverb uses this by default
-   The `RewriteRule` runs first (`[L]`) and proxies WebSocket upgrade requests to Reverb
-   `ProxyPass` / `ProxyPassReverse` handle fallback HTTP polling to the same `/app` path
-   If your API is served from the same host, ensure Laravel routes are not under `/app` so they are not proxied

**Restart Apache:**

```bash
sudo systemctl restart apache2
```

**Update frontend `.env.production`:**

```env
NEXT_PUBLIC_REVERB_HOST=your-production-domain.com
NEXT_PUBLIC_REVERB_PORT=443
```

**Rebuild frontend:**

```bash
cd /var/www/html/PremiereWarehousing/PremiereWarehousingDriver
npm run build
```

---

## 🔒 Step 8: Configure AWS Security Group

### Add Inbound Rule for Reverb

1. Go to **AWS Console → EC2 → Security Groups**
2. Select your backend server's security group
3. Add inbound rule:

| Type       | Protocol | Port Range | Source               | Description      |
| ---------- | -------- | ---------- | -------------------- | ---------------- |
| Custom TCP | TCP      | 8080       | Your IP or 0.0.0.0/0 | Reverb WebSocket |

**Note:** If using Apache proxy, you can restrict port 8080 to localhost only (127.0.0.1/32).

---

## 🧪 Step 9: Test Socket Functionality

### Test Checklist

1. **Verify Reverb is Running:**

    ```bash
    pm2 status reverb
    # Should show: online
    ```

2. **Check Redis Connection:**

    ```bash
    redis-cli -a your-password ping
    # Should return: PONG
    ```

3. **Test WebSocket Connection:**

    - Open Driver portal in browser
    - Open browser DevTools → Console
    - Check for WebSocket connection success
    - Look for: "Connected" or similar messages
    - No connection errors should appear

4. **Test Real-Time Updates:**

    - Open Driver portal
    - Create a new schedule in Admin/Manager portal
    - Verify schedule appears in Driver portal **automatically** (without refresh)
    - Test update: Modify schedule in Admin portal
    - Verify update appears in Driver portal automatically
    - Test delete: Delete schedule in Admin portal
    - Verify it disappears from Driver portal automatically

5. **Test Error Handling:**
    - Stop Reverb: `pm2 stop reverb`
    - Create/update schedule in Admin portal
    - Verify API still returns success (operation should not fail)
    - Check logs: `tail -f storage/logs/laravel.log | grep "Failed to broadcast"`
    - Should see warning (not error)
    - Restart Reverb: `pm2 start reverb`
    - Verify real-time updates resume

---

## 🐛 Troubleshooting

### Issue: Errors During Setup or Configuration

**If you're getting errors while setting up Reverb:**

1. **Set `BROADCAST_CONNECTION=null` in `.env`** during initial setup
2. Complete all configuration steps (encrypt values, etc.)
3. Only change to `BROADCAST_CONNECTION=reverb` after everything is configured
4. Clear config cache: `php artisan config:clear && php artisan config:cache`

**If encryption commands fail:**

-   Make sure you've set the values in `.env` first (before encrypting)
-   Verify the artisan command exists: `php artisan list | grep encrypt`
-   Check file permissions on `.env`

### Issue: Reverb Not Starting

**Check logs:**

```bash
pm2 logs reverb
php artisan reverb:start  # Run directly to see errors
```

**Common causes:**

-   Port 8080 already in use: `sudo lsof -i :8080`
-   Redis not running: `sudo systemctl status redis-server`
-   Invalid configuration: Check `.env` values
-   Missing PHP Redis extension: `php -m | grep redis`
-   Encrypted values not properly set: Verify encryption was successful

**Solutions:**

```bash
# Kill process on port 8080
sudo kill -9 $(sudo lsof -t -i:8080)

# Restart Redis
sudo systemctl restart redis-server

# Install PHP Redis extension (if missing)
sudo apt-get install php-redis
sudo systemctl restart php8.1-fpm  # or your PHP version
```

---

### Issue: WebSocket Connection Refused

**Check:**

1. Reverb is running: `pm2 status reverb`
2. Security Group allows port 8080
3. Firewall allows port 8080: `sudo ufw status`
4. Reverb host/port in `.env` matches frontend config
5. SSL certificate valid (if using HTTPS)

**Test connection:**

```bash
curl -i -N -H "Connection: Upgrade" \
  -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Version: 13" \
  -H "Sec-WebSocket-Key: test" \
  http://localhost:8080/app/your-app-key
```

**Debug frontend:**

-   Open browser DevTools → Network tab
-   Filter by WS (WebSocket)
-   Check connection status
-   Look for 401 (auth failed) or 403 (forbidden) errors

---

### Issue: Events Not Received

**Debug steps:**

1. **Check Redis pub/sub:**

    ```bash
    redis-cli -a your-password monitor
    # Watch for broadcast messages when creating/updating schedules
    ```

2. **Check Reverb logs:**

    ```bash
    pm2 logs reverb
    ```

3. **Verify channel name:**

    - Backend: `schedule.location.{locationId}`
    - Frontend: `schedule.location.${locationId}`

4. **Check browser console:**

    - Authentication errors
    - Connection errors
    - Channel subscription errors

5. **Test authentication endpoint:**
    ```bash
    curl -X POST https://your-api-domain.com/api/broadcasting/auth \
      -H "Authorization: Bearer YOUR_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"channel_name":"private-schedule.location.1"}'
    ```

---

### Issue: High Memory Usage

**Monitor:**

```bash
pm2 monit
redis-cli -a your-password info memory
```

**Solutions:**

-   Restart Reverb: `pm2 restart reverb`
-   Clear Redis if needed: `redis-cli -a your-password FLUSHDB` (careful!)
-   Check for memory leaks
-   Consider increasing EC2 instance size

---

## 📊 Monitoring Commands

### View Reverb Logs

```bash
# Real-time logs
pm2 logs reverb

# Last 100 lines
pm2 logs reverb --lines 100

# Error log file
tail -f storage/logs/reverb-error.log

# Output log file
tail -f storage/logs/reverb-out.log
```

### View Laravel Logs

```bash
tail -f storage/logs/laravel.log | grep "broadcast"
```

### Monitor Redis

```bash
# Monitor commands
redis-cli -a your-password monitor

# Check memory
redis-cli -a your-password info memory

# Check connected clients
redis-cli -a your-password info clients
```

### PM2 Management

```bash
# Status
pm2 status reverb

# Restart
pm2 restart reverb

# Stop
pm2 stop reverb

# Monitor (CPU, Memory)
pm2 monit
```

---

## 🔄 Maintenance

### Restart Reverb

```bash
pm2 restart reverb
```

### Update Reverb Package

```bash
cd /var/www/html/PremiereWarehousing/PremiereWarehousingBackend
composer update laravel/reverb
pm2 restart reverb
```

### Clear Config Cache

```bash
php artisan config:clear
php artisan config:cache
```

---

## 📝 Quick Setup Checklist

**Prerequisites:**

-   [ ] Node.js and npm installed

**Deployment Steps:**

-   [ ] Redis installed and configured (Step 1)
-   [ ] Latest code pulled from repository (Step 2)
-   [ ] Composer dependencies installed: `composer install` (Step 3)
-   [ ] Reverb configuration published (first time only): `php artisan reverb:install` (Step 4)
-   [ ] Backend `.env` configured with `BROADCAST_CONNECTION=null` (Step 5)
-   [ ] Environment values encrypted: `REVERB_APP_ID`, `REVERB_APP_KEY`, `REVERB_APP_SECRET`, `REDIS_PASSWORD` (Step 5)
-   [ ] Backend `.env` updated with `BROADCAST_CONNECTION=reverb` (after encryption) (Step 5)
-   [ ] Frontend `.env.production` configured with Reverb settings (hostname only, no protocol) (Step 5)
-   [ ] Config cache cleared: `php artisan config:clear && php artisan config:cache` (Step 5)
-   [ ] PM2 installed (if not already installed) (Step 6)
-   [ ] `ecosystem.config.cjs` created in backend directory (Step 6)
-   [ ] Reverb started with PM2 (Step 6)
-   [ ] PM2 startup configured for system boot (Step 6)
-   [ ] AWS Security Group allows port 8080 (or Apache proxy configured) (Step 8)
-   [ ] Apache proxy configured: updated `000-default.conf` and `000-default-le-ssl.conf` in `/etc/apache2/sites-available/` (Step 7, optional)
-   [ ] WebSocket connection successful in browser (Step 9)
-   [ ] Real-time updates working (create, update, delete) (Step 9)
-   [ ] Error handling verified (API works when Reverb is down) (Step 9)

---

## 🎯 Quick Reference Commands

```bash
# Pull latest code
cd /var/www/html/PremiereWarehousing
git pull origin master  # or your master branch

# Install dependencies
cd /var/www/html/PremiereWarehousing/PremiereWarehousingBackend
composer install

# Encrypt environment values (run after setting values in .env)
# Encrypt: REVERB_APP_ID, REVERB_APP_KEY, REVERB_APP_SECRET, REDIS_PASSWORD
php artisan app:encrypt-env-value <ENV_KEY>

# Start Reverb
pm2 start ecosystem.config.cjs --only reverb

# Restart Reverb
pm2 restart reverb

# View logs
pm2 logs reverb

# Check status
pm2 status reverb

# Test Redis
redis-cli -a your-password ping

# Clear config
php artisan config:clear && php artisan config:cache
```

---

## 🔧 Important Configuration Notes

### Production vs Local Development

**In Production:**

-   Laravel automatically uses `localhost:8080` for HTTP broadcasting (configured in `config/broadcasting.php`)
-   WebSocket clients use the public domain (`REVERB_HOST`) to connect
-   This prevents 404 errors when Laravel tries to broadcast events

**In Local Development:**

-   Both HTTP broadcasting and WebSocket clients can use `localhost` or your local domain
-   Use `http://localhost:8080` for both

### Understanding REVERB_HOST

-   **`REVERB_HOST`**: Public domain used by WebSocket clients (frontend) to connect

    -   Example: `api.premierwarehousingservices.com`
    -   Used in frontend: `NEXT_PUBLIC_REVERB_HOST=api.premierwarehousingservices.com`

-   **HTTP Broadcasting**: Laravel uses `localhost:8080` in production (automatic, configured in `config/broadcasting.php`)
    -   This is why the broadcaster works in production without 404 errors

### File Naming: ecosystem.config.cjs

The PM2 ecosystem file must be named `ecosystem.config.cjs` (not `.js`) because:

-   Your `package.json` has `"type": "module"` which makes all `.js` files ES modules
-   PM2 config uses CommonJS syntax (`module.exports`)
-   The `.cjs` extension tells Node.js to treat it as CommonJS

---

## 📚 Additional Resources

-   **Implementation Details**: See `REALTIME_IMPLEMENTATION_PLAN.md`
-   [Laravel Reverb Documentation](https://laravel.com/docs/reverb)
-   [PM2 Documentation](https://pm2.keymetrics.io/docs/)
-   [Node.js Installation Guide](https://nodejs.org/en/download/package-manager)

---

**Socket functionality setup complete! 🚀**
