1. 环境准备:从一台“裸机”Ubuntu服务器开始

大家好,我是老张,一个在运维和开发领域摸爬滚打了十多年的老手。今天咱们不聊那些虚的,就手把手地带你,在一台全新的Ubuntu服务器上,从零开始搭建一套完全属于你自己的Jitsi Meet视频会议系统。为什么选择私有化部署?很简单,数据安全、自主可控、没有使用限制,而且一旦部署好,它就是你的“数字会议室”,随时可用。整个过程我们会用到Docker和Docker Compose,这两个工具可以说是现代应用部署的“黄金搭档”,能帮你把复杂的服务依赖和环境配置打包管理,让部署变得像搭积木一样简单。

在开始之前,我们先明确一下目标服务器。我假设你手上有一台刚装好Ubuntu 24.04 LTS的云服务器或者本地虚拟机,拥有root权限,并且能通过SSH连接上去。服务器的配置嘛,对于一个小团队(比如20人以内同时开会)来说,2核4G的配置就够用了,当然,配置越高,能支持的并发会议和人数就越多。好了,废话不多说,咱们挽起袖子开干。第一步,就是把这台“裸机”服务器,变成一个能跑Docker的现代化应用平台。

1.1 系统基础更新与依赖安装

连上你的服务器,第一件事永远是更新系统。这就像你搬进新家,得先打扫一下,把该补的补丁都打好。打开终端,输入以下命令:

sudo apt update && sudo apt upgrade -y

这个命令会更新软件包列表,并升级所有可升级的软件包。-y参数是为了自动确认,省得我们一直按回车。这个过程可能需要几分钟,取决于网络速度和更新包的大小。更新完成后,我们安装一些后续步骤必需的软件包:

sudo apt install -y apt-transport-https ca-certificates curl software-properties-common git

我来解释一下这几个包是干嘛的:apt-transport-https允许apt通过HTTPS协议下载软件;ca-certificates是CA根证书,用于验证HTTPS连接的安全性;curl是一个命令行下载工具,我们待会儿会频繁用到;software-properties-common提供了一些管理软件源的工具;git则是为了从GitHub上拉取Jitsi的官方Docker配置仓库。这些是基础中的基础,必须装好。

1.2 Docker引擎的安装与配置

接下来是重头戏:安装Docker。Docker官方提供了非常方便的安装脚本,但我们作为严谨的运维,更推荐使用添加官方仓库的方式,这样便于后续管理和升级。首先,添加Docker的官方GPG密钥,这相当于给软件加了个“防伪码”,确保我们下载的包是官方正品:

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

然后,将Docker的APT软件源添加到系统源列表中。这里有个小技巧,我们使用$(lsb_release -cs)来自动获取当前Ubuntu版本的代号,比如“jammy”,这样命令就更通用了:

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

添加完仓库,再次更新软件包列表,并安装Docker引擎及其相关组件:

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

安装完成后,启动Docker服务并设置开机自启:

sudo systemctl start docker
sudo systemctl enable docker

最后,验证一下Docker是否安装成功,运行docker --version,如果能看到版本号输出,比如“Docker version 24.0.7”,那就恭喜你,第一步成功了。为了让后续拉取镜像的速度飞起来,我强烈建议配置一下国内镜像加速器。创建或编辑/etc/docker/daemon.json文件:

sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": [
    "https://docker.m.daocloud.io",
    "https://mirror.baidubce.com",
    "https://hub-mirror.c.163.com"
  ]
}
EOF

然后重启Docker服务使配置生效:

sudo systemctl daemon-reload
sudo systemctl restart docker

1.3 Docker Compose的独立安装

虽然我们上面安装了Docker官方的Compose插件,但Jitsi的官方文档和社区习惯上更多使用独立的docker-compose命令(注意中间有横杠)。为了兼容性,我们最好也把它装上。我们去Docker Compose的GitHub发布页面下载最新的稳定版二进制文件。你可以先访问页面看看最新版本号,或者直接用我写这篇文章时的v2.24.0版本:

sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

下载完成后,赋予它可执行权限:

sudo chmod +x /usr/local/bin/docker-compose

最后,创建一个软链接,让我们在任意目录都能直接输入docker-compose来调用它:

sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

现在,运行docker-compose --version检查一下,如果显示类似“Docker Compose version v2.24.0”的信息,那么我们的基础环境就全部准备妥当了。服务器已经从一张白纸,变成了一个功能完善的Docker运行环境,接下来就可以请出今天的主角——Jitsi Meet了。

