本页内容

  • 准备工作
  • 步骤 1 - 配置防火墙
  • 步骤 2 - 安装并配置 PostgreSQL
  • 步骤 3 - 安装 Matrix Synapse
  • 步骤 4 - 安装 Nginx
  • 步骤 5 - 安装 SSL
  • 步骤 6 - 配置 SELinux
  • 步骤 7 - 创建 Matrix Systemd 服务
  • 步骤 8 - 配置 Matrix Synapse
  • 步骤 9 - 配置 Nginx
  • 步骤 10 - 安装 Coturn
  • 步骤 11 - 访问 Matrix
  • 步骤 12 - 安装 Element
  • 步骤 13 - 配置 Element
  • 总结

Matrix 是一种用于去中心化和端到端加密通信的开放标准。它由一系列服务器和服务组成,这些服务器和服务通过标准化的 API 相互通信并实时同步。它使用 homeserver(家庭服务器)来存储账户信息和聊天记录。如果某个家庭服务器宕机,由于去中心化的特性,其他服务器仍可继续通信而不受影响。你可以使用他人托管的 Matrix 家庭服务器,也可以自己托管,从而保持对自己数据的控制。

在本教程中,你将学习如何使用 Synapse(Matrix 的家庭服务器实现)安装并搭建一个聊天服务器。Element 是一个使用 Matrix React SDK 构建的 Matrix Web 客户端。这将让你能够在 Web 上提供 Matrix 聊天服务。你也可以将该服务器与任何其他 Matrix 客户端配合使用。我们还会安装 Coturn 服务器,以启用语音和视频通话功能。如果你对此不感兴趣,Coturn 服务是可选的。

准备工作

  • 一台运行 Debian 12 的服务器。
  • 一个拥有 root 权限的非 sudo 用户。
  • 已启用并运行的 UFW(uncomplicated Firewall)防火墙。
  • 指向你服务器的 Matrix、Element 和 Coturn 的完全限定域名(FQDN)。三个服务我们将分别使用 matrix.example.com、element.example.com 和 coturn.example.com。
  • 确保所有软件包都已更新。$ sudo dnf update

一台运行 Debian 12 的服务器。

一个拥有 root 权限的非 sudo 用户。

已启用并运行的 UFW(uncomplicated Firewall)防火墙。

指向你服务器的 Matrix、Element 和 Coturn 的完全限定域名(FQDN)。三个服务我们将分别使用 matrix.example.com、element.example.com 和 coturn.example.com。

确保所有软件包都已更新。

$ sudo dnf update
  • 系统所需的一些软件包。$ sudo dnf install wget curl nano unzip yum-utils policycoreutils-python-utils -y 其中部分软件包可能已在你的系统上安装。

系统所需的一些软件包。

$ sudo dnf install wget curl nano unzip yum-utils policycoreutils-python-utils -y

其中部分软件包可能已在你的系统上安装。

步骤 1 - 配置防火墙

在安装任何软件包之前,第一步是配置防火墙,开放 HTTP、HTTPS 和 Synapse 所需的端口。Rocky Linux 使用 Firewalld 防火墙。请检查防火墙的状态。

$ sudo firewall-cmd --state
running

防火墙采用不同的区域(zone)工作,我们将使用默认的 public 区域。列出防火墙当前启用的所有服务和端口。

$ sudo firewall-cmd --zone=public --list-all

它应显示如下输出。

public
  target: default
  icmp-block-inversion: no
  interfaces: enp1s0
  sources: 
  services: cockpit dhcpv6-client ssh
  ports: 
  protocols: 
  forward: yes
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules:

在防火墙中开放 HTTP、HTTPS 和 Synapse 端口。

$ sudo firewall-cmd --zone=public --add-port=8448/tcp
$ sudo firewall-cmd --zone=public --add-service=http
$ sudo firewall-cmd --zone=public --add-service=https

再次检查防火墙的状态。

$ sudo firewall-cmd --zone=public --list-all

你应该会看到类似的输出。

public
  target: default
  icmp-block-inversion: no
  interfaces: enp1s0
  sources: 
  services: cockpit dhcpv6-client http https ssh
  ports: 8448/tcp
  protocols: 
  forward: yes
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules:

将所有更改设为永久生效,并重新加载防火墙以使更改生效。

$ sudo firewall-cmd --runtime-to-permanent
$ sudo firewall-cmd --reload

步骤 2 - 安装并配置 PostgreSQL

Rocky Linux 9 默认随附 PostgreSQL 13。我们将使用其官方仓库中的 PostgreSQL 16。

安装 PostgreSQL 的 RPM 仓库。

$ sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

禁用系统内置的 PostgreSQL 模块。

$ sudo dnf -qy module disable postgresql

现在,你可以使用以下命令安装 PostgreSQL。

$ sudo dnf install -y postgresql16-server postgresql16-contrib postgresql16-devel

sudo dnf install postgresql16-devel

export PATH=$PATH:/usr/pgsql-16/bin

postgresql-contrib 软件包包含一些额外的实用工具。

验证版本。

$ psql --version
psql (PostgreSQL) 16.1

