超详细 Matrix Synapse 部署教程:搭建去中心化聊天服务器

图片[1] - 超详细 Matrix Synapse 部署教程:搭建去中心化聊天服务器 - 白鱼小栈
图源 Matrix 官网|直达链接

引言

由于某些原因,保护个人隐私和通信秘密正变得越来越困难。

为满足私密通讯需求,开源社区一直在不断发展和改进即时通讯工具,Matrix 便是其中一个优秀的加密通信协议。

本人在研究这东西的时候,发现网上的教程比较零碎分散,于是干脆自己整理一篇比较完整的,希望对后来者有点帮助~

先请 ChatGPT 介绍一下 Matrix 协议:

Matrix 协议的灵活性和安全性使其成为一个强大的通信解决方案,特别适用于那些关注隐私和通信自由的用户。开放性和互操作性使 Matrix 协议成为一个极有前景的通信标准。

Matrix 有以下特点:

  1. 分散式架构:Matrix 采用了分散式架构,没有单一的中央服务器,而是由多个独立的服务器组成网络。这意味着用户可以选择自己的服务器,或者自行托管服务器,而不必依赖单一的服务提供商。
  2. 端到端加密:Matrix 提供了端到端加密的支持,确保消息在发送方和接收方之间加密,中间服务器无法访问消息内容。这提供了高级的通信隐私和安全性。
  3. 互操作性:Matrix 的一个主要目标是实现不同通信应用之间的互操作性。这意味着用户可以使用不同的客户端应用程序,仍然能够与其他用户进行通信,无论他们使用哪种应用程序或服务器。
  4. 开源和开放标准:Matrix 协议是一个开放标准,可供任何人查看和实施。这种开放性有助于确保安全性和可扩展性,并减少了隐藏的后门风险。
  5. 多种身份验证机制:Matrix 支持多种身份验证方式,包括用户名和密码、单点登录、OpenID Connect 等,使用户能够选择适合他们需求的身份验证方式。
  6. 活跃的社区支持:Matrix 社区非常活跃,有大量的开发者和用户参与,不断改进和扩展协议,以满足不断变化的通信需求。

作为一个去中心化通讯协议,你可以使用不同的客户端(只要客户端支持 Matrix 协议),连接到任意一个 Matrix 服务端。

Matrix 协议支持诸多特性:

  • 去中心化通信
  • 端到端加密
  • WebRTC 语音通话 / 视频通话
  • 消息已读提示
  • 输入状态提示
  • 群组聊天
图片[2] - 超详细 Matrix Synapse 部署教程:搭建去中心化聊天服务器 - 白鱼小栈
图源 Matrix 官网

不仅于此,正如其名:“矩阵”,如果你是这台服务器的管理员,你还可以允许你的 Matrix 服务器与其它 Matrix 服务器组成矩阵网络,让用户与其它 Matrix 服务器的用户进行通信。

Matrix 服务器上的所有对话都支持端到端加密,非常安全。

常见问题

Q:什么是端到端加密?

端到端加密可以理解为是两台终端的直接通信,我们举个例子更容易理解:

假设小明用 A 设备 给小红的 B 设备 发了一条消息,这时候小黑想看看他俩在聊什么,于是小黑盗取了小红的账号密码,并成功在 C 设备 上登录了小红的账号。

小黑能不能看到他们俩的聊天记录呢?不能。在端到端加密对话中,所有发出去的消息都会被自动加密。

当小明给小红发送一段消息时,还会自动附上一串用于解密这段消息的 解密密钥 。小红在 B 设备 上收到消息时,同时收到了这串 解密密钥 ,所以能正常查看消息。但小黑并没有收到 解密密钥 ,因此无法解密这些历史消息。

端到端加密算是当今相对最安全的一种隐私保护方式,能够满足大多数人的安全需求。

有人要说了:“我也不需要那么高的安全等级啊,这也太多余了!”

那么实际使用中,你可以在创建新对话时,将 “端到端加密” 选项取消勾选。

Q:Synapse 是什么?它和 Matrix Synapse 是什么关系?