2. 获取与配置Jitsi Meet的Docker项目

环境准备好了,就像厨房的灶台、锅碗瓢盆都齐了,现在该去拿菜谱和食材了。对于Jitsi Meet来说,这个“菜谱”就是官方维护的docker-jitsi-meet项目。它把Jitsi复杂的多个组件(像Web前端、视频桥接器、信令服务器等)用Docker Compose的方式编排好,我们只需要按照说明配置一下,就能一键启动,非常省心。

2.1 拉取项目代码与目录规划

首先,我习惯在/opt目录下管理这类服务,当然你也可以放在/home目录或者任何你喜欢的地方。我们创建一个专门的工作目录:

sudo mkdir -p /opt/jitsi
cd /opt/jitsi

然后,使用git克隆官方仓库。如果服务器没有git,我们之前已经安装过了:

sudo git clone https://github.com/jitsi/docker-jitsi-meet.git

克隆完成后,你会看到一个docker-jitsi-meet的文件夹。进入这个文件夹,所有后续的操作都在这里进行:

cd docker-jitsi-meet

这里有个非常重要的经验之谈:Jitsi在运行时会生成大量的配置文件、SSL证书、录音文件等。官方推荐的做法是通过环境变量CONFIG指定一个外部持久化目录,这样即使删除并重建容器,你的配置和数据也不会丢失。我们提前创建好这个目录,并给它合适的权限:

sudo mkdir -p /opt/jitsi/config
sudo chown -R $USER:$USER /opt/jitsi/config

2.2 详解.env环境配置文件

项目根目录下有一个env.example文件,这是所有配置的模板。我们的第一步就是复制它,并生成自己的配置文件:

cp env.example .env

这个.env文件是整个部署的核心,它定义了服务如何运行。用你喜欢的文本编辑器(如nanovim)打开它,我们来逐一解读和修改关键配置。别担心,我带你一个个过。

nano .env

首先看基本配置区域

  • CONFIG=/opt/jitsi/config:这就是我们刚才创建的持久化配置目录路径。请确保路径正确。
  • HTTP_PORT=8000:HTTP服务端口。Jitsi默认会将所有HTTP请求重定向到HTTPS,这个端口可以按需修改。
  • HTTPS_PORT=9443这是最重要的端口,Web界面将通过这个HTTPS端口访问。如果你有域名和标准443端口,可以改为443
  • TZ=Asia/Shanghai:设置容器内时区,确保会议预约、日志时间显示正确。

接下来是网络与访问配置,这里最容易出错:

  • PUBLIC_URL=https://your-domain.com:${HTTPS_PORT}请务必将your-domain.com替换成你的公网IP地址或域名。例如,如果你用IP,且HTTPS端口是9443,就写成https://117.141.143.200:9443。如果使用域名且端口是标准的443,可以写成https://meet.yourcompany.com。这个URL是生成会议链接的基础,配错了别人就无法正确访问。
  • DOCKER_HOST_ADDRESS=117.141.143.200:填写你服务器的公网IP地址。这个地址用于视频桥接器(JVB)向外界通告自己的位置,对于视频流传输至关重要。
  • ENABLE_GUESTS=1:我强烈建议设置为1。这意味着启用“访客”模式,用户无需注册账号,点击会议链接就能直接加入,体验和主流会议软件一样,极大降低了使用门槛。

然后是安全与证书配置。Jitsi强制要求HTTPS,你有两个选择:

  1. 使用Let‘s Encrypt自动证书(推荐给有域名的用户):将ENABLE_LETSENCRYPT=1,并设置LETSENCRYPT_DOMAIN=your-domain.comLETSENCRYPT_EMAIL=your-email@example.com。Docker会帮你自动申请和续期免费证书,非常方便。
  2. 使用自定义证书(适合IP访问或已有证书):就像原始文章里那样,你需要指定证书和私钥的路径。例如:
    ENABLE_LETSENCRYPT=0
    SSL_CERT=/opt/jitsi/certs/cert.pem
    SSL_KEY=/opt/jitsi/certs/key.pem
    
    你需要提前将你的PEM格式的证书和私钥文件放到服务器指定路径下。

最后,运行一个脚本来生成各个服务所需的随机密码(比如PostgreSQL数据库密码、Jicofo组件的密钥等):

./gen-passwords.sh

这个脚本会修改你的.env文件,在末尾添加一系列_PASSWORD_SECRET的变量。这些密码请务必保管好,不要泄露