初始化 PostgreSQL 数据库。

$ sudo /usr/pgsql-16/bin/postgresql-16-setup initdb
Initializing database ... OK

启用 PostgreSQL 服务。

$ sudo systemctl enable postgresql-16

启动 PostgreSQL 服务。

$ sudo systemctl start postgresql-16

检查 PostgreSQL 服务的状态。

$ sudo systemctl status postgresql-16
? postgresql-16.service - PostgreSQL 16 database server
     Loaded: loaded (/usr/lib/systemd/system/postgresql-16.service; enabled; preset: disabled)
     Active: active (running) since Tue 2024-01-30 11:55:26 UTC; 10s ago
       Docs: https://www.postgresql.org/docs/16/static/
    Process: 9610 ExecStartPre=/usr/pgsql-16/bin/postgresql-16-check-db-dir ${PGDATA} (code=exited, status=0/SUCCESS)
   Main PID: 9615 (postgres)
      Tasks: 7 (limit: 12225)
     Memory: 17.4M
        CPU: 98ms
     CGroup: /system.slice/postgresql-16.service
             ??9615 /usr/pgsql-16/bin/postgres -D /var/lib/pgsql/16/data/
             ??9616 "postgres: logger "
             ??9617 "postgres: checkpointer "
             ??9618 "postgres: background writer "
             ??9620 "postgres: walwriter "
             ??9621 "postgres: autovacuum launcher "
             ??9622 "postgres: logical replication launcher "

Jan 30 11:55:26 matrix.example.com systemd[1]: Starting PostgreSQL 16 database server...
Jan 30 11:55:26 matrix.example.com postgres[9615]: 2024-01-30 11:55:26.482 UTC [9615] LOG:  redirecting log output to logging collector process
Jan 30 11:55:26 matrix.example.com postgres[9615]: 2024-01-30 11:55:26.482 UTC [9615] HINT:  Future log output will appear in directory "log".
Jan 30 11:55:26 matrix.example.com systemd[1]: Started PostgreSQL 16 database server.

你可以看到该服务默认已启用并正在运行。

登录到 postgres 系统账户。

$ sudo -su postgres

为 PostgreSQL 创建一个新的数据库用户和数据库。创建用户时会提示你输入密码。

$ createuser --pwprompt synapse
$ createdb --encoding=UTF8 --locale=C --template=template0 --owner=synapse synapsedb

退出 postgres 账户。

$ exit

步骤 3 - 安装 Matrix Synapse

Matrix Synapse 没有针对 Rocky Linux 等基于 CentOS 的发行版提供的预编译软件包。因此,我们将以 Python 模块的形式从 PyPI 安装它。

第一步是安装 Synapse 运行所需的依赖项。我们还需要包含 python3-virtualenv 软件包的 EPEL 仓库。

$ sudo dnf install epel-release
$ sudo dnf install --enablerepo=crb libtiff-devel libjpeg-devel libzip-devel \
                 freetype-devel libwebp-devel libxml2-devel libxslt-devel \
                 libpq-devel  python3-virtualenv libffi-devel openssl-devel \
                 python3-devel libicu-devel
$ sudo dnf groupinstall "Development Tools"
$ sudo dnf install postgresql16-devel

为 Synapse 创建一个目录。

$ mkdir -p ~/synapse

在上述目录中创建 Python 虚拟环境。

$ virtualenv -p python3 ~/synapse/env

激活虚拟环境。

$ source ~/synapse/env/bin/activate

确保你拥有最新版本的 pip 和 setuptools。

(env) $ pip install --upgrade pip
(env) $ pip install --upgrade setuptools

安装 Matrix Synapse。

(env) $ pip install "matrix-synapse[postgres]"

这将从 PyPI 下载 Synapse 并将其安装,同时将它所依赖的 Python 库安装到 ~/synapse/env 目录下的虚拟环境中。它还会安装 Synapse 连接 PostgreSQL 服务器所需的 PostgreSQL Python 库。上述命令相当于 pip install matrix-synapse 与 pip install psycopg2 两条命令的组合。

下一步是生成一个包含基本设置的配置文件。切换到 Synapse 目录。

(env) $ cd ~/synapse

运行以下命令生成配置文件。

(env) $ python -m synapse.app.homeserver \
    --server-name matrix.example.com \
    --config-path homeserver.yaml \
    --generate-config \
    --report-stats=[yes|no]

--server-name 变量的值会构成你 Matrix ID 的一部分。请将其值设为你的 Matrix 域名。它将作为你的 homeserver 地址。

你可以通过 --report-stats 变量选择是否将你 homeserver 的匿名统计数据发送回 Matrix。根据自己的意愿选择 yes 或 no。

你将得到如下输出。

Generating config file homeserver.yaml
Generating log config file /home/navjot/synapse/matrix.example.com.log.config which will log to /home/navjot/synapse/homeserver.log
Generating signing key file /home/navjot/synapse/matrix.example.com.signing.key
A config file has been generated in 'homeserver.yaml' for server name 'matrix.example.com'. Please review this file and customise it to your needs.

