跳到主要內容
節省工具箱Jason Tools
專案分享

jt-vc-portal:替 Jitsi Meet 補上會議管理入口

Jason Cheng 瀏覽 1,122 次
jt-vc-portal:替 Jitsi Meet 補上會議管理入口
本文目錄
  1. 為什麼需要一個會議入口
  2. 兩種連線模式怎麼選
  3. 會議室管理與邀請
  4. 來賓流程
  5. 帳號、角色與稽核
  6. 用量統計
  7. 錄影調閱(搭配自建 Jibri)
  8. 會議室自訂與外觀
  9. 安全性實作
  10. 系統需求與安裝
  11. 部署注意事項
  12. 附帶的 Jitsi Meet 與 Jibri 安裝文件
  13. 結論
  14. 參考資料

五六年前我做了不少件 Jitsi Meet 開源視訊會議的建置案。如果想要一套完全自主可控的視訊會議系統,它至今仍是首選之一,我在 2020 年那篇「遠端會議與遠端教學開源套件如何選擇」裡把它跟 BigBlueButton 等方案做過一輪比較。

但它最大的缺點在於沒有好用的帳號管理功能。每次建置案都得做大量的客製修改與設定,主持人認證要去改 prosody、大廳要調 jicofo、錄影要另外接 Jibri,做起來真要命,所以後來我很少接這類專案了。

因緣際會最近又有一案,索性把這些缺的東西一次補上來,把 Webex、Zoom、Google Meet 那種風格的會議室建置與邀請流程做進去,成果就是 jt-vc-portal,目前版本 v1.6.1,以 Apache 2.0 授權釋出。

簡單說,它是一個架在 Jitsi Meet 前面的會議入口閘道:主持人登入後建立會議室、產生邀請連結與 QR Code、寄送含行事曆檔的邀請信,所有行為都留下稽核記錄。後端的連線模式可以選 8x8 JaaS 雲端託管,也可以指向自建的 Jitsi Meet,管理介面一鍵切換。

為什麼需要一個會議入口

Jitsi Meet 本身的設計哲學是「連結即會議室」,開箱就能用,這是它的優點,但放到公司環境裡就會出現一連串問題。

沒有入口閘道時

  • 邀請連結散落各處
    誰建的、給了誰,事後無從追查
  • 來賓可任意進入
    缺乏開放時段與身分控制,知道會議室名稱就能進去
  • 沒有登入與行為記錄
    無法稽核,也無法外拋到 SIEM
  • 綁死單一雲端服務
    要切換或改成自建以節省成本都不容易
  • 帳號管理只能魔改 prosody
    就算硬擠出主持人認證,設定繁瑣又難維護

最後那一點是我當年最有感的。我在 2022 年寫過一篇「拆解 Jitsi Meet 進階管理能力」,整理過主持人認證、大廳、麥克風與攝影機管理、錄影到本地伺服器這幾件事怎麼做。當時的結論是:能做,但每一項都得手動改設定檔,而且改完之後沒有介面可以管理。

加上 jt-vc-portal 之後

  • 統一入口
    主持人登入才能建立會議室,行為全程稽核
  • 預約時段與具名來賓
    來賓需自填名稱,且主持人在線上才放行
  • 多帳號、角色、2FA
    登入記錄可外拋 syslog、CEF、GELF
  • 雙連線模式
    8x8 JaaS 或自建 Jitsi Meet 一鍵切換,不動程式碼
  • 帳號與權限網頁化管理
    免碰 prosody 設定檔

整個系統零外部 PHP 套件,核心全部手工寫,前端只用到 CDN 上的 qrcodejs 與 flatpickr 兩支,並加上 SRI 完整性驗證。

兩種連線模式怎麼選

這裡先補一個背景:8x8 自 2018 年起就是 Jitsi 與 Jitsi Meet 的開發與維護公司,而 JaaS(Jitsi as a Service)就是他們官方的雲端託管 Jitsi 服務。所以這兩種模式並不是「原廠與山寨」的關係,而是同一套技術的託管版與自建版。

兩種模式都能在管理介面一鍵切換、不必改程式,依團隊規模與維運能力選擇即可:

8x8 JaaS(雲端託管)

