FICUSONLINE F9E
ビデオ会議システム Jitsi Meet on Docker (+ Podman)
オープンソースのビデオ会議システムJitsi Meetの最新版をDockerコンテナで運用しているほか、Podmanを利用したrootlessコンテナおよびポッド構成による運用への移行も視野に入れており、現在その実運用を試みています。従来のDocker Composeベースの構成では、root権限での実行が前提となるケースが多く、ホストシステムへのセキュリティリスクが課題となっていました。一方、PodmanはOCI(Open Container Initiative)準拠のコンテナランタイムであり、非特権ユーザーによる本番レベルの環境構築を可能とします。 Jitsi Meetの各コンポーネント(web, prosody, jicofo, jvb)を1つのPod内で統合し、相互通信をローカルネットワーク内に限定することで、外部との不要な通信を遮断しつつ、セキュリティとパフォーマンスの最適化を図ります。今回のPodmanによる運用は、将来的にKubernetesとの連携やオートスケーリングを見据えたシステム構築の足がかりとなることを想定しています。
Takanobu FuseAdministrator

5 days ago

Cloud / Server

フォーラム記事を纏めた内容です。詳細(内容の修正・追加・トラブルシュート)についてはここを参照願います(日本語のみ)。


SIPゲートウェイJigasiコンテナを追加(音声のみ対応)し最新安定版として再構築。 Nginxのリバースプロキシ経由でJitsi Meetシステムへアクセスする構成とします。

Jitsi Meet

最新安定版10078-1

Jitsi Docker導入ガイド


最新版のダウンロード

最新安定版をダウンロードして展開します。

$ wget $(curl -s https://api.github.com/repos/jitsi/docker-jitsi-meet/releases/latest | grep 'zip' | cut -d\" -f4)

展開

$ unzip stable-10078-1

展開したフォルダからenv.exampleが含まれるディレクトリへ移動し、環境変数ファイル.envを作成。

$ cp env.example .env

各コンテナ起動時に必要なセキュリティパスワードを.envに設定するスクリプトを実行。

$ ./gen-passwords.sh

各コンテナに必要な設定ファイルディレクトリを、展開したディレクトリ内に作成。

$ mkdir -p ~/.jitsi-meet-cfg/{web,transcripts,prosody/config,prosody/prosody-plugins-custom,jicofo,jvb,jigasi,jibri}

注) このディレクトリを .env 内で CONFIG=./.jitsi-meet-cfg として指定。

構成ディレクトリ・ファイル一覧は以下の通りです。

$ tree -aL 1 ../jitsi-docker-jitsi-meet-10078-1
../jitsi-docker-jitsi-meet-10078-1
├── .env
├── .env.bak
├── .github
├── .gitignore
├── .jitsi-meet-cfg
├── CHANGELOG.md
├── LICENSE
├── Makefile
├── README.md
├── base
├── base-java
├── docker-compose.yml
├── env.example
├── etherpad.yml
├── examples
├── gen-passwords.sh
├── grafana.yml
├── jibri
├── jibri.yml
├── jicofo
├── jigasi
├── jigasi.yml
├── jvb
├── log-analyser
├── log-analyser.yml
├── nginx
├── prometheus
├── prometheus.yml
├── prosody
├── release.sh
├── resources
├── transcriber.yml
├── web
└── whiteboard.yml

Nginxリバースプロキシ設定ファイルの作成

Jitsi MeetへのアクセスはNginxのリバースプロキシ経由とします。リバースプロキシでTLS認証を行うことでJitsi MeetでのTLS認証が不要となり証明書の管理・更新がしやすくなります。

Reverse proxy configuration

リバースプロキシでTLS認証を取得するため、WEBコンテナの以下の設定を無効とします。

  • .env
DISABLE_HTTPS=1
ENABLE_HTTP_REDIRECT=0
ENABLE_LETS_ENCRYPT=0

他にも.env内で以下の必要な設定をして下さい。

  • .env
#
# Basic configuration options
#

