Ubuntuで安定稼働するアプリケーションであるとは知りながら、一番好きなFreeBSDで動かすことに挑戦しました。
ウェブサーバーにもnginxではなくApacheを使いました。理由はただ一つ。慣れているからです。
結果、何とか動かすことに成功したので、成功した時点での設定内容をメモしておきます。
This is an instant note when I successfully set up Jitsi Meet with Apache 2.4 on FreeBSD 12.
I don’t think engineers need translations but with my pleasure translate words in English.
先にお断りを書いておきます。
- 暗号化されない経路を極力作らないような設定を目指したので、暗号化に関心がない方の助けにはならないかもしれません。
- websocketを使ってみたかったのですが、うまく動かせませんでした。掲載した設定の中にもコメントアウトで残してあります。
- どの設定にどういう意味があるのかの説明は、大変なので省略します。
- 困ったらマニュアルに戻ってください。なんだかんだ言って、基本はここにあります。
- This article in which I wrote about full encryption may not help you if you don’t want the full encrypted communications.
- I gave up using websocket, but remained the config lines in comments.
- I don’t add detailed explanations because it’s too much tough in this big article.
- Back to the manual when in trouble.
pkg
おそらく、以下のコマンドで必要はものはすべて揃います。
# pkg install jitsi-videobridge prosody jicofo
Apacheの設定
Jitsi用のバーチャルホストを作成します。
<VirtualHost _default_:443>
DocumentRoot /usr/local/www/jitsi-meet
ServerName jitsi.midgen.asia
ServerAdmin ryow@midgen.asia
ErrorLog "/var/log/httpd/jitsi.midgen.asia-error.log"
TransferLog "/var/log/httpd/jitsi.midgen.asia-access.log"
CustomLog "/var/log/httpd/jitsi.midgen.asia-ssl_request.log" \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
Header always set Strict-Transport-Security "max-age=63072000"
ErrorDocument 404 /static/404.html
SSLEngine on
SSLCertificateFile "/usr/local/etc/letsencrypt/live/jitsi.midgen.asia/fullchain.pem"
SSLCertificateKeyFile "/usr/local/etc/letsencrypt/live/jitsi.midgen.asia/privkey.pem"
SSLProxyEngine on
ProxyPreserveHost on
ProxyPass /http-bind https://localhost:5281/http-bind/
ProxyPassReverse /http-bind https://localhost:5281/http-bind/
#ProxyPass /xmpp-websocket wss://localhost:5281/xmpp-websocket
#ProxyPassReverse /xmpp-websocket wss://localhost:5281/xmpp-websocket
#ProxyPassMatch ^/colibri-ws/default-id http://localhost:9090
</VirtualHost>
通常ここにRewriteRuleを書きますが、わたしは日本語のトークルームを作成できるようにするために.htaccessに書きます。Wordpressに倣った書き方です。
As a not common way, I write RewriteRule/s in .htaccess to make it possible to create rooms with Japanese names (multi-byte strings). They are from WordPress.
# vi /usr/local/www/jitsi-meet/.htaccess
Options MultiViews Includes SymLinksIfOwnerMatch
AddOutputFilter INCLUDES .html
# WordPress-like RewriteRule settings.
RewriteEngine On
RewriteBase /
RewriteRule ^$ /index.html [L]
RewriteRule ^/lang/countries(.+?)\.json$ /lang/languages$1.json [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
Prosodyの設定
Prosodyの設定は主にモジュール、バーチャルホスト、コンポーネントから構成されています。
ProsodyはProsodyというユーザーとグループで実行されるようにできているので、/var/run/prosodyや/var/log/prosodyというようなProsodyという書き込み可能なディレクトリを用意する必要があります。
Prosody runs as prosody:prosody, so we have to create writable directory “/var/run/prosody” and “/var/log/prosody”.
---------- Server-wide settings ----------
admins = { "focus@auth.jitsi.midgen.asia" }
modules_enabled = {
-- Generally required
"roster"; -- Allow users to have a roster. Recommended ;)
"saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
"tls"; -- Add support for secure TLS on c2s/s2s connections
"dialback"; -- s2s dialback support
"disco"; -- Service discovery
-- Not essential, but recommended
"carbons"; -- Keep multiple clients in sync
"pep"; -- Enables users to publish their avatar, mood, activity, playing music and more
"private"; -- Private XML storage (for room bookmarks, etc.)
"blocklist"; -- Allow users to block communications with other users
"vcard4"; -- User profiles (stored in PEP)
"vcard_legacy"; -- Conversion between legacy vCard and PEP Avatar, vcard
-- Nice to have
"version"; -- Replies to server version requests
"uptime"; -- Report how long server has been running
"time"; -- Let others know the time here on this server
"ping"; -- Replies to XMPP pings with pongs
"register"; -- Allow users to register on this server using a client and change passwords
"mam"; -- Store messages in an archive and allow users to access it
--"csi_simple"; -- Simple Mobile optimizations
-- Admin interfaces
"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
--"admin_telnet"; -- Opens telnet console interface on localhost port 5582
-- HTTP modules
--"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
--"websocket"; -- XMPP over WebSockets
--"http_files"; -- Serve static files from a directory over HTTP
-- Other specific functionality
--"limits"; -- Enable bandwidth limiting for XMPP connections
--"groups"; -- Shared roster support
--"server_contact_info"; -- Publish contact information for this service
--"announce"; -- Send announcement to all online users
--"welcome"; -- Welcome users who register accounts
--"watchregistrations"; -- Alert admins of registrations
--"motd"; -- Send a message to users when they log in
--"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
--"proxy65"; -- Enables a file transfer proxy service which clients behind NAT can use
"external_services";
"turncredentials";
}
allow_registration = false
c2s_require_encryption = true
s2s_require_encryption = true
s2s_secure_auth = false
authentication = "internal_hashed"
archive_expires_after = "3d" -- Remove archived messages after 1 week
log = {
info = "/var/log/prosody/info.log"; -- Change 'info' to 'debug' for verbose logging
error = "/var/log/prosody/error.log";
}
statistics = "internal"
https_certificate = "certs/jitsi.midgen.asia.crt"
pidfile = "/var/run/prosody/prosody.pid"
consider_websocket_secure = true
turncredentials_host = "localhost"
turncredentials_port = 5349
turncredentials_secret = "TURNSERVER_SECRET"
----------- Virtual hosts -----------
VirtualHost "jitsi.midgen.asia"
key = "certs/jitsi.midgen.asia.key";
certificate = "certs/jitsi.midgen.asia.crt";
authentication = "anonymous"
modules_enabled = {
"bosh";
"http_files";
"pubsub";
}
VirtualHost "auth.jitsi.midgen.asia"
key = "certs/auth.jitsi.midgen.asia.key";
certificate = "certs/auth.jitsi.midgen.asia.crt";
------ Components ------
Component "conference.jitsi.midgen.asia" "muc"
key = "certs/conference.jitsi.midgen.asia.key";
certificate = "certs/conference.jitsi.midgen.asia.crt";
Component "jitsi-videobridge.jitsi.midgen.asia"
component_secret = "JVB_SECRET"
key = "certs/jitsi-videobridge.jitsi.midgen.asia.key";
certificate = "certs/jitsi-videobridge.jitsi.midgen.asia.crt";
Component "focus.jitsi.midgen.asia"
component_secret = "JICOFO_SECRET"
key = "certs/focus.jitsi.midgen.asia.key";
certificate = "certs/focus.jitsi.midgen.asia.crt";
Certificates (証明書の設定)
証明書を設定しないと煩雑なエラーが発生しますので、設定しましょう。Certbot(Let’s Encrypt)を使えば証明書は無料です。
Certificates must be installed for suppressing noisy errors. Certbot (Let’s Encrypt) are useful for free.
# prosodyctl --root cert import focus.jitsi.midgen.asia /usr/local/etc/letsencrypt/live/focus.jitsi.midgen.asia/fullchain.pem
Imported certificate and key for hosts focus.jitsi.midgen.asia
# prosodyctl --root cert import jitsi.midgen.asia /usr/local/etc/letsencrypt/live/jitsi.midgen.asia/fullchain.pem
Imported certificate and key for hosts jitsi.midgen.asia
# prosodyctl --root cert import conference.jitsi.midgen.asia /usr/local/etc/letsencrypt/live/conference.jitsi.midgen.asia/fullchain.pem
Imported certificate and key for hosts conference.jitsi.midgen.asia
# prosodyctl --root cert import jitsi-videobridge.jitsi.midgen.asia /usr/local/etc/letsencrypt/live/jitsi-videobridge.jitsi.midgen.asia/fullchain.pem
Imported certificate and key for hosts jitsi-videobridge.jitsi.midgen.asia
# prosodyctl --root cert import auth.jitsi.midgen.asia /usr/local/etc/letsencrypt/live/auth.jitsi.midgen.asia/fullchain.pem
Imported certificate and key for hosts auth.jitsi.midgen.asia
設定を確認するコマンドがありますので、積極的に使いましょう。
There is a command to check settings, so aggressively use it.
# prosodyctl check
Checking config...
Done.
Checking DNS for component jitsi-videobridge.jitsi.midgen.asia...
jitsi-videobridge.jitsi.midgen.asia A record points to internal address, external connections might fail
Checking DNS for host jitsi.midgen.asia...
jitsi.midgen.asia A record points to internal address, external connections might fail
Checking DNS for component conference.jitsi.midgen.asia...
conference.jitsi.midgen.asia A record points to internal address, external connections might fail
Checking DNS for component focus.jitsi.midgen.asia...
focus.jitsi.midgen.asia A record points to internal address, external connections might fail
Checking DNS for host auth.jitsi.midgen.asia...
auth.jitsi.midgen.asia A record points to internal address, external connections might fail
Checking certificates...
Checking certificate for jitsi-videobridge.jitsi.midgen.asia
Certificate: /usr/local/etc/prosody/certs/jitsi-videobridge.jitsi.midgen.asia.crt
Checking certificate for jitsi.midgen.asia
Certificate: /usr/local/etc/prosody/certs/jitsi.midgen.asia.crt
Checking certificate for conference.jitsi.midgen.asia
Certificate: /usr/local/etc/prosody/certs/conference.jitsi.midgen.asia.crt
Checking certificate for focus.jitsi.midgen.asia
Certificate: /usr/local/etc/prosody/certs/focus.jitsi.midgen.asia.crt
Checking certificate for auth.jitsi.midgen.asia
Certificate: /usr/local/etc/prosody/certs/auth.jitsi.midgen.asia.crt
All checks passed, congratulations!
Javaが証明書情報を参照できるようにする必要があります。以下のようにします。
We have to make Java refer to the certificates like this.
# keytool -noprompt -keystore /usr/local/etc/jitsi/jicofo/keystores/jitsiTrustStore.jks -importcert -alias auth.jitsi.midgen.asia -file /usr/local/etc/prosody/certs/auth.jitsi.midgen.asia.crt
キーストアのパスワードを入力してください:
証明書がキーストアに追加されました
# keytool -noprompt -keystore /usr/local/etc/jitsi/jicofo/keystores/jitsiTrustStore.jks -importcert -alias focus.jitsi.midgen.asia -file /usr/local/etc/prosody/certs/focus.jitsi.midgen.asia.crt
キーストアのパスワードを入力してください:
証明書がキーストアに追加されました
# keytool -noprompt -keystore /usr/local/etc/jitsi/jicofo/keystores/jitsiTrustStore.jks -importcert -alias jitsi.midgen.asia -file /usr/local/etc/prosody/certs/jitsi.midgen.asia.crt
キーストアのパスワードを入力してください:
証明書がキーストアに追加されました
# keytool -noprompt -keystore /usr/local/etc/jitsi/jicofo/keystores/jitsiTrustStore.jks -importcert -alias conference.jitsi.midgen.asia -file /usr/local/etc/prosody/certs/conference.jitsi.midgen.asia.crt
キーストアのパスワードを入力してください:
証明書がキーストアに追加されました
# keytool -noprompt -keystore /usr/local/etc/jitsi/jicofo/keystores/jitsiTrustStore.jks -importcert -alias jitsi-videobridge.jitsi.midgen.asia -file /usr/local/etc/prosody/certs/jitsi-videobridge.jitsi.midgen.asia.crt
キーストアのパスワードを入力してください:
証明書がキーストアに追加されました
Authentication (認証の設定)
トークルームを作成する際の認証情報は、Prosodyで管理します。これをしないと認証エラーになるはずです。
The authentication information to create rooms is handled by Prosody. Authentication failures should occur if you don’t do this.
# prosodyctl adduser focus@auth.jitsi.midgen.asia
Password: [SECRET1 and Enter]
Jicofo
# vi /usr/local/etc/jitsi/jicofo/jicofo.conf
JVB_XMPP_HOST=localhost
JVB_XMPP_DOMAIN=jitsi.midgen.asia
JVB_XMPP_PORT=5347
JVB_XMPP_SECRET=SECRET1
JVB_XMPP_USER_DOMAIN=auth.jitsi.midgen.asia
JVB_XMPP_USER_NAME=focus
JVB_XMPP_USER_SECRET=SECRET1
MAX_MEMORY=2048m
Prosodyの認証情報はJicofoにも必要です。JVB_XMPP_USER_NAMEとJVB_XMPP_USER_DOMAINとJVB_XMPP_USER_SECRETで作成します。
Authentication information of Prosody is needed to Jicofo. It is made from JVB_XMPP_USER_NAME, JVB_XMPP_USER_DOMAIN and JVB_XMPP_USER_SECRET.
# prosodyctl adduser <JVB_XMPP_USER_NAME>@auth.jitsi.midgen.asia
Password: [<JVB_XMPP_USER_SECRET> and Enter]
- Java言語を使ってSSLアクセスで失敗した時の対処方法
- JavaにSSL証明書を追加する
- PKIX path building failedエラーへの対処。JVMの信頼済ホストにAPIサーバ側のTLS証明書をインポートする
Videobridge (Jitsi Video Bridge)
音声と映像を司るサービスです。
# vi /usr/local/etc/jitsi/videobridge/jitsi-videobridge.conf
JVB_XMPP_HOST=localhost
JVB_XMPP_DOMAIN=jitsi.midgen.asia
JVB_XMPP_PORT=5347
JVB_XMPP_SECRET=JVB_SECRET
VIDEOBRIDGE_MAX_MEMORY=4096m
JVBとJicofoの共通設定
Jitsi VideoBridge(JVB)とJicofoには共通設定ファイルのようなものがあります。
最後の二行はNAT環境下では必ず必要です。
JVB and Jicofo have a “common” configuration file. The last two lines are necessary for the server behind NAT.
# vi /usr/local/etc/jitsi/jicofo/sip-communicator.properties
org.jitsi.videobridge.DISABLE_TCP_HARVESTER=true
org.jitsi.videobridge.PUBSUB_NODE=sharedStatsNode
org.jitsi.videobridge.PUBSUB_SERVICE=jitsi.midgen.asia
org.jitsi.videobridge.ENABLE_STATISTICS=true
org.jitsi.videobridge.STATISTICS_TRANSPORT=pubsub
org.jitsi.jicofo.auth.URL=XMPP:auth.jitsi.midgen.asia
org.jitsi.jicofo.STATS_PUBSUB_NODE=sharedStatsNode
# Running behind NAT
org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS=10.0.129.80
org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS=114.19.84.254
また、このファイルはJVBとJicofoの両方のホームディレクトリで読み込み可能なファイルでないといけませんが、インストール直後はJicofoの方にしかないので、JVBの方からリンクを張ります。それぞれのスタートアップスクリプトを読むと、この作業の必要性がわかります。
And this file must be stored in the home directory of both, but only Jicofo has one after installation, so create a link to the one from JVB home directory. You can find the necessity of this from their startup script.
# ln -s /usr/local/etc/jitsi/jicofo/sip-communicator.properties /usr/local/etc/jitsi/videobridge/sip-communicator.properties
Turnserver
jitsi.netではなく自前のネットワークでピアツーピアを実現したい場合は、TURN server(coTURN)をインストールする必要があります。pkgでもインストールできますが、MySQL5.7を要求されます。わたしはMySQL8.0を入れてしまってあった関係上、ソースコードからビルドしました。
If you want to set up Jitsi system completely DIY, need to install TURN server(coTURN). pkg has such package, but I didn’t choose it because it requires MySLQL5.7, while I installed MySQL 8.0. So I built from its source.
# cd /tmp
# git clone https://github.com/coturn/coturn.git
# cd coturn
# ./configure --prefix=/usr/local
# make
# make install
スタートアップスクリプトはJicofoのものを改造して作りました。
I created the startup script from Jicofo’s one.
# vi /usr/local/etc/rc.d/turnserver
#!/bin/sh
#
# turnserver_enable: run turnserver server (default=NO)
# turnserver_flags: additional flags for turnserver server (default="")
#
. /etc/rc.subr
name="turnserver"
rcvar=${name}_enable
load_rc_config "${name}"
: ${turnserver_enable="NO"}
: ${turnserver_flags=""}
command="/usr/local/bin/turnserver"
pidfile="/var/run/turnserver.pid"
start_cmd=${name}_start
stop_cmd=${name}_stop
status_cmd=${name}_status
restart_cmd=${name}_restart
turnserver_start()
{
${command} ${turnserver_flags} 2>&1 /dev/null
echo "Started"
}
turnserver_stop()
{
if [ -f ${pidfile} ]
then
kill `cat ${pidfile}`
rm ${pidfile}
echo "Stopped"
fi
}
turnserver_status()
{
# If running, show pid
if [ -f ${pidfile} ]
then
echo "${name} is running as pid" `cat ${pidfile}`
else
echo "${name} is not running"
fi
}
turnserver_restart()
{
echo "Performing restart"
turnserver_stop
sleep 3
turnserver_start
}
run_rc_command "$1"
設定はこんな感じ。
# vi /usr/local/etc/jitsi/jicofo/jicofo.conf
tls-listening-port=5349
listening-ip=192.168.1.180
use-auth-secret
static-auth-secret=TURNSERVER_SECRET
realm=turn.midgen.asia
cert=/usr/local/etc/letsencrypt/live/turn.midgen.asia/fullchain.pem
pkey=/usr/local/etc/letsencrypt/live/turn.midgen.asia/privkey.pem
log-file=/var/log/turnserver.log
pidfile="/var/run/turnserver.pid"
no-cli
config.js
フロント側のファイルです。こんな感じです。
var config = {
hosts: {
domain: 'jitsi.midgen.asia',
authdomain: 'auth.jitsi.midgen.asia',
focus: 'focus.jitsi.midgen.asia',
muc: 'conference.jitsi.midgen.asia',
},
bosh: '//jitsi.midgen.asia/http-bind',
clientNode: 'http://jitsi.org/jitsimeet',
focusUserJid: 'focus@auth.jitsi.midgen.asia',
testing: {
p2pTestMode: false
},
webrtcIceUdpDisable: false,
webrtcIceTcpDisable: false,
enableNoAudioDetection: true,
enableNoisyMicDetection: true,
desktopSharingChromeExtId: null,
desktopSharingChromeSources: [ 'screen', 'window', 'tab' ],
desktopSharingChromeMinExtVersion: '0.1',
channelLastN: -1,
useIPv6: true,
openBridgeChannel: true,
useNicks: false,
enableWelcomePage: true,
defaultLanguage: 'ja',
enableUserRolesBasedOnToken: false,
p2p: {
enabled: true,
useStunTurn: true,
stunServers: [
{ urls: 'stun:jitsi.midgen.asia:5349' }
],
preferH264: true
},
};
以上です。もし不明点があったらわかる範囲でお答えします。
That’s all. If you have any questions, ask me.