適合小團隊、想快速上線、不想維運伺服器的情境。

  • 提供免費 Dev 方案,每月 25 MAU 免費額度,小團隊幾乎零成本上線
  • 免維運,伺服器、JVB、錄影皆由 8x8 代管
  • 全球節點、品質穩定,幾分鐘即可開通
  • 缺點:依 MAU 計費,規模一大成本就上升;媒體流經第三方雲端,需自行評估隱私與合規

自建 Jitsi Meet

適合重視隱私自主、中小規模、且具備維運能力的情境。

  • 完全自主掌控,媒體資料不出自家機房
  • 沒有 MAU 計費,規模越大反而越省
  • 可深度客製,也方便與內網整合
  • 缺點:需自行維運 Jitsi、prosody、jicofo、JVB;錄影要搭配自建 Jibri;並發量大時需要擴充頻寬

對照表

  • 維運負擔
    JaaS:無,全代管 / 自建:需自行維運
  • 上線速度
    JaaS:幾分鐘 / 自建:需先架站
  • 費用模式
    JaaS:免費 Dev 方案 25 MAU,超過依 MAU 計費 / 自建:自有硬體與頻寬
  • 資料主權
    JaaS:經 8x8 雲端 / 自建:完全自有
  • 錄影
    JaaS:內建,依方案 / 自建:搭配自建 Jibri
  • 適合規模
    JaaS:不限規模,依 MAU 計費 / 自建:中小型或高隱私需求
  • JWT 簽章
    JaaS:RS256 加 kid / 自建:HS256 或免 JWT

順帶解釋一下 MAU(Monthly Active Users,月活躍使用者):指一個計費週期內「不重複」加入會議的人數,同一個人開十次會也只算一位。8x8 JaaS 以此計費,免費 Dev 方案每月含 25 位;自建 Jitsi Meet 則沒有這個限制。系統的用量統計頁會依訂閱週期統計目前的 MAU。

我的建議是小團隊先從 JaaS 起步,免架站、免維運就能上線,等規模成長再評估轉自建。

會議室管理與邀請

登入後的儀表板就是主控台:輸入會議室名稱一鍵建立或進入,也可以亂數產生名稱。

儀表板:近期會議室清單顯示建立者、進入時間與開了多久
儀表板:近期會議室清單顯示建立者、進入時間與開了多久

下方的「近期會議室」清單會顯示每一間是誰建立、何時進入、開了多久,以及預約、大廳、主持人是否在線上等狀態。

建立會議室時可以勾選兩個選項:

  • 限定開放時段
    設定會議的開放時間,未到時間來賓會看到等候倒數頁;主持人提前進入即自動放行
  • 大廳模式
    主持人進場後自動開啟,來賓需經主持人逐一允許才能進入
建立會議室:勾選開放時段後可直接寄送含 .ics 的 Email 邀請
建立會議室:勾選開放時段後可直接寄送含 .ics 的 Email 邀請

建立完成後會立刻拿到邀請連結與 QR Code 彈窗,兩種快速使用方式:連結貼給對方,或是讓對方直接掃 QR Code。

也可以直接填入與會者的 Email,系統會寄送含 .ics 行事曆邀請的信件,收件人一鍵就能加入自己的行事曆,主旨與內文範本都可以自訂。

來賓流程

來賓憑邀請連結進入,須先輸入顯示名稱才能進場,進入會議時會自動帶入這個名稱。整個來賓流程都套用站台主題與品牌,與主持端的體驗一致。

來賓進入:須先自填顯示名稱才能進場
來賓進入:須先自填顯示名稱才能進場

若不在開放時段,來賓會看到翻頁時鐘倒數與會議的起訖時間(就是本文的首圖)。一旦主持人提前進入,系統每隔數秒自動偵測並放行,來賓不需要重整頁面,也不必在那邊苦等。會議已結束則顯示對應的結束頁。

帳號、角色與稽核

這是當初 Jitsi Meet 最缺、也是我最想補的部分。

多帳號與角色

支援多個主持人帳號與兩種角色:admin 可以看全部會議室與所有管理頁,host 只看得到自己建立的。每個帳號可設定顯示名稱、Email、啟用 TOTP 雙因素認證,並可隨時編輯或停用。

