Dear Laravel Developers!

You are going to love me for this wonderful post!

Please feel free to buy me a coffee if you believe I saved you countless hours of research :-)

Having struggled for days on this issue, I decided to share my tips on setting up Laravel Websockets with a Self Signed Certificate and, without the use of pusher!

That's right, no monthly payments are needed, you will have your own free WebSocket server for FREE, how cool!

We are going to pass the Laravel installation, and instead, jump right away to the WebSocket stuff.

Remember that you have two ways of setting up your own websockets, either you build your own websocket server(we will not cover this as it is not needed) and use many server software for this, or you host your own Laravel websocket server and get the exact same result. We will go for the last solution as it is quick and easy.

QUICK QUICK!

If you came here because you tried to set up your WebSockets via SSL and struggle……well well, if you think you have everything setup right but the SSL is still not working try 2 things, you do not need to read the entire tutorial, just try the below solutions.

1)If you are on a VPS with supervisor, restart it as the paths of your SSL in your .ENV won't be cached otherwise, make sure you log as root via SSH and run these commands:

sudo service supervisord stop

sudo service supervisord start

sudo service supervisord status

If you are on a shared server, run this command:

php artisan websocket:serve

This should be enough to solve your SSL issue!

If you want the entire tutorial and would like to set up your websockets from scratch, here it is:

1)First, download this library:

https://beyondco.de/docs/laravel-websockets/getting-started/introduction


Run the 4 below commands to set it up:

composer require beyondcode/laravel-websockets
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"
php artisan migrate
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"



2)Install this library which will use the pusher script but reroute the communication to your own websocket server instead:

https://laravel.com/docs/8.x/broadcasting


Command:

composer require pusher/pusher-php-server



3)Add these variables in your .env:

PUSHER_APP_ID=your-pusher-app-id
PUSHER_APP_KEY=your-pusher-key
PUSHER_APP_SECRET=your-pusher-secret
PUSHER_APP_CLUSTER=mt1
BROADCAST_DRIVER=pusher



For the client-side, install Laravel echo + pusher js. Important note, yes we will use the pusher logic to push the communication to our own websockets(and not to pusher.com).

npm install --save-dev laravel-echo pusher-js



Add the code “in red” in your resources/js/app.js file:

window._ = require('lodash');

/**
 * We'll load jQuery and the Bootstrap jQuery plugin which provides support
 * for JavaScript based Bootstrap features such as modals and tabs. This
 * code may be modified to fit the specific needs of your application.
 */

try {
    window.Popper = require('popper.js').default;
    window.$ = window.jQuery = require('jquery');

    require('bootstrap');
} catch (e) {}

/**
 * We'll load the axios HTTP library which allows us to easily issue requests
 * to our Laravel back-end. This library automatically handles sending the
 * CSRF token as a header based on the value of the "XSRF" token cookie.
 */

window.axios = require('axios');

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';



/**
 * Echo exposes an expressive API for subscribing to channels and listening
 * for events that are broadcast by Laravel. Echo and event broadcasting
 * allows your team to easily build robust real-time web applications.
 */

import Echo from 'laravel-echo';

window.Pusher = require('pusher-js');

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: process.env.MIX_PUSHER_APP_KEY,
    cluster: process.env.MIX_PUSHER_APP_CLUSTER,
    forceTLS: true,
    wsHost: window.location.hostname,
    wsPort: 6001,
    wssPort: 6001,
    disableStats: true
});




4)In config/websockets.php, make sure you have the config set up this way:

'apps' => [
    [
        'id' => env('PUSHER_APP_ID'),
        'name' => env('APP_NAME'),
        'key' => env('PUSHER_APP_KEY'),
        'secret' => env('PUSHER_APP_SECRET'),
        'path' => env('PUSHER_APP_PATH'),
        'capacity' => null,
        'enable_client_messages' => false,//This is to allow communication between clients, I selected false as my app does not support this.
        'enable_statistics' => true,
    ],
],



5)Go here and generate a FREE SSL(add your domain name):

https://www.sslforfree.com/



You will get 2 files, something like:

1968979879_yourdomain.com.cert

1968979879_yourdomain.com.cert



