> For AI agents: the site index is available at https://www.juniortree.com/llms.txt; this page is available as Markdown at https://www.juniortree.com/blog/synapse-build.md.
> 详细讲解Synapse服务器及配套服务搭建流程，包括数据库、身份验证和TURN服务配置

## Page metadata

- **Published:** 2025-02-05
- **Updated:** 2025-02-05
- **Tags:** 计算机
- **Source URL:** https://www.juniortree.com/blog/synapse-build

# Synapse 完整搭建流程

目前很多博客只简单讲述了如何搭建 Synapse 服务器，但实际搭建完，用户使用后会出现大量问题，本文旨在详细讲述 Synapse 服务器以及其他的配套服务搭建

## Synapse 现状

Synapse 原本是由 Matrix基金会实现和维护的，是一个基于 Python 的 Matrix 协议实现服务，当然除此之外也有其他的服务端推荐，但是 Synapse 是其中最稳定，也是官方最为推荐的，在官网他们给出了[其他的服务端](https://matrix.org/ecosystem/servers/)

![](https://pic.juniortree.com/app/hide.php?key=UG5jWEVFY1ZQRit6V2dvclU4emFXRUxtSjZKYy80c0o=)

在2024年的八月份，Matrix基金会已经无力再维护 Synapse，而是将其转交给了 Element 维护

![](https://pic.juniortree.com/app/hide.php?key=aFVjeXNwRlNuaFZMNGRoL3ZwL2E1VUxtSjZKYy80c0o=)

你或许会问了，Element 是什么？和 Matrix 又是什么关系？

坦率地讲，我觉得 Element 有点像一个商业公司，他们为一些客户提供了 Matrix 服务器的托管服务，同时将一些客户端和服务端开源，Matrix 让 Element 来接手 Synapse 的维护其中应该也有 Matrix 作为一个非盈利基金会资源不够用的窘境

对于我们普通用户来说，不管是 Matrix 还是 Element，他们所提供的 Synapse 都是开源的，因此对于我们来说没有影响，只管好好用就可以了

但是在一些细微的配置中，Element 为了更好的适配直接的客户端，我们需要做一些细微的调整，这些在后面的章节中会详细讲述

## 安装 Synapse

一个完整的 Synapse 包括以下部分：
- [Synapse](https://github.com/element-hq/synapse)
- Postgres
- [Sydent](https://github.com/matrix-org/sydent)
- [Sliding Sync](https://github.com/matrix-org/sliding-sync)
- TURN 服务
- 反代，在这里使用 Caddy

如果英文能力可以的话我极力推荐阅读官方的文档，目前最新的文档是由 Element 所维护：[Welcome and Overview - Synapse](https://element-hq.github.io/synapse/latest/welcome_and_overview.html)

### 搭建基础服务

关于如何搭建 Synapse 基础服务器，我建议可以去看一看这位博主的文章，我第一次搭建就是跟着这个的：[超详细 Matrix Synapse 部署教程：搭建去中心化加密聊天服务器 - 白鱼小栈](https://www.baiyuyu.com/304.html)

但是这个博主使用的是默认的 SQLlite 数据库，虽然简单但是性能十分拉垮，所以我们可以安装官方给出的文档将其切换成 Postgres

首先请按照我给的 `docker-compose.yml` 起好容器：

```yml
services:
  synapse:
    image: matrixdotorg/synapse:latest
    container_name: synapse
    restart: unless-stopped
    healthcheck:
       test: ["CMD-SHELL", "curl -s localhost:8008/health || exit 1"]
    ports:
      - "8008: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: "no"
    networks:
      - matrix_network

  db:
    image: postgres13
    container_name: synapse_db
    restart: unless-stopped
    environment:
      POSTGRES_USER: synapse
      POSTGRES_PASSWORD: synapse
      POSTGRES_DB: synapse
      POSTGRES_INITDB_ARGS: "--locale=C --encoding=UTF8"
    volumes:
      - ./db_data:/var/lib/postgresql/data
    networks:
      - matrix_network

networks:
  matrix_network: {}
```

之后需要修改 `homeserver.yaml`，之后修改 `database` 字段为：

```
database:
  name: psycopg2
  args:
    user: synapse
    password: synapse
    database: synapse
    host: synapse_db
    port: 5432
    cp_min: 5
    cp_max: 10
```

其他按照博主给的配置就可以了，之后打开 `8008` 端口，看看是否会出现欢迎界面

![](https://pic.juniortree.com/app/hide.php?key=VVFUNk4rTjZEYUhyWXVYUnRuRzVzZHVocG1OTFJJbHE=)

其返回的路径为：`http://<ip>/_matrix/static/`

### 配置反向代理

官方提供了 Nginx 和 Caddy 两种配置文件：[Using a reverse proxy with Synapse](https://element-hq.github.io/synapse/latest/reverse_proxy.html)

**nginx**

```text
server {
    listen 443 ssl;
    listen [::]:443 ssl;

    # For the federation port
    listen 8448 ssl default_server;
    listen [::]:8448 ssl default_server;

    server_name matrix.example.com;

    location ~ ^(/_matrix|/_synapse/client) {
        # note: do not add a path (even a single /) after the port in `proxy_pass`,
        # otherwise nginx will canonicalise the URI and cause signature verification
        # errors.
        proxy_pass http://localhost:8008;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host:$server_port;

        # 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;

    # Synapse responses may be chunked, which is an HTTP/1.1 feature.
    proxy_http_version 1.1;
    }
}
```

**caddy**，在这里我们不使用官方的配置文件，不大好用

```text
matrix.example.com {
	reverse_proxy 127.0.0.1:8008
}
```

官方提供的配置文件是：

```text
matrix.example.com {
  reverse_proxy /_matrix/* localhost:8008
  reverse_proxy /_synapse/client/* localhost:8008
}

example.com:8448 {
  reverse_proxy /_matrix/* localhost:8008
}
```

但在实际的使用中，路径并不会被正确路由，按照我自己使用的方法进行路由可能存在一些风险，还是建议用 Nginx 进行反代

在这里我们需要指定来自联邦（Federation）的流量

![](https://pic.juniortree.com/app/hide.php?key=UnROend1WmppMEZTR29EMmQ0R21Fdm9zaHdDT1NFRU0=)

在这里我不打算使用 `8448` 端口，因此需要进行声明，要使用这种方法，需要配置 `https://<server_name>` 处的服务器为 `https://<server_name>/.well-known/matrix/server` 处的文件提供服务

在 `homeserver.yaml` 中，我们可以指定字段来提供服务

```
serve_server_wellknown: true
```

之后使用 `curl` 进行测试

```zsh
$ curl -i https://<server_name>/.well-known/matrix/server
HTTP/2 200
alt-svc: h3=":443"; ma=2592000
content-type: application/json
date: Wed, 05 Feb 2025 03:27:35 GMT
server: Caddy
server: Synapse/1.123.0
strict-transport-security: max-age=31536000; includeSubDomains; preload
content-length: 34

{"m.server":"<server_name>:443"}%
```

### 配置 Sydent

Sydent 是 Matrix 协议中的身份服务器，它允许用户通过邮件和电话号码发现对方，尽管官方并不推荐用户自己搭建 Sydent 服务器，但是为了完整展示全过程，我还是在这里贴出参考步骤

![](https://pic.juniortree.com/app/hide.php?key=dnlmM3JzejBsL1QxUGllakpIQ2dNZTFzM2w5WExPLzQ=)

直接使用 docker compose 进行部署

```yml
services:
  sydent:
    image: matrixdotorg/sydent:latest
    container_name: matrix_sydent
    environment:
    - SYDENT_SERVER_NAME=
    volumes:
    - ./sydent_data:/data
    ports:
    - "8090:8090"
    restart: unless-stopped
```

之后使用 Caddy 进行反代，在客户端中添加服务器

![](https://pic.juniortree.com/app/hide.php?key=TGJHU2ZISk14dHhxcXFlTnl5MFBJWjY3MG8rWlN0anU=)

### 配置 Sliding Sync

在一些比较新的客户端，如 Element X 中，要求服务器必须支持 Sliding Sync，在这里我们还是使用 docker compose 来进行部署

```yml
services:
  postgres:
    image: postgres:13
    container_name: sliding_sync_db
    environment:
      POSTGRES_DB: syncv3
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
    volumes:
      - ./data_db:/var/lib/postgresql/data
  sliding_sync:
    image: ghcr.io/matrix-org/sliding-sync:latest
    container_name: sliding_sync
    depends_on:
      - postgres
    ports:
      - "8009:8009"
    environment:
      SYNCV3_SERVER: "https://matrix.example.com"
      SYNCV3_DB: "postgres://postgres:${DATABASE_PASSWORD}@postgres:5432/syncv3?sslmode=disable"
      SYNCV3_SECRET: ${SYNCV3_SECRET}
      SYNCV3_BINDADDR: ":8009"
```

需要创建一个 `.env` 文件，在里面填入`DATABASE_PASSWORD` 和 `SYNCV3_SECRET`

```text
DATABASE_PASSWORD=password
SYNCV3_SECRET=password
```

同样需要配置反代，除此之外，在 Synapse 服务器的 `homeserver.yaml` 中也要配置对于的字段，来让服务器在 `https://matrix.example.com/.well-known/matrix/client` 返回一个 JSON 数组，来声明服务器的 Sliding Sync 的服务

```
public_baseurl: "https://matrix.example.com"
extra_well_known_client_content : # 用来配置 /.well-known/matrix/client
  org.matrix.msc3575.proxy: https://sliding.example.com
```

重启服务，使用 `curl` 进行检查

```zsh
$ curl -i https://matrix.example.com/.well-known/matrix/client
HTTP/2 200
access-control-allow-headers: X-Requested-With, Content-Type, Authorization, Date
access-control-allow-methods: GET, HEAD, POST, PUT, DELETE, OPTIONS
access-control-allow-origin: *
access-control-expose-headers: Synapse-Trace-Id, Server
alt-svc: h3=":443"; ma=2592000
cache-control: no-cache, no-store, must-revalidate
content-type: application/json
date: Wed, 05 Feb 2025 03:45:24 GMT
server: Caddy
server: Synapse/1.123.0
strict-transport-security: max-age=31536000; includeSubDomains; preload

{"m.homeserver":{"base_url":"https://matrix.example.com/"},"org.matrix.msc3575.proxy":"https://sliding.example.com"}%
```

至此，我们可以使用官方提供的工具来检查是否配置正常，能不能和 Matrix 联邦上的其他服务器进行通信：[Matrix Federation Tester](https://federationtester.matrix.org)

![](https://pic.juniortree.com/app/hide.php?key=YVpmV25ZcjYwWk5lRGg0VHdFcHB1MCswQTI5VndmdmM=)

### TRUN 服务器

Matrix 是支持 VoIP 通话的，你可以尝试使用官方提供的 turn.matrix.org，但是这样有 IP 地址泄漏风险，而且该服务在大陆存在网络问题，因此我建议进行自建

![](https://pic.juniortree.com/app/hide.php?key=M1VTVENjTzB2K2drRU9EM2ZxNE5yeUJFUkpqa2NVOUs=)

官方文档也提供了相应的指导：[Configuring a Turn Server - Synapse](https://element-hq.github.io/synapse/latest/turn-howto.html)，在这里我使用 coturn 作为 TURN 服务器

coturn 提供了包管理、docker和本地编译三种方式，由于我使用的是 Debian，提供了包

```bash
sudo apt install coturn
```

配置文件在 `/etc/turnserver.yaml`，在正式修改之前需要进行备份

```bash
cp /etc/turnserver.conf /etc/turnserver.conf.bak
```

基础配置如下：

```yml
# 填写你的 TURN 服务域名
realm=turn.example.com

# 启用服务器
listening-port=3478
tls-listening-port=5349

# 随机密码
cli-password=password

# 指定外网IP（重要！替换为你的公网IP）
external-ip=<ip>

# UDP端口范围（建议保留默认）
min-port=49152
max-port=65535

# 测试用户，实际使用需要删除！！
user=username:password

# 动态密钥 使用 pwgen -s 64 1 生成
use-auth-secret
static-auth-secret=password

# TLS证书配置（必须）
cert=/etc/letsencrypt/live/turn.example.com/fullchain.pem
pkey=/etc/letsencrypt/live/turn.example.com/privkey.pem

# 日志配置
log-file=/var/log/turn.log
verbose

# VoIP traffic is all UDP. There is no reason to let users connect to arbitrary TCP endpoints via the relay.
no-tcp-relay

# don't let the relay ever try to connect to private IP address ranges within your network (if any)
# given the turn server is likely behind your firewall, remember to include any privileged public IPs too.
denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=192.168.0.0-192.168.255.255
denied-peer-ip=172.16.0.0-172.31.255.255

# recommended additional local peers to block, to mitigate external access to internal services.
# https://www.rtcsec.com/article/slack-webrtc-turn-compromise-and-bug-bounty/#how-to-fix-an-open-turn-relay-to-address-this-vulnerability
no-multicast-peers
denied-peer-ip=0.0.0.0-0.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=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=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

# special case the turn server itself so that client->TURN->TURN->client flows work
# this should be one of the turn server's listening IPs
allowed-peer-ip=10.0.0.1

# consider whether you want to limit the quota of relayed streams per user (or total) to avoid risk of DoS.
user-quota=12 # 4 streams per video call, so 12 streams = 3 simultaneous relayed calls per user.
total-quota=1200
```

启动服务：

```bash
systemctl start coturn
```

设置开机启动：

```bash
systemctl enable coturn
```

虽然有很多教程提出可以使用 [Trickle ICE](https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/) 测试服务是否可用，但是我在实际使用过程中发现不太好用，因此使用 coturn 提供的测试工具 `turnutils_uclient`

```bash
turnutils_uclient -v -y -u username -w password <ip>
```

链接成功的关键点：

1. 成功的分配响应：多次发送的“allocate response received: success”表明客户端成功地从TURN服务器获得了中继地址。
2. 通道绑定成功：输出中显示“channel bind sent”和“cb response received: success”，这表明通道绑定请求也成功。
3. 消息传输统计：在消息客户端（mclient）部分，显示了发送和接收的消息数量，以及没有丢包（Total lost packets 0），这表明数据传输正常。
4. 延迟和抖动：输出中提供的平均往返延迟和抖动值（Average round trip delay 250.75 ms; Average jitter 1.35 ms）也在合理范围内，表明连接质量良好。

之后需要设置 TLS/DTLS，不要使用来自 Let's Encrypt 的证书，因为所有使用 Chromium's WebRTC 的 Matrix 客户端都无法使用

![](https://pic.juniortree.com/app/hide.php?key=Y0Urbk1uVzZFVzV6ZUtvN1B4T3o3WFowWFZhTVMxMkM=)

申请 ZeroSSL 即可，ZeroSSL 提供了自动化工具：[GitHub - zerossl/zerossl-bot: The repository for the ZeroSSL certbot wrapper](https://github.com/zerossl/zerossl-bot)

```bash
apt install certbot

bash <(wget -q -O - https://github.com/zerossl/zerossl-bot/raw/master/get-zerosslbot.sh)

sudo zerossl-bot certonly --standalone -m youremail@example.com -d turn.example.com
```

申请成功后证书会下放到 `/etc/letsencrypt/archive/turn.example.com` 中

直接运行会出现问题，因为 coturn 进程没有权限去读取相应的证书文件，在[cannot start TLS and DTLS listeners because private key file is not set properly · Issue #1139 · coturn/coturn](https://github.com/coturn/coturn/issues/1139)中可以看到

解决方法有两种，将文件所有权设置为 `644`

![](https://pic.juniortree.com/app/hide.php?key=a09wV2VGU2JYU0ltaExHMHJLSzdBbUhZeDk3L3AzcXY=)

或者以 `root` 用户运行 `coturn`

修改服务配置：

```bash
sudo nano /lib/systemd/system/coturn.service
```

修改配置为：

```text
[Unit]
Description=coTURN STUN/TURN Server
Documentation=man:coturn(1) man:turnadmin(1) man:turnserver(1)
After=network.target

[Service]
User=root
Group=root
Type=notify
ExecStart=/usr/bin/turnserver -c /etc/turnserver.conf --pidfile=
Restart=on-failure
InaccessibleDirectories=/home
PrivateTmp=yes

[Install]
WantedBy=multi-user.target
```

重启服务：

```bash
sudo systemctl daemon-reload
sudo systemctl restart coturn
```

查看日志是否正常

```bash
sudo journalctl -u coturn -f
```

可以使用 `openssl` 测试 TLS 是否正常

```bash
openssl s_client -connect turn.example.com:5349
```

![](https://pic.juniortree.com/app/hide.php?key=M25CZi9YOW1CcGN4dVpZNjhiV3BNNHdydUQ3RWpYMlo=)

可以看到我这里的 CA 确实是 ZeroSSL

之后需要在 Synapse 中的 `homeserver.yaml` 配置

```yml
turn_uris: [ "turn:turn.example.com?transport=udp", "turn:turn.example.com?transport=tcp" ]
turn_shared_secret: "password"
turn_user_lifetime: 86400000
turn_allow_guests: true
```

官方文档可以参考：[Configuring a Turn Server - Synapse](https://element-hq.github.io/synapse/latest/turn-howto.html#synapse-setup)

![](https://pic.juniortree.com/app/hide.php?key=ekhCN3YxMm9YbktrRit0c29kZUpERDhMdDRMMEdLWWw=)

## 总结

Matrix 是一个很牛逼的东西，希望未来的发展越来越好，能加入和 tg 类似的贴纸包，各种功能能够更完善一下，管理集成是什么东西还是不知道

![](https://pic.juniortree.com/app/hide.php?key=MDZVbWMxZHVqUlBWN1A4S2c4d0pFN0kwQUNFVWVoZkg=)

目前我这样配置还是不能支持 Element X 的创建用户，原因目前未知，还有待进一步解决