Matrix 是一个协议,而 Matrix Synapse 则是 Matrix 协议的一个具体实现。

另外,Synapse 本身也只是一个不包含图形界面的服务端,我们还需要一个支持 Matrix 协议的客户端才能正常聊天。常见支持 Matrix 协议的客户端包括:

Element (最为熟知和常用)

  • 跨平台支持:包括 Android、iOS 和 Web 端。有独立 App 的好处就是,移动设备能及时收到消息,毕竟你总不能一直后台挂个网页吧~
  • 功能丰富:音视频通话、插件支持等。
  • 社区支持:Element 在 Matrix 社区内知名度高,社区活跃。
图片[3] - 超详细 Matrix Synapse 部署教程:搭建去中心化聊天服务器 - 白鱼小栈

Cinny (新一代 Matrix 客户端,UI 设计简洁现代):

  • 轻量级:新一代轻量级 Matrix 客户端,更适合喜欢简洁界面的用户。
  • 不足:发布日期较新,因此功能不如 Element 全面,例如 Cinny 暂不支持音视频通话 (截至 2023 年) ;另外当前 Cinny 仅有 Web 端,无 Android 和 iOS 应用;
图片[4] - 超详细 Matrix Synapse 部署教程:搭建去中心化聊天服务器 - 白鱼小栈

这篇文章主要讲 Synapse 服务端的部署。

如果你正在部署客户端,可参考另一篇文章 https://www.baiyuyu.com/127.html

1. Synapse 安装

1.1 域名配置

先去你的域名管理面板,添加一条 DNS 解析 A 记录。

⚠ 注意

本文按照 “客户端/服务端共用一个域名” 的情况撰写,这是本人认为的最优方案。

“客户端/服务端共用一个域名” 的情况下,用户名格式是:@user:xxx.com。而如果服务端使用了二级域,则用户名会变成 @user:server.xxx.com ,个人感觉有点丑 … 所以推荐共用一个域名!

如果你希望客户端和服务端使用不同的两个域名(比如 xxx.com 作为客户端域名,server.xxx.com 作为服务端域名),可同时参阅 官方文档

1.2 安装 docker

方便起见,切换到 root 用户:

sudo su

更新一下软件源:

sudo apt upadte

安装 docker 和 docker compose:

curl -L https://get.docker.com | sh

1.3 创建一个工作目录

cd /
mkdir -p /var/matrix-synapse-data/

1.4 生成 Synapse 配置文件

注意:后续无法更改域名

docker run -it --rm -v /var/matrix-synapse-data/:/data/ -e SYNAPSE_SERVER_NAME=你的服务端域名 -e SYNAPSE_REPORT_STATS=no matrixdotorg/synapse:latest generate

解释一下各个参数:

-v /var/matrix-synapse-data/:/data/ 是映射的具体路径,可以不用修改

-e SYNAPSE_SERVER_NAME 是你的服务端域名,本文按照“客户端/服务端共用一个域名”的情况撰写

-e SYNAPSE_REPORT_STATS 是否发送匿名统计数据

1.5 安装运行

docker run -d --name synapse -v /var/matrix-synapse-data/:/data/ -p 8008:8008 -p 8009:8009 -p 8448:8448 matrixdotorg/synapse:latest

1.6 创建第一个管理员用户

用户名密码 改为你想要设置的值:

docker exec -it synapse register_new_matrix_user http://localhost:8008 -c /data/homeserver.yaml -a -u 用户名 -p 密码

1.7 配置 Synapse 服务端

建议亲自阅读一遍官方文档:https://matrix-org.github.io/synapse/latest/welcome_and_overview.html

现在,你的 /var/matrix-synapse-data/ 目录下应当有一个名为 homeserver.yaml 的文件,编辑它:

vi /var/matrix-synapse-data/homeserver.yaml

homeserver.yaml 里面的内容都是 Matrix 服务器的关键配置,用于定制服务器的各项功能和参数。

这里列出关键几项,可照搬:

# 为新用户启用注册
enable_registration: true

# 无需电子邮件或 recaptcha 验证即可注册(其实不推荐)
enable_registration_without_verification: true

