Laravel Echo & socket.io with Apache over SSL connection

Hello, if you’re like me developing web apps time to time and just tried to dive into websockets and got stuck – here is some pieces of code to help you out! I spent a lot of time looking all over the net to find a good solution as a begginer and finally got it working! This post is also for myself so I don’t spend 10+ hours when I’ll need these settings again.

Laravel 5.8, Apache 2.4 (I think), Laravel Echo 1.3.6.

1. Apache settings

I’m assuming you already know how to find the .conf files Apache uses and how to edit them along with how to enable, disable sites and restart Apache server. If you don’t – google it.

First of all just check if your http redirect site .conf looks like this:

<VirtualHost *:80>
ServerAdmin admin@your_domain.com
DocumentRoot /your/site/root/
ServerName www.example.com

RewriteEngine On
  RewriteCond %{HTTPS} !=on
  RewriteRule ^/(.*) https://www.example.com/$1 [R,L]

</VirtualHost>

Don’t forget to adapt it to your site.

Second and most important one is you ssl site .conf file:

<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin admin@your_domain.com
DocumentRoot /your/site/root/
ServerName www.example.com
SSLEngine On

# Websocket proxy
# wss redirects to working ws protocol
#---THIS IS THE IMPORTANT BIT---
ProxyRequests off
ProxyVia on

RewriteEngine On
RewriteCond %{REQUEST_URI}  ^/socket.io            [NC]
RewriteCond %{QUERY_STRING} transport=websocket    [NC]
RewriteRule /(.*)           ws://localhost:6001/$1 [P,L]

ProxyPass        /socket.io/ ws://localhost:6001/socket.io
ProxyPassReverse /socket.io/ ws://localhost:6001/socket.io
#---------------------------------------------------------

<Directory /your/site/root>

#---IF YOU HAVE CORS ERRORS ADD THIS LINE TOO---
Header set Access-Control-Allow-Origin "*"
#-----------------------------------------------

Options FollowSymLinks
AllowOverride All
Order allow,deny
allow from all

</Directory>
ErrorLog /var/log/apache2/error_log
CustomLog /var/log/apache2/access_log common

SSLCertificateFile /your/cert/path/fullchain.pem
SSLCertificateKeyFile /your/cert/path/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

Don’t forget to change DocumentRoot and ServerName if you copy the whole file.

How this works is apache will redirect all requests for www.example.com/socket.io to Laravel Echo server with a proxy. You also have to have apache proxy and ws_proxy mods enabled (google how to do it).

DO NOT FORGET TO RESTART APACHE AFTER SAVING CHANGES.

2. Laravel Echo server settings

I’m running these setting and they work for me the best. My current echo version is 1.3.6 so they might be a little different for you (laravel-echo-server.json):

{
	"authHost": "https://www.example.com",
	"authEndpoint": "/broadcasting/auth",
	"clients": [
	],

 	"database": "redis",
  	"databaseConfig": {
	    "redis" : {
	      "host": "localhost"
	    },
    	"publishPresence": true
  	},

	"devMode": true,
	"host": null,
	"port": "6001",
	"protocol": "http",
	"socketio": {
	},
	"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"
	}
}

Do not forget to restart echo server after making changes.

3. Client-side Echo settings

My echo settings reside in resources/assets/js/bootstrap.js (nothing to do with bootstrap.css framework) and they look like this:


import Echo from "laravel-echo"

window.io = require('socket.io-client');

if (typeof io !== 'undefined') {
	window.Echo = new Echo({    
		broadcaster: 'socket.io',    
		host: window.location.hostname,
		transports: ['websocket', 'polling', 'flashsocket']
	});
}

If you may notice there is no “+:6001” in the host parameter because we don’t need to add it to the host name anymore. The rewrite rule in Apache .conf file takes care of it.

If you are also using mixer don’t forget to run “npm run prod” or “npm run dev” to compile new js file and reload the page.

I hope this will also work for someone like me who was desperate to run socket.io over SSL.

Taip pat skaitykite