帳號管理:會議室依主持人個別隔離,可逐一啟用 TOTP 2FA
帳號管理:會議室依主持人個別隔離,可逐一啟用 TOTP 2FA

登入保護方面提供 fail2ban 登入失敗鎖定,並且是依真實來源 IP 判斷,這點在反向代理架構下要特別注意設定,後面會再提。

稽核記錄與 SIEM 外拋

登入登出、建立與進入會議室、寄送邀請、帳號與設定變更等行為全數留存。可依行為類型、關鍵字與日期範圍篩選,欄位標題可點擊排序。

稽核記錄:可依類型、關鍵字與日期篩選,並即時外拋至 SIEM
稽核記錄:可依類型、關鍵字與日期篩選,並即時外拋至 SIEM

記錄可以即時外拋 syslog、CEF、GELF 三種格式到 SIEM,要接 Graylog、Splunk 或 ArcSight 都可以。

用量統計

數據中心一頁掌握使用狀況,分成通用與 JaaS 專屬兩部分。

用量統計:會議時長時間軸、主持人排行榜與近 30 天活動趨勢
用量統計:會議時長時間軸、主持人排行榜與近 30 天活動趨勢
  • 兩種模式通用
    會議場次與時長、本期會議時長時間軸、主持人排行榜、近 30 天活動折線圖、尖峰同時人數、參與者進出時間軸
  • JaaS 模式專屬
    本期 MAU 用量與方案上限、各計費週期歷史趨勢,並可手動校正用量基準。另可接 USAGE webhook 做 MAU 統計

自建模式下,上述 JaaS 專屬的兩項會自動隱藏,頁籤名稱也會改稱「會議統計」。

錄影調閱(搭配自建 Jibri)

如果是自建 Jitsi Meet 加上 Jibri 的架構,可以在這裡調閱錄影檔。

錄影記錄:線上播放、下載、刪除,並顯示錄影主機磁碟容量
錄影記錄:線上播放、下載、刪除,並顯示錄影主機磁碟容量
  • 線上播放、下載、刪除
    並顯示每一筆的大小、長度、狀態
  • 依會議室、主持人、參與者搜尋
    點任一列可展開該場會議的參與者進出時間軸
  • 權限分明
    主持人只看得到自己主持會議的錄影,管理者可管全部
  • 主機容量與保留政策
    可依時間(保留 N 天)、容量(保留可用空間或總量上限)或殘留檔自動清理

請注意保留政策預設全部停用,這是為了避免誤刪,要用請自行評估後開啟。

錄製設定頁還可以設定錄製者在與會者清單中顯示的名稱,並串接 Jibri 主機的調閱服務,填入服務 URL 與 token 後會顯示連線狀態與已註冊的錄製器數量。

關於 Jitsi Meet 的錄影,我在 2023 年也寫過一篇「Jitsi Meet 本機錄影功能釋出」,講的是不需要 Jibri 的本機錄影方式,可以搭配著看,兩者適用的情境不同。

會議室自訂與外觀

自建 Jitsi Meet 模式下,可以逐間設定會議室的介面行為,而且不需要改動 Jitsi 的設定檔,所有設定都在進入會議時自動帶入。

會議室自訂:進入時靜音、畫質上限、預設檢視與工具列功能逐項勾選
會議室自訂:進入時靜音、畫質上限、預設檢視與工具列功能逐項勾選

可調整的項目包含進入時是否靜音與關鏡頭、畫質上限、預設檢視(演講者或畫廊)、是否關閉「視訊省頻寬」的自動降載,以及逐項勾選工具列要開放哪些功能,例如聊天、螢幕分享、舉手、錄影、虛擬背景、共享文件等。

外觀客製方面提供 60 種 Jitsi 介面語言、22 種佈景主題、站台名稱與 logo 替換,還有登入頁路徑偽裝。最後這項對於必須對外開放的站台特別有用,可以避免登入頁被自動化工具掃到。

安全性實作