Move these 2 files in your Laravel installation, create a new SSL folder as:

Laravel/ssl/

To give you an idea of the app structure, it should be like this:

Laravel/app

Laravel/config

Laravel/boostrap

Laravel/ssl/




6)Now this part made me lose days!!!!!!! Make sure you do not forget the double quotes on the path or the SSL won't be picked up!

Add these 2 variables in your .env:

LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT="/home/server-account-name/laravel/ssl/1968979879_yourdomain.com.cert"

LARAVEL_WEBSOCKETS_SSL_LOCAL_PK="/home/server-account-name/laravel/ssl/1968979879_yourdomain.com.cert"

Again, do not forget the double quotes or you will get stuck…. :-(




7)Now the server part………in order for your websockets to work, the command below must autostart when your server restarts:

php artisan websockets:serve


To make this happen automatically, you will have to ask your host if you can have access to the supervisor. Supervisor is a small software that runs in the background of your web server, it can restart automatically many processes by launching the command you tell to.



On Centos OS, you will find it here:

etc/supervisor.d




8)Make sure you have queues setup  in your Laravel app, queues will be used to keep track of jobs you send via the websockets requests.

To setup the queues on Laravel, follow this link:

https://laravel.com/docs/8.x/queues#introduction



To cut it short, I did this:

php artisan queue:table

php artisan migrate



The above will create a new table called “jobs” in your database.

In my .ENV file, I have setup the queue_connection variable to “database”

QUEUE_CONNECTION=database



Remember to always run these commands each time you change anything in your ENV file(copy/paste):

php artisan cache:clear
php artisan view:clear
php artisan config:clear
php artisan config:cache
php artisan route:cache




9)Create a new file called:

etc/supervisor.d/laravel-queues.ini



Paste the below code in it:

[program:laravel-queues-yourdomain]
command=/usr/bin/php /home/account-name/laravel/artisan queue:work
process_name =%(program_name)s_%(process_num)02d
numprocs=8 
priority=999 
autostart=true
autorestart=true 
startsecs=1
startretries=3
user=account-name(add your server domain acocunt name here)
stdout_logfile=/var/log/supervisor/laravel-supervisor-lqueues-yourdomain.log


[program:websockets-yourdomain] 
command=/usr/bin/php /home/account-name/laravel/artisan websockets:serve
numprocs=1
autostart=true
autorestart=true
user=account-name(add your server domain acocunt name here)



What will this do?

Supervisor will both start your Laravel queues and websocket server automatically.

Make sure supervisor restarts in order to register your new settings, here are the commands:

# Status of supervisor
sudo service supervisord status

# Start the service
sudo service supervisord start

# Stop the service
sudo service supervisord stop

# Restart the service
sudo service supervisord restart



10)You got the server set up, supervisor, your SSL.

Time to check if the installation is working by going to this URL:

https://your-domain-name.com/laravel-websockets




11)If you have followed my tutorial perfectly and still cannot start the test page.

Contact your hosting provider and ask them to open your server firewall on port TCP in and out 6001.

Restart the firewall and try again.

If you still struggle, verify that your SSL files are correct, in the right place with the right paths and that you have double quotes on their paths in your ENV file.

Finally, if you still experience a problem, empty your Laravel cache with the commands I added at the bottom of step 8.




12)Let's say that it is now working for you,

All you have to do now is create Laravel broadcast events and dispatch them to your database queue.

A broadcasting event will look like this:

message = $message;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel
     */
    public function broadcastOn()
    {
        return new Channel('chat');
    }
}



In your vue js front end, add a listener like that:

mounted() {
    Echo.channel('chat')
        .listen('ListingChat', () => {
            this.getMessages();
        })
},



What will happen is that when you dispatch a broadcasting event to the queue, the listener will be made aware that message XXX has been sent to channel ‘chat'(or whatever name you want to use).


Upon receiving the event, you can then trigger in your callback, a method “this.getMessages()” in this case, to start an ajax call(ie:get all the message of user id xxx in your table).

That's it!

I did all the hard work for you !!!!

Enjoy and remember, if you want to buy me a coffee, please feel free :-)