稍后你可以在 ~/synapse/homeserver.yaml 或 /home//synapse/homeserver.yaml 文件中修改这些设置。上述命令生成的密钥将允许你的 homeserver 向其他 homeserver 标识自己的身份。

是时候运行 Matrix 服务器了。请确保你位于 Synapse 目录内,并且虚拟环境已激活。

启动 homeserver。

(env) $ synctl start

你应该会看到类似的输出。

This server is configured to use 'matrix.org' as its trusted key server via the
'trusted_key_servers' config option. 'matrix.org' is a good choice for a key
server since it is long-lived, stable and trusted. However, some admins may
wish to use another server for this purpose.

To suppress this warning and continue using 'matrix.org', admins should set
'suppress_key_server_warning' to 'true' in homeserver.yaml.
--------------------------------------------------------------------------------
started synapse.app.homeserver(homeserver.yaml)

要停止服务器,运行以下命令。

(env) $ synctl stop

退出虚拟环境。

(env) $ deactivate

步骤 4 - 安装 Nginx

对于生产环境,建议使用 Nginx 代理来运行 Synapse 服务器。

Rocky Linux 9 随附的 Nginx 版本较旧。你需要使用 Nginx 官方仓库来安装最新版本。

创建并打开文件 /etc/yum.repos.d/nginx.repo 进行编辑。

$ sudo nano /etc/yum.repos.d/nginx.repo

在其中粘贴以下代码。

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

完成后,按 Ctrl + X 并在提示时输入 Y 保存文件。

我们将安装 Nginx 主线(mainline)版本,因此需要启用对应的软件包。

$ sudo dnf config-manager --enable nginx-mainline

安装 Nginx。

$ sudo dnf install nginx -y

验证安装。

$ nginx -v
nginx version: nginx/1.25.3

启用并启动 Nginx 服务。

$ sudo systemctl enable nginx --now

检查服务状态。

$ sudo systemctl status nginx
? nginx.service - nginx - high performance web server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled)
     Active: active (running) since Tue 2024-01-30 12:50:34 UTC; 4s ago
       Docs: http://nginx.org/en/docs/
    Process: 10810 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
   Main PID: 10811 (nginx)
      Tasks: 3 (limit: 12225)
     Memory: 3.1M
        CPU: 24ms
     CGroup: /system.slice/nginx.service
             ??10811 "nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf"
             ??10812 "nginx: worker process"
             ??10813 "nginx: worker process"

步骤 5 - 安装 SSL

我们需要安装 Certbot 来生成 SSL 证书。我们将使用 Snapd 软件包安装工具来完成。由于 Rocky Linux 没有自带 Snapd,需要安装 Snapd 安装器。它依赖 EPEL(Extra Packages for Enterprise Linux)仓库才能工作。但由于我们在步骤 3 中已经安装过,因此可以直接继续。

安装 Snapd 软件包。

$ sudo dnf install snapd -y

启用并启动 Snap 服务。

$ sudo systemctl enable snapd --now

安装 Snap core 软件包,并确保你的 Snapd 版本为最新。

$ sudo snap install core
$ sudo snap refresh core

创建 Snapd 工作所需的链接。

$ sudo ln -s /var/lib/snapd/snap /snap
$ echo 'export PATH=$PATH:/var/lib/snapd/snap/bin' | sudo tee -a /etc/profile.d/snapd.sh

安装 Certbot。

$ sudo snap install --classic certbot

使用以下命令,通过创建指向 /usr/bin 目录的符号链接,确保 Certbot 命令可以运行。

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

检查 Certbot 版本。

$ certbot --version
certbot 2.8.0

运行以下命令生成 SSL 证书。

$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m 
[email protected]
 -d matrix.example.com

上述命令会将证书下载到你服务器上的 /etc/letsencrypt/live/matrix.example.com 目录。

生成 Diffie-Hellman 组证书。

$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096

检查 Certbot 续期调度服务。

$ systemctl list-timers

你会发现 snap.certbot.renew.service 是已调度运行的服务之一。

NEXT                        LEFT         LAST                        PASSED      UNIT                         ACTIVATES                   ----------------------------------------------------------------------------------------------------------------------------------  
Tue 2024-01-30 14:37:50 UTC 29min left   Tue 2024-01-30 13:05:13 UTC 1h 3min ago dnf-makecache.timer          dnf-makecache.service
Tue 2024-01-30 15:13:00 UTC 1h 4min left -                           -           snap.certbot.renew.timer     snap.certbot.renew.service
Wed 2024-01-31 00:00:00 UTC 9h left      Tue 2024-01-30 06:35:44 UTC 7h ago      logrotate.timer              logrotate.service

对该过程进行一次空运行(dry run),以检查 SSL 续期是否正常工作。

$ sudo certbot renew --dry-run

如果没有看到错误,说明一切就绪。你的证书将自动续期。

步骤 6 - 配置 SELinux

SELinux 会阻止你运行二进制文件位于用户主目录中的系统服务。因此,如果我们为 Synapse 创建服务文件,它会被 SELinux 阻止。要解决此问题,我们需要运行以下命令,以允许将 Python 二进制文件作为系统服务运行。

$ sudo chcon -R -t bin_t /home/username/synapse/env/bin/python