安全性是依 OWASP Top 10:2025 逐項對應實作的:

  • A01 存取控制
    未授權頁面回 404、會議室依擁有者隔離、CSRF token
  • A02 安全設定
    關閉錯誤顯示與版本洩漏、加上安全標頭、敏感路徑拒絕存取
  • A03 供應鏈
    零外部 PHP 套件;前端 CDN 資源加 SRI 完整性驗證;映像建置時套用最新 OS 安全更新
  • A04 加密
    bcrypt 密碼、JWT 簽章、webhook HMAC、安全 session cookie
  • A05 注入
    輸出跳脫、輸入清洗、Email header injection 防護
  • A06 安全設計
    閘道式架構、預設安全(來賓須具名、主持人在線上才放行)、角色最小權限
  • A07 認證
    TOTP 2FA、fail2ban 登入鎖定(依真實來源 IP)
  • A08 資料完整性
    webhook 以 HMAC 簽章驗證來源,並用 idempotency key 去除重複事件
  • A09 記錄與告警
    完整稽核記錄加即時 SIEM 外拋
  • A10 例外處理
    失敗安全降級:讀取失敗回預設值、寄信或外拋失敗不阻斷主流程、錯誤訊息不外洩

系統需求與安裝

系統需求

  • PHP
    最低 8.2,建議 8.4
  • Web 伺服器
    Apache 加 mod_rewrite,需 AllowOverride All;建議再加上 HTTPS
  • PHP 擴充
    openssl、fileinfo、json、mbstring
  • 其他
    可寫入的資料目錄;JaaS 模式需要 8x8 私鑰;走 Docker 則需 Docker 24 以上

提供三種安裝方式,資料與設定皆持久化,更新不會遺失。

方法一:直接安裝(Apache + PHP)

# 取得程式並啟用 .htaccess
git clone https://github.com/jasoncheng7115/jt-vc-portal.git
cd jt-vc-portal
a2enmod rewrite headers
cp dot.htaccess .htaccess

# 持久化資料目錄(預設 /var/jaas-data,可於 config.php 調整)
sudo mkdir -p /var/jaas-data && sudo chown www-data:www-data /var/jaas-data

# JaaS 模式才需要:放入 8x8 私鑰
sudo mkdir -p keys && sudo cp /path/to/private.key keys/private.key

其餘設定在 config.php 調整,包含 DATA_DIR、JWT_PRIVATE_KEY_PATH、初始管理者帳密與可信代理設定。

方法二:Docker 自行打包

git clone https://github.com/jasoncheng7115/jt-vc-portal.git
cd jt-vc-portal
docker build --pull -t jt-vc-portal .

mkdir -p /opt/jt-vc-portal/keys /opt/jt-vc-portal/data
chown 33:33 /opt/jt-vc-portal/data
cp /path/to/private.key /opt/jt-vc-portal/keys/private.key   # JaaS 模式才需要

docker run -d --restart unless-stopped -p 127.0.0.1:58189:58189 \
    -e JTVC_ADMIN_EMAIL="admin@example.com" \
    -e JTVC_ADMIN_PASSWORD="請設定強密碼" \
    -e JTVC_TRUSTED_PROXIES="127.0.0.1,172.16.0.0/12" \
    -v /opt/jt-vc-portal/keys/:/var/www/html/keys \
    -v /opt/jt-vc-portal/data/:/var/jaas-data \
    --name jt-vc-portal jt-vc-portal

方法三:從 Release 載入預建映像

不想自己 build 的話,可以直接下載 Release 打包好的映像,目前僅提供 linux/amd64:

curl -LO https://github.com/jasoncheng7115/jt-vc-portal/releases/download/v1.6.1/jt-vc-portal-1.6.1-docker-amd64.tar.gz
sha256sum -c jt-vc-portal-1.6.1-docker-amd64.tar.gz.sha256   # 驗證完整性
docker load < jt-vc-portal-1.6.1-docker-amd64.tar.gz        # 載入為 jt-vc-portal:latest

之後的 docker run 參數與方法二相同。

更新與升級

所有設定與資料(帳號、會議室、稽核、用量等)都存在 DATA_DIR 或掛載卷裡,更新不會遺失,JSON 結構會自動相容升級。不過更新前仍建議先備份資料目錄與 keys/:

