前回は Nextcloud を AlmaLinux 9 + OpenLiteSpeed の環境にセットアップしました。

この Nextcloud に Talk アプリ(https://apps.nextcloud.com/apps/spreed)をインストールしたところ、高性能バックエンド(HPB: High Performance Backend)を設定するように促されました。

Nextcloud Talk は自前でチャットやビデオ通話の環境を持つことができるためとても重宝していますが、HPB を設定しないと 3 人以上のビデオ通話が不安定になってしまいます。
そこで今回は HPB を構築していきます。
環境
- OS: AlmaLinux release 9.5 (Teal Serval)
- ウェブサーバー: OpenLiteSpeed 1.8.3
- Nextcloud Hub 10(31.0.5)
- Nextcloud Talk 21.0.4
- ホスティング: ConoHa VPS(メモリ 2GB)
高性能バックエンドの構築
前回に引き続き Docker コンテナの All-in-One は使わず個別に設定をしていきます。
幸いにも Nextcloud 社公式パートナーの株式会社スタイルズから導入手順の例が公開されていますので、それに沿ってやっていく事にします。

coTURN
coTURN は、NAT やファイアウォールの背後に位置する端末間の IP 接続を確立するために必要な中継サーバである STUN(Session Traversal Utilities for NAT)/ TURN(Traversal Using Relays around NAT)サーバです。
coTURN のインストール
Enterprise Linux 9 では EPEL リポジトリに登録されていましたので、そこからインストールします。
dnf install coturn
(out) Dependencies resolved.
(out) ================================================================================
(out) Package Architecture Version Repository Size
(out) ================================================================================
(out) Installing:
(out) coturn x86_64 4.6.3-1.el9 epel 275 k
(out) Installing dependencies:
(out) hiredis x86_64 1.0.2-2.el9 epel 47 k
(out) libpq x86_64 13.20-1.el9_5 appstream 207 k
(out) Installing weak dependencies:
(out) telnet x86_64 1:0.17-85.el9 appstream 63 k
(out)
(out) Transaction Summary
(out) ================================================================================
(out) Install 4 Packages
(out)
(out) Total download size: 593 k
(out) Installed size: 2.2 M
(out) Is this ok [y/N]: ySSL 証明書の準備
coturn ユーザーから SSL 証明書を読み込めるよう、コピーして所有者を変更しておきます。
mkdir /etc/coturn/certs
chown coturn:coturn /etc/coturn/certs/
cp /etc/letsencrypt/live/example.com/fullchain.pem /etc/coturn/certs/
chown coturn:coturn /etc/coturn/certs/fullchain.pem
cp /etc/letsencrypt/live/example.com/privkey.pem /etc/coturn/certs/
chown coturn:coturn /etc/coturn/certs/privkey.pemLet's Encrypt で SSL 証明書が更新されたときに実行されるスクリプトを作成して、自動化しておくと良いでしょう。
#!/bin/bash
cp /etc/letsencrypt/live/example.com/fullchain.pem /etc/coturn/certs/
chown coturn:coturn /etc/coturn/certs/fullchain.pem
cp /etc/letsencrypt/live/example.com/privkey.pem /etc/coturn/certs/
chown coturn:coturn /etc/coturn/certs/privkey.pem
systemctl restart coturnデプロイスクリプトには実行権限を付けておいてください。
chmod +x /etc/letsencrypt/renewal-hooks/deploy/coturn.shcoTURN の設定
Nextcloud の公式ドキュメントに coTURN の詳細な設定方法がありますので、こちらを参考に設定します。
先に TURN サーバーシークレットを生成しておきます。
openssl rand -hex 32
(out) (TURN サーバーシークレット)coTURN の設定ファイル(/etc/coturn/turnserver.conf)を編集します。
#external-ip=60.70.80.91
↓ サーバーのグローバル IP を指定(Amazon EC2 の場合は、パブリック/プライベート IP を指定)
external-ip=xxx.xxx.xxx.xxx
#fingerprint
↓ コメント解除
fingerprint
#use-auth-secret
↓ コメント解除
use-auth-secret
#static-auth-secret=north
↓ TURN サーバーシークレットを指定
static-auth-secret=(TURN サーバーシークレット)
#realm=mycompany.org
↓ Nextcloud(Talk)のドメインを指定
realm=example.com
#total-quota=0
↓ コメント解除
total-quota=0
#bps-capacity=0
↓ コメント解除
bps-capacity=0
#cert=/etc/pki/coturn/public/turn_server_cert.pem
↓ コピーした fullchain.pem を指定
cert=/etc/coturn/certs/fullchain.pem
#pkey=/etc/pki/coturn/private/turn_server_pkey.pem
↓ コピーした privkey.pem を指定
pkey=/etc/coturn/certs/privkey.pem
#new-log-timestamp
↓ コメント解除
new-log-timestamp
#no-cli
↓ コメント解除
no-cli
# Trickle ICE テスト用
# https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
#user=<username>:<password>coTURN サービスのスタートと自動起動を設定します。
systemctl start coturn
systemctl enable coturnJanus
WebRTC(Web Real-Time Communication)サーバーの Janus をインストールしていきます。
Ubuntu 24.04 では apt でインストールできるようですが、Enterprise Linux 9 用のパッケージは見つけることができませんでした。
Snap のインストール
Snap Store で janus-gateway を見つけることができましたので、まずは Snap のインストールを行っていきます。
dnf install snapd
(out) Dependencies resolved.
(out) ================================================================================
(out) Package Architecture Version Repository Size
(out) ================================================================================
(out) Installing:
(out) snapd x86_64 2.68.3-0.el9 epel 18 M
(out) Installing dependencies:
(out) snap-confine x86_64 2.68.3-0.el9 epel 2.9 M
(out) snapd-selinux noarch 2.68.3-0.el9 epel 86 k
(out) xdelta x86_64 3.1.0-17.el9 epel 87 k
(out)
(out) Transaction Summary
(out) ================================================================================
(out) Install 4 Packages
(out)
(out) Total download size: 21 M
(out) Installed size: 69 M
(out) Is this ok [y/N]: ySnap がソケットを使って通信するための、systemd ユニットを有効化します。
systemctl enable --now snapd.socket
(out) Created symlink /etc/systemd/system/sockets.target.wants/snapd.socket → /usr/lib/systemd/system/snapd.socket.janus-gateway のインストール
Snap で janus-gateway をインストールします。
snap install janus-gateway
(out) INFO Waiting for automatic snapd restart...
(out) Warning: /var/lib/snapd/snap/bin was not found in your $PATH. If you've not restarted your session
(out) since you installed snapd, try doing that. Please see https://forum.snapcraft.io/t/9469
(out) for more details.
(out)
(out) janus-gateway v1.3.0 from Sergey Radionov (rsatom) installedjanus-gateway v1.3.0 がインストールされました。
janus-gateway の設定
TURN REST API キーを生成します。
openssl rand -base64 16
(out) (TURN REST API キー)Janus の設定ファイル(/var/snap/janus-gateway/common/etc/janus.jcfg)を編集します。
general: {
#log_to_file = "/path/to/janus.log"
↓ ログのパスを指定
log_to_file = "/var/log/janus/janus.log"
#debug_timestamps = true
↓ コメント解除
debug_timestamps = true
}
nat: {
#stun_server = "stun.voip.eutelia.it"
#stun_port = 3478
↓ STUN サーバー、ポート指定
stun_server = "hpb.example.com"
stun_port = 3478
#nat_1_1_mapping = "1.2.3.4"
↓ グローバル IP を指定
nat_1_1_mapping = "xxx.xxx.xxx.xxx"
#keep_private_host = true (Amazon EC2 の場合はコメント解除)
#turn_rest_api_key = "anyapikeyyoumayhaveset"
↓ 生成した TURN REST API キーを指定
turn_rest_api_key = "(TURN REST API キー)"
}
plugins: {
#disable = "libjanus_echotest.so,libjanus_recordplay.so"
↓
disable = "libjanus_audiobridge.so, libjanus_duktape.so, libjanus_echotest.so, libjanus_lua.so, libjanus_nosip.so, libjanus_recordplay.so, libjanus_sip.so, libjanus_sipre.so, libjanus_streaming.so, libjanus_textroom.so, libjanus_videocall.so, libjanus_voicemail.so"
}
transports: {
#disable = "libjanus_rabbitmq.so"
↓
disable = "libjanus_http.so, libjanus_mqtt.so, libjanus_nanomsg.so, libjanus_pfunix.so, libjanus_rabbitmq.so"
}
events: {
#disable = "libjanus_sampleevh.so"
↓
disable = "libjanus_gelfevh.so, libjanus_mqttevh.so, libjanus_nanomsgevh.so, libjanus_rabbitmqevh.so, libjanus_sampleevh.so, libjanus_wsevh.so"
}ログの保存用ディレクトリを作成します。
mkdir /var/log/janus/ルームの設定ファイル(/var/snap/janus-gateway/common/etc/janus.plugin.videoroom.jcfg)を編集して、Demo Room の設定を全てコメントアウトします。
#room-1234: {
# description = "Demo Room"
# secret = "adminpwd"
# publishers = 6
# bitrate = 128000 # This is a low cap, increase if you want to use simulcast or SVC
# fir_freq = 10
# #audiocodec = "opus"
# #videocodec = "vp8"
# record = false
# #rec_dir = "/path/to/recordings-folder"
#}WebSocket の設定ファイル(/var/snap/janus-gateway/common/etc/janus.transport.websockets.jcfg)を編集して、アドレスを指定します。
general: {
#ws_ip = "192.168.0.1"
↓ アドレスを指定
ws_ip = "127.0.0.1"
}サービスの起動順序を編集します。
systemctl edit --full snap.janus-gateway.janus-gateway.serviceUnit の After に coturn.service を追加し、coTURN の後に Janus が起動するように指定します。
[Unit]
#After=var-lib-snapd-snap-janus\x2dgateway-2420.mount network.target snapd.apparmor.service
# ↓ coturn.service を最後に追加
After=var-lib-snapd-snap-janus\x2dgateway-2420.mount network.target snapd.apparmor.service coturn.servicejanus-gateway サービスのスタートと自動起動を設定しようとしましたが、サービスが既に開始されていて、自動起動も設定されていました。設定変更を反映するため再起動だけしておきました。
systemctl status snap.janus-gateway.janus-gateway.service
(out) ● snap.janus-gateway.janus-gateway.service - Service for snap application janus-gateway.janus-gateway
(out) Loaded: loaded (/etc/systemd/system/snap.janus-gateway.janus-gateway.service; enabled; preset: disabled)
(out) Active: active (running)
(out)
systemctl is-enabled snap.janus-gateway.janus-gateway.service
(out) enabled
systemctl daemon-reload
systemctl restart snap.janus-gateway.janus-gateway.serviceNATS
NATS(Neural Automatic Transport System)は、軽量でハイパフォーマンスなメッセージングシステムを提供するミドルウェアです。
こちらも Ubuntu 24.04 では apt でインストールできるようですが、Enterprise Linux 9 用のリポジトリでパッケージを見つけることができませんでした。
nats-server のインストール
nats-server の公式サイトでRPM が配布されていたので、そこから最新版をインストールすることにしました。

dnf install https://github.com/nats-io/nats-server/releases/download/v2.11.4/nats-server-v2.11.4-amd64.rpm
(out) nats-server-v2.11.4-amd64.rpm 7.8 MB/s | 6.2 MB 00:00
(out) Dependencies resolved.
(out) ================================================================================
(out) Package Architecture Version Repository Size
(out) ================================================================================
(out) Installing:
(out) nats-server x86_64 2.11.4-1 @commandline 6.2 M
(out)
(out) Transaction Summary
(out) ================================================================================
(out) Install 1 Package
(out)
(out) Total size: 6.2 M
(out) Installed size: 16 M
(out) Is this ok [y/N]: yユーザーの追加
nats ユーザー/グループを、システムアカウントとして作成しておきます。
groupadd --system nats
useradd --system --gid nats --shell /sbin/nologin --comment "NATS Server" natsユニットファイルを作成
以下を参考に、ユニットファイル(/etc/systemd/system/nats-server.service)を作成します。

[Unit]
Description=NATS Server
After=network-online.target
[Service]
PrivateTmp=true
Type=simple
ExecStart=/usr/bin/nats-server -c /etc/nats-server.conf
ExecReload=/bin/kill -s HUP $MAINPID
# The nats-server uses SIGUSR2 to trigger Lame Duck Mode (LDM) shutdown
# https://docs.nats.io/running-a-nats-service/nats_admin/lame_duck_mode
ExecStop=/bin/kill -s SIGUSR2 $MAINPID
# This should be `lame_duck_duration` + some buffer to finish the shutdown.
# By default, `lame_duck_duration` is 2 mins.
TimeoutStopSec=150
Restart=on-failure
User=nats
Group=nats
[Install]
WantedBy=multi-user.targetsystemctl daemon-reload設定ファイル(/etc/nats-server.conf)を作成します。
listen: 127.0.0.1:4222nats-server サービスのスタートと自動起動を設定します。
systemctl start nats-server
systemctl enable nats-server
(out) Created symlink /etc/systemd/system/multi-user.target.wants/nats-server.service → /etc/systemd/system/nats-server.service.Signaling
いよいよ Nextcloud Talk 用のシグナリングサーバーをインストールしていきます。

Spreed standalone signaling server はパッケージが用意されていないため、ソースコードからビルドする必要があります。また、ビルドするために Go 言語も必要になります。
前提条件パッケージが入っていない場合は、事前にインストールしておいてください。
dnf install git make golangSignaling のインストール
cd /opt/
git clone https://github.com/strukturag/nextcloud-spreed-signaling.git
cd nextcloud-spreed-signaling/
make build
(out) /usr/bin/go build -ldflags '-X main.version=b74690defb4836ca21c7b8eb0bc8b361c7a27bdb' -o /opt/nextcloud-spreed-signaling/bin/signaling ./server/...
(out) go: downloading github.com/dlintw/goconf v0.0.0-20120228082610-dcc070983490
(out) go: downloading github.com/gorilla/mux v1.8.1
(out) go: downloading github.com/nats-io/nats.go v1.42.0
(out) go: downloading github.com/fsnotify/fsnotify v1.9.0
(out) go: downloading github.com/golang-jwt/jwt/v5 v5.2.2
(out) go: downloading github.com/gorilla/securecookie v1.1.2
(out) go: downloading github.com/gorilla/websocket v1.5.3
(out) go: downloading github.com/mailru/easyjson v0.9.0
(out) go: downloading github.com/notedit/janus-go v0.0.0-20200517101215-10eb8b95d1a0
(out) go: downloading github.com/oschwald/maxminddb-golang v1.13.1
(out) go: downloading github.com/pion/sdp/v3 v3.0.13
(out) go: downloading github.com/pquerna/cachecontrol v0.2.0
(out) go: downloading github.com/prometheus/client_golang v1.22.0
(out) go: downloading go.etcd.io/etcd/client/pkg/v3 v3.6.0
(out) go: downloading go.etcd.io/etcd/client/v3 v3.6.0
(out) go: downloading go.uber.org/zap v1.27.0
(out) go: downloading google.golang.org/grpc v1.72.2
(out) go: downloading google.golang.org/protobuf v1.36.6
(out) go: downloading github.com/klauspost/compress v1.18.0
(out) go: downloading github.com/nats-io/nkeys v0.4.11
(out) go: downloading github.com/nats-io/nuid v1.0.1
(out) go: downloading golang.org/x/sys v0.33.0
(out) go: downloading github.com/josharian/intern v1.0.0
(out) go: downloading github.com/pion/randutil v0.1.0
(out) go: downloading github.com/beorn7/perks v1.0.1
(out) go: downloading github.com/cespare/xxhash/v2 v2.3.0
(out) go: downloading github.com/prometheus/client_model v0.6.1
(out) go: downloading github.com/prometheus/common v0.62.0
(out) go: downloading github.com/prometheus/procfs v0.15.1
(out) go: downloading github.com/coreos/go-semver v0.3.1
(out) go: downloading go.etcd.io/etcd/api/v3 v3.6.0
(out) go: downloading go.uber.org/multierr v1.11.0
(out) go: downloading golang.org/x/net v0.38.0
(out) go: downloading google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb
(out) go: downloading golang.org/x/crypto v0.38.0
(out) go: downloading github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822
(out) go: downloading github.com/gogo/protobuf v1.3.2
(out) go: downloading github.com/golang/protobuf v1.5.4
(out) go: downloading github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3
(out) go: downloading google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb
(out) go: downloading github.com/coreos/go-systemd/v22 v22.5.0
(out) go: downloading golang.org/x/text v0.25.0
(out) /usr/bin/go build -ldflags '-X main.version=b74690defb4836ca21c7b8eb0bc8b361c7a27bdb' -o /opt/nextcloud-spreed-signaling/bin/proxy ./proxy/...
(out) go: downloading github.com/google/uuid v1.6.0ビルドしたファイルを、所定のディレクトリに配置します。
cp /opt/nextcloud-spreed-signaling/bin/signaling /usr/bin/
mkdir /etc/signaling/
cp /opt/nextcloud-spreed-signaling/server.conf.in /etc/signaling/server.conf
cp /opt/nextcloud-spreed-signaling/dist/init/systemd/signaling.service /etc/systemd/system/signaling.serviceキーに使用する乱数を 3 種類生成します。
openssl rand -hex 32
(out) (セッションハッシュキー)
(out)
openssl rand -hex 16
(out) (セッションブロックキー)
(out)
openssl rand -hex 32
(out) (HPB の共有秘密鍵)設定ファイル(/etc/signaling/server.conf)を編集します。
[http]
#listen = 127.0.0.1:8080
↓ コメント解除
listen = 127.0.0.1:8080
[sessions]
hashkey = the-secret-for-session-checksums
↓ openssl rand -hex 32 で生成したハッシュキー
hashkey = (セッションハッシュキー)
blockkey = -encryption-key-
↓ openssl rand -hex 16 で生成したブロックキー
blockkey = (セッションブロックキー)
[backend]
#backends = backend-id, another-backend
↓コメント解除、バックエンドを追加
backends = backend-1
# 追加したバックエンドのブロックを追加
[backend-1]
# Nextcloud(Talk)のドメインを指定
url = https://example.com
# openssl rand -hex 32 で生成した秘密鍵
secret = (HPB の共有秘密鍵)
[nats]
#url = nats://localhost:4222
↓ NATS サーバーを指定
url = nats://127.0.0.1:4222
[mcu]
#type =
↓ Multipoint Control Unit に Janus を指定
type = janus
#url =
↓ Janus サーバーを指定
url = ws://127.0.0.1:8188
[turn]
#apikey = the-api-key-for-the-rest-service
↓ /var/snap/janus-gateway/common/etc/janus.jcfg の TURN REST API キー
apikey = (TURN REST API キー)
#secret = 6d1c17a7-c736-4e22-b02c-e2955b7ecc64
↓ /etc/coturn/turnserver.conf の TURN サーバーシークレット
secret = (TURN サーバーシークレット)
#servers = turn:1.2.3.4:9991?transport=udp,turn:1.2.3.4:9991?transport=tcp
↓ TURN サーバーを指定
servers = turn:hpb.example.com:3478?transport=udp,turn:hpb.example.com:3478?transport=tcpユーザーの追加
signaling ユーザー/グループを、システムアカウントとして作成しておきます。
groupadd --system signaling
useradd --system --gid signaling --shell /sbin/nologin --comment "Nextcloud Talk signaling server" signaling設定ファイルのアクセス権を signaling ユーザーに変更しておきます。
chmod 600 /etc/signaling/server.conf
chown signaling: /etc/signaling/server.confユニットファイルを作成
ユニットファイル(/etc/systemd/system/signaling.service)を編集します。
[Unit]
Description=Nextcloud Talk signaling server
After=network.target
WantedBy=multi-user.targetsystemctl daemon-reloadsignaling サービスのスタートと自動起動を設定します。
systemctl start signaling
systemctl enable signalingファイアウォール の設定
nftables の設定ファイル(/etc/nftables/filter.nft)を編集して、STUN/TURN(S) のポートを許可します。
- STUN/TURN:3478(TCP、UDP)
- TURNS: 5349(TCP、UDP)
- Janus: 20000-40000(UDP)
- TURN: 49152-65535(UDP)
table inet filter {
…
省略
…
chain TCP {
# 管理者にのみ解放
# SSH, OLS 管理画面
tcp dport { 22, 7080 } ip saddr @admin accept
# 日本国内にのみ開放
# SUBMISSION, IMAPS, STUN/TURN, TURNS
tcp dport { 587, 993, 3478, 5349 } ip saddr @domestic accept
# 全開放
# SMTP, HTTP, HTTPS
tcp dport { 25, 80, 443 } accept
}
chain UDP {
# 日本国内にのみ開放
# TURN, TURNS, Janus
udp dport { 3478, 5349, 20000-40000, 49152-65535 } ip saddr @domestic accept
# 全開放
# http/3
udp dport { 443 } accept
}
}今回は国内向けにポートを開放しましたが、環境に合わせて調整してください。
systemctl reload nftablesOpenLiteSpeed の設定
今回設定した中で、ここが一番ハマりました。参考にしたサイトでは standalone-signaling ディレクトリを起点に Proxy 設定を入れていましたが、OLS の Web Socket Proxy が上手くいかなかったため、ドメイン直下で設定しました。

バーチャルホストにサブドメインを追加
高性能バックエンド用のサブドメインとして、hpb.example.com を追加します。
OLS の管理画面から、新しいバーチャルホストを追加し、リスナーのバーチャルホストマップに追加します。
- 基本
- バーチャルホスト名: hpb.example.com
- Virtual Host Root: /var/www/$VH_NAME
- 設定ファイル: $SERVER_ROOT/conf/vhosts/$VH_NAME/vhconf.conf
- 一般
- Document Root: $VH_ROOT
- ドメイン名: $VH_NAME
SSL 秘密鍵 & 証明書の設定も行っておきましょう。

外部アプリにシグナリングサーバーを追加
追加したバーチャルホストの外部アプリに、シグナリングサーバーを追加します。
- タイプ: Web サーバー
- 名前: Signaling
- アドレス: 127.0.0.1:8080

Rewrite ルールを追加
追加したバーチャルホストの Rewrite ルールを追加します。
- Rewrite 制御: はい
- Rewrite ルール
- RewriteCond %{REQUEST_URI} !^/.well-known/(acme-challenge|pki-validation)/
- RewriteRule ^/(.*) http://Signaling/$1 [P,L]
- Header set Host %{HTTP_HOST}
- Header set X-Real-IP %{REMOTE_ADDR}
- Header set X-Forwarded-For %{HTTP_X_FORWARDED_FOR}

Web Socket Proxy を追加
追加したバーチャルホストに Web Socket Proxy を追加します。
- URI: /spreed
- アドレス: 127.0.0.1:8080

以上で OLS の設定は完了です。緩やかな再起動をして、設定を反映させてください。
Nextcloud Talk に設定を反映
Nextcloud に管理者でログインし、設定画面から「管理」>「トーク」を開きます。
高性能バックエンド
- 高性能バックエンド URL: wss://hpb.example.com
- 共有秘密鍵:(HPB の共有秘密鍵)
- SSL 証明書を検証する: チェックする
共有秘密鍵には、Signaling の設定ファイル(/etc/signaling/server.conf)に記載された、backend-1 の secret を入力します。

正しく設定されるとステータスが「OK」になります。
STUN/TURN サーバー
- STUN サーバー: hpb.example.com:3478
- TURN サーバー:
- turn: hpb.example.com:3478(UDP と TCP)
- turns: hpb.example.com:5349(UDP と TCP)
TURN サーバーシークレットには、coTURN の設定ファイル(/etc/coturn/turnserver.conf)に記載したものを入力します。

TURN サーバーの設定欄の右に緑のチェックマークが付けば、正しく設定されています。

ビデオ通話の検証
テスト用に 6 アカウントを用意してグループを作成、ビデオ通話の検証を行ないました。
PC のブラウザから 3 回線(光回線)、iPhone の Nextcloud Talk アプリ から 3 回線(モバイル通信:Wi-Fi オフ)の合わせて 6 人でビデオ通話を行いましたが、カクついたりすることも無く非常にスムーズでした。
ConoHa VPS 2G プランでも余裕で動きましたので、小規模の運用なら全く問題ないと思います。
レコーディングバックエンド
レコーディングバックエンドサーバーの構築も考えたのですが、ハードウェア要件が高すぎて VPS では厳しそうなので諦めることにします。

参考にしたサイト




コメント