2

My prod. stack:

  1. Vue.js CLI - https://example.com
  2. Laravel API - https://example.com/api

I've already created a real-time chat using laravel-echo server & socket.io on my localhost.
However, I want to run it on my production server. For that purpose I use nginx.

The problem is that when I run laravel-echo-server start it launches successfully but gives no response when I access my site from web browser. (No use joined)

I've already rebuilt vue app, cleared laravel cache and restarted nginx service.


At /etc/nginx/sites-enabled/default I have:

server {
    server_name example.com www.example.com;

    root /var/www/html/Example/api/public/;    
    index index.html index.php;

    location / {
        root /var/www/html/Example/web/dist/;
        try_files $uri $uri/ /index.html;
    }

    location /socket.io/ {
        proxy_pass http://localhost:6001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $host;
    }

    location /api {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.0-fpm.sock;
    }
}

My main.js file where I connect to web sockets:

import Echo from "laravel-echo"
window.io = require('socket.io-client')

window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: 'https://example.com/socket.io',
    auth: {
        headers: {
            'Authorization': `Bearer ${localStorage.getItem('token')}`
        }
    }
});

My laravel-echo.server.json:

{
    "authHost": "https://example.com/api",
    "authEndpoint": "/broadcasting/auth",
    "clients": [
        {
            appId: "xxxxx",
            key: "xxxxx"
        }
    ],
    "database": "redis",
    "databaseConfig": {
        "redis": {},
        "sqlite": {
            "databasePath": "/database/laravel-echo-server.sqlite"
        }
    },
    "devMode": false,
    "host": null,
    "port": "6001",
    "protocol": "http",
    "socketio": {},
    "secureOptions": 67108864,
    "sslCertPath": "",
    "sslKeyPath": "",
    "sslCertChainPath": "",
    "sslPassphrase": "",
    "subscribers": {
        "http": true,
        "redis": true
    },
    "apiOriginAllow": {
        "allowCors": true,
        "allowOrigin": "*",
        "allowMethods": "GET, POST",
        "allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id"
    }
}
Tyoma Inagamov
  • 125
  • 4
  • 13

2 Answers2

0

Try changing this host: 'https://example.com/socket.io' to host: 'https://example.com'

Ikechukwu
  • 1,135
  • 1
  • 13
  • 30
  • It's a bit strange that it didn't throw 404 or 502, but it does pretty much the same: no error, no response :( – Tyoma Inagamov Apr 25 '21 at 11:20
  • From this answer https://stackoverflow.com/a/56934080/5929919 the idea was to set it up when on `https`, but not over `https,` but to get `Apache` to redirect this `/socket.io` to `http://localhost:6001/socket.io` and basically the only difference from that answer is that I was using `web.php` and not `api.php` route. – Ikechukwu Apr 25 '21 at 12:11
  • Check the `laravel-echo-server.json` over that answer properly. `"protocol": "http",` but yours is `"protocol": "https",`. `"sslCertPath": "",` and `"sslKeyPath": "",` but on yours `"sslCertPath": "/etc/ssl/certs/nginx-selfsigned.crt",` and `"sslKeyPath": "/etc/ssl/private/nginx-selfsigned.key",` – Ikechukwu Apr 25 '21 at 12:14
  • I believe yours is configured for SSL. Your solution isn't exactly the same with that. That solution isn't configured for SSL. While your website must still bear an SSL, that solution is to get Apache to redirect `/socket.io` to `http://localhost:6001/socket.io` already configured for `redis`. Then use version `2.2.3` of `socket io` – Ikechukwu Apr 25 '21 at 12:19
  • If this solution works for you. Don't forget to mark both answers up and accept this. – Ikechukwu Apr 25 '21 at 12:28
  • Unfortunately, switching `laravel-echo` back to `http` didn't help. As far as I understand the problem is with `laravel-echo`. There are no errors in browser or console. `Laravel-echo` starts and then nothing happens: no joined users, no errors – Tyoma Inagamov Apr 25 '21 at 14:37
  • If it worked locally for you, then i doubt that is the problem. I just used my proposed solution for a different project last month – Ikechukwu Apr 25 '21 at 20:25
  • Yeah, I rechecked it on my local machine, it works.. I am in pain.. – Tyoma Inagamov Apr 25 '21 at 20:42
  • You just have to keep debugging. I hope you noted that I said I was using `web.php` instead. Carefully go through my answer, i have updated it to explain the concept and make sure that your `nginx` config is correct. I get how you feel, this initially took me 7 days and I was on my own to say the least. – Ikechukwu Apr 25 '21 at 20:46
  • I hope this helps, but it might also be possible to use `.htaccess` to do the redirects instead. I haven't tested it but it does redirect. https://stackoverflow.com/questions/65223369/updating-htaccess-file-with-new-contents-gives-errors – Ikechukwu Apr 25 '21 at 20:49
  • Then see if this https://stackoverflow.com/a/35767433/5929919 helps you with`.htacess` over `nginx`. But it's a dirty hack though – Ikechukwu Apr 25 '21 at 20:56
  • well, I am still trying. I've tried enormous amount of methods and I've noticed something interesting. If I go to the "example.com/socket.io" it gives me "Cannot GET /socket.io", however, if I do it locally at "localhost:6001" it gives me "OK". The problem might be somewhere here, but I don't know how to solve it. I've tried changing GET to POST, but it throws an error of 400 – Tyoma Inagamov May 19 '21 at 00:59
  • another thing I've notice is that if I run laravel-echo-server in dev mode, I can actually see all the events (as well as in `php artisan queue:listen --timeout=0`). But I don't see anything related to the authentication or joining. Any thoughts? – Tyoma Inagamov May 19 '21 at 01:01
-1

I kept the sites with normal https in the laravel-echo config, but I removed ssl rules such as certificate etc... and instead of pointing to localhost I pointed to the host ip changing only the ports:

{
    "authHost": "https://example.com/api",
    "authEndpoint": "/broadcasting/auth",
    "clients": [
        {
            appId: "xxxxx",
            key: "xxxxx"
        }
    ],
    "database": "redis",
    "databaseConfig": {
           "redis": {
                        "port": "6379",
                        "host": "127.0.0.1"
                },
        "sqlite": {
            "databasePath": "/database/laravel-echo-server.sqlite"
        }
    },
    "devMode": false,
    "host": 127.0.0.1,
    "port": "6001",
    "protocol": "http",
    "socketio": {},
    "secureOptions": 67108864,
    "sslCertPath": "",
    "sslKeyPath": "",
    "sslCertChainPath": "",
    "sslPassphrase": "",
    "subscribers": {
        "http": true,
        "redis": true
    },
    "apiOriginAllow": {
        "allowCors": true,
        "allowOrigin": "*",
        "allowMethods": "GET, POST",
        "allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id"
    }
}

add in ngnix:

        location /socket.io {
                proxy_pass http://127.0.0.1:6001;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "Upgrade";
        }

in the vue client:

    window.Echo = new Echo({
        broadcaster: 'socket.io',
        host: window.location.origin, // sem a porta
        auth: {
            headers: {
                Authorization: 'Bearer ' + bearerToken,
            }
        }
    });
David
  • 5,882
  • 3
  • 33
  • 44
Elisilva
  • 29
  • 1