BLOG / 教程

Matrix 服务器部署教程:使用 Docker 搭建 Synapse 与 Element Web

基于 Docker Compose 部署 Matrix 服务端 Synapse 与 Element Web 的完整过程,涵盖反代、邮件验证、OIDC 单点登录、TURN 配置。

约 5 分钟0次浏览
  • #Matrix
  • #Synapse
  • #Element
  • #Docker
  • #教程

想自己搭一个可控的即时通讯服务,Matrix + Synapse + Element Web 目前还是最稳的一套组合。这篇文章把我实际部署时的配置整理了一下,密钥之类的敏感值换成了占位符,直接照着改就行。

架构说明

整体思路:

  • Synapse 跑 Matrix 服务端
  • Element Web 提供网页客户端
  • 反向代理把 matrix.example.com 转发到容器
  • 邮件服务处理注册验证和通知
  • Casdoor 通过 OIDC 做统一登录
  • TURN 服务做语音视频通话中继

大概长这样:

plain
matrix.example.com -> Reverse Proxy -> Synapse
matrix.example.com -> Reverse Proxy -> Element Web
casdoor.example.com -> OIDC -> Synapse
turn.example.com -> TURN -> Matrix VoIP
mail.example.com -> SMTP -> Synapse

Docker Compose 配置

docker-compose.yml 如下:

yaml
version: "3.3"

services:
  synapse:
    image: "matrixdotorg/synapse:latest"
    container_name: "matrix_synapse"
    restart: unless-stopped
    ports:
      - "9008:8008"
    volumes:
      - "./data:/data"
    environment:
      VIRTUAL_HOST: "matrix.example.com"
      VIRTUAL_PORT: "8008"
      LETSENCRYPT_HOST: "matrix.example.com"
      SYNAPSE_SERVER_NAME: "matrix.example.com"
      SYNAPSE_REPORT_STATS: "yes"

  element-web:
    image: "vectorim/element-web"
    container_name: "matrix_element_web"
    restart: unless-stopped
    ports:
      - "9009:80"
    # 如果需要自定义 Element 配置,可以取消下面的挂载
    # volumes:
    #   - "./element-config.json:/app/config.json:ro"

几个要注意的地方

  1. Synapse 映射到宿主机 9008,容器内部还是 8008
  2. Element Web 映射到宿主机 9009,容器内部是 80
  3. VIRTUAL_HOSTLETSENCRYPT_HOST 这些环境变量是给 nginx-proxy 之类的反代方案用的,如果你用的是别的反代就不需要。
  4. 生产环境建议把 latest 改成固定版本号,免得上游更新把你搞炸。

Synapse 配置

homeserver.yaml 的关键部分,密钥类的值换成了占位符:

yaml
public_baseurl: "https://matrix.example.com/"
server_name: "matrix.example.com"
pid_file: /data/homeserver.pid

listeners:
  - port: 8008
    tls: false
    type: http
    x_forwarded: true
    resources:
      - names: [client, federation, openid]
        compress: false

database:
  name: sqlite3
  args:
    database: /data/homeserver.db

log_config: "/data/matrix.example.com.log.config"
media_store_path: /data/media_store

registration_shared_secret: "<GENERATE_A_RANDOM_SECRET>"
macaroon_secret_key: "<GENERATE_A_RANDOM_SECRET>"
form_secret: "<GENERATE_A_RANDOM_SECRET>"
signing_key_path: "/data/matrix.example.com.signing.key"

report_stats: true

trusted_key_servers:
  - server_name: "matrix.org"

email:
  smtp_host: mail.example.com
  smtp_port: 465
  smtp_user: "[email protected]"
  smtp_pass: "<SMTP_PASSWORD>"
  force_tls: true
  require_transport_security: true
  enable_tls: true
  notif_from: "Matrix <[email protected]>"
  enable_notifs: true
  notif_for_new_users: false
  client_base_url: "https://matrix.example.com"
  validation_token_lifetime: 15m
  invite_client_location: "https://matrix.example.com"

registrations_require_3pid:
  - email

enable_registration: true
enable_registration_without_verification: false

