- #Matrix
- #Synapse
- #Element
- #Docker
- #教程

想自己搭一个可控的即时通讯服务,Matrix + Synapse + Element Web 目前还是最稳的一套组合。这篇文章把我实际部署时的配置整理了一下,密钥之类的敏感值换成了占位符,直接照着改就行。
架构说明
整体思路:
Synapse跑 Matrix 服务端Element Web提供网页客户端- 反向代理把
matrix.example.com转发到容器 - 邮件服务处理注册验证和通知
Casdoor通过 OIDC 做统一登录TURN服务做语音视频通话中继
大概长这样:
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 -> SynapseDocker Compose 配置
docker-compose.yml 如下:
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"几个要注意的地方
Synapse映射到宿主机9008,容器内部还是8008。Element Web映射到宿主机9009,容器内部是80。VIRTUAL_HOST、LETSENCRYPT_HOST这些环境变量是给nginx-proxy之类的反代方案用的,如果你用的是别的反代就不需要。- 生产环境建议把
latest改成固定版本号,免得上游更新把你搞炸。
Synapse 配置
homeserver.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_baseurl 与 server_name
这俩必须和你最终对外的域名一致:
public_baseurl: https://matrix.example.com/server_name: matrix.example.com
写错的话,客户端登录、回调地址、邮件链接、federation 全会出问题。
2. x_forwarded: true
Synapse 前面有反向代理,这个必须开。不开的话它拿不到真实 IP 和协议信息,回调 URL 和协议判断都会乱。
3. 数据库
用的 sqlite3:
database:
name: sqlite3
args:
database: /data/homeserver.db个人用或者小规模完全够了,部署也省事。用户多了再迁 PostgreSQL。
4. 邮件验证
配置里开了邮箱验证注册:
registrations_require_3pid: [email]enable_registration: trueenable_registration_without_verification: false
允许注册但必须过邮箱验证,比裸开放安全得多。
5. OIDC 单点登录
有统一认证中心(比如 Casdoor)的话可以直接接上:
oidc_providers:
- idp_id: "casdoor"
issuer: "https://casdoor.example.com"Matrix 的账号体系就能和你其他系统打通了。配置里还加了:
allow_existing_users: true- 用
preferred_username自动映射本地用户名 - 自动填充显示名和邮箱
已有账号迁移过来会方便很多。
6. TURN 配置
想语音视频通话能用,TURN 基本得配:
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. 启动服务
docker compose up -d起来之后看一下日志,确认 Synapse 正常加载了配置:
docker logs -f matrix_synapse3. 配置反向代理
用 Nginx 的话把域名反代到对应端口:
matrix.example.com -> 127.0.0.1:9008Element Web 所在域名 -> 127.0.0.1:9009
前后端想用同一个域名的话需要额外规划路径,这里就按最简单的分域名来。
4. 创建管理员账号
部署完先建一个管理员:
docker exec -it matrix_synapse register_new_matrix_user \
-c /data/homeserver.yaml \
http://localhost:8008按提示输入用户名、密码,选是否设为管理员。
Element Web 补充
Compose 里 element-web 的自定义配置挂载是注释掉的:
# volumes:
# - "./element-config.json:/app/config.json:ro"这样用的是默认配置。后面想让客户端默认连自己的 homeserver,补一个 config.json 挂载进去就行,不然首次登录还得手动填服务器地址。
上线前记得检查
- 占位符密钥全部换成随机高强度字符串。
- 域名解析指向你的反代服务器。
- 反向代理正确透传
X-Forwarded-For和X-Forwarded-Proto。 - 邮件服务能正常发信,不然注册验证会卡住。
- OIDC 回调地址在认证中心后台注册好了。
- TURN 的 3478 端口和中继端口防火墙放通了。
总结
Synapse + Element Web 这套方案本身不复杂,容易踩坑的都在外围:反代配置、邮件发信、OIDC 回调、TURN 中继、域名一致性,还有密钥管理。
个人用的话 Docker Compose 加 SQLite 就够了;后期要长期跑,再上 PostgreSQL、加监控和备份。
DISCUSSION
文章评论
昵称、头像与账号资料会自动同步,无需手动填写。