# Directory where all configuration will be stored
CONFIG=./.jitsi-meet-cfg

# Exposed HTTP port (will redirect to HTTPS port)
HTTP_PORT=8000

# Exposed HTTPS port
HTTPS_PORT=8443

# System time zone
TZ=JST

# Public URL for the web service (required)
# Keep in mind that if you use a non-standard HTTPS port, it has to appear in the public URL
#PUBLIC_URL=https://test.ficusonline.com:${HTTPS_PORT}
PUBLIC_URL=https://test.ficusonline.com

# Media IP addresses to advertise by the JVB
# This setting deprecates DOCKER_HOST_ADDRESS, and supports a comma separated list of IPs
# See the "Running behind NAT or on a LAN environment" section in the Handbook:
# https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-docker#running-behind-nat-or-on-a-lan-environment
JVB_ADVERTISE_IPS=192.168.1.1,1.2.3.4

# Enable authentication (will ask for login and password to join the meeting)
ENABLE_AUTH=1

# Enable guest access (if authentication is enabled, this allows for users to be held in lobby until registered user lets them in)
ENABLE_GUESTS=1

# Select authentication type: internal, jwt, ldap or matrix
AUTH_TYPE=internal

リバースプロキシでTLS接続するため、Jitsi WEBコンテナへの接続はHTTPとします。このため、ウェブソケット(wss)接続エラーが発生します。これに対処するため、コンテナ内ではウェブソケットをws接続とします。Nginxの設定にlocation /xmpp-websocket, location /colibri-ws を追加します。

最終的な設定ファイルは以下のようになります。

  • nginx/default.conf
server {
    server_name test.ficusonline.com;

    server_tokens off;
    # access_log  /var/log/nginx/test.ficusonline.com.access.log;
    # error_log   /var/log/nginx/test.ficusonline.com.error.log error;

	location / {
		proxy_pass http://web:80;
		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 $scheme;
	}
    
	location /xmpp-websocket {
		proxy_pass http://prosody:5280/xmpp-websocket;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
	}

	location /colibri-ws {
		proxy_pass http://jvb:8080/colibri-ws;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
	}

    listen 443 ssl; # managed by Certbot
    listen [::]:443 ssl;
    ssl_certificate /etc/letsencrypt/live/ficusonline.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ficusonline.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

}
server {
    if ($host = test.ficusonline.com) {
        return 301 https://$host$request_uri;
    } 

    server_name test.ficusonline.com;
    listen [::]:80;
    listen 80;
    return 404; 
}

Nginx専用のdocker-compose-nginx.ymlを作成

PodmanでPodでシステム運用するため、Jitsi Meetシステムとは独立した、Nginx専用のdocker-composeファイルを作成します。Podmanではセキュリティ上の理由から、ユーザレベルで1000未満のポート番号へはアクセスできないため、ポート80, 443へのアクセスをiptablesにより、8080, 8443へポートリダイレクトします。永続的にリダイレクトさせるにはシステムデーモンへの登録が必要です。詳細についてはここを参照願います(日本語)。

$ sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
$ sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
$ sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8443
$ sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8443
  • docker-compose-nginx.yml
    nginx:
        container_name: nginx
        image: nginx:alpine
        tty: true
        ports:
            - "8080:80"
            - "8443:443"
        volumes:
            # nginx config
            - ./nginx:/etc/nginx/conf.d
            - /etc/letsencrypt:/etc/letsencrypt
        restart: always
        networks:
            meet.jitsi:

コンテナ起動

JitsiとNginxの両方のdocker-composeファイルを指定して起動します。

$ docker compose -f docker-compose.yml -f docker-compose-nginx.yml up -d

管理ユーザの登録

ミーティングの管理ユーザの登録はProsodyコンテナ内で行います。

$ docker compose exec prosody bash
# prosodyctl --config /config/prosody.cfg.lua register USER_NAME meet.jitsi PASSWORD

登録ユーザの確認

# find /config/data/meet%2ejitsi/accounts -type f -exec basename {} .dat \;

