LoginSignup
3
1

More than 1 year has passed since last update.

さくらVPS(Rocky Linux) + laravel + Inetria(vue3)でbroadcastの実装メモ(laravel-websockets + SSL)

Posted at

外部サービス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だと以下のような感じ。

config/broadcast.php
        '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更新

.env
# 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のドキュメントルートの設定

/etc/nginx/conf.d/black.jp.conf
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へのリダイレクトもコメント化しておく。

/etc/nginx/conf.d/socket.black.jp.conf
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で自前のサーバのドメインとポートを指定する。

resources/js/boostrap.js
()
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)から直接アクセス

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1