# 更新前備份(建議)
cp -a /opt/jt-vc-portal/data /opt/jt-vc-portal/data.bak-$(date +%Y%m%d)

# 方法一:直接安裝
git pull
cp dot.htaccess .htaccess        # 若 .htaccess 有更新
sudo systemctl reload apache2    # 清 opcache

# 方法二:Docker 自行 build
git pull
docker build --pull -t jt-vc-portal .
docker stop jt-vc-portal && docker rm jt-vc-portal
# 再以原本的參數重新 docker run

登入後可以從左上角的版本號確認是否已更新到新版。

部署注意事項

反向代理與真實來源 IP

系統對外是 :58189,正式環境建議前面再以 nginx 或 Apache 反向代理掛上 HTTPS:

server {
    listen 443 ssl;
    server_name vc.example.com;

    # ssl_certificate     /etc/letsencrypt/live/vc.example.com/fullchain.pem;
    # ssl_certificate_key /etc/letsencrypt/live/vc.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:58189/;
        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;
    }
}

系統以 X-Real-IP 取得真實來源 IP,供 fail2ban 鎖定與稽核使用,因此請務必讓反向代理帶上這個 header。若前面經過 Cloudflare,請讓反向代理由 CF-Connecting-IP 帶入 X-Real-IP。

務必設定 JTVC_TRUSTED_PROXIES

這是要對外開放時最重要的一項。JTVC_TRUSTED_PROXIES 以逗號分隔 IP 或 CIDR,設定後系統只採信這些可信代理送來的來源標頭。

同時請以 -p 127.0.0.1:58189:58189 或防火牆限制容器埠只讓反向代理可達。否則攻擊者可以直接偽造 X-Real-IP,繞過 fail2ban 並污染稽核記錄。

這個變數留空等於相容模式,也就是盲信標頭,只有在容器埠確實有做隔離的情況下才安全,請勿在對外環境下留空。

啟用 JWT 後行動 App 無法直接加入

這點務必先評估清楚。啟用 JWT 驗證後(8x8 JaaS 一律需要;自建 Jitsi Meet 設 ENABLE_AUTH=1 時),會議室只接受 jt-vc-portal 簽發的 token。

因此官方的 Jitsi Meet 行動 App(iOS 與 Android)將無法直接加入,手機使用者請改用手機瀏覽器開啟邀請連結。

附帶的 Jitsi Meet 與 Jibri 安裝文件

如果要走自建路線,這個專案同時附上兩份完整的部署文件,這也是我當年做建置案時最希望有人先寫好的東西:

  • JITSI-MEET-SETUP.md
    從官方 Docker 版 Jitsi Meet 一路設定到與 jt-vc-portal 搭配,包含架構、連接埠與 NAT、TLS、JWT 與主持人權限、媒體後援與 TURN
  • JIBRI-SETUP.md
    在自建 Jitsi Meet 上加裝 Jibri 錄影,包含 VM 需求、snd-aloop、同時多會議室錄製、錄影中文顯示所需的 CJK 字型、獨立 Jibri VM 的實作方式

Jibri 屬於選配,不安裝完全不影響 Jitsi Meet 與會議運作,只是不提供錄影功能,需要時再加裝即可。

結論

Jitsi Meet 本身的技術一直都很好,我當年不再接這類案子的原因,從來不是它的視訊品質不行,而是缺少一層企業環境該有的管理與稽核,導致每一案都要重新客製一遍。

jt-vc-portal 想補的就是這一層。把帳號、角色、2FA、預約、大廳、邀請、稽核、統計、錄影調閱這些東西做成網頁介面,讓維運的人不用再去碰 prosody 設定檔。

另外我覺得雙模式的設計蠻實用的:小團隊先用 8x8 JaaS 的免費 Dev 方案(每月 25 MAU)幾分鐘上線,等到規模成長、或是合規上要求媒體資料不得出自家機房,再切換成自建 Jitsi Meet,這個切換是在管理介面改設定,不需要改程式碼。

專案以 Apache 2.0 授權釋出,歡迎取用、修改與回報問題。如果你也曾經為了 Jitsi Meet 的帳號管理魔改過 prosody,應該會懂我在說什麼。

參考資料

延伸閱讀