oidc_providers:
  - idp_id: "casdoor"
    idp_name: "meow auth"
    discover: true
    issuer: "https://casdoor.example.com"
    client_id: "<OIDC_CLIENT_ID>"
    client_secret: "<OIDC_CLIENT_SECRET>"
    user_profile_method: userinfo_endpoint
    scopes: ["openid", "profile", "email"]
    allow_existing_users: true
    user_mapping_provider:
      config:
        subject_template: "{{ user.sub }}"
        localpart_template: "{{ user.preferred_username|default(user.name, true)|lower }}"
        display_name_template: "{{ user.name|default(user.preferred_username, true) }}"
        email_template: "{{ user.email }}"
        confirm_localpart: true

turn_uris:
  - "turn:turn.example.com:3478?transport=udp"
  - "turn:turn.example.com:3478?transport=tcp"
turn_shared_secret: "<TURN_SHARED_SECRET>"
turn_user_lifetime: 86400000
turn_allow_guests: true

关键配置解释

1. public_baseurlserver_name

这俩必须和你最终对外的域名一致:

  • public_baseurl: https://matrix.example.com/
  • server_name: matrix.example.com

写错的话,客户端登录、回调地址、邮件链接、federation 全会出问题。

2. x_forwarded: true

Synapse 前面有反向代理,这个必须开。不开的话它拿不到真实 IP 和协议信息,回调 URL 和协议判断都会乱。

3. 数据库

用的 sqlite3

yaml
database:
  name: sqlite3
  args:
    database: /data/homeserver.db

个人用或者小规模完全够了,部署也省事。用户多了再迁 PostgreSQL。

4. 邮件验证

配置里开了邮箱验证注册:

  • registrations_require_3pid: [email]
  • enable_registration: true
  • enable_registration_without_verification: false

允许注册但必须过邮箱验证,比裸开放安全得多。

5. OIDC 单点登录

有统一认证中心(比如 Casdoor)的话可以直接接上:

yaml
oidc_providers:
  - idp_id: "casdoor"
    issuer: "https://casdoor.example.com"

Matrix 的账号体系就能和你其他系统打通了。配置里还加了:

  • allow_existing_users: true
  • preferred_username 自动映射本地用户名
  • 自动填充显示名和邮箱

已有账号迁移过来会方便很多。

6. TURN 配置

想语音视频通话能用,TURN 基本得配:

yaml
turn_uris:
  - "turn:turn.example.com:3478?transport=udp"
  - "turn:turn.example.com:3478?transport=tcp"
turn_shared_secret: "<TURN_SHARED_SECRET>"

光靠 P2P 打洞成功率看脸,跨运营商、跨 NAT、移动网络下 TURN 能减少很多通话失败的情况。

部署步骤

1. 准备目录

docker-compose.yml 丢进去,homeserver.yaml 放到 ./data/homeserver.yaml

2. 启动服务

bash
docker compose up -d

起来之后看一下日志,确认 Synapse 正常加载了配置:

bash
docker logs -f matrix_synapse

3. 配置反向代理

用 Nginx 的话把域名反代到对应端口:

  • matrix.example.com -> 127.0.0.1:9008
  • Element Web 所在域名 -> 127.0.0.1:9009

前后端想用同一个域名的话需要额外规划路径,这里就按最简单的分域名来。

4. 创建管理员账号

部署完先建一个管理员:

bash
docker exec -it matrix_synapse register_new_matrix_user \
  -c /data/homeserver.yaml \
  http://localhost:8008

按提示输入用户名、密码,选是否设为管理员。

Element Web 补充

Compose 里 element-web 的自定义配置挂载是注释掉的:

yaml
# volumes:
#   - "./element-config.json:/app/config.json:ro"

这样用的是默认配置。后面想让客户端默认连自己的 homeserver,补一个 config.json 挂载进去就行,不然首次登录还得手动填服务器地址。

上线前记得检查

  1. 占位符密钥全部换成随机高强度字符串。
  2. 域名解析指向你的反代服务器。
  3. 反向代理正确透传 X-Forwarded-ForX-Forwarded-Proto
  4. 邮件服务能正常发信,不然注册验证会卡住。
  5. OIDC 回调地址在认证中心后台注册好了。
  6. TURN 的 3478 端口和中继端口防火墙放通了。

总结

Synapse + Element Web 这套方案本身不复杂,容易踩坑的都在外围:反代配置、邮件发信、OIDC 回调、TURN 中继、域名一致性,还有密钥管理。

个人用的话 Docker Compose 加 SQLite 就够了;后期要长期跑,再上 PostgreSQL、加监控和备份。

KEEP READING

继续阅读

DISCUSSION

文章评论

0
正在读取