应用策略以允许向外部主机建立连接。

$ sudo setsebool -P httpd_can_network_connect 1

应用策略以允许 Nginx 访问 PostgreSQL。

$ sudo setsebool -P httpd_can_network_connect_db 1

步骤 7 - 创建 Matrix Systemd 服务

Synapse 服务的状态在重启后不会保留,这意味着如果你重启服务器,需要手动启动该服务。为了解决此问题,我们需要为其创建 Systemd 文件。

在进行此操作之前,请确保 Synapse 服务已停止。

$ cd ~/synapse
$ source env/bin/activate
(env) $ synctl stop
(env) $ deactivate

在 /etc/systemd/system/ 目录中创建并打开 matrix-synapse.service 文件进行编辑。

$ sudo nano /etc/systemd/system/matrix-synapse.service

在其中粘贴以下代码。将 username 变量替换为你安装 Synapse 时使用的 Linux 系统用户。

# This assumes that Synapse has been installed by a user named username.
# This assumes that Synapse has been installed in a virtualenv in
# the user's home directory: `/home/username/synapse/env`.

[Unit]
Description=Synapse Matrix homeserver
After=postgresql-16.service

[Service]
Type=notify
NotifyAccess=main
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-abort

WorkingDirectory=/home/username/synapse
ExecStart=/home/username/synapse/env/bin/python -m synapse.app.homeserver --config-path=/home/username/synapse/homeserver.yaml
SyslogIdentifier=matrix-synapse

# adjust the cache factor if necessary
# Environment=SYNAPSE_CACHE_FACTOR=2.0

[Install]
WantedBy=multi-user.target

完成后,按 Ctrl + X 并在提示时输入 Y 保存文件。

重新加载服务守护进程。

$ sudo systemctl daemon-reload

启用 Matrix Synapse 服务。

$ sudo systemctl enable matrix-synapse

启动 Matrix Synapse 服务。

$ sudo systemctl start matrix-synapse

检查服务状态。

$ sudo systemctl status matrix-synapse

你应该会看到如下输出。

? matrix-synapse.service - Synapse Matrix homeserver
     Loaded: loaded (/etc/systemd/system/matrix-synapse.service; enabled; preset: disabled)
     Active: active (running) since Tue 2024-01-30 14:20:20 UTC; 5s ago
   Main PID: 14687 (python)
      Tasks: 8 (limit: 12225)
     Memory: 77.6M
        CPU: 3.527s
     CGroup: /system.slice/matrix-synapse.service
             ??14687 /home/navjot/synapse/env/bin/python -m synapse.app.homeserver --config-path=/home/navjot/synapse/homeserver.yaml

Jan 30 14:20:16 matrix.example.com systemd[1]: Starting Synapse Matrix homeserver...
Jan 30 14:20:19 matrix.example.com matrix-synapse[14687]: This server is configured to use 'matrix.org' as its trusted key server via the
Jan 30 14:20:19 matrix.example.com matrix-synapse[14687]: 'trusted_key_servers' config option. 'matrix.org' is a good choice for a key
Jan 30 14:20:19 matrix.example.com matrix-synapse[14687]: server since it is long-lived, stable and trusted. However, some admins may
Jan 30 14:20:19 matrix.example.com matrix-synapse[14687]: wish to use another server for this purpose.
Jan 30 14:20:19 matrix.example.com matrix-synapse[14687]: To suppress this warning and continue using 'matrix.org', admins should set
Jan 30 14:20:19 matrix.example.com matrix-synapse[14687]: 'suppress_key_server_warning' to 'true' in homeserver.yaml.
Jan 30 14:20:19 matrix.example.com matrix-synapse[14687]: --------------------------------------------------------------------------------
Jan 30 14:20:20 matrix.example.com systemd[1]: Started Synapse Matrix homeserver.

步骤 8 - 配置 Matrix Synapse

在继续之前,先创建一个保密的注册密钥。该密钥应当妥善保管,因为即使已禁用注册,持有它也能注册新用户。

$ echo "registration_shared_secret: '$(cat /dev/urandom | tr -cd '[:alnum:]' | fold -w 256 | head -n 1)'"
registration_shared_secret: '1y75ja0RUxvbWcS6SdZhakenukUwHHEjOXWC9Mu3FpO0QenOnpKRsc6NBZSxuzPcHYsOEuIQziwVjSZcP87dlWK4ZkIGYniurMqNsCYL4xg5xXs4bJDuTJH2CUXab4U9liv399lmkIZFaMpJCLxV9lVWB9mKHILYsjeLgGY5wAARv1SiK07bFsQOwKJGFqIvsUXmxymx5QCNDzTHw8R4ShqZ7elnnZrbdYk4r2f7qogERNHvQaRV7IEYUIOtMhVP'

复制上一行命令的输出并保存。

你可以通过 /home/username/synapse/homeserver.yaml 文件配置 Matrix 服务器。打开它进行编辑。

$ nano ~/synapse/homeserver.yaml

将注册密钥命令的输出粘贴到文件末尾。

默认情况下,Synapse 配置为使用 SQLite 数据库。我们需要编辑它,添加 PostgreSQL 凭据。