2.3 首次启动与问题排查

配置保存好后,激动人心的时刻到了——启动所有服务!在项目目录下执行:

docker-compose up -d

这个-d参数代表“detached”,让服务在后台运行。Docker Compose会根据docker-compose.yml文件,依次拉取镜像(如果本地没有)、创建网络、启动容器。第一次运行会下载好几个镜像,总大小约1.5GB,请耐心等待,喝杯咖啡。

启动完成后,用docker-compose ps命令查看所有容器的状态。正常情况下,你应该看到webprosodyjicofojvb这几个容器的状态都是“Up”。如果某个容器是“Restarting”或“Exit”,就需要查看日志了:

docker-compose logs [服务名]  # 例如 docker-compose logs web

最常见的启动问题

  1. 端口冲突:如果80009443端口被占用,去.env文件里改成其他端口。
  2. 证书问题:如果使用自定义证书但路径或权限不对,web容器会启动失败。检查证书文件是否存在,并且Docker进程有读取权限。
  3. PUBLIC_URL配置错误:这是最普遍的问题。确保这个URL能从外部网络访问,并且协议(https)、IP/域名、端口号完全匹配。

当所有容器都稳定运行后,打开浏览器,访问你配置的PUBLIC_URL(例如https://你的IP:9443)。你应该能看到Jitsi Meet的欢迎界面,输入一个会议名称(如MyFirstMeeting),点击“Go”,就能进入一个崭新的视频会议室了!至此,一个基础功能的私有化Jitsi Meet已经部署成功。

3. 网络、防火墙与性能调优

系统跑起来了,但这只是开始。要让它在生产环境中稳定、安全地为团队服务,我们还需要做一些“加固”和“调优”的工作。这一部分,我们就来聊聊网络配置、防火墙规则以及一些提升体验的性能参数调整。

3.1 防火墙与端口开放指南

你的Ubuntu服务器很可能默认开启了防火墙(如ufw)。为了让外部用户能访问会议服务,我们必须开放相关端口。Jitsi Meet主要涉及三类端口:

  1. Web访问端口:就是你在.env里设置的HTTP_PORTHTTPS_PORT(例如8000和9443)。我们需要开放TCP协议。
  2. 媒体流端口(最关键):这是视频、音频数据实际传输的通道。Jitsi Video Bridge(JVB)默认使用UDP 10000端口范围。在.env中,这个范围由JVB_PORT定义,默认是10000/udp。但在高并发场景下,JVB会使用多个端口。安全起见,我建议开放一个UDP端口范围,比如10000-20000/udp
  3. STUN/TURN服务器端口:在复杂网络环境下(如对称型NAT),可能需要TURN服务器来中继媒体流。如果你启用了内置的TURN服务器(通过设置ENABLE_TURN=1),还需要开放其端口(默认TCP和UDP的3478)。

使用ufw开放端口的命令如下:

# 开放Web端口(TCP)
sudo ufw allow 8000/tcp
sudo ufw allow 9443/tcp

# 开放媒体流端口范围(UDP,非常重要!)
sudo ufw allow 10000:20000/udp

# 如果启用了TURN,开放其端口
# sudo ufw allow 3478/tcp
# sudo ufw allow 3478/udp

# 别忘了开放SSH端口,否则下次就连不上了
sudo ufw allow 22/tcp

# 启用防火墙
sudo ufw enable

执行后,使用sudo ufw status verbose查看规则是否已生效。特别注意:如果你使用的是阿里云、腾讯云等云服务器,除了系统防火墙,还需要在云服务商的控制台(安全组)中同样添加上述入站规则,否则流量在到达服务器前就会被拦截。

3.2 性能关键参数调优

默认配置适合小规模使用。如果你们团队经常有十几人以上的大会,或者对视频质量要求很高,调整以下参数能带来显著提升。这些配置都在.env文件中。

  • 调整JVB(视频桥接器)资源:JVB是负责转发所有视频、音频流的组件,最吃资源。你可以通过环境变量为JVB容器分配更多CPU和内存。但这需要在docker-compose.yml中修改jvb服务的deploy.resources部分。更简单的方法是确保宿主机有足够资源,并调整JVB的内部参数:

    # 设置JVB可以使用的最大端口数,更多端口意味着支持更多并发流
    JVB_PORT=10000
    # 这个变量实际定义的是起始端口,JVB会使用从该端口开始的一系列端口。
    # 修改docker-compose.yml中jvb服务的`--apis=rest,xmpp`参数后,可以添加`--min-port=10000 --max-port=20000`来明确范围。
    

    更直接的性能提升是给JVB容器分配更多CPU核心和内存。你可以创建一个docker-compose.override.yml文件来覆盖默认配置,这是一个更优雅的方式。

  • 开启视频编码硬件加速:如果服务器有Intel GPU(支持QSV)或NVIDIA GPU,可以开启硬件编码来大幅降低CPU负载,提升多人会议流畅度。这需要额外的Docker配置和驱动安装,属于进阶优化。对于绝大多数场景,优先保证CPU(建议4核以上)和内存(JVB容器建议分配2GB+)充足更为关键。

  • 配置TURN服务器:当参会者双方都处于严格的对称型NAT或防火墙后时,直接P2P连接可能失败,此时必须通过TURN服务器中转。虽然Jitsi套件包含了coturn组件(通过ENABLE_TURN=1开启),但对于生产环境,我建议将TURN服务部署在独立的、拥有公网IP的服务器上,并配置域名和SSL证书。然后在Jitsi的Web配置中指定这个外部的TURN服务器。这样可以获得更好的中继性能和稳定性。

3.3 日常维护与监控命令

部署不是一劳永逸,我们需要知道如何查看状态、更新和排错。

  • 查看服务状态和日志

    # 查看所有容器状态
    docker-compose ps
    # 查看web服务的实时日志
    docker-compose logs -f web
    # 查看jvb(视频桥)的日志,关注视频流健康度
    docker-compose logs -f jvb
    
  • 重启、停止和启动服务

    # 修改.env配置后,重启所有服务使配置生效
    docker-compose restart
    # 停止所有服务
    docker-compose down
    # 启动所有服务(在已停止的情况下)
    docker-compose up -d
    
  • 备份关键数据:最重要的就是CONFIG目录(/opt/jitsi/config),里面包含了SSL证书、自定义配置、插件等。定期备份这个目录即可。录音文件(如果启用)默认存储在CONFIG目录下的recordings子文件夹中,也需要定期备份。

  • 更新Jitsi版本:官方镜像会持续更新。更新前,请务必备份你的.env文件和CONFIG目录。然后拉取最新的镜像并重启:

    docker-compose pull
    docker-compose up -d
    

    更新后,首次启动可能会因为数据库 schema 变更而稍慢一些,属于正常现象。

4. 深度定制:打造专属品牌会议系统

现在,我们的Jitsi Meet已经稳定运行了。但它看起来还是那个“大众脸”。接下来,我要教你如何给它“整容”,换上自己公司的Logo、修改界面文字、调整颜色主题,让它真正成为你们团队或公司的专属会议平台。这个定制过程,其实就是替换前端资源文件的过程。

4.1 理解定制文件的存放结构

Jitsi Meet的Web界面(由web容器提供)的所有静态资源,在容器内部都存放在/usr/share/jitsi-meet目录下。我们需要做的,就是把想修改的文件从容器里复制到宿主机,修改后再拷贝回去。为了方便管理,我们在宿主机上建立一个镜像目录:

# 在宿主机上创建用于定制的工作目录
mkdir -p /opt/jitsi/customization

首先,我们将容器内的整个静态资源目录拷贝出来:

# 先查看web容器的确切名称
docker-compose ps | grep web
# 假设容器名是 docker-jitsi-meet-web-1
docker cp docker-jitsi-meet-web-1:/usr/share/jitsi-meet /opt/jitsi/customization/

现在,/opt/jitsi/customization/jitsi-meet目录下就有了和容器内一模一样的文件结构。其中,我们最关心的几个文件夹是:

  • images/:存放所有图片,如Logo、水印、图标。
  • lang/:存放各种语言的翻译文件,我们要修改的中文界面就在main-zh-CN.json里。
  • css/:存放样式表,可以修改主题颜色、字体等(高级定制)。

4.2 修改界面文字与语言

Jitsi Meet支持多语言,界面文字都定义在JSON文件中。我们要定制中文界面,就修改/opt/jitsi/customization/jitsi-meet/lang/main-zh-CN.json文件。

用编辑器打开这个文件,你会发现它是一个巨大的JSON对象。别怕,我们只需要找几个关键字段修改。我推荐使用jq工具来格式化查看,或者用支持JSON高亮的编辑器。

nano /opt/jitsi/customization/jitsi-meet/lang/main-zh-CN.json

使用搜索功能(在nano里按Ctrl+W),查找以下关键词并修改:

  • "headerTitle":这是欢迎页顶部的大标题。把它的值从"Jitsi Meet"改成你们公司的名字,比如"星辰科技视频会议"
  • "appName":应用名称,出现在浏览器标签页和关于对话框中。
  • "inviteTitle":邀请他人加入会议时的弹窗标题。
  • 你还可以修改"toolbar"部分的按钮提示,或者"settings"里的各种设置项标签,让术语更符合你们公司的习惯。

注意:JSON格式非常严格,修改时只改双引号内的值,不要动键名、引号或逗号,否则会导致界面加载错误。

4.3 替换Logo与图标

接下来是换Logo。Jitsi Meet的Logo主要出现在两个地方:欢迎页(水印)和会议内左上角。

  1. 准备图片:你需要准备两个SVG格式的图片文件。一个用于欢迎页水印(建议尺寸大一些,比如512x512),命名为watermark.svg;一个用于会议内标题栏图标(尺寸小一些,比如64x64),命名为logo.svg。如果你只有PNG或JPG图片,可以用在线工具(如cloudconvert.com)转换成SVG,但复杂图片转换效果可能不佳,简单的Logo没问题。

  2. 替换文件:将你准备好的watermark.svglogo.svg文件,直接覆盖到宿主机拷贝目录的对应位置:

    # 假设你的图片放在 /opt/jitsi/customization/my_logos/ 下
    cp /opt/jitsi/customization/my_logos/watermark.svg /opt/jitsi/customization/jitsi-meet/images/
    cp /opt/jitsi/customization/my_logos/logo.svg /opt/jitsi/customization/jitsi-meet/images/
    
  3. 修改界面配置指向新Logo:光替换文件还不够,还需要告诉界面去使用它们。这需要修改另一个关键配置文件:interface_config.js。这个文件在容器内的路径是/config,它已经被映射到我们宿主机CONFIG目录下的web子目录中。我们直接修改宿主机的文件:

    nano /opt/jitsi/config/web/interface_config.js
    

    在这个文件里,找到以下配置行并进行修改:

    // 欢迎页的Logo
    DEFAULT_WELCOME_PAGE_LOGO_URL: 'images/logo.svg',
    // 会议内左上角的水印Logo
    WATERMARK_LOGO_URL: 'images/watermark.svg',
    

    确保这里的文件名和你放入images/目录的文件名一致。

4.4 应用定制并验证效果

所有文件修改完成后,我们需要将它们“同步”回正在运行的Docker容器中。注意,我们修改了三类文件:

  1. 语言文件 (main-zh-CN.json) -> 容器路径:/usr/share/jitsi-meet/lang/
  2. 图片文件 (watermark.svg, logo.svg) -> 容器路径:/usr/share/jitsi-meet/images/
  3. 界面配置文件 (interface_config.js) -> 容器路径:/config

使用docker cp命令将它们拷贝回去:

# 拷贝语言文件
docker cp /opt/jitsi/customization/jitsi-meet/lang/main-zh-CN.json docker-jitsi-meet-web-1:/usr/share/jitsi-meet/lang/
# 拷贝图片文件
docker cp /opt/jitsi/customization/jitsi-meet/images/watermark.svg docker-jitsi-meet-web-1:/usr/share/jitsi-meet/images/
docker cp /opt/jitsi/customization/jitsi-meet/images/logo.svg docker-jitsi-meet-web-1:/usr/share/jitsi-meet/images/
# 拷贝界面配置文件
docker cp /opt/jitsi/config/web/interface_config.js docker-jitsi-meet-web-1:/config/

最后,重启web容器,使改动生效:

docker-compose restart web

等待十几秒后,刷新浏览器页面(可能需要强制刷新,Ctrl+F5)。现在,你应该能看到欢迎页的标题变成了你自定义的名称,Logo也换成了自己公司的标识,一个充满品牌感的专属视频会议系统就此诞生了。

定制化是一个持续的过程。你还可以深入研究interface_config.js,隐藏不需要的按钮(如直播、录屏),修改主色调,甚至通过修改CSS文件来彻底改变界面风格。每次修改,都遵循“宿主机编辑 -> 拷贝回容器 -> 重启服务”这个流程即可。这套基于Docker Compose的部署方案,将复杂的Jitsi组件管理变得极其简单,而灵活的定制能力又让它能完美融入任何组织的IT生态。

更多推荐