外部サービスPusherの代わりに代替オープンソースのlaravel-websocketsでbroadcastを使う。
websocket用に6001など、別途ポートを開きたくない場合nginxのSSL(443)からアクセスさせて
nginxのリバースプロキシでlaravel-Websockets(6001)にアクセスさせる。
1. laravel-websocketsを導入
composerコマンドで導入、vendor:publish
でmigrateファイルとconfigファイルをコピーする。
$ 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"
config/websockets.php
は編集なし。
config/broadcast.php
のpusherの要素が古い場合があるので更新しておく。
laravel9xだと以下のような感じ。
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'host' => env('PUSHER_HOST', 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com'),
'port' => env('PUSHER_PORT', 443),
'scheme' => env('PUSHER_SCHEME', 'https'),
'encrypted' => true,
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => env('PUSHER_SCHEME', 'https') === 'https',
],
'client_options' => [
// Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
],
],
これに合わせて.env
ファイルのPUSHER_*
系の値を追加or更新
# for pusherjs
#PUSHER_APP_ID=xxxxxx
#PUSHER_APP_KEY=yyyyyyyyyyyyyyyy
#PUSHER_APP_SECRET=zzzzzzzzzzzzzzzzzz
#PUSHER_APP_CLUSTER=ap3
# 以下はpuhserではそのまま
#PUSHER_HOST=
#PUSHER_PORT=443
#PUSHER_SCHEME=https
# for laravel-websockets
# ID、KEY、SECRETは1
# CLUSTERは初期値(mt1)
PUSHER_APP_ID=1
PUSHER_APP_KEY=1
PUSHER_APP_SECRET=1
# リバースプロキシーではhttp://127.0.0.1:6001/で待ち受けるため以下の設定
PUSHER_HOST=127.0.0.1
PUSHER_PORT=6001
PUSHER_SCHEME=http
PUSHER_APP_CLUSTER=mt1
laravel-websocketsを起動するにはphp artisan websocket:serve
コマンドなので
supervisorでデーモン化する。
--host=127.0.0.1
を指定してローカルIPで待ち受けるように設定。
numprocsは1でマルチプロセスにはしないようにする。
$ sudo vi /etc/supervisord.d/laravel-websocket.ini
[program:laravel-websocket-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/app/artisan websockets:serve --host=127.0.0.1
autostart=true
autorestart=true
user=root
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/html/app/storage/logs/laravel-websocket.log
ss -atn
などで6001ポートで待ち受けてるか確認。
2. ドメインを用意する。
例)
black.jp:laravelのbackend及びfrontendを実装するドメイン
socket.black.jp:websocket用のドメイン
ドメインに対応するIPアドレスの向き先を設定しておく。
3. nginxで各ドメインの設定を行う。
black.jpにはlaravelのドキュメントルートの設定
server {
listen 80;
server_name black.jp;
root /var/www/html/black.jp/public;
index index.php index.html index.htm;
access_log /var/log/nginx/black.jp/access.log main;
error_log /var/log/nginx/black.jp/error.log warn;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ^~ /.well-known/acme-challenge/ {
root /var/www/html/letsencrypt;
}
location = /.well-known/acme-challenge/ {
return 404;
}
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name black.jp;
charset utf-8;
access_log /var/log/nginx/black.jp/access.log main;
error_log /var/log/nginx/black.jp/error.log warn;
root /var/www/html/black.jp/public;
index index.php index.html index.htm;
ssl_protocols TLSv1.3 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDH !aNULL !eNULL !SSLv2 !SSLv3';
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_certificate /etc/letsencrypt/live/black.jp/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/black.jp/privkey.pem;
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ^~ /.well-known/acme-challenge/ {
root /var/www/html/letsencrypt;
}
location = /.well-known/acme-challenge/ {
return 404;
}
location / {
index index.php index.html index.htm;
try_files $uri $uri/ /index.php?$query_string;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /$document_root$fastcgi_script_name;
include fastcgi_params;
}
}
socket.black.jpのnginxのconfは
ssl_certificateとssl_certificate_keyは後述のcertbotコマンドで生成するパスとなるため
コメント化、httpsへのリダイレクトもコメント化しておく。
server {
listen 80;
listen [::]:80;
server_name socket.black.jp;
root /var/www/html/black.jp/public;
index index.php index.html index.htm;
access_log /var/log/nginx/black.jp/access.log main;
error_log /var/log/nginx/black.jp/error.log warn;
location ^~ /.well-known/acme-challenge/ {
root /var/www/html/letsencrypt;
}
location = /.well-known/acme-challenge/ {
return 404;
}
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name socket.black.jp;
access_log /var/log/nginx/black.jp/access.log main;
error_log /var/log/nginx/black.jp/error.log warn;
root /var/www/html/black.jp/public;
index index.php index.html index.htm;
ssl_protocols TLSv1.3 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDH !aNULL !eNULL !SSLv2 !SSLv3';
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_certificate /etc/letsencrypt/live/black.jp/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/black.jp/privkey.pem;
location ^~ /.well-known/acme-challenge/ {
root /var/www/html/letsencrypt;
}
location = /.well-known/acme-challenge/ {
return 404;
}
# ここからlaravel-websocketsへのリバースプロキシーの設定
location / {
proxy_pass http://127.0.0.1:6001; #could be localhost if Echo and NginX are on the same box
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-VerifiedViaNginx yes;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
# Allow the use of websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
4. Let's encryptでドメインのSSL証明書を発行
# certbot certonly --webroot -w /var/www/html/letsencrypt -d black.jp -d socket.black.jp
コマンド実行し、SSL証明書が生成されたら、httpsへのリダイレクトと
ssl_certificateとssl_certificate_keyのコメントを解除し、systemctl reload nginx
する。
他の端末などからopensslコマンドで証明書が有効か確認
$ openssl s_client -connect socket.black.jp:443 -showcerts
5. Laravel-Echo(Js側)の設定
bootstrap.js
を書き換える。
laravel-echoはWebsocketのラッパーライブラリで外部サービスpusherとablyに対応している。
pusher互換のwebsocketとして
laravel-websockets、soketiもある。
利用する場合は別途pusher-jsも必要。
socket.io
の場合はsocket-io-client
が必要。
pusher互換のwebsocketの場合は、broadcaster: 'pusher'
、
socket.ioの場合はbroadcaster: 'socket-io'
wsHostとwssHostで自前のサーバのドメインとポートを指定する。
(略)
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: 'socket.black.jp',
wssPort: 443
});
次に試すこと
リバースプロキシを使わずに別ポート(6001)から直接アクセス