在文件中找到以下部分,并按所示将其注释掉。

#database:
#  name: sqlite3
#  args:
#    database: /home/navjot/synapse/homeserver.db

在其下方添加以下部分。将 your-password 字段替换为你在步骤 3 中创建的 PostgreSQL 用户密码。如果你将数据库托管在其他位置,请将 localhost 替换为你的服务器 IP 地址。

database:
  name: psycopg2
  args:
    user: synapse
    password: 'your-password'
    database: synapsedb
    host: localhost
    cp_min: 5
    cp_max: 10

默认情况下,Synapse 启用了在线状态指示(显示某人是否在线)。这可能会导致较高的 CPU 占用,因此你可以将其禁用。在文件末尾粘贴以下行。

presence:
  enabled: false

完成后,按 Ctrl + X 并在提示时输入 Y 保存文件。

创建一个新 Matrix 用户。系统会提示你输入用户名和密码。由于我们创建的是第一个用户,当被问及是否将该用户设为管理员时,请输入 yes。你需要先激活虚拟环境才能创建该用户。

$ cd ~/synapse
$ source env/bin/activate
(env) $ register_new_matrix_user -c homeserver.yaml http://localhost:8008
New user localpart [navjot]: navjot
Password: 
Confirm password: 
Make admin [no]: yes
Sending registration request...
Success!
(env) $ deactivate

你可以看到我们在上面的命令中使用了 8008 端口。这是因为它是 Matrix Synapse 默认监听的端口。

默认情况下,新用户的注册是关闭的,这意味着你需要像上面那样手动注册每个用户。如果你希望开放公开注册,可以通过编辑 homeserver.yaml 文件来实现。

再次打开它进行编辑。

$ nano ~/synapse/homeserver.yaml

在文件末尾粘贴以下行。

enable_registration: true

默认情况下,Synapse 不允许未经邮箱验证的注册。要启用邮箱验证,请粘贴以下行。

registrations_require_3pid:
  - email

email:
  smtp_host: mail.example.com
  smtp_port: 587

  # If mail server has no authentication, skip these 2 lines
  smtp_user: '
[email protected]
'
  smtp_pass: 'password'

  # Optional, require encryption with STARTTLS
  require_transport_security: true

  app_name: 'HowtoForge Example Chat'  # defines value for %(app)s in notif_from and email subject
  notif_from: "%(app)s <
[email protected]
>"

要禁用邮箱验证,请改为粘贴以下行。

enable_registration_without_verification: true

完成后,按 Ctrl + X 并在提示时输入 Y 保存文件。

重启 Synapse 以使配置生效。

$ sudo systemctl restart matrix-synapse

步骤 9 - 配置 Nginx

打开文件 /etc/nginx/nginx.conf 进行编辑。

$ sudo nano /etc/nginx/nginx.conf