Jitsiメイン画面 Jitsi Meet Main

ミーティング画面


PodmanでPodを作成して起動

NginxのPodとJitsi Meetを構成するコンテナ郡をパッケージにしたPodで運用します。

Jitsi Meet on Pod

Nginxのproxy_passの設定をpodmanのネットワークに合わせて書換えます。

  • nginx/default.conf
server {
    server_name test.ficusonline.com;

    server_tokens off;
    # access_log  /var/log/nginx/test.ficusonline.com.access.log;
    # error_log   /var/log/nginx/test.ficusonline.com.error.log error;

	location / {
		# jitsi-meet network 172.18.0.0/16
		# web container
#		proxy_pass http://web:80/;		
		proxy_pass http://meet.jitsi:80/;
		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 $scheme;
	}
    
	location /xmpp-websocket {
	    # prosody ws
#	    proxy_pass http://prosody:5280/xmpp-websocket;
		proxy_pass http://meet.jitsi:5280/xmpp-websocket;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
	}

	location /colibri-ws {
	    # jvb ws
#		proxy_pass http://jvb:8080/colibri-ws;
		proxy_pass http://meet.jitsi:8080/colibri-ws;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
	}

    listen 443 ssl; # managed by Certbot
    listen [::]:443 ssl;
    ssl_certificate /etc/letsencrypt/live/ficusonline.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ficusonline.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

}
server {
    if ($host = test.ficusonline.com) {
        return 301 https://$host$request_uri;
    } 

    server_name test.ficusonline.com;
    listen [::]:80;
    listen 80;
    return 404; 
}

Podmanによるネットワークの作成、Podの作成、コンテナをPod内に配置する一連のコマンドは以下の通りです。

$ JITSI_IMAGE_VERSION=stable-10078-1

$ podman network create meet-jitsi

$ podman pod create --name pod-nginx --hostname host-nginx --network meet-jitsi -p 8080:80 -p 8443:443

$ podman pod create --name pod-jitsi --hostname meet.jitsi --network meet-jitsi -p 10000:10000/udp -p 20000-20050:20000-20050/udp \
    --add-host=xmpp.meet.jitsi:127.0.0.1

$ podman create \
    --pod pod-nginx \
    --name nginx \
    -v ./nginx:/etc/nginx/conf.d \
    -v ./letsencrypt:/etc/letsencrypt \
    nginx:alpine
    
$ podman create \
    --name web \
    --pod pod-jitsi \
    --env-file .env \
    -v .jitsi-meet-cfg/web:/config:Z \
    -v .jitsi-meet-cfg/web/crontabs:/var/spool/cron/crontabs:Z \
    -v .jitsi-meet-cfg/transcripts:/usr/share/jitsi-meet/transcripts:Z \
    -v .jitsi-meet-cfg/web/load-test:/usr/share/jitsi-meet/load-test:Z \
    --label service=jitsi-web \
    jitsi/web:${JITSI_IMAGE_VERSION}
    
$ podman create \
  --name prosody \
  --pod pod-jitsi \
  --env-file .env \
  -v .jitsi-meet-cfg/prosody/config:/config:Z \
  -v .jitsi-meet-cfg/prosody/prosody-plugins-custom:/prosody-plugins-custom:Z \
  --label service="jitsi-prosody" \
  jitsi/prosody:${JITSI_IMAGE_VERSION}
  
$ podman create \
  --name jicofo \
  --pod pod-jitsi \
  --env-file .env \
  -v .jitsi-meet-cfg/jicofo:/config:Z \
  --label service="jitsi-jicofo" \
  jitsi/jicofo:${JITSI_IMAGE_VERSION}
  
$ podman create \
  --name jvb \
  --pod pod-jitsi \
  --env-file .env \
  -v .jitsi-meet-cfg/jvb:/config:Z \
  --label service="jitsi-jvb" \
  jitsi/jvb:${JITSI_IMAGE_VERSION}
  