# 客户端用于访问此 Homeserver 的面向公众的基本 URL
public_baseurl: 你的服务端域名

# 默认情况下,其他服务器将尝试通过端口 8448 访问我们的服务器,告诉其他服务器将流量发送到端口 443
serve_server_wellknown: true

最终的配置文件大概长这样,可参考:

server_name: "<server.xxx.com>" # 修改为你的服务端域名

pid_file: /data/homeserver.pid

listeners:
  - port: 8008
    tls: false
    type: http
    x_forwarded: true
    #bind_addresses: ['127.0.0.1']

    resources:
      - names: [client, federation, openid]  # 这里的openid是为了方便后续使用OIDC第三方登录
        compress: false

log_config: "/data/<server.baiyuyu.com>.log.config" # 修改为你的服务端域名

media_store_path: /data/media_store # media文件存储路径,一般不需要修改



registration_shared_secret: "****************" # 保留原来的配置,不需要修改
report_stats: true
macaroon_secret_key: "****************" # 保留原来的配置,不需要修改
form_secret: "****************" # 保留原来的配置,不需要修改
signing_key_path: "/data/<server.baiyuyu.com>.signing.key" #修改为你的服务端域名
trusted_key_servers:
  - server_name: "matrix.org"


suppress_key_server_warning: true



presence:
  enabled: true

email:
  smtp_host: smtp.exmail.qq.com #你的smtp服务器
  smtp_port: 465 #一般是465
  smtp_user: "<你的邮箱>" #自行填写
  smtp_pass: "<你的邮箱密码>" #自行填写
  force_tls: true
  require_transport_security: true
  enable_tls: true
  notif_from: "发件人名称" #修改为你想要设置的发件人名称
  enable_notifs: true
  notif_for_new_users: false
  client_base_url: "https://<xxx.com>" #修改为你的客户端域名
  validation_token_lifetime: 15m
  invite_client_location: https://<xxx.com> #修改为你的客户端域名

#templates:
#   custom_template_directory: /path/to/custom/templates/
#自定义邮件模板,请参考官方文档配置 https://matrix-org.github.io/synapse/latest/templates.html

#以下是各类邮件的标题,可自定义:

  subjects:
    message_from_person_in_room: "%(person)s 在 %(room)s 聊天室中给你发送了一条消息"
    message_from_person: "%(person)s 给你发送了一条消息"
    messages_from_person: "%(person)s 给你发送了多条消息"
    messages_in_room: "你有一条来自 %(room)s 聊天室的消息"
    messages_in_room_and_others: "你有一些来自 %(room)s 聊天室和其他人的消息"
    messages_from_person_and_others: "[%(app)s] 你有一些来自 %(person)s 和其他人的消息"
    invite_from_person_to_room: "%(person)s 邀请你加入 %(room)s 聊天室"
    invite_from_person: "%(person)s 邀请你注册<xxx.com>"
    password_reset: "【<xxx.com>】密码重置"
    email_validation: "【<xxx.com>】验证您的电子邮件"


max_avatar_size: 10M #最大头像上传大小,一般不需要修改


federation_domain_whitelist:  #与其它Matrix服务器联合的白名单,一般不需要修改
#  - www.baiyuyu.com
#  - bbb.example.com
#  - ccc.example.com


allow_profile_lookup_over_federation: false


database:
  name: sqlite3  #这里为了方便起见,选用sqlite3作为数据库。你也可以使用PostgreSQL数据库,参考官方文档自行配置
  args:
    database: /data/homeserver.db


max_upload_size: 1024M #最大文件上传大小,一般不需要修改

enable_registration: true #是否启用注册,一般不需要修改

enable_registration_captcha: true  #是否启用 recaptchat
recaptcha_public_key: "<填入你的recaptchat公钥>"
recaptcha_private_key: "<填入你的recaptchat私钥>"

registrations_require_3pid: #允许的3pid注册方式
  - email

allow_guest_access: false #禁止访客


user_directory:
    enabled: true
    search_all_users: true
    prefer_local_users: true
    show_locked_users: false

###这条分割线以下的内容,首次配置时建议全部删掉,查看官方文档有关 OIDC 的教程后,再进行配置