在 include /etc/nginx/conf.d/*.conf; 这一行之前添加以下行。

server_names_hash_bucket_size 64;

按 Ctrl + X 并在提示时输入 Y 保存文件。

创建并打开文件 /etc/nginx/conf.d/synapse.conf 进行编辑。

$ sudo nano /etc/nginx/conf.d/synapse.conf

在其中粘贴以下代码。

# enforce HTTPS
server {
    # Client port
    listen 80;
    listen [::]:80;
    server_name matrix.example.com;
    return 301 https://$host$request_uri;
}

server {
    server_name matrix.example.com;

    # Client port
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    # Federation port
    listen 8448 ssl default_server;
    listen [::]:8448 ssl default_server;

    access_log  /var/log/nginx/synapse.access.log;
    error_log   /var/log/nginx/synapse.error.log;

    # TLS configuration
    ssl_certificate /etc/letsencrypt/live/matrix.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/matrix.example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/matrix.example.com/chain.pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets off;
    ssl_prefer_server_ciphers on;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] 8.8.8.8 8.8.4.4 [2001:4860:4860::8888] [2001:4860:4860::8844] valid=60s;
    resolver_timeout 2s;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

    tcp_nopush on;
    gzip on;

    location ~ ^(/_matrix|/_synapse/client) {
            proxy_pass http://localhost:8008;
            proxy_http_version 1.1;

            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Host $host;

            # Nginx by default only allows file uploads up to 1M in size
            # Increase client_max_body_size to match max_upload_size defined in homeserver.yaml
            client_max_body_size 50M;
    }
}

完成后按 Ctrl + X 并在提示时输入 Y 保存文件。上述配置的前提是 example.com 和 matrix.example.com 这两个域名的 IP 地址指向同一台服务器。如果不是,则对 example.com 服务器使用以下配置文件。

server {
    server_name example.com;

    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    # TLS configuration
    ssl_certificate /etc/letsencrypt/live/matrix.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/matrix.example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/matrix.example.com/chain.pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets off;
    ssl_prefer_server_ciphers on;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] 8.8.8.8 8.8.4.4 [2001:4860:4860::8888] [2001:4860:4860::8844] valid=60s;
    resolver_timeout 2s;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

    # Redirect
    location ~ ^(/_matrix|/_synapse/client) {
            return 301 "https://matrix.example.com$request_uri";
    }

    # Client homeserver autodiscovery
    location /.well-known/matrix/client {
        default_type application/json;
        add_header Access-Control-Allow-Origin *;

        return 200 '{ "m.homeserver": { "base_url": "https://matrix.example.com" } }';
    }

    # Domain delegation
    location /.well-known/matrix/server {
        default_type application/json;
        add_header Access-Control-Allow-Origin *;

        return 200 '{ "m.server": "matrix.example.com" }';
    }
}

检查 Nginx 配置文件语法。

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

重启 Nginx 服务。

$ sudo systemctl restart nginx

步骤 10 - 安装 Coturn

要启用语音和视频通话,你需要安装一个 TURN(Traversal Using Relays around NAT,NAT 穿透中继)服务器。为此,我们将安装 Coturn 软件包。如果你不需要此功能,可以跳过本步骤。

安装 Coturn。

$ sudo dnf install coturn

开放 TURN 和 UDP 端口。

$ sudo firewall-cmd --zone=public --add-port=3478/{tcp,udp}
$ sudo firewall-cmd --zone=public --add-port=5349/{tcp,udp}
$ sudo firewall-cmd --zone=public --add-port=49152-65535/udp
$ sudo firewall-cmd --runtime-to-permanent
$ sudo firewall-cmd --reload

为 Turn 生成 SSL 证书(coturn.example.com)。

$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m 
[email protected]
 -d coturn.example.com

为 Coturn 生成身份验证密钥(secret)。

$ echo "static-auth-secret=$(cat /dev/urandom | tr -cd '[:alnum:]' | fold -w 256 | head -n 1)"
static-auth-secret=u3ksgJ9X876sFMO00A8KabXwZvzVwCmV30wWvZ7DzGiepRwNRYSCTYzf2E8olNzdDHu7oO3XpT3l5bv5mVdhXEQ3pnoTWBquSVPFFBJtyD6y9gBxiMaD2TYTD2WohQLE9s7OKJVpkDeKTnZQnkmjrFadE3M9DRxPL1W5Lgdg6XLLKABgb5XGkutRgkJOV0JRH4sBYsot63fWq9mcGTm6nAMdIycvDVDOs7vhoeqRzcTbMF0wsfAHVJNhXpGGFDyZ

打开配置文件进行编辑。

$ sudo nano /etc/coturn/turnserver.conf

我们将通读该文件并启用所需的设置。首先,通过取消 use-auth-secret 行的注释来启用身份验证方法。

# Be aware that use-auth-secret overrides some parts of lt-cred-mech.
# The use-auth-secret feature depends internally on lt-cred-mech, so if you set
# this option then it automatically enables lt-cred-mech internally
# as if you had enabled both.
#
# Note that you can use only one auth mechanism at the same time! This is because,
# both mechanisms conduct username and password validation in different ways.
#
# Use either lt-cred-mech or use-auth-secret in the conf
# to avoid any confusion.
#
use-auth-secret

接下来,我们将 static-auth-secret 变量配置为上面生成的值。稍后配置 Synapse 时我们也需要用到这个密钥。

# 'Static' authentication secret value (a string) for TURN REST API only.
# If not set, then the turn server
# will try to use the 'dynamic' value in the turn_secret table
# in the user database (if present). The database-stored  value can be changed on-the-fly
# by a separate program, so this is why that mode is considered 'dynamic'.
#
static-auth-secret=u3ksgJ9X876sFMO00A8KabXwZvzVwCmV30wWvZ7DzGiepRwNRYSCTYzf2E8olNzdDHu7oO3XpT3l5bv5mVdhXEQ3pnoTWBquSVPFFBJtyD6y9gBxiMaD2TYTD2WohQLE9s7OKJVpkDeKTnZQnkmjrFadE3M9DRxPL1W5Lgdg6XLLKABgb5XGkutRgkJOV0JRH4sBYsot63fWq9mcGTm6nAMdIycvDVDOs7vhoeqRzcTbMF0wsfAHVJNhXpGGFDyZ

接下来需要修改的值是 realm。它指的是我们为 Coturn 选择的域名。

# The default realm to be used for the users when no explicit
# origin/realm relationship is found in the database, or if the TURN
# server is not using any database (just the commands-line settings
# and the userdb file). Must be used with long-term credentials
# mechanism or with TURN REST API.
#
# Note: If the default realm is not specified, then realm falls back to the host domain name.
#       If the domain name string is empty, or set to '(None)', then it is initialized as an empty string.
#
realm=coturn.example.com

接下来,定义会话总数和每个用户的会话数。选择一个适合你服务器的数值。

# Per-user allocation quota.
# default value is 0 (no quota, unlimited number of sessions per user).
# This option can also be set through the database, for a particular realm.
#
user-quota=12

# Total allocation quota.
# default value is 0 (no quota).
# This option can also be set through the database, for a particular realm.
#
total-quota=1200

接下来,我们需要禁用 TCP,因为 VOIP 使用的是 UDP。

# Uncomment if no TCP relay endpoints are allowed.
# By default TCP relay endpoints are enabled (like in RFC 6062).
#
no-tcp-relay

我们还需要配置为 Coturn 创建的证书的位置。

# Certificate file.
# Use an absolute path or path relative to the
# configuration file.
# Use PEM file format.
#
cert=/etc/letsencrypt/live/coturn.example.com/fullchain.pem

# Private key file.
# Use an absolute path or path relative to the
# configuration file.
# Use PEM file format.
#
pkey=/etc/letsencrypt/live/coturn.example.com/privkey.pem

接下来,我们需要禁用流向私有 IP 段的流量,并禁止多播地址上的对等节点,以提高安全性。

# Flag that can be used to disallow peers on well-known broadcast addresses (224.0.0.0 and above, and FFXX:*).
# This is an extra security measure.
#
no-multicast-peers

...............

# Option to allow or ban specific ip addresses or ranges of ip addresses.
# If an ip address is specified as both allowed and denied, then the ip address is
# considered to be allowed. This is useful when you wish to ban a range of ip
# addresses, except for a few specific ips within that range.
#
# This can be used when you do not want users of the turn server to be able to access
# machines reachable by the turn server, but would otherwise be unreachable from the
# internet (e.g. when the turn server is sitting behind a NAT)
#
# Examples:
# denied-peer-ip=83.166.64.0-83.166.95.255
# allowed-peer-ip=83.166.68.45
denied-peer-ip=0.0.0.0-0.255.255.255
denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=100.64.0.0-100.127.255.255
denied-peer-ip=127.0.0.0-127.255.255.255
denied-peer-ip=169.254.0.0-169.254.255.255
denied-peer-ip=172.16.0.0-172.31.255.255
denied-peer-ip=192.0.0.0-192.0.0.255
denied-peer-ip=192.0.2.0-192.0.2.255
denied-peer-ip=192.88.99.0-192.88.99.255
denied-peer-ip=192.168.0.0-192.168.255.255
denied-peer-ip=198.18.0.0-198.19.255.255
denied-peer-ip=198.51.100.0-198.51.100.255
denied-peer-ip=203.0.113.0-203.0.113.255
denied-peer-ip=240.0.0.0-255.255.255.255
denied-peer-ip=::1
denied-peer-ip=64:ff9b::-64:ff9b::ffff:ffff
denied-peer-ip=::ffff:0.0.0.0-::ffff:255.255.255.255
denied-peer-ip=100::-100::ffff:ffff:ffff:ffff
denied-peer-ip=2001::-2001:1ff:ffff:ffff:ffff:ffff:ffff:ffff
denied-peer-ip=2002::-2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff
denied-peer-ip=fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
denied-peer-ip=fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff

完成后,按 Ctrl + X 并在提示时输入 Y 保存文件。

重启 Coturn 以使配置生效。

$ sudo systemctl restart coturn

打开 Synapse 配置文件(homeserver.yaml)以添加 Coturn 设置。

$ nano ~/synapse/homeserver.yaml

在其中粘贴以下行。将 turn_shared_secret 的值替换为 \etc\coturn\turnserver.conf 文件中 static-auth-secret 的值。

turn_uris: [ "turn:coturn.example.com?transport=udp", "turn:coturn.example.com?transport=tcp" ]
turn_shared_secret: 'static-auth-secret'
turn_user_lifetime: 86400000
turn_allow_guests: True

# vim:ft=yaml

按 Ctrl + X 并在提示时输入 Y 保存文件。

重启 Synapse 以使更改生效。

$ sudo systemctl restart matrix-synapse

步骤 11 - 访问 Matrix

你可以通过 https://app.element.io 上的 Element Web 客户端访问 Matrix 聊天。点击 Sign in(登录)按钮继续。

在 Rocky Linux 9 上安装 Matrix Synapse 与 Element 搭建聊天服务器

点击 Homeserver(家庭服务器)下方的 Edit(编辑)链接。输入 matrix.example.com 作为你的 homeserver。

在 Rocky Linux 9 上安装 Matrix Synapse 与 Element 搭建聊天服务器

如果客户端正确检测到你的 homeserver,边框和文字会变为绿色,否则会显示为红色。点击 Continue(继续)按钮。

在 Rocky Linux 9 上安装 Matrix Synapse 与 Element 搭建聊天服务器

输入你在步骤 8 配置 Synapse 时创建的用户名和密码。点击 Sign in 按钮登录。系统会要求你创建一个安全的加密备份。

在 Rocky Linux 9 上安装 Matrix Synapse 与 Element 搭建聊天服务器

选择 Enter a Security Phrase(输入安全口令)选项,创建一个每次登录时都需要的安全口令。点击 Continue 继续。

在 Rocky Linux 9 上安装 Matrix Synapse 与 Element 搭建聊天服务器

输入一个安全口令并点击 Continue 按钮继续。下一屏会要求你再次确认。

在 Rocky Linux 9 上安装 Matrix Synapse 与 Element 搭建聊天服务器

再次输入该口令并点击 Continue 继续。

在 Rocky Linux 9 上安装 Matrix Synapse 与 Element 搭建聊天服务器

系统会提供一组安全密钥,在你忘记安全口令时可以使用。点击 Download(下载)按钮将其保存。

点击 Continue 按钮继续。

在 Rocky Linux 9 上安装 Matrix Synapse 与 Element 搭建聊天服务器

系统会要求你输入账户密码。输入密码并点击 Continue 按钮,完成加密备份的设置。

在 Rocky Linux 9 上安装 Matrix Synapse 与 Element 搭建聊天服务器

我们使用首页上的 Create a Group Chat(创建群聊)按钮创建了一个名为 HowtoForge 的群聊房间。点击该按钮时,你会看到如下弹窗。

在 Rocky Linux 9 上安装 Matrix Synapse 与 Element 搭建聊天服务器

你可以展开高级菜单并选择相应选项,将成员限制在指定域名内。点击 Create room(创建房间)按钮完成房间创建。

步骤 12 - 安装 Element

为 Element 创建一个目录。

$ sudo mkdir -p /var/www/html/element

创建一个新文件用于获取最新的 Element 版本。

$ sudo nano /var/www/html/element/update.sh

在其中添加以下行。

#!/bin/sh
set -e

install_location="/var/www/html/element"
latest="$(curl -I https://github.com/element-hq/element-web/releases/latest | awk -F '/' '/^location/ {print  substr($NF, 1, length($NF)-1)}')"

cd "$install_location"

[ ! -d "archive" ] && mkdir -p "archive"
[ -d "archive/element-${latest}" ] && rm -r "archive/element-${latest}"
[ -f "archive/element-${latest}.tar.gz" ] && rm "archive/element-${latest}.tar.gz"

wget "https://github.com/element-hq/element-web/releases/download/${latest}/element-${latest}.tar.gz" -P "archive"
tar xf "archive/element-${latest}.tar.gz" -C "archive"

[ -L "${install_location}/current" ] && rm "${install_location}/current"
ln -sf "${install_location}/archive/element-${latest}" "${install_location}/current"
ln -sf "${install_location}/config.json" "${install_location}/current/config.json"

按 Ctrl + X 并在提示时输入 Y 保存文件。

使该文件可执行。

$ sudo chmod +x /var/www/html/element/update.sh

运行该脚本以下载 Element。

$ sudo /var/www/html/element/update.sh

步骤 13 - 配置 Element

复制同一个 Element 配置文件。

$ sudo cp /var/www/html/element/current/config.sample.json /var/www/html/element/config.json

打开配置文件进行编辑。

$ sudo nano /var/www/html/element/config.json

找到以下行。

"m.homeserver": {
    "base_url": "https://matrix-client.matrix.org",
    "server_name": "matrix.org"
},

将默认的 Matrix homeserver 地址更改为你的 homeserver,并删除 server_name 变量。

"m.homeserver": {
    "base_url": "https://matrix.example.com",
    "server_name": "example.com"
},

如果你想在网站标题中使用自己的名称而不是 Element,可以修改品牌名称(brand name)。

"brand": "HowtoForge Example Chat",

将 disable_guests 变量设为 true,以禁止访客(Guests)使用 Element。

"disable_guests": true,

按 Ctrl + X 并在提示时输入 Y 保存文件。

为 Element 客户端生成 SSL 证书。

$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m 
[email protected]
 -d element.example.com

创建并打开文件 /etc/nginx/conf.d/element.conf 进行编辑。

$ sudo nano /etc/nginx/conf.d/element.conf

在其中粘贴以下行。

server {
    listen 80;
    listen [::]:80;
    server_name element.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    server_name element.example.com;

    root /var/www/html/element/current;
    index index.html;

    access_log  /var/log/nginx/element.access.log;
    error_log   /var/log/nginx/element.error.log;

    add_header Referrer-Policy "strict-origin" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;

    # TLS configuration
    ssl_certificate /etc/letsencrypt/live/element.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/element.example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/element.example.com/chain.pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets off;
    ssl_prefer_server_ciphers on;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] 8.8.8.8 8.8.4.4 [2001:4860:4860::8888] [2001:4860:4860::8844] valid=60s;
    resolver_timeout 2s;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
}

按 Ctrl + X 并在提示时输入 Y 保存文件。

检查 Nginx 配置文件语法。

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

重启 Nginx 服务。

$ sudo systemctl restart nginx

在访问 Element 之前,我们需要配置 SELinux 设置。运行以下命令以允许 Element 运行。

$ sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/element(/.*)?"
$ sudo restorecon -Rv /var/www/html/element/

你可以通过浏览器访问 https://element.example.com 来使用 Element 客户端。登录后,你会进入应用仪表盘。系统会要求你先用 https://app.element.io 验证该应用,请确保你已在原始 Element 应用中登录,并且会被要求匹配表情符号。验证通过后,你会看到如下仪表盘。

在 Rocky Linux 9 上安装 Matrix Synapse 与 Element 搭建聊天服务器

总结

至此,本教程关于在 Debian 12 机器上以 Nginx 作为代理服务器,安装 Matrix Synapse 聊天服务器以及 Coturn 和 Element Web 客户端的内容就结束了。如果你有任何问题,请在下方评论区留言。