$ podman create \
  --name jigasi \
  --pod pod-jitsi \
  --env-file .env \
  -v .jitsi-meet-cfg/jigasi:/config:Z \
  --label service="jitsi-jigasi" \
  jitsi/jigasi:${JITSI_IMAGE_VERSION}

Podmanデスクトップをインストールすれば、上記コマンドで作成したPodとコンテナを管理できるようになります。各Podの起動・停止は、Podmanデスクトップから行うか、 $ podman pod start POD_NAME コマンドで行って下さい。

Podman Conteiners


Kubernetes環境で起動

Podmanで作成したPodからKubernetesのyamlファイルを作成します。

$ podman generate kube pod-nginx >> pod-nginx.yaml
$ podman generate kube pod-jitsi >> pod-jitsi.yaml

pod-jitsi.yamlから

metadata -> annotations を削除します。

https://github.com/containers/podman/issues/17761#issuecomment-1845394695

  • pod-jitsi.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2025-03-27T14:17:48Z"
  labels:
    app: pod-jitsi
  name: pod-jitsi
.....
.....

作成したKubernetesのyamlファイルからPodを起動

$ podman play kube pod-jitsi.yaml
$ podman play kube pod-nginx.yaml

Podが起動するまでのログを確認する場合

$ podman --log-level=debug play kube pod-jitsi.yaml
$ podman --log-level=debug play kube pod-nginx.yaml

システムデーモンで管理(自動起動)

Podmanはシステムデーモンとして稼働しないため、ホストを再起動後はプロセスが停止したままとなります。ただし、Podをシステムデーモンのサービスとして登録することで、ユーザログイン時、またはホストマシン起動時に自動起動することができます。

システムデーモンを利用する方法として以下の2つの方法が提供されています。

1) $ podman generate systemd ~

既存のポッド、コンテナからsystemdユニットファイルを生成しますが、あくまで既存のポッドやコンテナを起動・停止するサービスのため、ポッドやコンテナを削除するとサービスは無効になります。機能的には、docker-composeのstop,startに相当します。

2) Quadlet(推奨)

既存のコンテナ定義を参照して、イメージから新規にコンテナを起動するsystemdユニットファイルを生成します(既存のコンテナに依存しません)。サービスを停止するとコンテナは削除されます。機能的にはdocker-composeのup,downに相当します。 注) Podman v4.9.3時点では、ポッドとコンテナの連携機能が未実装(v5以降で対応)


1) $ podman generate systemd ~

Podの確認

$ podman pod ps
POD ID        NAME        STATUS      CREATED      INFRA ID      # OF CONTAINERS
8479ea3524b9  pod-jitsi   Exited      4 hours ago  de6fb0a4d245  5
7787d93bd426  pod-nginx   Exited      4 hours ago  20552d55e11c  2

各Podの管理をシステムデーモンに受け渡します。そのためのサービスファイルをpodman generate コマンドで作成します。

$ podman generate systemd --name pod-nginx --files

以下の2つのファイルが作成されます。

  • pod-pod-nginx.service
  • container-nginx.service
$ podman generate systemd --name pod-jitsi --files

以下の6つのファイルが作成されます。

  • pod-pod-jitsi.service
  • container-web.service
  • container-prosody.service
  • container-jicofo.service
  • container-jvb.service
  • container-jigasi.service

作成された上記ファイルを、ユーザレベルでシステムデーモンで管理する場合には、~/.config/systemd/user ディレクトリへコピーして下さい。

$ cp *.service ~/.config/systemd/user 

各サービスの有効化

$ systemctl --user daemon-reload
$ systemctl --user enable pod-pod-jitsi
$ systemctl --user enable pod-pod-nginx

サービスの起動

$ systemctl --user start pod-pod-jitsi
$ systemctl --user start pod-pod-nginx

上記の方法では、ユーザがログインする時のみ有効なので、ユーザログインに関係なく起動するには、以下の設定が必要です。

$ sudo loginctl enable-linger $(whoami)

Systendサービスの有効化