oidc_providers:

  - idp_id: microsoft
    idp_name: Microsoft
    #idp_icon: "mxc://**********/**********" #图标(可选)

    issuer: "https://login.microsoftonline.com/**********/v2.0"
  
    client_id: "**********"
    client_secret: "**********"
    scopes: ["openid", "profile"]
    authorization_endpoint: "https://login.microsoftonline.com/**********/oauth2/v2.0/authorize"

    token_endpoint: "https://login.microsoftonline.com/**********/oauth2/v2.0/token"


    userinfo_endpoint: "https://graph.microsoft.com/oidc/userinfo"

    user_mapping_provider:
      config:
        localpart_template: "{{ user.preferred_username.split('@')[0] }}"
        display_name_template: "{{ user.name }}"


(共 133 行,可滚动查看)

⚠ 注意

这套配置使用了内置的 SQLite 数据库,如果用户数比较多,也可以换成官方推荐的 PostgreSQL

编辑完成之后,保存并重启 docker 容器。

docker ps
docker restart synapse

2. Nginx 反向代理

接下来编辑 nginx 配置文件。

由于服务端和客户端共用一个域名,这里的配置略有复杂,可以照搬以下配置,也可以先读一下官方文档:https://matrix-org.github.io/synapse/latest/delegate.html

map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
}


server {
    listen 80;
    server_name www.xxx.com xxx.com;
    return 301 https://$host$request_uri;
}


server {

    listen 443 ssl http2;

    server_name www.xxx.com xxx.com;

    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets on;
    
    ssl_protocols TLSv1 TLSv1.1 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:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA;
    #指定当使用 SSLv3 和 TLS 协议时,服务器密码应优先于客户端密码。
    ssl_prefer_server_ciphers on;
    ssl_stapling on;
    #启用或禁用服务器对 OCSP 响应的验证。
    ssl_stapling_verify on;

    #HSTS策略, 一年:31536000 ,180天:15552000,30天:2592000
    ###########add_header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload" always;

    #防XSS攻击
    add_header X-Xss-Protection 1;

    ssl_certificate https/chat.pem; #自行修改实际位置
    ssl_certificate_key https/chat.key;

    ignore_invalid_headers off;
    client_max_body_size 0;
    proxy_read_timeout 600s;

    error_page 403 404 500 502 503 504 /index.html;

    index index.htm index.html;

    # 访问 WEB 客户端
    location / {
        root /www/wwwroot/server.baiyuyu.com/123; #web客户端路径,可以选element或者cinny,把客户端源码放到你喜欢的目录下
        try_files $uri $uri/ =404;



    }

    # 把 /.well-known/ 和 /_matrix/ 路径下的请求都转发给后端服务器
    location ~ ^/(_matrix|.well-known|_synapse)/ {
        proxy_pass                          http://127.0.0.1:8008;
        proxy_set_header Host               $http_host;
        proxy_set_header Upgrade            $http_upgrade;
        proxy_set_header Connection         $connection_upgrade;
        proxy_set_header X-Proxy-Host       $proxy_host;
        proxy_set_header X-Forwarded-Host   $host;
        proxy_set_header X-Forwarded-Server $host:$server_port;
        proxy_set_header X-Forwarded-Proto  $scheme;
        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP          $remote_addr;
        proxy_ssl_protocols                 TLSv1.2 TLSv1.3;
    }

}

重启或重载 nginx ,使配置生效:

nginx -s reload

3. 完成

至此,祝贺你成功完成了 Synapse 服务器的搭建。

接下来你可以去研究客户端了,也可以看看我这篇文章:https://www.baiyuyu.com/127.html

4. 可选配置

接下来都是一些可选配置。

4.1 Synapse-admin (可选)

还记得刚才生成第一个管理员账号的步骤吗,是不是有点麻烦?

Synapse-admin 是一个很好用的管理面板,可以让你通过图形化界面轻松管理 Matrix 服务器上的用户、房间。

图片[5] - 超详细 Matrix Synapse 部署教程:搭建去中心化聊天服务器 - 白鱼小栈
图源 Synapse-admin 项目仓库|直达链接

注意

如果刚才的 “Nginx 反向代理” 步骤中,你直接照搬了我提供的配置文件,那么此处不需要进行任何额外配置,请跳过此栏继续阅读后面的内容。

否则,请检查你配置文件的 location 是否包含 /_matrix/_synapse/admin 两部分,以便将这个端口正确地暴露到互联网上。

4.1.1 下载 Synapse-admin

https://github.com/Awesome-Technologies/synapse-admin/releases/latest 下载最新的 Synapse-admin 到你的服务器目录。

 

4.1.2 在网站目录新建一个文件夹

转到网站根目录,新建一个文件夹,你可以取一个类似 synapse-adminsynapse-panel 这样的名字。

⚠ 注意

当然了,最好取一个复杂且只有你知道的名字,提高安全性。

 

4.1.3 把下载的 tar.gz 文件移动到此文件夹并解压

如题。接下来就可以正常使用了。

假如你的文件夹命名为 panel,那么你可以通过 https://<你的域名>/panel 访问到 Synapse-admin 面板。

 

至此,已完成 Synapse-admin 的安装。

 

4.2 OIDC 登录 (可选)

OIDC,即 OpenID Connect,是一种第三方登录协议,可以看作是 OAuth 的分支

可以看看官方的服务器,支持很多种第三方登录:

图片[6] - 超详细 Matrix Synapse 部署教程:搭建去中心化聊天服务器 - 白鱼小栈
 
图片[7] - 超详细 Matrix Synapse 部署教程:搭建去中心化聊天服务器 - 白鱼小栈
 

配置起来也很简单,只需要编辑刚刚那个 homeserver.yaml 的相关部分就可以了。

有关 OIDC 的这块内容,官方文档 写的非常详细,可以去看看。

 

这里简单把我遇到的问题列一下:

  1. 国内的微信、QQ 没法配置 OIDC 登录,它们不遵循标准的 OpenID 协议,本人搞了很长时间也没成功。

2023/12 补充:

如果通过 auth0 这种中转一下,似乎有戏?还未研究

 

  1. 微软 OIDC:如果按官方文档的去配置,你会发现个人账户无法登录。建议参考以下配置(改了终结点)
  - idp_id: microsoft
    idp_name: Microsoft
    issuer: "https://login.microsoftonline.com/consumers/v2.0"
    client_id: "填你自己的"
    client_secret: "填你自己的"
    scopes: ["openid", "profile"]
    authorization_endpoint: "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize"
    token_endpoint: "https://login.microsoftonline.com/consumers/oauth2/v2.0/token"
    userinfo_endpoint: "https://graph.microsoft.com/oidc/userinfo"

    user_mapping_provider:
      config:
        localpart_template: "{{ user.preferred_username.split('@')[0] }}"
        display_name_template: "{{ user.name }}"

 

  1. Apple OIDC:难搞。如果想开通 Login with Apple,则必须交 688 元年费,光注册一个开发者账号是没用的…

  1. 关于第三方登录:每种登录方式都可以单独设置图标,但设置图标的方式就很有意思了:你需要先随便在一个聊天界面中发送这个图标文件,然后右键审查元素,获取这个图标的 mxc 资源地址 ,复制下来备用。然后再回到 homeserver.yaml 文件的相关部分,把这个 mxc 地址填进去。头一次搞的时候,本人找了大半天,愣是一篇教程也没找到。。

全文完,总之就这些!希望对你有点帮助 ( •̀ ω •́ )


全文完

有用13阅读 2518版权提示
留言 共 32 条
其实你有必要说两句
匿名的头像 - 白鱼小栈

昵称

有回复时发送邮件通知我

取消
身份 表情 图片
    • summer的头像 - 白鱼小栈summer0
    • toto的头像 - 白鱼小栈toto1
    • Zhihuijie的头像 - 白鱼小栈Zhihuijie0
    • xinianlee的头像 - 白鱼小栈xinianlee0
    • oicn的头像 - 白鱼小栈oicn0
    • nameless的头像 - 白鱼小栈nameless1